Skip to content

Commit 45aee51

Browse files
authored
add windows and mac builds to ci (#873)
* add windows and mac builds to ci * fall back to mac 10.15 * split lcov target out from the ci-postbuild target * Specify which build does C++ coverage w/ lcov * move the env config out to the top level * sanitize paths when writing autogen docs * windows is stricter about using file handles that are already open, so switching to a pattern where TemporaryDirectory is used to create things should be safer. Its also cleaner than the mkdtemp/try/except pattern that had been used in the tests before. * remove BOM from example xml file * only run XGES unit tests on linux w/ python3
1 parent 5005650 commit 45aee51

File tree

13 files changed

+277
-206
lines changed

13 files changed

+277
-206
lines changed

.github/workflows/python-package.yml

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33

44
name: OpenTimelineIO
55

6+
# for configuring which build will be a C++ coverage build / coverage report
7+
env:
8+
GH_COV_PY: 3.7
9+
GH_COV_OS: ubuntu-latest
10+
611
on:
712
push:
813
branches: [ master ]
@@ -11,16 +16,16 @@ on:
1116

1217
jobs:
1318
build:
14-
15-
runs-on: ubuntu-latest
19+
runs-on: ${{ matrix.os }}
1620
strategy:
1721
matrix:
22+
os: [ubuntu-latest, windows-latest, macos-latest]
1823
python-version: [2.7, 3.7, 3.8]
1924

2025
env:
2126
OTIO_CXX_COVERAGE_BUILD: ON
2227
OTIO_CXX_BUILD_TMP_DIR: ${{ github.workspace }}/build
23-
28+
2429
steps:
2530
- uses: actions/checkout@v2
2631
with:
@@ -29,19 +34,27 @@ jobs:
2934
uses: actions/setup-python@v2
3035
with:
3136
python-version: ${{ matrix.python-version }}
32-
- name: Install build dependencies
37+
- name: Install coverage dependency
38+
if: matrix.python-version == env.GH_COV_PY && matrix.os == env.GH_COV_OS
3339
run: |
3440
sudo apt-get install lcov
41+
- name: Install python build dependencies
42+
run: |
3543
python -m pip install --upgrade pip setuptools wheel flake8>=3.5 check-manifest
3644
- name: Run check-manifest and lint check
3745
run: make ci-prebuild
3846
- name: Build and Install
3947
run: |
4048
# compile and install into virtualenv/virtual machine (verbosely)
4149
pip install .[dev] -v
42-
- name: Run tests and generate coverage report
50+
- name: Run tests w/ python coverage
4351
run: make ci-postbuild
52+
# (only on ubuntu/pyhton3.7)
53+
- name: Generate C++ coverage report
54+
if: matrix.python-version == env.GH_COV_PY && matrix.os == env.GH_COV_OS
55+
run: make lcov
4456
- name: Upload coverage to Codecov
57+
if: matrix.python-version == env.GH_COV_PY && matrix.os == env.GH_COV_OS
4558
uses: codecov/codecov-action@v1
4659
with:
4760
flags: unittests

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ test-contrib: python-version
5454
# CI
5555
###################################
5656
ci-prebuild: manifest lint
57-
ci-postbuild: coverage lcov
57+
ci-postbuild: coverage
5858
###################################
5959

6060
python-version:

contrib/opentimelineio_contrib/adapters/tests/test_hls_playlist_adapter.py

Lines changed: 88 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,19 @@
2323
#
2424

2525
import os
26-
import tempfile
2726
import unittest
2827

2928
import opentimelineio as otio
3029

3130

31+
# handle python2 vs python3 difference
32+
try:
33+
from tempfile import TemporaryDirectory # noqa: F401
34+
import tempfile
35+
except ImportError:
36+
# XXX: python2.7 only
37+
from backports import tempfile
38+
3239
# Reference data
3340
SAMPLE_DATA_DIR = os.path.join(os.path.dirname(__file__), "sample_data")
3441
HLS_EXAMPLE_PATH = os.path.join(SAMPLE_DATA_DIR, "v1_prog_index.m3u8")
@@ -162,13 +169,15 @@ def test_media_pl_from_mem(self):
162169
track.append(segment1)
163170

164171
# Write out and validate the playlist
165-
media_pl_tmp_path = tempfile.mkstemp(suffix=".m3u8", text=True)[1]
166-
otio.adapters.write_to_file(t, media_pl_tmp_path)
167-
168-
with open(media_pl_tmp_path) as f:
169-
pl_string = f.read()
172+
with tempfile.TemporaryDirectory() as temp_dir:
173+
media_pl_tmp_path = os.path.join(
174+
temp_dir,
175+
"test_media_pl_from_mem.m3u8"
176+
)
177+
otio.adapters.write_to_file(t, media_pl_tmp_path)
170178

171-
os.remove(media_pl_tmp_path)
179+
with open(media_pl_tmp_path) as f:
180+
pl_string = f.read()
172181

173182
# Compare against the reference value
174183
self.assertEqual(pl_string, MEM_PLAYLIST_REF_VALUE)
@@ -243,21 +252,22 @@ def test_media_roundtrip(self):
243252
self._validate_sample_playlist(timeline)
244253

245254
# Write out and validate both playlists have the same lines
246-
media_pl_tmp_path = tempfile.mkstemp(suffix=".m3u8", text=True)[1]
247-
otio.adapters.write_to_file(timeline, media_pl_tmp_path)
248-
249-
# Read in both playlists
250-
with open(hls_path) as f:
251-
reference_lines = f.readlines()
255+
with tempfile.TemporaryDirectory() as temp_dir:
256+
media_pl_tmp_path = os.path.join(
257+
temp_dir,
258+
"test_media_roundtrip.m3u8"
259+
)
260+
otio.adapters.write_to_file(timeline, media_pl_tmp_path)
252261

253-
with open(media_pl_tmp_path) as f:
254-
adapter_out_lines = f.readlines()
262+
# Read in both playlists
263+
with open(hls_path) as f:
264+
reference_lines = f.readlines()
255265

256-
# Using otio as well
257-
in_timeline = otio.adapters.read_from_file(media_pl_tmp_path)
266+
with open(media_pl_tmp_path) as f:
267+
adapter_out_lines = f.readlines()
258268

259-
# Remove the temp out file
260-
os.remove(media_pl_tmp_path)
269+
# Using otio as well
270+
in_timeline = otio.adapters.read_from_file(media_pl_tmp_path)
261271

262272
# Strip newline chars
263273
reference_lines = [line.strip('\n') for line in reference_lines]
@@ -287,12 +297,15 @@ def test_media_segment_size(self):
287297
timeline_streaming_md['max_segment_duration'] = seg_max_duration
288298

289299
# Write out the playlist
290-
media_pl_tmp_path = tempfile.mkstemp(suffix=".m3u8", text=True)[1]
291-
otio.adapters.write_to_file(timeline, media_pl_tmp_path)
300+
with tempfile.TemporaryDirectory() as temp_dir:
301+
media_pl_tmp_path = os.path.join(
302+
temp_dir,
303+
"test_media_segment_size.m3u8"
304+
)
305+
otio.adapters.write_to_file(timeline, media_pl_tmp_path)
292306

293-
# Read in the playlist
294-
in_timeline = otio.adapters.read_from_file(media_pl_tmp_path)
295-
os.remove(media_pl_tmp_path)
307+
# Read in the playlist
308+
in_timeline = otio.adapters.read_from_file(media_pl_tmp_path)
296309

297310
# Pick a duration that segments won't exceed but is less than max
298311
seg_upper_duration = otio.opentime.RationalTime(7, 1)
@@ -339,15 +352,18 @@ def test_iframe_segment_size(self):
339352
track_hls_metadata['EXT-X-I-FRAMES-ONLY'] = None
340353

341354
# Write out the playlist
342-
media_pl_tmp_path = tempfile.mkstemp(suffix=".m3u8", text=True)[1]
343-
otio.adapters.write_to_file(timeline, media_pl_tmp_path)
355+
with tempfile.TemporaryDirectory() as temp_dir:
356+
media_pl_tmp_path = os.path.join(
357+
temp_dir,
358+
"test_iframe_segment_size.m3u8"
359+
)
360+
otio.adapters.write_to_file(timeline, media_pl_tmp_path)
344361

345-
# Read in the playlist
346-
in_timeline = otio.adapters.read_from_file(media_pl_tmp_path)
347-
with open(media_pl_tmp_path) as f:
348-
pl_lines = f.readlines()
349-
pl_lines = [line.strip('\n') for line in pl_lines]
350-
os.remove(media_pl_tmp_path)
362+
# Read in the playlist
363+
in_timeline = otio.adapters.read_from_file(media_pl_tmp_path)
364+
with open(media_pl_tmp_path) as f:
365+
pl_lines = f.readlines()
366+
pl_lines = [line.strip('\n') for line in pl_lines]
351367

352368
# validate the TARGETDURATION value is correct
353369
self.assertTrue('#EXT-X-TARGETDURATION:6' in pl_lines)
@@ -420,16 +436,15 @@ def test_simple_master_pl_from_mem(self):
420436
t.tracks.append(atrack)
421437

422438
# Write out and validate the playlist
423-
media_pl_tmp_path = tempfile.mkstemp(
424-
suffix="master.m3u8",
425-
text=True
426-
)[1]
427-
otio.adapters.write_to_file(t, media_pl_tmp_path)
428-
429-
with open(media_pl_tmp_path) as f:
430-
pl_string = f.read()
439+
with tempfile.TemporaryDirectory() as temp_dir:
440+
media_pl_tmp_path = os.path.join(
441+
temp_dir,
442+
"master.m3u8"
443+
)
444+
otio.adapters.write_to_file(t, media_pl_tmp_path)
431445

432-
os.remove(media_pl_tmp_path)
446+
with open(media_pl_tmp_path) as f:
447+
pl_string = f.read()
433448

434449
# Drop blank lines before comparing
435450
pl_string = '\n'.join((line for line in pl_string.split('\n') if line))
@@ -483,16 +498,15 @@ def test_master_pl_with_iframe_pl_from_mem(self):
483498
t.tracks.append(atrack)
484499

485500
# Write out and validate the playlist
486-
media_pl_tmp_path = tempfile.mkstemp(
487-
suffix="master.m3u8",
488-
text=True
489-
)[1]
490-
otio.adapters.write_to_file(t, media_pl_tmp_path)
491-
492-
with open(media_pl_tmp_path) as f:
493-
pl_string = f.read()
501+
with tempfile.TemporaryDirectory() as temp_dir:
502+
media_pl_tmp_path = os.path.join(
503+
temp_dir,
504+
"master.m3u8"
505+
)
506+
otio.adapters.write_to_file(t, media_pl_tmp_path)
494507

495-
os.remove(media_pl_tmp_path)
508+
with open(media_pl_tmp_path) as f:
509+
pl_string = f.read()
496510

497511
# Drop blank lines before comparing
498512
pl_string = '\n'.join(line for line in pl_string.split('\n') if line)
@@ -568,16 +582,15 @@ def test_master_pl_complex_from_mem(self):
568582
t.tracks.append(atrack)
569583

570584
# Write out and validate the playlist
571-
media_pl_tmp_path = tempfile.mkstemp(
572-
suffix="master.m3u8",
573-
text=True
574-
)[1]
575-
otio.adapters.write_to_file(t, media_pl_tmp_path)
576-
577-
with open(media_pl_tmp_path) as f:
578-
pl_string = f.read()
585+
with tempfile.TemporaryDirectory() as temp_dir:
586+
media_pl_tmp_path = os.path.join(
587+
temp_dir,
588+
"master.m3u8"
589+
)
590+
otio.adapters.write_to_file(t, media_pl_tmp_path)
579591

580-
os.remove(media_pl_tmp_path)
592+
with open(media_pl_tmp_path) as f:
593+
pl_string = f.read()
581594

582595
# Drop blank lines before comparing
583596
pl_string = '\n'.join(line for line in pl_string.split('\n') if line)
@@ -610,16 +623,15 @@ def test_master_playlist_hint_metadata(self):
610623
)
611624

