-
-
Save fish2000/1af4b852d20b7568a9b9c90fe2346b6d to your computer and use it in GitHub Desktop.
Revisions
-
fish2000 revised this gist
Nov 20, 2018 . 1 changed file with 36 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -13,6 +13,7 @@ import typing as tx import re import types import collections.abc __all__ = ('overloaded', 'T', 'U') @@ -32,6 +33,12 @@ def origin(arg): def is_generic_sequence(arg): return origin(arg) is collections.abc.Sequence def is_generic_iterable(arg): return origin(arg) is collections.abc.Iterable def can_be_iterated(arg): return is_generic_sequence(arg) or is_generic_iterable(arg) def to_matchgroup(arg, groups): if type(arg) is tx.TypeVar: if arg in groups: @@ -43,10 +50,12 @@ def to_matchgroup(arg, groups): return to_regex(arg, groups) def to_regex(typevar, groups): if typevar in { float, int, str, bytes }: return nameof(typevar) elif is_generic_sequence(typevar): return "(?:list|tuple)\[{}\]".format(to_matchgroup(typevar.__args__[0], groups)) elif is_generic_iterable(typevar): return "(?:set|frozenset|generator)\[{}\]".format(to_matchgroup(typevar.__args__[0], groups)) return ".*?" def get_element_types(sequence): @@ -59,15 +68,17 @@ def get_element_types(sequence): return out def to_callee(arg): if type(arg) in { float, int, str, bytes }: return typename(arg) elif type(arg) in { list, tuple, set, frozenset }: t = typename(arg) + '[{}]' eltypes = get_element_types(arg) if len(eltypes) == 1: return t.format(nameof(eltypes[0])) else: raise RuntimeError("Not implemented yet.") elif type(arg) in { types.GeneratorType }: return typename(arg) + '[.*?]' else: raise RuntimeError("Not implemented yet.") @@ -121,9 +132,29 @@ def add(a: tx.Sequence[T], b: tx.Sequence[str]): def add(a: tx.Sequence[T], b: tx.Sequence[U]): return [x + y for x, y in zip(a, b)] @overloaded def add(a: tx.Sequence[T], b: tx.Iterable[U]): return add(a, list(b)) if __name__ == '__main__': print(add(3, 5)) print() print(add(4.5, 8.2)) print() print(add([1, 2, 3], 5.0)) print() print(add([1, 2, 3], [1, 2, 3])) print() print(add([1, 2, 3], ["a", "b", "c"])) print() print(add([1, 2, 3], { "a", "b", "c" })) print() print(add([1, 2, 3], (x.upper() for x in ["a", "b", "c"]))) print() -
fish2000 revised this gist
Nov 20, 2018 . 1 changed file with 10 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -20,8 +20,11 @@ VERBOSE = True def nameof(arg): return arg.__name__ def typename(arg): return nameof(type(arg)) def origin(arg): return getattr(arg, '__origin__', object) @@ -32,16 +35,16 @@ def is_generic_sequence(arg): def to_matchgroup(arg, groups): if type(arg) is tx.TypeVar: if arg in groups: return "(?P={})".format(nameof(arg)) else: groups |= { arg } return "(?P<{}>.*?)".format(nameof(arg)) else: return to_regex(arg, groups) def to_regex(typevar, groups): if typevar in { float, int, str }: return nameof(typevar) elif is_generic_sequence(typevar): return "(?:list|set|tuple)\[{}\]".format(to_matchgroup(typevar.__args__[0], groups)) return ".*?" @@ -62,18 +65,18 @@ def to_callee(arg): t = typename(arg) + '[{}]' eltypes = get_element_types(arg) if len(eltypes) == 1: return t.format(nameof(eltypes[0])) else: raise RuntimeError("Not implemented yet.") else: raise RuntimeError("Not implemented yet.") def to_match_target(caller_signature): return ", ".join(to_callee(el) for el in caller_signature) def to_regex_sig(caller_signature): groups = set() return ", ".join(to_regex(el, groups) for el in caller_signature) class overloaded(object): -
fish2000 revised this gist
Nov 20, 2018 . 1 changed file with 48 additions and 19 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,36 +1,65 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # # multiple_dispatch.py # # My version: # https://gist.github.com/fish2000/1af4b852d20b7568a9b9c90fe2346b6d # # Forked from the originall by @wolfv: # https://gist.github.com/wolfv/73f56e4a9cac84eea6a796fde3213456 # # * See below for usage notes import typing as tx import re import collections.abc __all__ = ('overloaded', 'T', 'U') __dir__ = lambda: list(__all__) VERBOSE = True def typename(arg): return type(arg).__name__ def origin(arg): return getattr(arg, '__origin__', object) def is_generic_sequence(arg): return origin(arg) is collections.abc.Sequence def to_matchgroup(arg, groups): if type(arg) is tx.TypeVar: if arg in groups: return "(?P={})".format(arg.__name__) else: groups |= { arg } return "(?P<{}>.*?)".format(arg.__name__) else: return to_regex(arg, groups) def to_regex(typevar, groups): if typevar in { float, int, str }: return typevar.__name__ elif is_generic_sequence(typevar): return "(?:list|set|tuple)\[{}\]".format(to_matchgroup(typevar.__args__[0], groups)) return ".*?" def get_element_types(sequence): typeset = { type(el) for el in sequence } out = [] for el in sequence: eltype = type(el) if eltype in typeset and eltype not in out: out.append(eltype) return out def to_callee(arg): if type(arg) in { float, int }: return typename(arg) elif type(arg) in { list, set, tuple }: t = typename(arg) + '[{}]' eltypes = get_element_types(arg) if len(eltypes) == 1: return t.format(list(eltypes)[0].__name__) @@ -81,14 +110,14 @@ def add(a: float, b: float): def add(a: tx.Sequence[T], b: float): return [x + b for x in a] @overloaded def add(a: tx.Sequence[T], b: tx.Sequence[str]): return [str(x) + y for x, y in zip(a, b)] @overloaded def add(a: tx.Sequence[T], b: tx.Sequence[U]): return [x + y for x, y in zip(a, b)] if __name__ == '__main__': print(add(3, 5)) print(add(4.5, 8.2)) -
fish2000 revised this gist
Nov 20, 2018 . 1 changed file with 0 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -52,7 +52,6 @@ class overloaded(object): def __init__(self, f): signature = tuple(x[1] for x in f.__annotations__.items()) self.fmap[to_regex_sig(signature)] = f def __call__(self, *args): -
fish2000 revised this gist
Nov 20, 2018 . 1 changed file with 5 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,6 +4,7 @@ __all__ = ('overloaded', 'T', 'U') __dir__ = lambda: list(__all__) VERBOSE = True def to_regex(typevar, groups): def to_matchgroup(arg, groups): @@ -57,9 +58,11 @@ def __init__(self, f): def __call__(self, *args): match_sig = to_match_target(args) for key, func in self.fmap.items(): if VERBOSE: print("Matching: {} against\n {}\n".format(match_sig, key)) if (re.match(key, match_sig)): if VERBOSE: print(" === MATCH ===\n\n") return func(*args) else: raise RuntimeError("No overload found for ", match_sig) -
fish2000 revised this gist
Nov 20, 2018 . 1 changed file with 13 additions and 9 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,9 +1,13 @@ import typing as tx import re __all__ = ('overloaded', 'T', 'U') __dir__ = lambda: list(__all__) def to_regex(typevar, groups): def to_matchgroup(arg, groups): if type(arg) is tx.TypeVar: if arg in groups: return "(?P={})".format(arg.__name__) else: @@ -12,9 +16,9 @@ def to_matchgroup(arg, groups): else: return to_regex(arg, groups) if typevar in { float, int, str }: return typevar.__name__ elif typevar.mro()[1] is tx.Sequence: return "(?:list|set|tuple)\[{}\]".format(to_matchgroup(typevar.__args__[0], groups)) return ".*?" @@ -68,19 +72,19 @@ def add(a: int, b: int): def add(a: float, b: float): return a + b T = tx.TypeVar('T') U = tx.TypeVar('U') @overloaded def add(a: tx.Sequence[T], b: float): return [x + b for x in a] @overloaded def add(a: tx.Sequence[T], b: tx.Sequence[T]): return [x + y for x, y in zip(a, b)] @overloaded def add(a: tx.Sequence[T], b: tx.Sequence[str]): return [str(x) + y for x, y in zip(a, b)] if __name__ == '__main__': -
wolfv revised this gist
Oct 24, 2018 . No changes.There are no files selected for viewing
-
wolfv created this gist
Oct 24, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,91 @@ from typing import * import re def to_regex(typevar, groups): def to_matchgroup(arg, groups): if type(arg) is TypeVar: if arg in groups: return "(?P={})".format(arg.__name__) else: groups |= {arg} return "(?P<{}>.*?)".format(arg.__name__) else: return to_regex(arg, groups) if typevar in {float, int, str}: return typevar.__name__ elif typevar.mro()[1] is Sequence: return "(?:list|set|tuple)\[{}\]".format(to_matchgroup(typevar.__args__[0], groups)) return ".*?" def get_element_types(sequence): return set(type(el) for el in sequence) def to_callee(arg): if type(arg) in [float, int]: return type(arg).__name__ elif type(arg) in [list, set, tuple]: t = type(arg).__name__ + '[{}]' eltypes = get_element_types(arg) if len(eltypes) == 1: return t.format(list(eltypes)[0].__name__) else: raise RuntimeError("Not implemented yet.") else: raise RuntimeError("Not implemented yet.") def to_match_target(caller_signature): return ", ".join([to_callee(el) for el in caller_signature]) def to_regex_sig(caller_signature): groups = set() return ", ".join([to_regex(el, groups) for el in caller_signature]) class overloaded(object): fmap = {} def __init__(self, f): signature = tuple(x[1] for x in f.__annotations__.items()) groups = set() self.fmap[to_regex_sig(signature)] = f def __call__(self, *args): match_sig = to_match_target(args) for key, func in self.fmap.items(): print("Matching: {} against\n {}\n".format(match_sig, key)) if (re.match(key, match_sig)): print(" === MATCH ===\n\n") return func(*args) else: raise RuntimeError("No overload found for ", match_sig) @overloaded def add(a: int, b: int): return a + b + 100 @overloaded def add(a: float, b: float): return a + b T = TypeVar('T') U = TypeVar('U') @overloaded def add(a: Sequence[T], b: float): return [x + b for x in a] @overloaded def add(a: Sequence[T], b: Sequence[T]): return [x + y for x, y in zip(a, b)] @overloaded def add(a: Sequence[T], b: Sequence[str]): return [str(x) + y for x, y in zip(a, b)] if __name__ == '__main__': print(add(3, 5)) print(add(4.5, 8.2)) print(add([1, 2, 3], 5.0)) print(add([1, 2, 3], [1, 2, 3])) print(add([1, 2, 3], ["a", "b", "c"]))