diff --git a/my/core/query.py b/my/core/query.py index 4ab7aec..bbc0623 100644 --- a/my/core/query.py +++ b/my/core/query.py @@ -23,8 +23,6 @@ T = TypeVar("T") ET = Res[T] -# e.g. ("my.reddit", "comments") -Locator = Tuple[str, str] U = TypeVar("U") # In a perfect world, the return value from a OrderFunc would just be U, # not Optional[U]. However, since this has to deal with so many edge @@ -61,6 +59,16 @@ def locate_function(module_name: str, function_name: str) -> Callable[[], Iterab raise QueryException(f"Could not find function {function_name} in {module_name}") +def locate_qualified_function(qualified_name: str) -> Callable[[], Iterable[ET]]: + """ + As an example, 'my.reddit.comments' -> locate_function('my.reddit', 'comments') + """ + if "." not in qualified_name: + raise QueryException("Could not find a '.' in the function name, e.g. my.reddit.comments") + rdot_index = qualified_name.rindex(".") + return locate_function(qualified_name[:rdot_index], qualified_name[rdot_index + 1:]) + + def attribute_func(obj: T, where: Where, default: Optional[U] = None) -> Optional[OrderFunc]: """ Attempts to find an attribute which matches the 'where_function' on the object, @@ -341,7 +349,7 @@ def _handle_generate_order_by( def select( - src: Union[Locator, Iterable[ET], Callable[[], Iterable[ET]]], + src: Union[Iterable[ET], Callable[[], Iterable[ET]]], *, where: Optional[Where] = None, order_by: Optional[OrderFunc] = None, @@ -397,8 +405,8 @@ def select( The 'drop_exceptions' and 'raise_exceptions' let you ignore or raise when the src contains exceptions - src: a locator to import a function from, an iterable of mixed types, - or a function to be called, as the input to this function + src: an iterable of mixed types, or a function to be called, + as the input to this function where: a predicate which filters the results before sorting @@ -432,10 +440,7 @@ def select( """ it: Iterable[ET] = [] # default - # check if this is a locator - if type(src) == tuple and len(src) == 2: # type: ignore[arg-type] - it = locate_function(src[0], src[1])() # type: ignore[index] - elif callable(src): + if callable(src): # hopefully this returns an iterable and not something that causes a bunch of lag when its called? # should typically not be the common case, but giving the option to # provide a function as input anyways @@ -443,7 +448,7 @@ def select( else: # assume it is already an iterable if not isinstance(src, Iterable): - low(f"""Input was neither a locator for a function, or a function itself. + low(f"""Input was neither a function, or some iterable Expected 'src' to be an Iterable, but found {type(src).__name__}... Will attempt to call iter() on the value""") it = src diff --git a/my/core/query_range.py b/my/core/query_range.py index 939682b..ee8ff00 100644 --- a/my/core/query_range.py +++ b/my/core/query_range.py @@ -330,7 +330,7 @@ Specify a type or a key to order the value by""") attr_func=order_by_chosen, # type: ignore[arg-type] default_before=time.time(), value_coercion_func=_datelike_to_float) - elif order_by_value_type in [str, int, float]: + elif order_by_value_type in [int, float]: # allow primitives to be converted using the default int(), float() callables filter_func = _create_range_filter( unparsed_range=unparsed_range,