Add Python 3.10 support (close #254) - #260
Conversation
f5fd42f to
abd9ef1
Compare
|
I'm also assigning Ada Tzereme (@adatzer) to review this. I'll hopefully get to it too shortly but I'd love her input on this too given she has been the most recent maintainer on this tracker. |
* Remove pycontracts library that wasn't compatible with Python 3.10 * Add Python type hints to all function arguments and return values * Remove support for Python 2 due to the type hints * Add custom contracts (e.g., non_empty_string) evaluated at the start of functions * Run through Flake8 linter and correct style * Remove Python 2 from Github action build
abd9ef1 to
45eba92
Compare
Paul Boocock (paulboocock)
left a comment
There was a problem hiding this comment.
This is looking good to me. I'll let Ada Tzereme (@adatzer) have the final say on approving this PR though.
Just a note that when preparing the 0.10.0 release, we should add a table to the README to make it clear what versions of the tracker support what versions of python (i.e. Python 2.7 is 0.9.x only, Python 3+ is 0.10.x+)
Ada Tzereme (adatzer)
left a comment
There was a problem hiding this comment.
Looks great!! Feels much cleaner and with less dependencies too! Just added few comments below.
Also, just noting this PR targets master, i guess it will go for a release branch eventually, right?
Finally, what do you think of removing the pycontracts's :type function comments too?
|
|
||
| # pyenv install 3.10.0 | ||
| if [ ! -e ~/.pyenv/versions/tracker310 ]; then | ||
| pyenv virtualenv 3.10.0 tracker310 |
There was a problem hiding this comment.
Also here, could we go straight for latest 3.10.1?
There was a problem hiding this comment.
You're right, I didn't there was 3.10.1 already, updated!
| pyVersion = sys.version_info[0] | ||
| if pyVersion < 3: | ||
| if isinstance(x, basestring): | ||
| if isinstance(x, str): |
There was a problem hiding this comment.
This comment refers to lines 165-166: Can we now assume that pyVersion will not be < 3?
There was a problem hiding this comment.
True, we don't need that if anymore, removed it.
|
|
||
| class EmitterProtocol(Protocol): | ||
| def input(self, payload: PayloadDict) -> None: | ||
| ... |
There was a problem hiding this comment.
Just to confirm on the ..., is it just used like pass here?
There was a problem hiding this comment.
Yes, the ellipsis can have more uses (in slices), but they are commonly used instead of pass. It just looks a bit nicer.
| strategy: | ||
| matrix: | ||
| python-version: [2.7, 3.6, 3.7, 3.8, 3.9] | ||
| python-version: [3.6, 3.7, 3.8, 3.9] |
There was a problem hiding this comment.
Could we add 3.10 as well for the tests?
There was a problem hiding this comment.
Yes, added 3.10 here as well. Just had to make it string, otherwise Github actions understood it as version 3.1.
| node_name: FormNodeName, | ||
| value: Optional[str], | ||
| type_: Optional[str] = None, | ||
| element_classes: Optional[Union[List[str], Tuple[str]]] = None, |
There was a problem hiding this comment.
Also here, for element_classes, the tuple in their previous contract was tuple(str,*). Would that map to Tuple[str, Any]?
There was a problem hiding this comment.
Good catch! Changed the tuple to Tuple[str, Any] and moved it to typing.py since it's a bit too long.
| def __exit__(self, type, value, traceback): | ||
| enable_all() | ||
| def __enter__(self) -> None: | ||
| disable_contracts |
There was a problem hiding this comment.
nit - was this meant as a function call? i.e. disable_contracts()
There was a problem hiding this comment.
This is a really good catch! It actually means that the ContractsDisabled was useless since all the tests passed without it doing anything. I added the function call and removed ContractsDisabled from it where it wasn't necessary anymore. Also added a couple of tests that make use of it.
| disable_contracts | ||
|
|
||
| def __exit__(self, type: Any, value: Any, traceback: Any) -> None: | ||
| enable_contracts |
There was a problem hiding this comment.
also here, to call enable_contracts?
There was a problem hiding this comment.
Commented above, thanks for this!
| DEFAULT_PLATFORM = "pc" | ||
|
|
||
| new_contract("subject", lambda x: isinstance(x, Subject)) | ||
| SupportedPlatform = Literal["pc", "tv", "mob", "cnsl", "iot", "web", "srv", "app"] |
There was a problem hiding this comment.
nit - would it make sense for this type to be defined in snowplow_tracker.typing as well?
There was a problem hiding this comment.
Yes, moved to typing.py.
| ENV PYENV_ROOT $HOME/.pyenv | ||
| ENV PATH $PYENV_ROOT/shims:$PYENV_ROOT/bin:$PATH | ||
|
|
||
| RUN pyenv install 3.5.10 && pyenv install 3.6.14 && pyenv install 3.7.11 && pyenv install 3.8.11 && pyenv install 3.9.6 && pyenv install 3.10.0 |
There was a problem hiding this comment.
could we also go straight for 3.10.1 ?
There was a problem hiding this comment.
Yes, updated to 3.10.1.
|
|
||
| new_contract("function", lambda x: hasattr(x, "__call__")) | ||
| SuccessCallback = Callable[[PayloadDictList], None] | ||
| FailureCallback = Callable[[int, PayloadDictList], None] |
There was a problem hiding this comment.
nit - would it make sense for these types to be defined in snowplow_tracker.typing as well?
There was a problem hiding this comment.
Right, moved all of these types to typing.py.
|
Thanks a lot Ada Tzereme (@adatzer) for the thorough review! Those were really useful comments and also uncovered a few important problems. Not sure about removing the |
Ada Tzereme (adatzer)
left a comment
There was a problem hiding this comment.
Really happy to approve from my side!
Concerning the pycontracts' comments, they are not used to generate API docs as far as i know. They do indeed add some value, so no objection from me for them to stay.
* Fix pycontracts incompatibility with pyparsing v3 (closes snowplow#255) * Update python versions in run-tests script (closes snowplow#256) * Prepare for release * Add Python 3.10 support (close snowplow#254) PR snowplow#260 * Remove pycontracts library that wasn't compatible with Python 3.10 * Add Python type hints to all function arguments and return values * Remove support for Python 2 due to the type hints * Add custom contracts (e.g., non_empty_string) evaluated at the start of functions * Run through Flake8 linter and correct style * Remove Python 2 from Github action build * Add Dockerfile for running tests under all supported Python versions * Add configurable timeout for HTTP requests (close snowplow#258) PR snowplow#259 * Prepare for release * Increment version Co-authored-by: adatzer <ada@snowplowanalytics.com> Co-authored-by: Matúš Tomlein <matus.tomlein@gmail.com> Co-authored-by: Deyan Deyanov <deyan@insurify.com>
This PR addresses issue #254 and adds support for Python 3.10 by dropping the pycontracts library (not updated for some time and incompatible with 3.10 at this time) and adding some other features that require support for Python 2 to be dropped.
The full list of changes is:
Note:
mypystatic type checking or through IDEs such as PyCharm) so some types of issues that previously raised errors no longer do soContractNotRespectederror (from pycontracts) when contracts are violated but the standardValueError