Skip to content
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

Get argument infos from method descriptors #1368

Closed
wants to merge 8 commits into from

Conversation

tristanlatr
Copy link
Contributor

@tristanlatr tristanlatr commented Jan 24, 2022

Steps

  • For new features or bug fixes, add a ChangeLog entry describing what your PR does.
  • Write a good description on what the PR does.

Description

This PR adds argument infos from method descriptors, meaning from functions defined in python C-extensions.

Type of Changes

Type
✨ New feature
🔨 Refactoring

Comment on lines +801 to +816
def _find_dot_so_files(path: Path) -> Iterator[Path]:
for entry in path.iterdir():
if entry.suffix in importlib.machinery.EXTENSION_SUFFIXES:
yield entry

def _import_module(path: Path, module_full_name: str) -> types.ModuleType:
spec = importlib.util.spec_from_file_location(module_full_name, path)
if spec is None:
raise RuntimeError(
f"Cannot find spec for module {module_full_name} at {path}"
)
py_mod = importlib.util.module_from_spec(spec)
loader = spec.loader
assert isinstance(loader, importlib.abc.Loader), loader
loader.exec_module(py_mod)
return py_mod
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is probably a utility in astroid to do this...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume it's OK to include these private helpers, it's only going to be used in the tests. And I didn't see anything the does such imports in astroid, but maybe I did not look at the right place.

@Pierre-Sassoulas Pierre-Sassoulas added this to the 2.10.0 milestone Jan 24, 2022
@Pierre-Sassoulas Pierre-Sassoulas added the Needs review 🔍 Needs to be reviewed by one or multiple more persons label Jan 24, 2022
@@ -790,5 +797,53 @@ def test_parse_module_with_invalid_type_comments_does_not_crash():
assert isinstance(node, nodes.Module)


def test_c_module_text_signature():
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this test cannot pass on pypy, since they do not support CPython extensions natively.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to tell pytest to skip it right?

Although I must confess I don't know if this is actually true. Did you find any documentation about this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to tell pytest to skip it right?

Yes we can

Although I must confess I don't know if this is actually true. Did you find any documentation about this?

Yes I've read that from pypy's documentation, but I can't find the link now. But here's what the pypy wiki says: "There is a compatibility layer for CPython C API extensions called CPyExt, but it is incomplete and experimental.". So I'm positive that, by default, pypy has no support for c-modules built for cpython.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's skip then!

@DanielNoord DanielNoord self-requested a review January 24, 2022 18:10
Comment on lines -231 to -224
# set node's arguments to None to notice that we have no information, not
# and empty argument list
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To still be inline with this, I should set None to args if we get a ValueError calling signature.signature().

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! Let's do that!

@tristanlatr
Copy link
Contributor Author

Also it seems that the python 3.10 tests are consistently failling the following three tests:

tests/unittest_brain.py::SixBrainTest::test_attribute_access 
tests/unittest_brain.py::test_http_client_brain
tests/unittest_regrtest.py::NonRegressionTests::test_ssl_protocol

I'll looks into that, but I'de like to hear opinions in favour of such features before I spend too much time on it and at the end it does not fit in your agenda..

Thanks.

Still Todo:

@cdce8p cdce8p modified the milestones: 2.10.0, 2.11.0 Feb 26, 2022
@tristanlatr
Copy link
Contributor Author

Up!

@Pierre-Sassoulas Pierre-Sassoulas self-requested a review March 25, 2022 19:42
@DanielNoord
Copy link
Collaborator

@tristanlatr Could you resolve the merge conflicts?

@tristanlatr
Copy link
Contributor Author

@DanielNoord,

Conflicts are resolved, but I've not yet lint the code. There are still a couple points to discuss first.

Thanks

@tristanlatr
Copy link
Contributor Author

It looks like linux python 3.10 tests are sill failing, any clue @DanielNoord ?

Thanks

Talk to you later

Copy link
Collaborator

@DanielNoord DanielNoord left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it difficult to review this as I have absolutely zero knowledge of C-extensions or C in general. I'm not sure we actually have anybody in the maintainers team who does..

