From 473b81103e6238b382a61cba18ac683a65ae5b5c Mon Sep 17 00:00:00 2001 From: Julien Langlois Date: Wed, 16 Jul 2025 10:29:01 +0200 Subject: [PATCH 1/7] six.moves imports --- docs/cookbook/examples/ami_handler.rst | 2 +- shotgun_api3/lib/mockgun/schema.py | 2 +- shotgun_api3/shotgun.py | 25 +++++++++++++------------ tests/base.py | 6 +++--- tests/test_api.py | 5 +++-- tests/test_client.py | 3 ++- tests/test_unit.py | 3 ++- 7 files changed, 25 insertions(+), 21 deletions(-) diff --git a/docs/cookbook/examples/ami_handler.rst b/docs/cookbook/examples/ami_handler.rst index 3fb5e3571..6b8f3384b 100644 --- a/docs/cookbook/examples/ami_handler.rst +++ b/docs/cookbook/examples/ami_handler.rst @@ -218,7 +218,7 @@ via ``POST``. If you're using a custom protocol the data is sent via ``GET``. params = params.split("&") p = {"column_display_names": [], "cols": []} for arg in params: - key, value = map(six.moves.urllib.parse.unquote, arg.split("=", 1)) + key, value = map(urllib.parse.unquote, arg.split("=", 1)) if key == "column_display_names" or key == "cols": p[key].append(value) else: diff --git a/shotgun_api3/lib/mockgun/schema.py b/shotgun_api3/lib/mockgun/schema.py index 5d5019df4..ab671629d 100644 --- a/shotgun_api3/lib/mockgun/schema.py +++ b/shotgun_api3/lib/mockgun/schema.py @@ -30,8 +30,8 @@ ----------------------------------------------------------------------------- """ -from ..six.moves import cPickle as pickle import os +import pickle from .errors import MockgunError diff --git a/shotgun_api3/shotgun.py b/shotgun_api3/shotgun.py index 2bede5da1..338413810 100644 --- a/shotgun_api3/shotgun.py +++ b/shotgun_api3/shotgun.py @@ -32,6 +32,8 @@ import copy import datetime import json +import http.client # Used for secure file upload +import http.cookiejar # used for attachment upload import logging import os import re @@ -40,24 +42,23 @@ import stat # used for attachment upload import sys import time +import urllib.error +import urllib.parse +import urllib.request import uuid # used for attachment upload +# Import Error and ResponseError (even though they're unused in this file) since they need +# to be exposed as part of the API. +from xmlrpc.client import Error, ProtocolError, ResponseError # noqa + # Python 2/3 compatibility from .lib import six from .lib import sgsix from .lib import sgutils from .lib.six import BytesIO # used for attachment upload -from .lib.six.moves import map -from .lib.six.moves import http_cookiejar # used for attachment upload -from .lib.six.moves import urllib -from .lib.six.moves import http_client # Used for secure file upload. from .lib.httplib2 import Http, ProxyInfo, socks, ssl_error_classes from .lib.sgtimezone import SgTimezone -# Import Error and ResponseError (even though they're unused in this file) since they need -# to be exposed as part of the API. -from .lib.six.moves.xmlrpc_client import Error, ProtocolError, ResponseError # noqa - if six.PY3: from base64 import encodebytes as base64encode else: @@ -3003,8 +3004,8 @@ def get_auth_cookie_handler(self): This is used internally for downloading attachments from FPTR. """ sid = self.get_session_token() - cj = http_cookiejar.LWPCookieJar() - c = http_cookiejar.Cookie( + cj = http.cookiejar.LWPCookieJar() + c = http.cookiejar.Cookie( "0", "_session_id", sid, @@ -4663,13 +4664,13 @@ def _send_form(self, url, params): raise ShotgunError("Max attemps limit reached.") -class CACertsHTTPSConnection(http_client.HTTPConnection): +class CACertsHTTPSConnection(http.client.HTTPConnection): """ " This class allows to create an HTTPS connection that uses the custom certificates passed in. """ - default_port = http_client.HTTPS_PORT + default_port = http.client.HTTPS_PORT def __init__(self, *args, **kwargs): """ diff --git a/tests/base.py b/tests/base.py index cc8634996..48df427a1 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,11 +1,13 @@ """Base class for Flow Production Tracking API tests.""" +import configparser import contextlib import os import random import re import time import unittest +import urllib.error from . import mock @@ -13,8 +15,6 @@ from shotgun_api3.shotgun import json from shotgun_api3.shotgun import ServerCapabilities from shotgun_api3.lib import six -from shotgun_api3.lib.six.moves import urllib -from shotgun_api3.lib.six.moves.configparser import ConfigParser try: # Attempt to import skip from unittest. Since this was added in Python 2.7 @@ -456,7 +456,7 @@ def config_keys(self): ] def read_config(self, config_path): - config_parser = ConfigParser() + config_parser = configparser.ConfigParser() config_parser.read(config_path) for section in config_parser.sections(): for option in config_parser.options(section): diff --git a/tests/test_api.py b/tests/test_api.py index 751ace799..36f3ef375 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -22,6 +22,9 @@ import time import types import unittest +import urllib.parse +import urllib.request +import urllib.error import uuid import warnings @@ -33,8 +36,6 @@ # class for the current Python version. from shotgun_api3.lib.sgsix import ShotgunSSLError -from shotgun_api3.lib.six.moves import range, urllib - import shotgun_api3 from . import base diff --git a/tests/test_client.py b/tests/test_client.py index 9cb50a168..98d2ab127 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -19,8 +19,9 @@ import sys import time import unittest +import urllib.parse +import urllib.error -from shotgun_api3.lib.six.moves import urllib from shotgun_api3.lib import six, sgutils try: diff --git a/tests/test_unit.py b/tests/test_unit.py index ff78253c2..d2853e5df 100644 --- a/tests/test_unit.py +++ b/tests/test_unit.py @@ -13,11 +13,12 @@ import os import unittest from unittest import mock +import urllib.request +import urllib.error from .mock import patch import shotgun_api3 as api from shotgun_api3.shotgun import _is_mimetypes_broken -from shotgun_api3.lib.six.moves import range, urllib from shotgun_api3.lib.httplib2 import Http, ssl_error_classes From f68f1ae6c1161848067f04c15b81001256ca9294 Mon Sep 17 00:00:00 2001 From: Julien Langlois Date: Wed, 16 Jul 2025 10:53:24 +0200 Subject: [PATCH 2/7] Cleanup BytesIO import from six --- shotgun_api3/shotgun.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shotgun_api3/shotgun.py b/shotgun_api3/shotgun.py index 338413810..77f2d57b5 100644 --- a/shotgun_api3/shotgun.py +++ b/shotgun_api3/shotgun.py @@ -34,6 +34,7 @@ import json import http.client # Used for secure file upload import http.cookiejar # used for attachment upload +import io # used for attachment upload import logging import os import re @@ -55,7 +56,6 @@ from .lib import six from .lib import sgsix from .lib import sgutils -from .lib.six import BytesIO # used for attachment upload from .lib.httplib2 import Http, ProxyInfo, socks, ssl_error_classes from .lib.sgtimezone import SgTimezone @@ -4434,7 +4434,7 @@ def _multipart_upload_file_to_storage(self, path, upload_info): data_size = len(data) # keep data as a stream so that we don't need to worry how it was # encoded. - data = BytesIO(data) + data = io.BytesIO(data) bytes_read += data_size part_url = self._get_upload_part_link( upload_info, filename, part_number @@ -4762,7 +4762,7 @@ def encode(self, params, files, boundary=None, buffer=None): # We'll do this across both python 2/3 rather than add more branching. boundary = uuid.uuid4() if buffer is None: - buffer = BytesIO() + buffer = io.BytesIO() for key, value in params: if isinstance(key, bytes): key = key.decode("utf-8") From 0b956cce92b6b99befae39f748b4d2452b9369b7 Mon Sep 17 00:00:00 2001 From: Julien Langlois Date: Wed, 16 Jul 2025 10:58:18 +0200 Subject: [PATCH 3/7] simple json --- tests/base.py | 2 +- tests/test_client.py | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/tests/base.py b/tests/base.py index 48df427a1..2e742ad8b 100644 --- a/tests/base.py +++ b/tests/base.py @@ -2,6 +2,7 @@ import configparser import contextlib +import json import os import random import re @@ -12,7 +13,6 @@ from . import mock import shotgun_api3 as api -from shotgun_api3.shotgun import json from shotgun_api3.shotgun import ServerCapabilities from shotgun_api3.lib import six diff --git a/tests/test_client.py b/tests/test_client.py index 98d2ab127..84fb94cb8 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -13,6 +13,7 @@ need a live server to run against.""" import datetime +import json import os import platform import re @@ -24,14 +25,6 @@ from shotgun_api3.lib import six, sgutils -try: - import simplejson as json -except ImportError: - try: - import json as json - except ImportError: - import shotgun_api3.lib.simplejson as json - from . import mock import shotgun_api3.lib.httplib2 as httplib2 From b94da1a72686ae332543ae7d1acd9cb72a486efa Mon Sep 17 00:00:00 2001 From: Julien Langlois Date: Wed, 16 Jul 2025 10:57:01 +0200 Subject: [PATCH 4/7] Cleanup Py2-3 compat with ImportError --- tests/base.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/base.py b/tests/base.py index 2e742ad8b..e30ec01a4 100644 --- a/tests/base.py +++ b/tests/base.py @@ -16,17 +16,6 @@ from shotgun_api3.shotgun import ServerCapabilities from shotgun_api3.lib import six -try: - # Attempt to import skip from unittest. Since this was added in Python 2.7 - # in the case that we're running on Python 2.6 we'll need a decorator to - # provide some equivalent functionality. - from unittest import skip -except ImportError: - # On Python 2.6 we'll just have to ignore tests that are skipped -- we won't - # mark them as skipped, but we will not fail on them. - def skip(f): - return lambda self: None - THUMBNAIL_MAX_ATTEMPTS = 30 THUMBNAIL_RETRY_INTERVAL = 10 From 6e89b9826e529d8859bbdb472adba73c9a44a14a Mon Sep 17 00:00:00 2001 From: Julien Langlois Date: Wed, 16 Jul 2025 11:14:54 +0200 Subject: [PATCH 5/7] Simplify Base64 --- shotgun_api3/shotgun.py | 14 +++++--------- tests/test_client.py | 8 ++------ 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/shotgun_api3/shotgun.py b/shotgun_api3/shotgun.py index 77f2d57b5..c7ab8a50d 100644 --- a/shotgun_api3/shotgun.py +++ b/shotgun_api3/shotgun.py @@ -29,6 +29,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ +import base64 import copy import datetime import json @@ -59,11 +60,6 @@ from .lib.httplib2 import Http, ProxyInfo, socks, ssl_error_classes from .lib.sgtimezone import SgTimezone -if six.PY3: - from base64 import encodebytes as base64encode -else: - from base64 import encodestring as base64encode - LOG = logging.getLogger("shotgun_api3") """ @@ -709,13 +705,13 @@ def __init__( # and auth header # Do NOT self._split_url(self.base_url) here, as it contains the lower - # case version of the base_url argument. Doing so would base64encode + # case version of the base_url argument. Doing so would base64.encodebytes # the lowercase version of the credentials. auth, self.config.server = self._split_url(base_url) if auth: - auth = base64encode(urllib.parse.unquote(auth).encode("utf-8")).decode( - "utf-8" - ) + auth = base64.encodebytes( + urllib.parse.unquote(auth).encode("utf-8") + ).decode("utf-8") self.config.authorization = "Basic " + auth.strip() # foo:bar@123.456.789.012:3456 diff --git a/tests/test_client.py b/tests/test_client.py index 84fb94cb8..ae1f1345e 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -12,6 +12,7 @@ CRUD functions. These tests always use a mock http connection so not not need a live server to run against.""" +import base64 import datetime import json import os @@ -32,17 +33,12 @@ from shotgun_api3.shotgun import ServerCapabilities, SG_TIMEZONE from . import base -if six.PY3: - from base64 import encodebytes as base64encode -else: - from base64 import encodestring as base64encode - def b64encode(val): if isinstance(val, str): val = val.encode("utf-8") - return base64encode(val).decode("utf-8") + return base64.encodebytes(val).decode("utf-8") class TestShotgunClient(base.MockTestBase): From 439d0b3db81b3da4c4f66e77a1367c1ca7ac1f8b Mon Sep 17 00:00:00 2001 From: Julien Langlois Date: Thu, 17 Jul 2025 16:16:02 +0200 Subject: [PATCH 6/7] fixup! six.moves imports --- tests/test_api.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index 36f3ef375..5c618d7a9 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -630,7 +630,7 @@ def test_linked_thumbnail_url(self): # For now skip tests that are erroneously failling on some sites to # allow CI to pass until the known issue causing this is resolved. - @base.skip("Skipping test that erroneously fails on some sites.") + @unittest.skip("Skipping test that erroneously fails on some sites.") def test_share_thumbnail(self): """share thumbnail between two entities""" @@ -2934,7 +2934,7 @@ def _check_attachment(self, data, attachment_id, additional_fields): # For now skip tests that are erroneously failling on some sites to # allow CI to pass until the known issue causing this is resolved. - @base.skip("Skipping test that erroneously fails on some sites.") + @unittest.skip("Skipping test that erroneously fails on some sites.") def test_simple(self): """ Test note reply thread API call @@ -3013,7 +3013,7 @@ def test_simple(self): # For now skip tests that are erroneously failling on some sites to # allow CI to pass until the known issue causing this is resolved. - @base.skip("Skipping test that erroneously fails on some sites.") + @unittest.skip("Skipping test that erroneously fails on some sites.") def test_complex(self): """ Test note reply thread API call with additional params From adbc0da846e85af856a3b9d9c5c81d17ccbfce79 Mon Sep 17 00:00:00 2001 From: Julien Langlois Date: Thu, 17 Jul 2025 16:29:08 +0200 Subject: [PATCH 7/7] fixup! six.moves imports --- tests/test_client.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_client.py b/tests/test_client.py index ae1f1345e..27e384b12 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -12,6 +12,7 @@ CRUD functions. These tests always use a mock http connection so not not need a live server to run against.""" +import configparser import base64 import datetime import json @@ -180,7 +181,7 @@ def test_read_config(self): """Validate that config values are properly coerced.""" this_dir = os.path.dirname(os.path.realpath(__file__)) config_path = os.path.join(this_dir, "test_config_file") - config = base.ConfigParser() + config = configparser.ConfigParser() config.read(config_path) result = config.get("SERVER_INFO", "api_key") expected = "%abce"