Skip to content

Commit 41ceb58

Browse files
Remove python2.7 support (#1423)
* Sets VFX platform supported years as 2022, 2021, and 2020 * Removes Python2.7 support from the library * Removes Python2.7 build matrix lines from CI/github actions * updates setup.py project metadata to drop 2.7 from versions * modernizes to python3 patterns by running pyupgrade --py37-plus Signed-off-by: Stephan Steinbach <[email protected]> Co-authored-by: ssteinbach <[email protected]> Co-authored-by: Jean-Christophe Morin <[email protected]>
1 parent 238e64c commit 41ceb58

File tree

91 files changed

+1005
-1163
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+1005
-1163
lines changed

.github/workflows/python-package.yml

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ jobs:
8787
strategy:
8888
matrix:
8989
os: [ubuntu-latest, windows-latest, macos-latest]
90-
python-version: ['2.7', '3.7', '3.8', '3.9', '3.10']
90+
python-version: ['3.7', '3.8', '3.9', '3.10']
9191
include:
9292
- { os: ubuntu-latest, shell: bash }
9393
- { os: macos-latest, shell: bash }
@@ -130,9 +130,6 @@ jobs:
130130
- name: Install python build dependencies
131131
run: |
132132
python -m pip install --upgrade pip setuptools wheel "flake8>=3.5" check-manifest
133-
- name: install mock for python 2.7 tests only
134-
if: matrix.python-version == 2.7
135-
run: python -m pip install --upgrade mock
136133
- name: Run check-manifest and lint check
137134
run: make ci-prebuild
138135
- name: Build and Install
@@ -172,22 +169,6 @@ jobs:
172169
# by CMake. CMake is able to find the right toolchain, thanks to
173170
# the -A argument that we specify in the setup.py to set the
174171
# target platform (x86, x64, etc).
175-
- name: Set Windows Python 2.7 environment variables
176-
if: matrix.python-build == 'cp27*' && runner.os == 'Windows'
177-
shell: bash
178-
run: |
179-
echo "DISTUTILS_USE_SDK=1" >> $GITHUB_ENV
180-
echo "MSSdk=1" >> $GITHUB_ENV
181-
182-
- name: Build wheels (Python 2.7)
183-
if: matrix.python-build == 'cp27*'
184-
# cibuildwheel 1.12.0 is the last release that supported Python 2.7.
185-
uses: pypa/[email protected]
186-
with:
187-
output-dir: wheelhouse
188-
env:
189-
CIBW_BUILD: ${{ matrix.python-build }}
190-
191172
- name: Build wheels (Python 3)
192173
uses: pypa/[email protected]
193174
if: matrix.python-build != 'cp27*'

CMakeLists.txt

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,18 +114,6 @@ else()
114114
# Note that this has no effect on Windows.
115115
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
116116
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
117-
118-
if(MSVC AND Python_VERSION_MAJOR VERSION_LESS 3)
119-
# Statically link run-time library (vcruntime and msvcp)
120-
# See https://docs.microsoft.com/en-us/cpp/build/reference/md-mt-ld-use-run-time-library?view=msvc-160
121-
# This allows us to compile OTIO bindings with a newer MSVC version
122-
# than the one used by the interpreter where OTIO will be installed.
123-
# This is only required for Python < 3 because only these are
124-
# compiled with an older compiler (9.0). CPython 3.5+ uses at least
125-
# Visual C++ 14.X.
126-
# See https://wiki.python.org/moin/WindowsCompilers#Which_Microsoft_Visual_C.2B-.2B-_compiler_to_use_with_a_specific_Python_version_.3F
127-
add_compile_options(/MT)
128-
endif()
129117
endif()
130118
endif()
131119

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ OpenTimelineIO
33
[![OpenTimelineIO](docs/_static/[email protected])](http://opentimeline.io)
44
==============
55

6-
[![Supported VFX Platform Versions](https://img.shields.io/badge/vfx%20platform-2019--2022-lightgrey.svg)](http://www.vfxplatform.com/)
7-
![Supported Versions](https://img.shields.io/badge/python-2.7%2C%203.7%2C%203.8%2C%203.9%2C%203.10-blue)
6+
[![Supported VFX Platform Versions](https://img.shields.io/badge/vfx%20platform-2020--2023-lightgrey.svg)](http://www.vfxplatform.com/)
7+
![Supported Versions](https://img.shields.io/badge/python-3.7%2C%203.8%2C%203.9%2C%203.10-blue)
88
[![Build Status](https://github.com/AcademySoftwareFoundation/OpenTimelineIO/actions/workflows/python-package.yml/badge.svg)](https://github.com/AcademySoftwareFoundation/OpenTimelineIO/actions/workflows/python-package.yml)
99
[![codecov](https://codecov.io/gh/AcademySoftwareFoundation/OpenTimelineIO/branch/main/graph/badge.svg)](https://codecov.io/gh/AcademySoftwareFoundation/OpenTimelineIO)
1010
[![docs](https://readthedocs.org/projects/opentimelineio/badge/?version=latest)](https://opentimelineio.readthedocs.io/en/latest/index.html)
@@ -54,8 +54,8 @@ Documentation, including quick start, architecture, use cases, API docs, and muc
5454
Supported VFX Platforms
5555
-----------------
5656
The current release supports:
57-
- VFX platform 2022, 2021, 2020, 2019
58-
- Python 2.7 - 3.10
57+
- VFX platform 2023, 2022, 2021, 2020
58+
- Python 3.7 - 3.10
5959

6060
For more information on our vfxplatform support policy: [Contribution Guidelines Documentation Page](https://opentimelineio.readthedocs.io/en/latest/tutorials/contributing.html)
6161
For more information on the vfxplatform: [VFX Platform Homepage](https://vfxplatform.com)
@@ -155,8 +155,8 @@ You can also install the PySide2 dependency with `python -m pip install .[view]`
155155

156156
You may need to escape the `[` depending on your shell, `\[view\]` .
157157

158-
Currently the code base is written against python 2.7, 3.7, 3.8 and 3.9,
159-
in keeping with the pep8 style. We ask that before developers submit pull
158+
Currently the code base is written against python 3.7, 3.8, 3.9, and 3.10, in
159+
keeping with the pep8 style. We ask that before developers submit pull
160160
request, they:
161161

162162
- run `make test` -- to ensure that none of the unit tests were broken

contrib/opentimelineio_contrib/adapters/aaf_adapter/aaf_writer.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class AAFValidationError(AAFAdapterError):
6262
pass
6363

6464

65-
class AAFFileTranscriber(object):
65+
class AAFFileTranscriber:
6666
"""
6767
AAFFileTranscriber
6868
@@ -137,7 +137,7 @@ def track_transcriber(self, otio_track):
137137
transcriber = AudioTrackTranscriber(self, otio_track)
138138
else:
139139
raise otio.exceptions.NotSupportedError(
140-
"Unsupported track kind: {}".format(otio_track.kind))
140+
f"Unsupported track kind: {otio_track.kind}")
141141
return transcriber
142142

143143

@@ -236,7 +236,7 @@ def _generate_empty_mobid(clip):
236236
clip_mob_ids[otio_clip] = mob_id
237237
break
238238
else:
239-
raise AAFAdapterError("Cannot find mob ID for clip {}".format(otio_clip))
239+
raise AAFAdapterError(f"Cannot find mob ID for clip {otio_clip}")
240240

241241
return clip_mob_ids
242242

@@ -260,7 +260,7 @@ def _stackify_nested_groups(timeline):
260260
return copied
261261

262262

263-
class _TrackTranscriber(object):
263+
class _TrackTranscriber:
264264
"""
265265
_TrackTranscriber is the base class for the conversion of a given otio track.
266266
@@ -305,7 +305,7 @@ def transcribe(self, otio_child):
305305
return operation_group
306306
else:
307307
raise otio.exceptions.NotSupportedError(
308-
"Unsupported otio child type: {}".format(type(otio_child)))
308+
f"Unsupported otio child type: {type(otio_child)}")
309309

310310
@property
311311
@abc.abstractmethod
@@ -662,11 +662,11 @@ def aaf_sourceclip(self, otio_clip):
662662
length = int(otio_clip.duration().value)
663663
c1 = self.aaf_file.create.ControlPoint()
664664
c1["ControlPointSource"].value = 2
665-
c1["Time"].value = aaf2.rational.AAFRational("0/{}".format(length))
665+
c1["Time"].value = aaf2.rational.AAFRational(f"0/{length}")
666666
c1["Value"].value = 0
667667
c2 = self.aaf_file.create.ControlPoint()
668668
c2["ControlPointSource"].value = 2
669-
c2["Time"].value = aaf2.rational.AAFRational("{}/{}".format(length - 1, length))
669+
c2["Time"].value = aaf2.rational.AAFRational(f"{length - 1}/{length}")
670670
c2["Value"].value = 0
671671
varying_value = self.aaf_file.create.VaryingValue()
672672
varying_value.parameterdef = param_def
@@ -675,7 +675,7 @@ def aaf_sourceclip(self, otio_clip):
675675
opgroup = self.timeline_mobslot.segment
676676
opgroup.parameters.append(varying_value)
677677

678-
return super(AudioTrackTranscriber, self).aaf_sourceclip(otio_clip)
678+
return super().aaf_sourceclip(otio_clip)
679679

680680
def _create_timeline_mobslot(self):
681681
"""
@@ -738,7 +738,7 @@ def _transition_parameters(self):
738738
return [param_def_level], level
739739

740740

741-
class __check(object):
741+
class __check:
742742
"""
743743
__check is a private helper class that safely gets values given to check
744744
for existence and equality

contrib/opentimelineio_contrib/adapters/advanced_authoring_format.py

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,7 @@
1212
import os
1313
import sys
1414

15-
try:
16-
# Python 2
17-
text_type = unicode
18-
except NameError:
19-
# Python 3
20-
text_type = str
21-
22-
try:
23-
# Python 3.3+
24-
import collections.abc as collections_abc
25-
except ImportError:
26-
import collections as collections_abc
15+
import collections
2716
import fractions
2817
import opentimelineio as otio
2918

@@ -66,7 +55,7 @@ class AAFAdapterError(otio.exceptions.OTIOError):
6655

6756

6857
def _get_parameter(item, parameter_name):
69-
values = dict((value.name, value) for value in item.parameters.value)
58+
values = {value.name: value for value in item.parameters.value}
7059
return values.get(parameter_name)
7160

7261

@@ -99,9 +88,7 @@ def _get_class_name(item):
9988

10089

10190
def _transcribe_property(prop, owner=None):
102-
# XXX: The unicode type doesn't exist in Python 3 (all strings are unicode)
103-
# so we have to use type(u"") which works in both Python 2 and 3.
104-
if isinstance(prop, (str, type(u""), numbers.Integral, float, dict)):
91+
if isinstance(prop, (str, numbers.Integral, float, dict)):
10592
return prop
10693
elif isinstance(prop, set):
10794
return list(prop)
@@ -371,7 +358,7 @@ def _extract_timecode_info(mob):
371358
def _add_child(parent, child, source):
372359
if child is None:
373360
if debug:
374-
print("Adding null child? {}".format(source))
361+
print(f"Adding null child? {source}")
375362
elif isinstance(child, otio.schema.Marker):
376363
parent.markers.append(child)
377364
else:
@@ -409,7 +396,7 @@ def _transcribe(item, parents, edit_rate, indent=0):
409396
# complex than OTIO.
410397

411398
if isinstance(item, aaf2.content.ContentStorage):
412-
msg = "Creating SerializableCollection for {}".format(_encoded_name(item))
399+
msg = f"Creating SerializableCollection for {_encoded_name(item)}"
413400
_transcribe_log(msg, indent)
414401
result = otio.schema.SerializableCollection()
415402

@@ -419,7 +406,7 @@ def _transcribe(item, parents, edit_rate, indent=0):
419406
_add_child(result, child, mob)
420407

421408
elif isinstance(item, aaf2.mobs.Mob):
422-
_transcribe_log("Creating Timeline for {}".format(_encoded_name(item)), indent)
409+
_transcribe_log(f"Creating Timeline for {_encoded_name(item)}", indent)
423410
result = otio.schema.Timeline()
424411

425412
for slot in item.slots:
@@ -442,7 +429,7 @@ def _transcribe(item, parents, edit_rate, indent=0):
442429
_encoded_name(item), clipUsage
443430
)
444431
else:
445-
itemMsg = "Creating SourceClip for {}".format(_encoded_name(item))
432+
itemMsg = f"Creating SourceClip for {_encoded_name(item)}"
446433

447434
_transcribe_log(itemMsg, indent)
448435
result = otio.schema.Clip()
@@ -599,7 +586,7 @@ def _transcribe(item, parents, edit_rate, indent=0):
599586
result.out_offset = otio.opentime.RationalTime(out_offset, edit_rate)
600587

601588
elif isinstance(item, aaf2.components.Filler):
602-
_transcribe_log("Creating Gap for {}".format(_encoded_name(item)), indent)
589+
_transcribe_log(f"Creating Gap for {_encoded_name(item)}", indent)
603590
result = otio.schema.Gap()
604591

605592
length = item.length
@@ -609,7 +596,7 @@ def _transcribe(item, parents, edit_rate, indent=0):
609596
)
610597

611598
elif isinstance(item, aaf2.components.NestedScope):
612-
msg = "Creating Stack for NestedScope for {}".format(_encoded_name(item))
599+
msg = f"Creating Stack for NestedScope for {_encoded_name(item)}"
613600
_transcribe_log(msg, indent)
614601
# TODO: Is this the right class?
615602
result = otio.schema.Stack()
@@ -619,7 +606,7 @@ def _transcribe(item, parents, edit_rate, indent=0):
619606
_add_child(result, child, slot)
620607

621608
elif isinstance(item, aaf2.components.Sequence):
622-
msg = "Creating Track for Sequence for {}".format(_encoded_name(item))
609+
msg = f"Creating Track for Sequence for {_encoded_name(item)}"
623610
_transcribe_log(msg, indent)
624611
result = otio.schema.Track()
625612

@@ -639,13 +626,13 @@ def _transcribe(item, parents, edit_rate, indent=0):
639626
_add_child(result, child, component)
640627

641628
elif isinstance(item, aaf2.components.OperationGroup):
642-
msg = "Creating operationGroup for {}".format(_encoded_name(item))
629+
msg = f"Creating operationGroup for {_encoded_name(item)}"
643630
_transcribe_log(msg, indent)
644631
result = _transcribe_operation_group(item, parents, metadata,
645632
edit_rate, indent + 2)
646633

647634
elif isinstance(item, aaf2.mobslots.TimelineMobSlot):
648-
msg = "Creating Track for TimelineMobSlot for {}".format(_encoded_name(item))
635+
msg = f"Creating Track for TimelineMobSlot for {_encoded_name(item)}"
649636
_transcribe_log(msg, indent)
650637
result = otio.schema.Track()
651638

@@ -654,7 +641,7 @@ def _transcribe(item, parents, edit_rate, indent=0):
654641
_add_child(result, child, item.segment)
655642

656643
elif isinstance(item, aaf2.mobslots.MobSlot):
657-
msg = "Creating Track for MobSlot for {}".format(_encoded_name(item))
644+
msg = f"Creating Track for MobSlot for {_encoded_name(item)}"
658645
_transcribe_log(msg, indent)
659646
result = otio.schema.Track()
660647

@@ -671,7 +658,7 @@ def _transcribe(item, parents, edit_rate, indent=0):
671658
pass
672659

673660
elif isinstance(item, aaf2.components.ScopeReference):
674-
msg = "Creating Gap for ScopedReference for {}".format(_encoded_name(item))
661+
msg = f"Creating Gap for ScopedReference for {_encoded_name(item)}"
675662
_transcribe_log(msg, indent)
676663
# TODO: is this like FILLER?
677664

@@ -687,7 +674,7 @@ def _transcribe(item, parents, edit_rate, indent=0):
687674
event_mobs = [p for p in parents if isinstance(p, aaf2.mobslots.EventMobSlot)]
688675
if event_mobs:
689676
_transcribe_log(
690-
"Create marker for '{}'".format(_encoded_name(item)), indent
677+
f"Create marker for '{_encoded_name(item)}'", indent
691678
)
692679

693680
result = otio.schema.Marker()
@@ -731,7 +718,7 @@ def _transcribe(item, parents, edit_rate, indent=0):
731718
)
732719

733720
elif isinstance(item, aaf2.components.Selector):
734-
msg = "Transcribe selector for {}".format(_encoded_name(item))
721+
msg = f"Transcribe selector for {_encoded_name(item)}"
735722
_transcribe_log(msg, indent)
736723

737724
selected = item.getvalue('Selected')
@@ -766,7 +753,7 @@ def _transcribe(item, parents, edit_rate, indent=0):
766753
# Perform a check here to make sure no potential Gap objects
767754
# are slipping through the cracks
768755
if isinstance(result, otio.schema.Gap):
769-
err = "AAF Selector parsing error: {}".format(type(item))
756+
err = f"AAF Selector parsing error: {type(item)}"
770757
raise AAFAdapterError(err)
771758

772759
# A Selector can have a set of alternates to handle multiple options for an
@@ -824,7 +811,7 @@ def _transcribe(item, parents, edit_rate, indent=0):
824811
# elif isinstance(item, pyaaf.AxProperty):
825812
# self.properties['Value'] = str(item.GetValue())
826813

827-
elif isinstance(item, collections_abc.Iterable):
814+
elif isinstance(item, collections.abc.Iterable):
828815
msg = "Creating SerializableCollection for Iterable for {}".format(
829816
_encoded_name(item))
830817
_transcribe_log(msg, indent)
@@ -836,7 +823,7 @@ def _transcribe(item, parents, edit_rate, indent=0):
836823
# For everything else, we just ignore it.
837824
# To see what is being ignored, turn on the debug flag
838825
if debug:
839-
print("SKIPPING: {}: {} -- {}".format(type(item), item, result))
826+
print(f"SKIPPING: {type(item)}: {item} -- {result}")
840827

841828
# Did we get anything? If not, we're done
842829
if result is None:
@@ -911,7 +898,7 @@ def _find_timecode_track_start(track):
911898
start = aaf_metadata["Segment"]["Start"]
912899
except KeyError as e:
913900
raise AAFAdapterError(
914-
"Timecode missing '{}'".format(e)
901+
f"Timecode missing '{e}'"
915902
)
916903

917904
if edit_rate.denominator == 1:

contrib/opentimelineio_contrib/adapters/ale.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def _parse_data_line(line, columns, fps, ale_name_column_key='Name'):
6060
try:
6161
start = otio.opentime.from_timecode(value, fps)
6262
except (ValueError, TypeError):
63-
raise ALEParseError("Invalid Start timecode: {}".format(value))
63+
raise ALEParseError(f"Invalid Start timecode: {value}")
6464
duration = None
6565
end = None
6666
if metadata.get("Duration", "") != "":
@@ -137,7 +137,7 @@ def _parse_data_line(line, columns, fps, ale_name_column_key='Name'):
137137

138138
def _cdl_values_from_metadata(asc_sop_string):
139139

140-
if not isinstance(asc_sop_string, (type(''), type(u''))):
140+
if not isinstance(asc_sop_string, str):
141141
return {}
142142

143143
asc_sop_values = ASC_SOP_REGEX.findall(asc_sop_string)
@@ -285,7 +285,7 @@ def write_to_string(input_otio, columns=None, fps=None, video_format=None):
285285
headers = list(header.items())
286286
headers.sort() # make the output predictable
287287
for key, val in headers:
288-
result += "{}\t{}\n".format(key, val)
288+
result += f"{key}\t{val}\n"
289289

290290
# If the caller passed in a list of columns, use that, otherwise
291291
# we need to discover the columns that should be output.

0 commit comments

Comments
 (0)