[Python-modules-commits] [python-m3u8] 01/03: Import python-m3u8_0.2.10.orig.tar.gz

Ondrej Koblizek kobla-guest at moszumanska.debian.org
Fri Aug 12 11:35:51 UTC 2016


This is an automated email from the git hooks/post-receive script.

kobla-guest pushed a commit to branch master
in repository python-m3u8.

commit 5e1b18ae277fb9d3f04721a8c4536e1a08c4c5eb
Author: Ondřej Kobližek <ondrej.koblizek at firma.seznam.cz>
Date:   Fri Aug 12 12:43:21 2016 +0200

    Import python-m3u8_0.2.10.orig.tar.gz
---
 m3u8/__init__.py     |  9 +++++----
 m3u8/model.py        | 12 ++++++++++--
 m3u8/parser.py       | 12 ++++++++++++
 m3u8/protocol.py     |  3 +++
 setup.py             |  2 +-
 tests/m3u8server.py  |  7 +++++++
 tests/playlists.py   | 37 +++++++++++++++++++++++++++++++++++++
 tests/test_loader.py |  7 +++++++
 tests/test_model.py  |  7 +++++++
 tests/test_parser.py |  7 +++++++
 10 files changed, 96 insertions(+), 7 deletions(-)

diff --git a/m3u8/__init__.py b/m3u8/__init__.py
index 80a5da0..0f364fb 100644
--- a/m3u8/__init__.py
+++ b/m3u8/__init__.py
@@ -32,19 +32,20 @@ def loads(content):
     '''
     return M3U8(content)
 
-def load(uri):
+def load(uri, timeout = None):
     '''
     Retrieves the content from a given URI and returns a M3U8 object.
     Raises ValueError if invalid content or IOError if request fails.
+    Raises socket.timeout(python 2.7+) or urllib2.URLError(python 2.6) if timeout happens when loading from uri
     '''
     if is_url(uri):
-        return _load_from_uri(uri)
+        return _load_from_uri(uri, timeout)
     else:
         return _load_from_file(uri)
 
 # Support for python3 inspired by https://github.com/szemtiv/m3u8/
-def _load_from_uri(uri):
-    resource = urlopen(uri)
+def _load_from_uri(uri, timeout = None):
+    resource = urlopen(uri, timeout=timeout)
     base_uri = _parsed_url(_url_for(uri))
     if PYTHON_MAJOR_VERSION < (3,):
         content = _read_python2x(resource)
diff --git a/m3u8/model.py b/m3u8/model.py
index 05850f5..8f653e9 100644
--- a/m3u8/model.py
+++ b/m3u8/model.py
@@ -328,6 +328,12 @@ class Segment(BasePathMixin):
     `cue_out`
       Returns a boolean indicating if a EXT-X-CUE-OUT-CONT tag exists
 
+    `scte35`
+      Base64 encoded SCTE35 metadata if available
+
+    `scte35_duration`
+      Planned SCTE35 duration
+
     `duration`
       duration attribute from EXTINF parameter
 
@@ -342,7 +348,8 @@ class Segment(BasePathMixin):
     '''
 
     def __init__(self, uri, base_uri, program_date_time=None, duration=None,
-                 title=None, byterange=None, cue_out=False, discontinuity=False, key=None):
+                 title=None, byterange=None, cue_out=False, discontinuity=False, key=None,
+                 scte35=None, scte35_duration=None):
         self.uri = uri
         self.duration = duration
         self.title = title
@@ -351,6 +358,8 @@ class Segment(BasePathMixin):
         self.program_date_time = program_date_time
         self.discontinuity = discontinuity
         self.cue_out = cue_out
+        self.scte35 = scte35
+        self.scte35_duration = scte35_duration
         self.key = Key(base_uri=base_uri,**key) if key else None
 
 
@@ -382,7 +391,6 @@ class Segment(BasePathMixin):
     def __str__(self):
         return self.dumps(None)
 
-
 class SegmentList(list, GroupedBasePathMixin):
 
     def __str__(self):
diff --git a/m3u8/parser.py b/m3u8/parser.py
index 40616bf..9840d1a 100644
--- a/m3u8/parser.py
+++ b/m3u8/parser.py
@@ -82,7 +82,9 @@ def parse(content, strict=False):
             state['discontinuity'] = True
 
         elif line.startswith(protocol.ext_x_cue_out):
+            _parse_cueout(line, state)
             state['cue_out'] = True
+            state['cue_start'] = True
 
         elif line.startswith(protocol.ext_x_version):
             _parse_simple_parameter(line, data)
@@ -163,6 +165,9 @@ def _parse_ts_chunk(line, data, state):
         state['current_program_date_time'] += datetime.timedelta(seconds=segment['duration'])
     segment['uri'] = line
     segment['cue_out'] = state.pop('cue_out', False)