612625
# Write out and validate the playlist
613-
media_pl_tmp_path = tempfile.mkstemp(
614-
suffix="master.m3u8",
615-
text=True
616-
)[1]
617-
otio.adapters.write_to_file(timeline, media_pl_tmp_path)
618-
619-
with open(media_pl_tmp_path) as f:
620-
pl_string = f.read()
626+
with tempfile.TemporaryDirectory() as temp_dir:
627+
media_pl_tmp_path = os.path.join(
628+
temp_dir,
629+
"test_media_pl_from_mem.m3u8"
630+
)
631+
otio.adapters.write_to_file(timeline, media_pl_tmp_path)
621632

622-
os.remove(media_pl_tmp_path)
633+
with open(media_pl_tmp_path) as f:
634+
pl_string = f.read()
623635

624636
# ensure metadata that wasn't supposed to didn't leak out
625637
for line in pl_string.split('\n'):
@@ -696,16 +708,15 @@ def test_explicit_master_pl_from_mem(self):
696708
track.append(segment1)
697709

698710
# Write out and validate the playlist
699-
master_pl_tmp_path = tempfile.mkstemp(
700-
suffix='master.m3u8',
701-
text=True
702-
)[1]
703-
otio.adapters.write_to_file(t, master_pl_tmp_path)
704-
705-
with open(master_pl_tmp_path) as f:
706-
pl_string = f.read()
711+
with tempfile.TemporaryDirectory() as temp_dir:
712+
master_pl_tmp_path = os.path.join(
713+
temp_dir,
714+
"master.m3u8"
715+
)
716+
otio.adapters.write_to_file(t, master_pl_tmp_path)
707717

