Skip to content
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

SG-31340 Deprecation of Python 2 #295

Merged
merged 8 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from 6 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
57 changes: 0 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,63 +37,6 @@ The API comes with a copy of the `httplib2` inside the `shotgun_api3/lib` folder

where `vX.Y.Z` is a release found on `httplib2`'s [release page](https://github.com/httplib2/httplib2/releases).

## Maintaining Python 2 and 3 compatibility

python-api should remain compatible with both Python 2, and 3. To make this easier, we use [six](https://six.readthedocs.io/). When adding code that works with types that have changed between Python 2 and 3, notably strings and files, it's advisable to use the `six` types for casting and comparisons. Be sure to follow Python 2 and 3 compatible conventions in code, especially when raising or capturing exceptions and printing. While we don't use `future`, [this page](https://python-future.org/compatible_idioms.html) contains a fairly comprehensive list of Python 2/3 compatibility sticking points to look out for.

Additionally, the [python-modernize](https://python-modernize.readthedocs.io/en/latest/) tool can be helpful when updating Python 2 code for Python 3 compatibility.

### Examples:

#### Comparisons against changed types:

Python 2:

```
if isinstance(my_variable, str):
```

Python 2/3:

```
if isinstance(my_variable, six.string_types):
```

#### Catching exceptions

Python 2:

```
except SomeExceptionType, e:
print "I like to swallow exceptions!"
```

Python 2/3:

```
from __future__ import print_function
except SomeExceptionType as e:
print("I like to swallow exceptions!")
```

#### Print statements

Python 2:

```
print "My spoon is too big!"
```

Python 2/3:

```
from __future__ import print_function
print("My spoon is too big!")
```


Additionally, when testing locally, tests should be run for both python 2 and python 3 to ensure changes won't break cross-compatibility.

## Tests

Integration and unit tests are provided.
Expand Down
2 changes: 0 additions & 2 deletions azure-pipelines-templates/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ jobs:
strategy:
matrix:
# We support these two versions of Python.
Python27:
python.version: '2.7'
Python37:
python.version: '3.7'
Python39:
Expand Down
7 changes: 1 addition & 6 deletions tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,7 @@
from shotgun_api3.shotgun import ServerCapabilities
from shotgun_api3.lib import six
from shotgun_api3.lib.six.moves import urllib

if six.PY2:
from shotgun_api3.lib.six.moves.configparser import SafeConfigParser as ConfigParser
else:
from shotgun_api3.lib.six.moves.configparser import ConfigParser

from shotgun_api3.lib.six.moves.configparser import ConfigParser

try:
# Attempt to import skip from unittest. Since this was added in Python 2.7
Expand Down
6 changes: 0 additions & 6 deletions tests/mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,6 @@
# may not have inspect
inspect = None

try:
BaseException
except NameError:
# Python 2.4 compatibility
BaseException = Exception

try:
from functools import wraps
except ImportError:
Expand Down
6 changes: 1 addition & 5 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1206,11 +1206,7 @@ def _id_in_result(self, entity_type, filters, expected_id):
for particular filters.
"""
results = self.sg.find(entity_type, filters)
# can't use 'any' in python 2.4
for result in results:
if result['id'] == expected_id:
return True
return False
return any(result['id'] == expected_id for result in results)
Copy link
Contributor

Choose a reason for hiding this comment

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

Good job on this one!


# TODO test all applicable data types for 'in'
# 'currency' => [BigDecimal, Float, NilClass],
Expand Down
1 change: 0 additions & 1 deletion tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,6 @@ def test_parse_records(self):
system = platform.system().lower()
if system == 'darwin':
local_path_field = "local_path_mac"
# python 2.4 returns 'Microsoft'
elif system in ['windows', 'microsoft']:
local_path_field = "local_path_windows"
elif system == 'linux':
Expand Down
32 changes: 5 additions & 27 deletions tests/test_mockgun.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,28 +53,6 @@
)


# FIXME: This should probably be refactored into a base class for
# all test bases
class TestBaseWithExceptionTests(unittest.TestCase):
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice!

"""
Implements a Python 2.4 compatible assertRaisesRegexp like method. This
was introduced in Python 2.7.
"""
def assertRaisesRegexp(self, exception_type, re_msg, func):
try:
func()
except exception_type as exception:
matches = re.findall(re_msg, str(exception))
if not matches:
self.fail("Expected exception to match '%s', got '%s' instead." % (
re_msg, str(exception)
))
except Exception as ex:
self.fail("Expected exception of type %s, got %s" % (exception_type, type(ex)))
else:
self.fail("Expected %s was not raised." % exception_type)


class TestMockgunModuleInterface(unittest.TestCase):
"""
mockgun.py was turned into a module. Ensure we haven't broken the interface.
Expand All @@ -93,7 +71,7 @@ def test_interface_intact(self):
mockgun.Shotgun


class TestValidateFilterSyntax(TestBaseWithExceptionTests):
class TestValidateFilterSyntax(unittest.TestCase):
"""
Tests filter syntax support.
"""
Expand Down Expand Up @@ -137,7 +115,7 @@ def test_filter_array_or_dict(self):
)


class TestEntityFieldComparison(TestBaseWithExceptionTests):
class TestEntityFieldComparison(unittest.TestCase):
"""
Checks if entity fields comparison work.
"""
Expand Down Expand Up @@ -191,7 +169,7 @@ def test_find_entity_with_none_link(self):
self.assertEqual(items[0]["id"], self._project_link["id"])


class TestTextFieldOperators(TestBaseWithExceptionTests):
class TestTextFieldOperators(unittest.TestCase):
"""
Checks if text field comparison work.
"""
Expand All @@ -210,7 +188,7 @@ def test_operator_contains(self):
self.assertTrue(item)


class TestMultiEntityFieldComparison(TestBaseWithExceptionTests):
class TestMultiEntityFieldComparison(unittest.TestCase):
"""
Ensures multi entity field comparison work.
"""
Expand Down Expand Up @@ -293,7 +271,7 @@ def test_find_with_none(self):
self.assertTrue(len(item["users"]) > 0)


class TestFilterOperator(TestBaseWithExceptionTests):
class TestFilterOperator(unittest.TestCase):
"""
Unit tests for the filter_operator filter syntax.
"""
Expand Down
11 changes: 0 additions & 11 deletions tests/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,16 +506,5 @@ def _test_mimetypes_import(self, platform, major, minor, patch_number, result, m
mock.platform = platform
self.assertEqual(_is_mimetypes_broken(), result)

def test_correct_mimetypes_imported(self):
"""
Makes sure fix is imported for only for Python 2.7.0 to 2.7.7 on win32
"""
self._test_mimetypes_import("win32", 2, 6, 9, False)
for patch_number in range(0, 10): # 0 to 9 inclusively
self._test_mimetypes_import("win32", 2, 7, patch_number, True)
self._test_mimetypes_import("win32", 2, 7, 10, False)
self._test_mimetypes_import("win32", 3, 0, 0, False)
self._test_mimetypes_import("darwin", 2, 7, 0, False)

if __name__ == '__main__':
unittest.main()