+    if state.get('current_cue_out_scte35'):
+        segment['scte35'] = state['current_cue_out_scte35']
+        segment['scte35_duration'] = state['current_cue_out_duration'] 
     segment['discontinuity'] = state.pop('discontinuity', False)
     if state.get('current_key'):
       segment['key'] = state['current_key']
@@ -233,6 +238,13 @@ def _parse_and_set_simple_parameter_raw_value(line, data, cast_to=str, normalize
 def _parse_simple_parameter(line, data, cast_to=str):
     return _parse_and_set_simple_parameter_raw_value(line, data, cast_to, True)
 
+def _parse_cueout(line, state):
+    param, value = line.split(':', 1)
+    res = re.match('.*Duration=(.*),SCTE35=(.*)$', value)
+    if res:
+        state['current_cue_out_duration'] = res.group(1)
+        state['current_cue_out_scte35'] = res.group(2)
+
 def string_to_lines(string):
     return string.strip().replace('\r\n', '\n').split('\n')
 
diff --git a/m3u8/protocol.py b/m3u8/protocol.py
index fd0e128..bfa5992 100644
--- a/m3u8/protocol.py
+++ b/m3u8/protocol.py
@@ -20,3 +20,6 @@ ext_x_i_frame_stream_inf = '#EXT-X-I-FRAME-STREAM-INF'
 ext_x_discontinuity = '#EXT-X-DISCONTINUITY'
 ext_x_cue_out = '#EXT-X-CUE-OUT-CONT'
 ext_is_independent_segments = '#EXT-X-INDEPENDENT-SEGMENTS'
+ext_x_scte35 = '#EXT-OATCLS-SCTE35'
+ext_x_cue_start = '#EXT-X-CUE-OUT'
+ext_x_cue_end = '#EXT-X-CUE-IN'
diff --git a/setup.py b/setup.py
index 61c2501..1315e2c 100644
--- a/setup.py
+++ b/setup.py
@@ -11,7 +11,7 @@ setup(
     name="m3u8",
     author='Globo.com',
     author_email='videos3 at corp.globo.com',
-    version="0.2.9",
+    version="0.2.10",
     license='MIT',
     zip_safe=False,
     include_package_data=True,
diff --git a/tests/m3u8server.py b/tests/m3u8server.py
index a1068e5..247d80b 100644
--- a/tests/m3u8server.py
+++ b/tests/m3u8server.py
@@ -9,6 +9,7 @@ from os.path import dirname, abspath, join
 
 from bottle import route, run, response, redirect
 import bottle
+import time
 
 playlists = abspath(join(dirname(__file__), 'playlists'))
 
@@ -21,6 +22,12 @@ def simple():
     response.set_header('Content-Type', 'application/vnd.apple.mpegurl')
     return m3u8_file('simple-playlist.m3u8')
 
+ at route('/timeout_simple.m3u8')
+def simple():
+    time.sleep(5)
+    response.set_header('Content-Type', 'application/vnd.apple.mpegurl')
+    return m3u8_file('simple-playlist.m3u8')
+
 @route('/path/to/relative-playlist.m3u8')
 def simple():
     response.set_header('Content-Type', 'application/vnd.apple.mpegurl')
diff --git a/tests/playlists.py b/tests/playlists.py
index e17ae09..3c9c78d 100755
--- a/tests/playlists.py
+++ b/tests/playlists.py
@@ -18,8 +18,10 @@ http://media.example.com/entire.ts
 SIMPLE_PLAYLIST_FILENAME = abspath(join(dirname(__file__), 'playlists/simple-playlist.m3u8'))
 
 SIMPLE_PLAYLIST_URI = TEST_HOST + '/simple.m3u8'
+TIMEOUT_SIMPLE_PLAYLIST_URI = TEST_HOST + '/timeout_simple.m3u8'
 REDIRECT_PLAYLIST_URI = TEST_HOST + '/path/to/redirect_me'
 
+
 PLAYLIST_WITH_NON_INTEGER_DURATION = '''
 #EXTM3U
 #EXT-X-TARGETDURATION:5220.5
@@ -325,6 +327,41 @@ CUE_OUT_PLAYLIST = '''
 
 '''
 
+CUE_OUT_WITH_SCTE35_PLAYLIST = '''
+#EXTM3U
+#EXT-X-VERSION:3
+#EXT-X-TARGETDURATION:10
+#EXT-X-MEDIA-SEQUENCE:47224
+#EXTINF:10.000,
+master2500_47224.ts
+#EXTINF:10.000,
+master2500_47225.ts
+#EXTINF:2.040,
+master2500_47226.ts
+#EXT-OATCLS-SCTE35:/DAlAAAAAAAAAP/wFAUAAAABf+//wpiQkv4ARKogAAEBAQAAQ6sodg==
+#EXT-X-CUE-OUT:50.000
+#EXTINF:7.960,
+master2500_47227.ts
+#EXT-X-CUE-OUT-CONT:ElapsedTime=7.960,Duration=50,SCTE35=/DAlAAAAAAAAAP/wFAUAAAABf+//wpiQkv4ARKogAAEBAQAAQ6sodg==
+#EXTINF:10.000,
+master2500_47228.ts
+#EXT-X-CUE-OUT-CONT:ElapsedTime=17.960,Duration=50,SCTE35=/DAlAAAAAAAAAP/wFAUAAAABf+//wpiQkv4ARKogAAEBAQAAQ6sodg==
+#EXTINF:10.000,
+master2500_47229.ts
+#EXT-X-CUE-OUT-CONT:ElapsedTime=27.960,Duration=50,SCTE35=/DAlAAAAAAAAAP/wFAUAAAABf+//wpiQkv4ARKogAAEBAQAAQ6sodg==
+#EXTINF:10.000,
+master2500_47230.ts
+#EXT-X-CUE-OUT-CONT:ElapsedTime=37.960,Duration=50,SCTE35=/DAlAAAAAAAAAP/wFAUAAAABf+//wpiQkv4ARKogAAEBAQAAQ6sodg==
+#EXTINF:10.000,
+master2500_47231.ts
+#EXT-X-CUE-OUT-CONT:ElapsedTime=47.960,Duration=50,SCTE35=/DAlAAAAAAAAAP/wFAUAAAABf+//wpiQkv4ARKogAAEBAQAAQ6sodg==
+#EXTINF:2.040,
+master2500_47232.ts
+#EXT-X-CUE-IN
+#EXTINF:7.960,
+master2500_47233.ts
+'''
+
 MULTI_MEDIA_PLAYLIST = '''#EXTM3U
 #EXT-X-VERSION:3
 #EXT-X-MEDIA:URI="chinese/ed.ttml",TYPE=SUBTITLES,GROUP-ID="subs",LANGUAGE="zho",NAME="Chinese",AUTOSELECT=YES,FORCED=NO
diff --git a/tests/test_loader.py b/tests/test_loader.py
index 3bc6700..f53c517 100644
--- a/tests/test_loader.py
+++ b/tests/test_loader.py
@@ -101,3 +101,10 @@ def test_absolute_uri_should_handle_empty_base_uri_path():
     key = m3u8.model.Key(method='AES', uri='/key.bin', base_uri='http://example.com')
     assert 'http://example.com/key.bin' == key.absolute_uri
 
+def test_raise_timeout_exception_if_timeout_happens_when_loading_from_uri():
+    try:
+        obj = m3u8.load(playlists.TIMEOUT_SIMPLE_PLAYLIST_URI, timeout=1)
+    except:
+        assert True
+    else:
+        assert False
diff --git a/tests/test_model.py b/tests/test_model.py
index 344590d..2b68d31 100755
--- a/tests/test_model.py
+++ b/tests/test_model.py
@@ -65,6 +65,13 @@ def test_segment_cue_out_attribute():
     assert segments[2].cue_out == True
     assert segments[3].cue_out == False
 
+def test_segment_scte35_attribute():
+    obj = m3u8.M3U8(playlists.CUE_OUT_WITH_SCTE35_PLAYLIST)
+    segments = obj.segments
+    assert segments[4].cue_out == True
+    assert segments[9].cue_out == False
+    assert segments[4].scte35 == '/DAlAAAAAAAAAP/wFAUAAAABf+//wpiQkv4ARKogAAEBAQAAQ6sodg==' 
+
 def test_key_attribute():
     obj = m3u8.M3U8(playlists.SIMPLE_PLAYLIST)
     data = {'key': {'method': 'AES-128',
diff --git a/tests/test_parser.py b/tests/test_parser.py
index 9eeb50d..ef03b17 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -172,3 +172,10 @@ def test_should_parse_VERSION():
 def test_should_parse_program_date_time_from_playlist():
     data = m3u8.parse(playlists.SIMPLE_PLAYLIST_WITH_PROGRAM_DATE_TIME)
     assert cast_date_time('2014-08-13T13:36:33+00:00') == data['program_date_time']
+
+def test_should_parse_scte35_from_playlist():
+    data = m3u8.parse(playlists.CUE_OUT_WITH_SCTE35_PLAYLIST)
+    print(data)
+    assert '/DAlAAAAAAAAAP/wFAUAAAABf+//wpiQkv4ARKogAAEBAQAAQ6sodg==' == data['segments'][4]['scte35'] 
+    assert '50' == data['segments'][4]['scte35_duration']
+    

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-m3u8.git



More information about the Python-modules-commits mailing list