-
Notifications
You must be signed in to change notification settings - Fork 64
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
Add Python 3.10 support (close #254) #260
Conversation
f5fd42f
to
abd9ef1
Compare
I'm also assigning @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
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.
This is looking good to me. I'll let @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+)
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.
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?
run-tests.sh
Outdated
|
||
# pyenv install 3.10.0 | ||
if [ ! -e ~/.pyenv/versions/tracker310 ]; then | ||
pyenv virtualenv 3.10.0 tracker310 |
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.
Also here, could we go straight for latest 3.10.1
?
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.
You're right, I didn't there was 3.10.1 already, updated!
snowplow_tracker/emitters.py
Outdated
pyVersion = sys.version_info[0] | ||
if pyVersion < 3: | ||
if isinstance(x, basestring): | ||
if isinstance(x, str): |
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.
This comment refers to lines 165-166: Can we now assume that pyVersion
will not be < 3
?
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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to confirm on the ...
, is it just used like pass
here?
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.
Yes, the ellipsis can have more uses (in slices), but they are commonly used instead of pass
. It just looks a bit nicer.
.github/workflows/ci.yml
Outdated
@@ -12,7 +12,7 @@ jobs: | |||
|
|||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add 3.10
as well for the tests?
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.
Yes, added 3.10 here as well. Just had to make it string, otherwise Github actions understood it as version 3.1.
snowplow_tracker/tracker.py
Outdated
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit - was this meant as a function call? i.e. disable_contracts()
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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also here, to call enable_contracts
?
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.
Commented above, thanks for this!
snowplow_tracker/subject.py
Outdated
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit - would it make sense for this type to be defined in snowplow_tracker.typing
as well?
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.
Yes, moved to typing.py.
Dockerfile
Outdated
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we also go straight for 3.10.1
?
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.
Yes, updated to 3.10.1
.
snowplow_tracker/emitters.py
Outdated
|
||
new_contract("function", lambda x: hasattr(x, "__call__")) | ||
SuccessCallback = Callable[[PayloadDictList], None] | ||
FailureCallback = Callable[[int, PayloadDictList], None] |
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.
nit - would it make sense for these types to be defined in snowplow_tracker.typing
as well?
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.
Right, moved all of these types to typing.py.
Thanks a lot @adatzer for the thorough review! Those were really useful comments and also uncovered a few important problems. Not sure about removing the |
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.
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:
mypy
static type checking or through IDEs such as PyCharm) so some types of issues that previously raised errors no longer do soContractNotRespected
error (from pycontracts) when contracts are violated but the standardValueError