708-
os.remove(master_pl_tmp_path)
718+
with open(master_pl_tmp_path) as f:
719+
pl_string = f.read()
709720

710721
# Drop blank lines before comparing
711722
pl_string = '\n'.join((line for line in pl_string.split('\n') if line))

contrib/opentimelineio_contrib/adapters/tests/tests_xges_adapter.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#
2424

2525
import os
26+
import platform
27+
import sys
2628
import tempfile
2729
import unittest
2830
from fractions import Fraction
@@ -1018,6 +1020,10 @@ def assertXgesTimelineMarkerListEqual(self, ges_el, marker_list):
10181020
timeline, "markers", "GESMarkerList", marker_list)
10191021

10201022

1023+
@unittest.skipIf(
1024+
platform.system() != 'Linux' or sys.version_info[0] < 3,
1025+
"XGES only suppported on Linux in Python3."
1026+
)
10211027
class AdaptersXGESTest(
10221028
unittest.TestCase, otio_test_utils.OTIOAssertions,
10231029
CustomOtioAssertions, CustomXgesAssertions):

setup.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ class _Ctx(object):
5252
_ctx.debug = False
5353

5454

55+
INSTALL_REQUIRES = [
56+
'pyaaf2==1.4.0',
57+
]
58+
# python2 dependencies
59+
if sys.version_info[0] < 3:
60+
INSTALL_REQUIRES.append(
61+
"backports.tempfile",
62+
)
63+
64+
5565
def cmake_version_check():
5666
if platform.system() == "Windows":
5767
required_minimum_version = '3.17.0'
@@ -406,11 +416,7 @@ def test_otio():
406416
'opentimelineview': 'src/opentimelineview',
407417
},
408418

409-
install_requires=(
410-
[
411-
'pyaaf2==1.4.0',
412-
]
413-
),
419+
install_requires=INSTALL_REQUIRES,
414420
entry_points={
415421
'console_scripts': [
416422
'otioview = opentimelineview.console:main',

0 commit comments

Comments
 (0)