At least I answered one question 😅

"""create astroid for a living function object"""
signature = inspect.signature(member)
def _get_args_info_from_callable(
member: Callable,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we know more about this Callable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it can be any python callable.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so I finally got some time to review this after having spent some time in the module myself (see #1589).

I don't think this typing is correct as normally all members are either type or narrowed down types from the types packages.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you more explicit and maybe suggest another typing for the function ?

astroid/raw_building.py Show resolved Hide resolved
Comment on lines -231 to -224
# set node's arguments to None to notice that we have no information, not
# and empty argument list
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! Let's do that!

name="mymod",
ext_modules=[cmodule],
packages=['mymod'],
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
)
)

@@ -790,5 +797,53 @@ def test_parse_module_with_invalid_type_comments_does_not_crash():
assert isinstance(node, nodes.Module)


def test_c_module_text_signature():
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to tell pytest to skip it right?

Although I must confess I don't know if this is actually true. Did you find any documentation about this?

@tristanlatr
Copy link
Contributor Author

There is still the issue of the failing tests...
I'll work on this when I have some time.

This is definitely a required feature for pydoctor to adopt astroid, because we offer support for c-modules.
I hope in can be merged once I've fixed the issues.

Talk to you later,

Tristan

"""create astroid for a living function object"""
signature = inspect.signature(member)
def _get_args_info_from_callable(
member: Callable,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so I finally got some time to review this after having spent some time in the module myself (see #1589).

I don't think this typing is correct as normally all members are either type or narrowed down types from the types packages.

# __text_signature__ attribute
if getattr(member, "__text_signature__", None) is not None:
f"Cannot parse __text_signature__ signature of {member}"
signature = inspect.Signature()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a change in behaviour, at least for ClassDefs. Instead of setting the arguments to None we now set it to empty lists, implying that there are no arguments. That should be reverted to mimic the current situation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you are right, this was part of the stuff that I needed to change.

# __text_signature__ attribute
if getattr(member, "__text_signature__", None) is not None:
f"Cannot parse __text_signature__ signature of {member}"
signature = inspect.Signature()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a change in behaviour, at least for ClassDefs. Instead of setting the arguments to None we now set it to empty lists, implying that there are no arguments. That should be reverted to mimic the current situation.

@DanielNoord
Copy link
Collaborator

@tristanlatr I have done some exploring in the module and am now more confident in merging changes here. Please let me know if you have any further questions. We should be cautious about changing stuff here, but I'm willing to help get this merged.

One thing I believe would help is if you separated the creation of the new method from also using it in object_build_methoddescriptor. That makes this the diff smaller and more reviewable.

@tristanlatr
Copy link
Contributor Author

Hi @DanielNoord,

I don’t think we’re going to use astroid with pydoctor in the end, turns out to be much more complicated than I thought because of divergences compared to the standard library.

So I probably won’t update this PR anytime soon. If one likes this feature please fell free to build off my changes and open another PR.

Cheers,

@DanielNoord
Copy link
Collaborator

Hi @DanielNoord,

I don’t think we’re going to use astroid with pydoctor in the end, turns out to be much more complicated than I thought because of divergences compared to the standard library.

So I probably won’t update this PR anytime soon. If one likes this feature please fell free to build off my changes and open another PR.

Cheers,

Thanks for the headups! I'll likely cherry pick some changes from this PR and see what I can merge without too much trouble.

@DanielNoord DanielNoord removed this from the 2.12.0 milestone Jun 5, 2022
@DanielNoord
Copy link
Collaborator

@tristanlatr I have opened #1593 based on your work and some previous cherry picking. I'm going to close this PR as the discussion is quite long and most issues have been resolved in that PR.

Would you be willing to do a review of that PR? I think most issue have been addressed, but considering I have no experience with C I'd like some other reviews before undrafting it.

@DanielNoord DanielNoord closed this Jun 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs review 🔍 Needs to be reviewed by one or multiple more persons
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants