-
Notifications
You must be signed in to change notification settings - Fork 122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: has_operation #1807
base: main
Are you sure you want to change the base?
feat: has_operation #1807
Conversation
thanks Cam! i'm out teaching this week so have very limited time, but i'll take a look soon! |
thanks for doing this! would we need to remove blanket notimplementederrors like narwhals/narwhals/_arrow/dataframe.py Lines 380 to 392 in 05cb650
for this to be accurate? |
This is correct, though we may be able to detect this type of blanket β ASTfrom inspect import getsource
from textwrap import dedent
from ast import parse, NodeVisitor
from narwhals._arrow.dataframe import ArrowDataFrame
class Visitor(NodeVisitor):
def __init__(self):
self.has_notimplemented = False
self.has_return = False
super().__init__()
def visit_Return(self, node):
self.has_return = True
def visit_Raise(self, node):
if node.exc.func.id == 'NotImplementedError':
self.has_notimplemented = True
source = dedent(getsource(ArrowDataFrame.join_asof))
tree = parse(source)
v = Visitor()
v.visit(tree)
print(f'{v.has_notimplemented = }')
print(f'{v.has_return = }')
if v.has_notimplemented and not v.has_return:
print('This method is likely not implemented')
# v.has_notimplemented = True
# v.has_return = False
# This method is likely not implemented β‘ Not Implemented Decorator (store on method)Something more reliable may be to implement a from functools import wraps
def not_implemented(msg):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
raise NotImplementedError(msg)
wrapper.not_implemented = True # store info on the method itself
return wrapper
return decorator
class T:
@not_implemented('Not available in ...')
def f(self):
pass
def g(self):
pass
t = T()
# t.f()
print(
f"{hasattr(T.f, 'not_implemented') = }",
f"{hasattr(T.g, 'not_implemented') = }",
sep='\n'
)
T.f()
β’ Not Implemented Decorator (store in registry)from functools import wraps
def not_implemented(msg):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
raise NotImplementedError(msg)
not_implemented.registry.add(wrapper)
return wrapper
if not hasattr(not_implemented, 'registry'):
not_implemented.registry = set()
return decorator
class T:
@not_implemented('Not available in ...')
def f(self):
pass
def g(self):
pass
t = T()
print(
f'{not_implemented.registry = }',
f'{T.f in not_implemented.registry = }',
f'{T.g in not_implemented.registry = }',
sep='\n',
end='\n'*2
)
t.f()
|
What type of PR is this? (check all applicable)
Related issues
has_operation
in IbisΒ #1610Checklist
If you have comments or can explain your changes, please do so below
Review Items
Wanted to get feedback for an idea I had to implement
has_operation
. The current API implements the following changesmetaproperty
decorator that behaves similarly toproperty
(only the getter syntax other functionality would need to be implemented or would need to inherit from property itself).nw.Expr.dt.date
is valid syntax.has_operation
to check if a given function passed using the above syntax is available for any given backend.What would be nice for this feature would be if these components were more readily accessible from the narwhals namespace, dynamic imports based on internalized mappings can become tricky to maintain (see
narwhals/utils:has_operation locals.backend_mapping
) Instead these expressions could be added to the Implementation enum providing more informative metadata (such as import location lookups as well as namespace import names).Feedback on the concept as a whole or the specific implementation is welcome! If @MarcoGorelli likes this approach, I do believe some additional work is required here to get this working correctly with the internal versioning interface so guidance in this spot would be appreciated.
Here are a few examples to show what this PR contains