Improve type hints for BaseTemporalField and JSONField in forms#3293
Improve type hints for BaseTemporalField and JSONField in forms#329301xnikhil wants to merge 11 commits into
Conversation
e375c92 to
8541823
Compare
0735208 to
1a064f3
Compare
| min_value: int | Callable[[], int] | None | ||
| step_size: int | Callable[[], int] | None | ||
| re_decimal: Any | ||
| re_decimal: Pattern[str] | SimpleLazyObject[Pattern[str]] |
There was a problem hiding this comment.
Does this align with how we type other regex created by the django util function _lazy_re_compile ?
There was a problem hiding this comment.
Does this align with how we type other regex created by the django util function _lazy_re_compile ?
Yeah, it matches the existing patterns in the codebase. I checked django-stubs/utils/functional.pyi and saw that SimpleLazyObject is a Generic[_T]. Since _lazy_re_compile wraps the compiled pattern, using Pattern[str] | SimpleLazyObject[Pattern[str]] makes sure Mypy is happy whether the object is still lazy or already evaluated. It’s consistent with how we've handled other lazy objects here.
There was a problem hiding this comment.
Looking at usage in django of _lazy_re_compile, i find these for ex that are annotated like so:
RFC1123_DATE: Pattern[str]
RFC850_DATE: Pattern[str]
ASCTIME_DATE: Pattern[str]
long_open_tag_without_closing_re: SimpleLazyObject
word_split_re: Pattern[str] | SimpleLazyObject
cc_delim_re: Any # Any: SimpleLazyObject wrapping a compiled regexSo you proposal would be yet another way of expressing the same idea.
What is the correct version ? Can we pick one and use it in every places ?
Given the typing of _lazy_re_compile, I think we should use Pattern everywhere because it reflects the runtime behavior even if it's not 100% correct.
def _lazy_re_compile(regex: _P | Pattern[_P], flags: int = 0) -> Pattern[_P]: ...There was a problem hiding this comment.
Looking at usage in django of
_lazy_re_compile, i find these for ex that are annotated like so:RFC1123_DATE: Pattern[str] RFC850_DATE: Pattern[str] ASCTIME_DATE: Pattern[str] long_open_tag_without_closing_re: SimpleLazyObject word_split_re: Pattern[str] | SimpleLazyObject cc_delim_re: Any # Any: SimpleLazyObject wrapping a compiled regexSo you proposal would be yet another way of expressing the same idea. What is the correct version ? Can we pick one and use it in every places ?
Given the typing of
_lazy_re_compile, I think we should usePatterneverywhere because it reflects the runtime behavior even if it's not 100% correct.def _lazy_re_compile(regex: _P | Pattern[_P], flags: int = 0) -> Pattern[_P]: ...
Thanks for the guidance, I totally agree—sticking with Pattern[str] for consistency makes the most sense.
I have my college minor exams until April 18th, so I will be back on the 18th evening to update the PR and standardize the other occurrences.
Thanks for understanding.
3407a8b to
120b4c4
Compare
|
Hello 👋 @UnknownPlatypus , Let me know what's better ! |
I have made things!
I noticed that some fields in forms/fields.pyi were still using Any for many important attributes, which makes type-checking less effective. I have updated these to be more specific.
What I changed:
In BaseTemporalField, I changed input_formats to Collection[str] | None. This helps when passing custom date/time formats.
In JSONField, I narrowed encoder and decoder from Any to their respective json module types (type[json.JSONEncoder], etc.).
I also noticed re_decimal in IntegerField was Any, so I've updated that to Pattern[str] as well.
Added a new test file tests/assert_type/forms/test_fields.py to make sure these new types actually work with assert_type.
Testing:
Ran Mypy on the modified files and the new test case, and both returned success.
AI Policy