Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[![VFX Platform](https://img.shields.io/badge/vfxplatform-2020-yellow.svg)](http://www.vfxplatform.com/)
[![Python 2.7 3.7](https://img.shields.io/badge/python-2.7%20%7C%203.7-blue.svg)](https://www.python.org/)
[![VFX Platform](https://img.shields.io/badge/vfxplatform-2023%202022%202021%202020-blue.svg)](http://www.vfxplatform.com/)
[![Python 3.7 3.9 3.10](https://img.shields.io/badge/python-3.7%20%7C%203.9%20%7C%203.10-blue.svg)](https://www.python.org/)
[![Reference Documentation](http://img.shields.io/badge/doc-reference-blue.svg)](http://developer.shotgridsoftware.com/tk-core)
[![Build Status](https://dev.azure.com/shotgun-ecosystem/Toolkit/_apis/build/status/shotgunsoftware.tk-core?branchName=master)](https://dev.azure.com/shotgun-ecosystem/Toolkit/_build/latest?definitionId=38&branchName=master)
[![codecov](https://codecov.io/gh/shotgunsoftware/tk-core/branch/master/graph/badge.svg)](https://codecov.io/gh/shotgunsoftware/tk-core)
Expand Down
1 change: 1 addition & 0 deletions python/tank/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
is_version_newer,
is_version_older_or_equal,
is_version_newer_or_equal,
suppress_known_deprecation,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Again, not a blocker but I really wonder why bother listing all these modules, classes, and methods in this file instead of using Python's default import system? (from utils import version then version.suppress_known_deprecation)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

From what I've seen it's just to simplify the importing workflow. Maybe that was the original code style for tk-core.

)

from .shotgun_entity import get_sg_entity_name_field
Expand Down
2 changes: 1 addition & 1 deletion python/tank/util/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ def run(self):
)

# Run until halted
while not self._halt_event.isSet():
while not self._halt_event.is_set():

# get the next available metric and dispatch it
try:
Expand Down
87 changes: 56 additions & 31 deletions python/tank/util/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,19 @@
# By accessing, using, copying or modifying this work you indicate your
# agreement to the Shotgun Pipeline Toolkit Source Code License. All rights
# not expressly granted therein are reserved by Shotgun Software Inc.
import warnings
import contextlib
import sys

if sys.version_info[0:2] >= (3, 10):
from setuptools._distutils.version import LooseVersion
else:
from distutils.version import LooseVersion

from distutils.version import LooseVersion
from . import sgre as re
from ..errors import TankError


GITHUB_HASH_RE = re.compile("^[0-9a-fA-F]{7,40}$")


Expand Down Expand Up @@ -115,6 +123,20 @@ def is_version_number(version):
return False


@contextlib.contextmanager
def suppress_known_deprecation():
"""
Imported function from setuptools.distutils module
"""
with warnings.catch_warnings(record=True) as ctx:
warnings.filterwarnings(
action="default",
category=DeprecationWarning,
message="distutils Version classes are deprecated.",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am confused now. Should we not use this method then?

@carlos-villavicencio-adsk carlos-villavicencio-adsk Sep 22, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You can find more information in the PR description. To sum up, distutils is now deprecated, and starting from Python 3.10 we will use the distutils copy that is shipped on setuptools.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ok but this is a temporary solution, right? At some point, we need to migrate to packaging.version.parse, no?
If so, do we have a plan for that (a Jira ticket)? And why not now (too big?)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, it's too big. At first, I tried the migration to packaging.version.parse but the existing code for tk-core, tk-nuke, and probably more components rely on the existing logic (e.g. comparisons for DCC versions) and they break because it doesn't always comply with PEP 440.

We won't be able to easily move to packaging. I'd suggest to keep using LooseVersion from the legacy distutils and keep suppressing the deprecation. Or fork the class code ourselves and strip out the deprecation.

)
yield ctx


def _compare_versions(a, b):
"""
Tests if version a is newer than version b.
Expand All @@ -124,8 +146,8 @@ def _compare_versions(a, b):

:rtype: bool
"""
if b is None:
# a is always newer than None
if b in [None, "Undefined"]:
# a is always newer than None or `Undefined`
return True

if _is_git_commit(a) and not _is_git_commit(b):
Expand Down Expand Up @@ -157,37 +179,40 @@ def _compare_versions(a, b):
# First, try to use LooseVersion for comparison. This should work in
# most cases.
try:
version_a = LooseVersion(a).version
version_b = LooseVersion(b).version
version_num_a = []
version_num_b = []
# taking only the integers of the version to make comparison
for version in version_a:
if isinstance(version, (int)):
version_num_a.append(version)
elif version == "-":
break
for version in version_b:
if isinstance(version, (int)):
version_num_b.append(version)
elif version == "-":
break

# Comparing equal number versions with with one of them with '-' appended, if a version
# has '-' appended it's older than the same version with '-' at the end
if version_num_a == version_num_b:
if "-" in a and "-" not in b:
return False # False, version a is older than b
elif "-" in b and "-" not in a:
return True # True, version a is older than b
with suppress_known_deprecation():
# Supress `distutils Version classes are deprecated.` for Python 3.10
version_a = LooseVersion(a).version
version_b = LooseVersion(b).version

version_num_a = []
version_num_b = []
# taking only the integers of the version to make comparison
for version in version_a:
if isinstance(version, (int)):
version_num_a.append(version)
elif version == "-":
break
for version in version_b:
if isinstance(version, (int)):
version_num_b.append(version)
elif version == "-":
break

# Comparing equal number versions with with one of them with '-' appended, if a version
# has '-' appended it's older than the same version with '-' at the end
if version_num_a == version_num_b:
if "-" in a and "-" not in b:
return False # False, version a is older than b
elif "-" in b and "-" not in a:
return True # True, version a is older than b
else:
return LooseVersion(a) > LooseVersion(
b
) # If both has '-' compare '-rcx' versions
else:
return LooseVersion(a) > LooseVersion(
b
) # If both has '-' compare '-rcx' versions
else:
return LooseVersion(a) > LooseVersion(
b
) # If they are different numeric versions
) # If they are different numeric versions
except TypeError:
# To mimick the behavior in Python 2.7 as closely as possible, we will
# If LooseVersion comparison didn't work, try to extract a numeric
Expand Down
2 changes: 1 addition & 1 deletion python/tank_vendor/shotgun_api3/commit_id
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1f132f8f495333acc7303996a8151d73b2c204ae
11db780c4a18993130a988d73f9e50bd7d17e53f
69 changes: 69 additions & 0 deletions python/tank_vendor/shotgun_api3/lib/httplib2/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import base64
import re

from ... import pyparsing as pp

from .error import *


try: # pyparsing>=3.0.0
downcaseTokens = pp.common.downcaseTokens
except AttributeError:
downcaseTokens = pp.downcaseTokens

UNQUOTE_PAIRS = re.compile(r"\\(.)")
unquote = lambda s, l, t: UNQUOTE_PAIRS.sub(r"\1", t[0][1:-1])

# https://tools.ietf.org/html/rfc7235#section-1.2
# https://tools.ietf.org/html/rfc7235#appendix-B
tchar = "!#$%&'*+-.^_`|~" + pp.nums + pp.alphas
token = pp.Word(tchar).setName("token")
token68 = pp.Combine(pp.Word("-._~+/" + pp.nums + pp.alphas) + pp.Optional(pp.Word("=").leaveWhitespace())).setName(
"token68"
)

quoted_string = pp.dblQuotedString.copy().setName("quoted-string").setParseAction(unquote)
auth_param_name = token.copy().setName("auth-param-name").addParseAction(downcaseTokens)
auth_param = auth_param_name + pp.Suppress("=") + (quoted_string | token)
params = pp.Dict(pp.delimitedList(pp.Group(auth_param)))

scheme = token("scheme")
challenge = scheme + (params("params") | token68("token"))

authentication_info = params.copy()
www_authenticate = pp.delimitedList(pp.Group(challenge))


def _parse_authentication_info(headers, headername="authentication-info"):
"""https://tools.ietf.org/html/rfc7615
"""
header = headers.get(headername, "").strip()
if not header:
return {}
try:
parsed = authentication_info.parseString(header)
except pp.ParseException as ex:
# print(ex.explain(ex))
raise MalformedHeader(headername)

return parsed.asDict()


def _parse_www_authenticate(headers, headername="www-authenticate"):
"""Returns a dictionary of dictionaries, one dict per auth_scheme."""
header = headers.get(headername, "").strip()
if not header:
return {}
try:
parsed = www_authenticate.parseString(header)
except pp.ParseException as ex:
# print(ex.explain(ex))
raise MalformedHeader(headername)

retval = {
challenge["scheme"].lower(): challenge["params"].asDict()
if "params" in challenge
else {"token": challenge.get("token")}
for challenge in parsed
}
return retval
Loading