Skip to content

Commit e14a0f0

Browse files
committed
add raise and logging of errors during parsing. also added tests to see correct errors are raised
1 parent 41f6c3a commit e14a0f0

3 files changed

Lines changed: 75 additions & 2 deletions

File tree

src/mpd_parser/exceptions.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ class UnicodeDeclaredError(Exception):
77
""" Raised when the XML has an encoding declaration in it's manifest and the parser did not remove it """
88
description = "xml has encoding declaration, lxml cannot process it"
99

10+
class UnknownValueError(Exception):
11+
""" Raised when the XML parsing fails on unexpected issue, check error for more information """
12+
description = "lxml failed to parse manifest, verify the input"
1013

1114
class UnknownElementTreeParseError(Exception):
1215
""" Raised after a etree parse operation fails on an unexpected error """

src/mpd_parser/parser.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,19 @@
22
Main module of the package, Parser class
33
"""
44

5+
import logging
56
from re import Match, sub
67
from urllib.request import urlopen
78

89
from lxml import etree
910

10-
from mpd_parser.exceptions import UnicodeDeclaredError, UnknownElementTreeParseError
11+
from mpd_parser.exceptions import UnicodeDeclaredError, UnknownElementTreeParseError, UnknownValueError
1112
from mpd_parser.models.composite_tags import MPD
1213

14+
# module level logger, application will configure formatting and handlers
15+
logger = logging.getLogger(__name__)
1316

17+
# Regular expression to match encoding declaration in XML
1418
ENCODING_PATTERN = r"<\?.*?\s(encoding=\"\S*\").*\?>"
1519

1620

@@ -48,7 +52,10 @@ def cut_and_burn(match: Match) -> str:
4852
except ValueError as err:
4953
if "Unicode" in err.args[0]:
5054
raise UnicodeDeclaredError() from err
55+
logger.exception("Failed to parse manifest string")
56+
raise UnknownValueError() from err
5157
except Exception as err:
58+
logger.exception("Failed to parse manifest string")
5259
raise UnknownElementTreeParseError() from err
5360
if encoding:
5461
return MPD(root, encoding=encoding[0].groups()[0])
@@ -69,7 +76,10 @@ def from_file(cls, manifest_file_name: str) -> MPD:
6976
except ValueError as err:
7077
if "Unicode" in err.args[0]:
7178
raise UnicodeDeclaredError() from err
79+
logger.exception("Failed to parse manifest file %s", manifest_file_name)
80+
raise UnknownValueError() from err
7281
except Exception as err:
82+
logger.exception("Failed to parse manifest file %s", manifest_file_name)
7383
raise UnknownElementTreeParseError() from err
7484
return MPD(tree.getroot())
7585

@@ -89,7 +99,10 @@ def from_url(cls, url: str) -> MPD:
8999
except ValueError as err:
90100
if "Unicode" in err.args[0]:
91101
raise UnicodeDeclaredError() from err
102+
logger.exception("Failed to parse manifest from URL %s", url)
103+
raise UnknownValueError() from err
92104
except Exception as err:
105+
logger.exception("Failed to parse manifest from URL %s", url)
93106
raise UnknownElementTreeParseError() from err
94107
return MPD(tree.getroot())
95108

tests/test_manifets.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
"""
22
Test the parsing of full manifests
33
"""
4+
import io
45
import os
56

6-
from pytest import mark
7+
from pytest import mark, raises
8+
from mpd_parser.exceptions import UnicodeDeclaredError, UnknownElementTreeParseError, UnknownValueError
79
from mpd_parser.parser import Parser
810

911
from tests.conftest import touch_attributes, MANIFESTS_DIR
1012

13+
class DummyFile(io.BytesIO):
14+
def __enter__(self):
15+
return self
16+
def __exit__(self, exc_type, exc_val, exc_tb):
17+
self.close()
18+
19+
def dummy_urlopen(url):
20+
return DummyFile(b"<MPD></MPD>")
21+
1122

1223
@mark.parametrize("input_file", [
1324
"./../manifests/bigBuckBunny-onDemend.mpd",
@@ -104,3 +115,49 @@ def test_to_string(input_file):
104115
0].range == \
105116
transformed_mpd.periods[0].adaptation_sets[0].representations[0].segment_bases[0].initializations[
106117
0].range
118+
119+
@mark.parametrize(
120+
"exception,patch_func",
121+
[
122+
(UnicodeDeclaredError, lambda: ValueError("Unicode something")),
123+
(UnknownValueError, lambda: ValueError("Some other value error")),
124+
(UnknownElementTreeParseError, lambda: RuntimeError("Some runtime error")),
125+
]
126+
)
127+
def test_from_string_error_handling(monkeypatch, exception, patch_func):
128+
def fake_parse(*args, **kwargs):
129+
raise patch_func()
130+
monkeypatch.setattr("mpd_parser.parser.etree.fromstring", fake_parse)
131+
with raises(exception):
132+
Parser.from_string("<MPD></MPD>")
133+
134+
@mark.parametrize(
135+
"exception,patch_func",
136+
[
137+
(UnicodeDeclaredError, lambda: ValueError("Unicode something")),
138+
(UnknownValueError, lambda: ValueError("Some other value error")),
139+
(UnknownElementTreeParseError, lambda: RuntimeError("Some runtime error")),
140+
]
141+
)
142+
def test_from_file_error_handling(monkeypatch, exception, patch_func):
143+
def fake_parse(*args, **kwargs):
144+
raise patch_func()
145+
monkeypatch.setattr("mpd_parser.parser.etree.parse", fake_parse)
146+
with raises(exception):
147+
Parser.from_file("dummy_file.mpd")
148+
149+
@mark.parametrize(
150+
"exception,patch_func",
151+
[
152+
(UnicodeDeclaredError, lambda: ValueError("Unicode something")),
153+
(UnknownValueError, lambda: ValueError("Some other value error")),
154+
(UnknownElementTreeParseError, lambda: RuntimeError("Some runtime error")),
155+
]
156+
)
157+
def test_from_url_error_handling(monkeypatch, exception, patch_func):
158+
def fake_parse(*args, **kwargs):
159+
raise patch_func()
160+
monkeypatch.setattr("mpd_parser.parser.etree.parse", fake_parse)
161+
monkeypatch.setattr("mpd_parser.parser.urlopen", dummy_urlopen)
162+
with raises(exception):
163+
Parser.from_url("http://dummy.url/manifest.mpd")

0 commit comments

Comments
 (0)