-
Notifications
You must be signed in to change notification settings - Fork 22
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
fix: type hints weren't installed properly, add type hints for Django Fields #259
Conversation
Thanks for the pull request, @bradenmacdonald! Please note that it may take us up to several weeks or months to complete a review and merge your PR. Feel free to add as much of the following information to the ticket as you can:
All technical communication about the code itself will be done via the GitHub pull request interface. As a reminder, our process documentation is here. Please let us know once your PR is ready for our review and all tests are green. |
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## master #259 +/- ##
==========================================
+ Coverage 94.12% 94.14% +0.01%
==========================================
Files 29 29
Lines 2860 2868 +8
Branches 292 292
==========================================
+ Hits 2692 2700 +8
Misses 142 142
Partials 26 26
Flags with carried forward coverage won't be shown. Click here to find out more.
☔ View full report in Codecov by Sentry. |
Hi @openedx/teaching-and-learning! Would someone please be able to review/merge this for us? |
Yes, thanks - I would appreciate a review of this |
55cd73a
to
3fbf0af
Compare
3fbf0af
to
92b9102
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm reviewing this since it was mentioned during the last CC meeting. I hope it helps!
I installed this version in a local venv:
(venv) ~/venv/lib/python3.8/site-packages/opaque_keys ls
edx __init__.py __pycache__ py.typed tests
While in my current nightly installation with edx-opaque-keys 2.5.0:
app@d3bd25e0d8c4:~/venv/lib/python3.8/site-packages/opaque_keys$ ls
edx __init__.py __pycache__ tests
Then, I removed this comment just so type-checking warnings are raised. Then, I ran mypy with edx-opaque-keys==2.5.0 in edx-platform and got:
app@d3bd25e0d8c4:~/edx-platform$ mypy
Success: no issues found in 103 source files
After installing this version I got:
app@d3bd25e0d8c4:~/edx-platform$ mypy
openedx/core/djangoapps/content_staging/data.py:66: error: Only concrete class can be given where "Type[UsageKey]" is expected [type-abstract]
Found 1 error in 1 file (checked 103 source files)
So now it's working! Thanks. Let me know if I miss something :)
opaque_keys/edx/django/models.py
Outdated
# for examples of how this works for the standard field types in the upstream codebase. | ||
# Note that these particular type annotations have no effect at runtime nor on Django itself nor on PyLance. | ||
_pyi_private_set_type: LearningContextKey | str | None # The types that you can set into this field. | ||
_pyi_private_get_type: LearningContextKey # The type that you get when you read from this field |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I've seen this pattern elsewhere, and I totally believe you're doing the right thing. But I don't understand this part–why is None
a settable type, but not a gettable type for this field?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is None a settable type, but not a gettable type for this field?
My understanding was that for these type definitions you generally don't specify None
as either a setter or a getter, and the mypy plugin will automatically add the | None
union type if you declare a specific field instance with null=True
. And I noticed that even if you don't declare it with null=True
, you can still set a None
value because the field type converts that to an empty string.
That said, I think I was not really thinking things through. OpaqueKeyField
s should never be declared as null=True
, because they're CharField
-based, but instead they should use blank=True
or not to indicate whether they accept empty values. The problem is that OpaqueKeyField
will convert empty strings to None
in the getter, which mypy is unaware of without null=True
. So in the end, I think it's best to just explicitly specify None
as one of the possible types on both the getter and the setter, which I have now done.
Thanks for the helpful question. I have pushed a commit to add | None
to the getters.
@bradenmacdonald FYI your call for review has been discussed during the contributors meetup this week - there are potentially 3 reviewers: @mariajgrimaldi just had a look, Stefania will ask @ghassanmas and @auraz will try to get someone from Raccoon Gang. |
Even when null=False, e.g. if blank=True and "" is stored, then you'll read out None.
Thanks for testing this @mariajgrimaldi! I still technically need an approval from someone with merge rights on this specific repo before I can merge, but it should be easier to find with your test done. |
@itsjeyd See @bradenmacdonald 's request above ^ Do we have a list of people who can give a 👍 on this repo? I see from https://openedx.atlassian.net/wiki/spaces/COMM/pages/3632070677/Pilot+Phase+3 that it's being taken on by Axim for maintainership in phase 3, though that's likely not the only ones who can give a binding 👍 ? And @bradenmacdonald any suggestion who would be a good person for the binding review, even if that person doesn't have access to it yet? |
@felipemontoya would you be able and comfortable approving this PR like you did the last one? :)
@antoviaque Isn't it as simple as this list? There are three people, but one is me. I probably should have just pinged them directly as I did last time since that eventually worked. |
@bradenmacdonald 🎉 Your pull request was merged! Please take a moment to answer a two question survey so we can improve your experience in the future. |
@felipemontoya @antoviaque Never mind - as you can see now that @ormsbee is back I got his help :) Thx anyways! |
@antoviaque @bradenmacdonald Glad to see that you already found a reviewer :) |
Hey @antoviaque JFYI I'm not in Raccoon Gang for 4+ years. |
My last PR #256 wasn't quite working with
mypy
in edx-platform. It was working fine in "editable" mode withpython setup.py develop
orpip install -e .
but when installed viapip install edx-opaque-keys==2.5.0
orpython setup.py install
, the importantpy.typed
marker file was missing.I thought that using
include_package_data=True
was sufficient, but it turns out I also needed to add a line toMANIFEST.in
.With this change, the
py.typed
file is installed and mypy will use the type hints added in #256.I also added type hints for the django fields like
UsageKeyField
. This only works because of the django-stubs mypy plugin that we use in edx-platform, and requires setting a "private" class attribute to define the types, but it seems to work very well. Now mypy is aware that reading from aUsageKeyField
will result in aUsageKey
and writing to one accepts aUsageKey
orstr
orNone
. (Keep in mind these additional static fields are type-only and will be ignored at runtime; they only affect mypy and then only if the django-stubs mypy plugin is installed.)