-
Notifications
You must be signed in to change notification settings - Fork 11
Fix import mechanism for task modules. #373
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
Conversation
I get this obscure error from within dataclasses: ────────────────────────── Failures during collection ────────────────────────── ───────── Could not collect test_collect_module_name_0/task_module.py ────────── ╭───────────────────── Traceback (most recent call last) ──────────────────────╮ │ in exec_module:883 │ │ in _call_with_frames_removed:241 │ │ │ │ /private/var/folders/nz/wfwcn6md1796t48tx9dhf0v40000gn/T/pytest-of-nickcrews │ │ /pytest-41/test_collect_module_name_0/task_module.py:7 in <module> │ │ │ │ 4 import dataclasses │ │ 5 │ │ 6 @dataclasses.dataclass │ │ ❱ 7 class Data: │ │ 8 │ x: int │ │ 9 │ │ │ │ /Users/nickcrews/.pyenv/versions/3.10.4/lib/python3.10/dataclasses.py:1263 │ │ in dataclass │ │ │ │ 1260 │ │ return wrap │ │ 1261 │ │ │ 1262 │ # We're called as @DataClass without parens. │ │ ❱ 1263 │ return wrap(cls) │ │ 1264 │ │ 1265 │ │ 1266 def fields(class_or_instance): │ │ │ │ /Users/nickcrews/.pyenv/versions/3.10.4/lib/python3.10/dataclasses.py:1253 │ │ in wrap │ │ │ │ 1250 │ """ │ │ 1251 │ │ │ 1252 │ def wrap(cls): │ │ ❱ 1253 │ │ return _process_class( │ │ 1254 │ │ │ cls, init, repr, eq, order, unsafe_hash, frozen, match_ar │ │ 1255 │ │ ) │ │ 1256 │ │ │ │ /Users/nickcrews/.pyenv/versions/3.10.4/lib/python3.10/dataclasses.py:1003 │ │ in _process_class │ │ │ │ 1000 │ │ # See if this is a marker to change the value of kw_only. │ │ 1001 │ │ if _is_kw_only(type, dataclasses) or ( │ │ 1002 │ │ │ isinstance(type, str) │ │ ❱ 1003 │ │ │ and _is_type(type, cls, dataclasses, dataclasses.KW_ONLY, │ │ 1004 │ │ ): │ │ 1005 │ │ │ # Switch the default to kw_only=True, and ignore this │ │ 1006 │ │ │ # annotation: it's not a real field. │ │ │ │ /Users/nickcrews/.pyenv/versions/3.10.4/lib/python3.10/dataclasses.py:764 in │ │ _is_type │ │ │ │ 761 │ │ if not module_name: │ │ 762 │ │ │ # No module name, assume the class's module did │ │ 763 │ │ │ # "from dataclasses import InitVar". │ │ ❱ 764 │ │ │ ns = sys.modules.get(cls.__module__).__dict__ │ │ 765 │ │ else: │ │ 766 │ │ │ # Look up module_name in the class's module. │ │ 767 │ │ │ module = sys.modules.get(cls.__module__) │ ╰──────────────────────────────────────────────────────────────────────────────╯ AttributeError: 'NoneType' object has no attribute '__dict__'
Codecov Report
@@ Coverage Diff @@
## main #373 +/- ##
==========================================
+ Coverage 96.09% 96.16% +0.06%
==========================================
Files 93 93
Lines 7664 7797 +133
==========================================
+ Hits 7365 7498 +133
Misses 299 299
Flags with carried forward coverage won't be shown. Click here to find out more.
|
It wasn't actually failing before. Test collection DID fail, but we weren't inspecting it.
for more information, see https://pre-commit.ci
Hi @NickCrews, do the changes solve your issue? |
Thanks for the quick turnaround! This fixes that exact problem, but introduces a new one: Say I have I'm not exactly sure, but should we be doing what pytest does, and search up the directory tree until we don't find an |
You are right. This was too quick. Thanks for the comment. To comment on your example with the The approach implemented in pytask is closest to the The major drawback that I see is that task modules need to have unique names like The benefit of this approach is that we do not need to change If we follow this approach, I think three things must be done.
@NickCrews, how does it sound to you? Since you mentioned the |
Thanks for the patience, and thanks for going ahead and implementing something concrete. I was having trouble understanding exactly what you were proposing until I read those commits. I'll leave a few nits as review but in general looks good, thank you!
You're saying this is the drawback of
I respectfully disagree. I would like to have my tasks mixed with my "main logic" code. I have a layout where each .py files represents one discrete step in processing. I want each step to export 3 different interfaces:
I want all three of these related functionalities to be in one file. This requires that one module containing tasks needs to import other modules containing tasks. Now, this actually works fine right now and I have no complaints! I just need to import as I think avoiding adjusting This implementation worked fine for my project. I could see this still not covering someone else's use case, but I think this is at least moving in the right direction, and I don't think should break anyone (unless they are relying on something weird/fragile with the value of |
Hi @NickCrews, thank you for your review 🙏. Unfortunately, I won't be able to answer you soon, but I will return to you on Monday. |
Thanks for staying with me!
You are right. I misremembered when I wrote it.
I should have been more precise since I do not disagree with your setup. Nor do I want to strictly separate app and task code. I was thinking more about situations like those described in this article of the documentation. In this example, general functions that provide access to the inputs and outputs of a stage like You don't need to do that, as you said. Though, in bigger projects, this recommendation has helped beginners to care more about code separation, avoiding long modules, and by that also avoiding circular imports. It might be misguided to say it is best practice because it concerns this specific case and is only documented in one article. I will integrate the proposed changes soon and, then, I will release a new version as well. |
This looks great, thank you so much for your work here! |
Closes #374.
Corresponding issue in pytest:
https://github.com/pytest-dev/pytest/issues/7856
I get this obscure error from within dataclasses:
Changes
Provide a description and/or bullet points to describe the changes in this PR.
Todo