Skip to content

Commit

Permalink
Improved dynamic signatures on _union_member_factory
Browse files Browse the repository at this point in the history
  • Loading branch information
timbernat committed Apr 22, 2024
1 parent b025a91 commit a4a70a7
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 15 deletions.
2 changes: 1 addition & 1 deletion polymerist/duration.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

# TYPING AND CONVERSION
Timeable : TypeAlias = Union[int, float, timedelta, Quantity]
istimeable = _union_member_factory(Timeable)
istimeable = _union_member_factory(Timeable, 'Timeable')

def _convert_interval_to_seconds(interval : Timeable) -> float:
'''Takes an object interpretable as a duration in seconds and returns a float or int corresponding to that interval (in seconds)'''
Expand Down
33 changes: 20 additions & 13 deletions polymerist/genutils/typetools/categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,38 @@


# TYPECHECKING FOR CUSTOM UNION TYPE ALIASES
def _union_member_factory(union : U) -> Callable[[Any], bool]:
'''Factory for making Uion-membership-checking functions'''
def _union_member_factory(union : U, regname : str='Union') -> Callable[[Any], bool]:
'''Factory for making Union-membership-checking functions'''
def isinunion(var : Any) -> bool:
'''Check if an object is a member of a Union class'''
return isinstance(var, union.__args__)
return isinunion

isunion_function_name = f'is{regname.lower()}'
isinunion.__name__ = isunion_function_name
isinunion.__qualname__ = isunion_function_name
isinunion.__doc__ = f'''Check if an object is an instance of the {regname} class'''

Numeric : TypeAlias = Union[int, float, complex, np_number]
StringLike : TypeAlias = Union[str, bytes, bytearray]
JSONSerializable : TypeAlias = Union[str, bool, int, float, tuple, list, dict]
return isinunion

_TYPE_UNIONS : tuple[Type] = (Numeric, StringLike, JSONSerializable)
for klass in _TYPE_UNIONS:
globals[f'is{klass.__name__.lower()}'] = _union_member_factory(klass) # register to module-level scope
_UNION_TYPES : dict[str, U] = { # registry of aliases type Unions (will be dynamically registered with isinstance-like checkers at module level)
'Numeric' : Union[int, float, complex, np_number],
'StringLike' : Union[str, bytes, bytearray],
'JSONSerializable' : Union[str, bool, int, float, tuple, list, dict],
}
for union_name, union_type in _UNION_TYPES.items():
globals()[union_name] = union_type
_union_checker_func = _union_member_factory(union_type, union_name) # register to module-level scope
globals()[_union_checker_func.__name__] = _union_checker_func # register to module-level scope


# REGISTRIES OF ALL BUILTIN TYPES WITH GIVEN BASE CLASS BEHAVIOR
BUILTIN_TYPES : dict[str, Type] = {}
_BUILTIN_BASES_TO_CHECK : tuple[Type] = (Exception, Callable, Container, Iterable, Sequence)
for klass in _BUILTIN_BASES_TO_CHECK:
for _klass in _BUILTIN_BASES_TO_CHECK:
class_reg : dict[str, Type] = {}
for builtin_name in dir(builtins):
builtin_obj = getattr(builtins, builtin_name)
if isclass(builtin_obj):
BUILTIN_TYPES[builtin_obj.__name__] = builtin_obj
if issubclass(builtin_obj, klass):
if issubclass(builtin_obj, _klass):
class_reg[builtin_obj.__name__] = builtin_obj
globals()[f'BUILTIN_{klass.__name__.upper()}S'] = class_reg # register to module-level scope
globals()[f'BUILTIN_{_klass.__name__.upper()}S'] = class_reg # register to module-level scope
2 changes: 1 addition & 1 deletion polymerist/rdutils/rdtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
RDBond = Chem.rdchem.Bond

RDObj : TypeAlias = Union[RDMol, RWMol, RDAtom, RDBond]
isrdobj = _union_member_factory(RDObj)
isrdobj = _union_member_factory(RDObj, 'RDObj')

0 comments on commit a4a70a7

Please sign in to comment.