Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Complete typing with strict type-checking #43

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

@Avasam
Copy link
Contributor

@Avasam Avasam commented Aug 25, 2024
edited
Loading

Closes #42
I figured this library is small enough I could lend a hand.

This is everything to have complete type annotations, be on par with typeshed's stubs, and use strict type-checking. I can split into smaller PRs if needed.

More details in GitHub file comments.

run: python3 tests.py
- name: verify type hints
run: mypy datemath
run: mypy . --strict
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Running on tests is important too. This ensures expected usage is correctly typed. In fact, it found that parse was missing the int annotation on its first parameter.

@@ -1,9 +1,18 @@
from .helpers import parse, DateMathException
from __future__ import annotations
Copy link
Contributor Author

@Avasam Avasam Aug 25, 2024
edited
Loading

Choose a reason for hiding this comment

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

This allows the use of | in Pyton < 3.10, and use symbols that won't be present at runtime, in annotations.

from typing_extensions import Unpack
from arrow import Arrow

from .helpers import ParseParams, parse as parse, DateMathException as DateMathException
Copy link
Contributor Author

@Avasam Avasam Aug 25, 2024
edited
Loading

Choose a reason for hiding this comment

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

as imports without renaming is a typing convention understood by type-checkers to mean that the symbol is purposefully / explicitly re-exported (the other option is to use __all__)


from .helpers import ParseParams, parse as parse, DateMathException as DateMathException

def dm(expr: str | int, **kwargs: Unpack[ParseParams]) -> Arrow:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

By using an unpacked TypedDict to annotate kwargs, you don't have to duplicate all your default keyword argument parameter's default values to have these functions fully typed.

raise DateMathException("Not a valid timeunit: {0}".format(c))

def parse(expression: str, now: Any = None, tz: str = 'UTC', type: Any = None, roundDown: bool = True) -> Arrow:
class ParseParams(TypedDict, total=False):
Copy link
Contributor Author

@Avasam Avasam Aug 25, 2024
edited
Loading

Choose a reason for hiding this comment

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

See comment in datemath/__init__.py
total=False means all members are optional (since we use this to annotate optional kwargs)

if debug: print("parse() - Now, no dm: {0}".format(now))
if type:
return getattr(now, type)
return cast(Arrow, getattr(now, type))
Copy link
Contributor Author

@Avasam Avasam Aug 25, 2024
edited
Loading

Choose a reason for hiding this comment

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

In strict mode, mypy will whine about returning Any from a typed function.
This can either be cast or type-ignored to accept the "type unsafety".

Suggested change
return cast(Arrow, getattr(now, type))
return getattr(now, type)# type: ignore[no-any-return]

if debug: print("parse() - will now convert tz to {0}".format(tz))
now = now.to(tz)

expression = str(expression)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Less runtime casting in some cases. But more importantly, this is now type-safe.

nickmaccarthy reacted with thumbs up emoji
Comment on lines +189 to +190
now = now.floor(unit)# type: ignore[arg-type]
else:
now = now.ceil(unit)
now = now.ceil(unit)# type: ignore[arg-type]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

arrow types these only with the literal strings they accept. I figured you'd probably prefer keeping the types and checks simpler with a more general str, as any usage of roundDate would also have to comply to only using statically known literals.

nickmaccarthy reacted with thumbs up emoji
@@ -1,4 +1,4 @@
import unittest2asunittest
Copy link
Contributor Author

Choose a reason for hiding this comment

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

unittest2 is untyped, but also no longer needed without Python 2 support.

nickmaccarthy reacted with thumbs up emoji
Copy link
Owner

@nickmaccarthy nickmaccarthy Aug 27, 2024

Choose a reason for hiding this comment

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

This file is going to get removed in the next release anyways since this package is only going to be python3 going forward

@Avasam Avasam force-pushed the complete-typing-with-strict-checking branch 2 times, most recently from 2fa344b to c90f0bc Compare August 25, 2024 03:41

if type:
return getattr(rettime, type)
return cast(Arrow, getattr(rettime, type))
Copy link
Contributor Author

@Avasam Avasam Aug 25, 2024
edited
Loading

Choose a reason for hiding this comment

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

In strict mode, mypy will whine about returning Any from a typed function.
This can either be cast or type-ignored to accept the "type unsafety".

Suggested change
return cast(Arrow, getattr(rettime, type))
return getattr(rettime, type)# type: ignore[no-any-return]

nickmaccarthy reacted with thumbs up emoji
@Avasam Avasam force-pushed the complete-typing-with-strict-checking branch from c90f0bc to 5d1bb8f Compare August 25, 2024 03:49
Copy link
Owner

Thank you so much for your contribution @Avasam ! This is quite awesome!! I've been writing so much golang lately that I have taking the typing for granted and it seems folks really needed it for this module. I'll approve it and merge it. I'll get a release out soon. There are few other things I'd like to tidy up before the next one first related to the legacy python 2.7 support we had.

Avasam reacted with heart emoji

@Avasam Avasam force-pushed the complete-typing-with-strict-checking branch from 5d1bb8f to 360cc11 Compare August 26, 2024 21:46
linecache2==1.0.0
mypy==1.5.1
mypy-extensions==1.0.0
mypy==1.7.1
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'd personally bump mypy all the way to latest. 1.7 is the minimum where Unpack is no longer an incomplete feature https://mypy-lang.blogspot.com/2023/11/mypy-17-released.html

Copy link
Owner

@nickmaccarthy nickmaccarthy Aug 27, 2024

Choose a reason for hiding this comment

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

Thank you for this. mypy is only used in this package to do the type checking so its probably good that its at the latest anyways. That got the tests to pass now

@nickmaccarthy nickmaccarthy merged commit c4c6265 into nickmaccarthy:master Aug 27, 2024
@Avasam Avasam deleted the complete-typing-with-strict-checking branch August 27, 2024 14:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@nickmaccarthy nickmaccarthy nickmaccarthy left review comments

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Completing type annotations

AltStyle によって変換されたページ (->オリジナル) /