-
Notifications
You must be signed in to change notification settings - Fork 0
Block datetime from being used where date is expected with optional safe-datetime check #1
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
base: master
Are you sure you want to change the base?
Conversation
Co-authored-by: m-aciek <[email protected]>
Co-authored-by: m-aciek <[email protected]>
|
@copilot Comparison between date and date is also unsafe, as one of them can be a datetime. Is it covered? |
Currently, the check only flags comparisons where the static types are explicitly Flagging all Would you like me to:
Could you clarify which approach you prefer? |
|
@copilot 2. Try to detect cases where the inferred type is more specific than the annotation (more complex but more precise) |
Co-authored-by: m-aciek <[email protected]>
Implemented in commit 857f0fa. The check now flags This catches cases where both parameters are typed as def compare_dates(d1: date, d2: date) -> bool:
return d1 < d2 # Now flagged as unsafe
dt = datetime.now()
d = date.today()
compare_dates(dt, d) # TypeError at runtime |
Co-authored-by: m-aciek <[email protected]>
|
@copilot Is it possible to disable the inheritance in mypy? Instead of recognizing the illegal comparisons, block the inheritance? |
Blocking the inheritance would require changes to mypy's core type system and would be more invasive. It would mean The current approach (flagging comparisons) is opt-in and less disruptive - it allows normal subtyping for assignments but warns about the specific operations (comparisons) that fail at runtime. Blocking inheritance would require:
Is this the behavior you want? Or would you prefer to keep the current approach that only flags the problematic comparisons? |
|
@copilot Yes, that's the behavior I want. |
Co-authored-by: m-aciek <[email protected]>
Implemented in commit 901cdec. When This means:
Without the flag, normal Python subtyping continues to work as usual. |
Co-authored-by: m-aciek <[email protected]>
Co-authored-by: m-aciek <[email protected]>
You're absolutely right! Removed in commit 2d231f5. With inheritance blocking, the operator check already fails with "Unsupported operand types" before our custom message could run (due to the Note: |
|
@copilot Add documentation |
Co-authored-by: m-aciek <[email protected]>
Added in commit 4a0a75d. Documentation for the
The documentation follows the existing format for optional error codes. |
|
@copilot Please add also mypyc C implementation. |
The changes to
The Is there a specific aspect of mypyc implementation you'd like me to address? For example:
|
|
@copilot No action needed on this. Thank you for explaining. Please add a warning about str used as Iterable[str] to the unsafe-subtype error. |
Co-authored-by: m-aciek <[email protected]>
Added in commit 2b3e1b3. The This prevents bugs where a single string is accidentally treated as a collection of strings, causing iteration over individual characters instead of the full string. Example: def process(items: Iterable[str]) -> None:
for item in items:
print(item)
process("hello") # Error: would iterate over 'h', 'e', 'l', 'l', 'o'
process(["hello"]) # OK: iterates over "hello"The documentation has been updated with a dedicated section explaining this case. |
|
@copilot 1. Error being raised for those cases should have error type "unsafe-subtype" (possible to ignore) |
Co-authored-by: m-aciek <[email protected]>
Implemented in commit 3aa9743: 1. Sub-codes for fine-grained control:
Usage: # Enable only specific checks
mypy --enable-error-code unsafe-subtype-datetime file.py
mypy --enable-error-code unsafe-subtype-str file.py
# Enable all
mypy --enable-error-code unsafe-subtype file.py2. Error codes: The errors shown are standard type errors ( The sub-codes allow you to selectively control which unsafe subtype relationships are blocked, addressing the need for fine-grained control. |
|
@copilot Please refactor to focus only on the datetime/date case, not other subtyping relations. Use code |
Co-authored-by: m-aciek <[email protected]>
Refactored in commit e16b5ab: Changes:
Usage: mypy --enable-error-code safe-datetime file.pyThe implementation is now focused exclusively on preventing datetime from being used where date is expected, making it cleaner and more specific to this particular type safety issue. |
Implements JukkaL's proposal from issue python#9015 to prevent
datetimeobjects from being used wheredateis expected. Whiledatetimeis a subclass ofdateat runtime, comparing them raisesTypeError, making this inheritance relationship problematic in practice.Summary
When enabled with
--enable-error-code safe-datetime, mypy blocks the datetime→date subtype relationship, preventing runtime errors from comparisons between these types.Changes Made
safe-datetime(disabled by default)datetimefrom being treated as a subtype ofdatewhen enabledsubtypes.pyto reject datetime→date when flag is enableddocs/source/error_code_list2.rstUsage
Command-line usage:
The Problem
Without this check, code that passes type checking can fail at runtime:
When
safe-datetimeis enabled, the problematic assignments and function calls are blocked at type-check time, preventing the runtime error.Note: Equality comparisons (
==and!=) still work between these types, as__eq__acceptsobjectas its parameter.Testing
The implementation is focused, minimal, and opt-in, ensuring backward compatibility while providing a way to catch this specific class of runtime errors at type-check time.
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.