def setUp(self): """ Set up the unit tests with a StringElement class with some custom data (id: 0x4F40, value: 'bork'). """ self.mockStream = StringIO('\x4f\x40bork\x4f\x40bork') mide_schema = loadSchema('mide_ide.xml') matroska_schema = loadSchema('matroska.xml') eclass1 = type('StrEl1Element', (StringElement,), {'id':0x7c, 'name':'StrEl1', 'schema':mide_schema, '__slots__': StringElement.__slots__}) eclass2 = type('StrEl2Element', (StringElement,), {'id':0x7c, 'name':'StrEl2', 'schema':mide_schema, '__slots__': StringElement.__slots__}) eclass3 = type('StrEl3Element', (StringElement,), {'id':0x5e, 'name':'StrEl3', 'schema':matroska_schema, '__slots__': StringElement.__slots__}) self.strEl1 = eclass1(stream=self.mockStream, offset=0, size=4, payloadOffset=2) self.strEl2 = eclass2(stream=self.mockStream, offset=0, size=4, payloadOffset=2) self.strEl3 = eclass3(stream=self.mockStream, offset=0, size=8, payloadOffset=2) self.uniEl = UnicodeElement(stream=self.mockStream, offset=0, size=4, payloadOffset=2)
def setUp(self): """ Set up a Schema from mide_ide.xml and create a Document from an IDE file. """ self.schema = loadSchema('./ebmlite/schemata/mide_ide.xml') self.doc = self.schema.load('./tests/SSX46714-doesnot.IDE') self.stream = BytesIO(b'test')
def testIntEq(self): """ Test equality of IntegerElements. """ # Define buffers for IntegerElements m1 = StringIO('\x4f\x56\x71\xea') m2 = StringIO('abcd') m3 = StringIO('\x4f\x56\x71\xea') # Create IntegerElements mide_schema = loadSchema('mide_ide.xml') eclass1 = type('IntEl1Element', (IntegerElement,), {'id':0x7c, 'name':'IntEl1', 'schema':mide_schema, '__slots__': IntegerElement.__slots__}) eclass2 = type('IntEl2Element', (IntegerElement,), {'id':0x7c, 'name':'IntEl2', 'schema':mide_schema, '__slots__': IntegerElement.__slots__}) eclass3 = type('IntEl3Element', (IntegerElement,), {'id':0x7c, 'name':'IntEl3', 'schema':mide_schema, '__slots__': IntegerElement.__slots__}) intEl1 = eclass1(stream=m1, offset=0, size=4, payloadOffset=2) intEl2 = eclass2(stream=m2, offset=0, size=4, payloadOffset=2) intEl3 = eclass3(stream=m3, offset=0, size=4, payloadOffset=2) # Assert that the first two elements are not equal self.assertNotEqual(intEl1, intEl2) # Assert that the first and last elements are equal intEl1.stream.seek(0) intEl3.stream.seek(0) self.assertEqual(intEl1, intEl3)
def testCreateID(self): """ Test the EBML ID generation utility function. """ schema = core.loadSchema('matroska.xml') ranges = dict(A=(0x81, 0xFE), B=(0x407F, 0x7FFE), C=(0x203FFF, 0x3FFFFE), D=(0x101FFFFF, 0x1FFFFFFE)) # Test IDs not already in schema for idClass in ranges.keys(): ids = util.createID(schema, idClass, count=1000) self.assertTrue(all(eid not in schema for eid in ids), "createID() produced a used class %s ID" % idClass) self.assertRaises(KeyError, util.createID, schema, 'E') # Test exclusion of indicated IDs ids = util.createID(schema, 'A', count=100) ids2 = util.createID(schema, 'A', count=100, exclude=ids) self.assertTrue(len(ids2) == 0, "createID() failed to exclude specified IDs") # Test count restriction. # Note: May need changing if the Matroska schema is modified self.assertTrue(4 < len(util.createID(schema, 'A', count=5)) <= 5) # Test ID class range restrictions for idClass, (minId, maxId) in ranges.items(): m = min(util.createID(schema, idClass, minId=minId-50, count=100)) self.assertGreaterEqual(m, minId, "createID() generated out-of-range value ID for class %s: %s" % (idClass, m)) m = max(util.createID(schema, idClass, minId=maxId-50, count=100)) self.assertLessEqual(m, maxId, "createID() generated out-of-range value ID for class %s: %s" % (idClass, m))
def setUp(self): """ Set up the unit tests with a DateElement class with some custom data (id: -, value: 0x00 00 00 41). """ self.mockStream = BytesIO() self.mockStream.string = b'\x00\x00\x00A' mide_schema = loadSchema('mide_ide.xml') self.unkEl1 = UnknownElement(stream=self.mockStream, offset=1, size=4, payloadOffset=1, schema=mide_schema, eid=0x7c) self.unkEl2 = UnknownElement(stream=self.mockStream, offset=1, size=4, payloadOffset=1, schema=mide_schema, eid=0x7c) self.unkEl3 = UnknownElement(stream=self.mockStream, offset=1, size=4, payloadOffset=1, schema=mide_schema, eid=0x7d)
def testInfiniteElement(self): """ Test parsing an EBML file with an infinite-length element. """ schemaFile = './ebmlite/schemata/matroska.xml' ebmlFile1 = './tests/video-2.mkv' ebmlFile2 = './tests/video-3.mkv' schema = core.loadSchema(schemaFile) # Convert the MKV files into human-readable xml strings ebmlDoc1 = schema.load(ebmlFile1, headers=True) ebmlRoot1 = util.toXml(ebmlDoc1) xmlString1 = ET.tostring(ebmlRoot1, encoding='UTF-8').replace(b'><', b'>\r\n<') ebmlDoc2 = schema.load(ebmlFile2, headers=True) ebmlRoot2 = util.toXml(ebmlDoc2) xmlString2 = ET.tostring(ebmlRoot2, encoding='UTF-8').replace(b'><', b'>\r\n<') # Convert the xml strings into lists of lines to make comparison easier, # dropping the second line because that will reference different source # file names xmlLines1 = xmlString1.splitlines() xmlLines2 = xmlString2.splitlines() # Compare as lists to narrow the location of any differences self.assertListEqual(xmlLines1[1:], xmlLines2[1:], 'One or more lines are different in the xml documents')
def setUp(self): """ Set up the unit tests with a generic Element class with some custom data (id: 0x4F56, value: 0x71EA). """ # set element as: # id: 00 1111 0101 0110 # value: 11 0001 1110 1010 # header: 0100 1111 0101 0110 # data: 0111 0001 1110 1010 self.mockStream = BytesIO(b'\x4f\x56\x71\xea') GenericElement = type( 'GenericElement', (Element, ), { 'id': 0x4343, 'name': b'Generic Element', 'schema': loadSchema('./ebmlite/schemata/mide_ide.xml'), 'mandatory': False, 'multiple': False, 'precache': False, 'length': 4, 'children': dict(), '__doc__': b'no' }) self.element = GenericElement(stream=self.mockStream, offset=0, size=4, payloadOffset=2)
def setUp(self): """ Set up the unit tests with an IntegerElement class with some custom data (id: -, value: 0xFC18). """ # -1000 = -0b0000 0011 1110 1000 => # 0b1111 1100 0001 1000 => # 0xfc18 self.mockStream = BytesIO(b'\xfc\x18') mide_schema = loadSchema('mide_ide.xml') eclass1 = type( 'IntEl1Element', (IntegerElement, ), { 'id': 0x7c, 'name': b'IntEl1', 'schema': mide_schema, '__slots__': IntegerElement.__slots__ }) eclass2 = type( 'UIntEl1Element', (UIntegerElement, ), { 'id': 0x7c, 'name': b'UIntEl1', 'schema': mide_schema, '__slots__': UIntegerElement.__slots__ }) self.intEl1 = eclass1(stream=self.mockStream, offset=0, size=4, payloadOffset=2) self.uintEl1 = eclass2(stream=self.mockStream, offset=0, size=4, payloadOffset=2)
def setUp(self): """ Set up a new Schema. It is necessary to clear the cache to properly run tests. """ from ebmlite import core core.SCHEMATA = {} self.schema = loadSchema('./ebmlite/schemata/mide_ide.xml') self.stream = BytesIO(b'test')
def testMkv(self): """ Test the functionality of the ebmlite library by converting a known good MKV file (a derivative of EBML) back and forth, then compare the results. """ schemaFile = './ebmlite/schemata/matroska.xml' ebmlFile1 = './tests/video-1.mkv' ebmlFile2 = './tests/video-1-copy.mkv' xmlFile1 = './tests/video-1.xml' xmlFile2 = './tests/video-1-copy.xml' schema = core.loadSchema(schemaFile) # Start with toXml ebmlDoc1 = schema.load(ebmlFile1, headers=True) ebmlRoot = util.toXml(ebmlDoc1) xmlString1 = ET.tostring(ebmlRoot, encoding='UTF-8') # Save xml with open(xmlFile1, 'wt') as f: f.write(xmlString1.decode()) # Convert xml2ebml with open(ebmlFile2, 'wb') as out: util.xml2ebml(xmlFile1, out, schema) # write the second xml file ebmlDoc2 = schema.load(ebmlFile2, headers=True) mkvRoot2 = util.toXml(ebmlDoc2) xmlString2 = ET.tostring(mkvRoot2, encoding='UTF-8') # self.assertEqual(xmlString1, xmlString2, "xml strings aren't matching up") with open(xmlFile2, 'wt') as f: f.write(xmlString2.decode()) # Load back the XML files in order to compare the two xmlDoc1 = util.loadXml(xmlFile1, schema) xmlDoc2 = util.loadXml(xmlFile2, schema) # Compare each element from the XML xmlEls1 = [xmlDoc1] xmlEls2 = [xmlDoc2] while len(xmlEls1) > 0: self.assertEqual(xmlEls1[0], xmlEls2[0], 'Element ' + repr(xmlEls1[0]) + ' was not converted properly') for x in list(xmlEls1.pop(0).children.values()): if issubclass(x, core.Element): xmlEls1.append(x) for x in list(xmlEls2.pop(0).children.values()): if issubclass(x, core.Element): xmlEls2.append(x)
def testPPrint(self): """ Test pretty-printing EBML files. """ schemaFile = './ebmlite/schemata/mide_ide.xml' schema = core.loadSchema(schemaFile) ebmlDoc = schema.load('./tests/SSX46714-doesnot.IDE', headers=True) util.pprint(ebmlDoc, out=open('./tests/IDE-Pretty.txt', 'wt')) xmlString = ET.tostring(util.toXml(ebmlDoc)) prettyXmlFile = open('./tests/IDE-Pretty.xml', 'wt') parseString(xmlString).writexml(prettyXmlFile, addindent='\t', newl='\n', encoding='utf-8')
def setUp(self): """ Set up the unit tests with a FloatElement class with some custom data (id: 0x4F56, value: 0x3E AA AB). """ self.mockStream = StringIO('\x4f\x56\x3e\xaa\xaa\xab') mide_schema = loadSchema('mide_ide.xml') eclass1 = type('FloatEl1Element', (FloatElement,), {'id':0x7c, 'name':'FloatEl1', 'schema':mide_schema, '__slots__': FloatElement.__slots__}) self.floatEl = eclass1(stream=self.mockStream, offset=0, size=4, payloadOffset=2)
def testIde(self): """ Test the functionality of the ebmlite library by converting a known good IDE file (a derivative of EBML) back and forth, then compare the results. """ schemaFile = './ebmlite/schemata/mide_ide.xml' ebmlFile1 = './tests/SSX46714-doesnot.IDE' ebmlFile2 = './tests/SSX46714-new.IDE' xmlFile1 = './tests/ssx-1.xml' xmlFile2 = './tests/ssx-2.xml' schema = core.loadSchema(schemaFile) # Start with toXml ebmlDoc1 = schema.load(ebmlFile1, headers=True) ebmlRoot = util.toXml(ebmlDoc1) xmlString1 = ET.tostring(ebmlRoot, encoding='UTF-8') # Save xml with open(xmlFile1, 'wt') as f: f.write(xmlString1.replace('><', '>\r\n<')) # Convert xml2ebml with open(ebmlFile2, 'wb') as out: util.xml2ebml(xmlFile1, out, schema) # write the second xml file ebmlDoc2 = schema.load(ebmlFile2, headers=True) mkvRoot2 = util.toXml(ebmlDoc2) xmlString2 = ET.tostring(mkvRoot2, encoding='UTF-8') with open(xmlFile2, 'wt') as f: f.write(xmlString2.replace('><', '>\r\n<')) # Load back the XML files in order to compare the two xmlDoc1 = util.loadXml(xmlFile1, schema) xmlDoc2 = util.loadXml(xmlFile2, schema) # Compare each element from the XML xmlEls1 = [xmlDoc1] xmlEls2 = [xmlDoc2] while len(xmlEls1) > 0: self.assertEqual( xmlEls1[0], xmlEls2[0], 'Element ' + repr(xmlEls1[0]) + ' was not converted properly') for x in xmlEls1.pop(0).children.values(): if issubclass(x, core.Element): xmlEls1.append(x) for x in xmlEls2.pop(0).children.values(): if issubclass(x, core.Element): xmlEls2.append(x)
def setUp(self): """ Set up the unit tests with a DateElement class with some custom data (id: -, value: 0x00 00 00 41). """ self.mockStream = StringIO() self.mockStream.string = '\x00\x00\x00A' mide_schema = loadSchema('mide_ide.xml') eclass1 = type('VoidEl1Element', (VoidElement,), {'schema':mide_schema, id:0xEC, '__slots__': VoidElement.__slots__}) self.voiEl = eclass1(stream=self.mockStream, offset=1, size=4, payloadOffset=1)
def setUp(self): """ Set up a MasterElement with a single UIntegerElement child. """ schema = loadSchema('./ebmlite/schemata/mide_ide.xml') """ Master Element: ID: 0x1A45DFA3 Size: 0x84 Value: UInt Element: ID: 0x4286 Size: 0x81 value: 0x42 """ self.mockStream = BytesIO(b'\x1A\x45\xDF\xA3\x84\x42\x86\x81\x10') self.element = schema.elements[0x1A45DFA3](stream=self.mockStream, offset=0, size=4, payloadOffset=5)
# imports from python's built in xml library from xml.etree import ElementTree as ET from xml.dom.minidom import parseString # ======================================= # converting a file from EBML to XML # ======================================= # Files to use in this example schemaFile = './schemata/mide_ide.xml' ebmlFile1 = './tests/SSX46714-doesnot.IDE' xmlFile1 = './tests/example-xml.xml' # load the schema to use with these files. This creates an object that is used # to parse EBML files. schema = core.loadSchema(schemaFile) # Convert the EBML file to XML ebmlDoc1 = schema.load(ebmlFile1, headers=True) # load the file through # the schema ebmlRoot = toXml(ebmlDoc1) # convert the file into # a tree of XML elements xmlString1 = ET.tostring(ebmlRoot, encoding='UTF-8') # convert the xml tree # into a string # Save xml with open(xmlFile1, 'wt') as f: # convert the xml string into a minidom object and pretty-print f.write(parseString(xmlString1).toprettyxml(indent=' ')) # =======================================
def xml2ebml(xmlFile, ebmlFile, schema, sizeLength=None, headers=True, unknown=True): """ Convert an XML file to EBML. @todo: Convert XML on the fly, rather than parsing it first, allowing for the conversion of arbitrarily huge files. @param xmlFile: The XML source. Can be a filename, an open file-like stream, or a parsed XML document. @param ebmlFile: The EBML file to write. Can be a filename or an open file-like stream. @param schema: The EBML schema to use. Can be a filename or an instance of a `Schema`. @keyword sizeLength: The default length of each element's size descriptor. Must be large enough to store the largest 'master' element. If an XML element has a ``sizeLength`` attribute, it will override this. @keyword headers: If `True`, generate the standard ``EBML`` EBML element if the XML document does not contain one. @param unknown: If `True`, unknown element names will be allowed, provided their XML elements include an ``id`` attribute with the EBML ID (in hexadecimal). @return: the size of the ebml file in bytes. @raise NameError: raises if an xml element is not present in the schema. """ if isinstance(ebmlFile, str): ebmlFile = open(ebmlFile, 'wb') openedEbml = True else: openedEbml = False if not isinstance(schema, core.Schema): schema = core.loadSchema(schema) if isinstance(xmlFile, ET.Element): # Already a parsed XML element xmlRoot = xmlFile elif isinstance(xmlFile, ET.ElementTree): # Already a parsed XML document xmlRoot = xmlFile.getroot() else: xmlDoc = ET.parse(xmlFile) xmlRoot = xmlDoc.getroot() if xmlRoot.tag not in schema and xmlRoot.tag != schema.document.__name__: raise NameError("XML element %s not an element or document in " "schema %s (wrong schema)" % (xmlRoot.tag, schema.name)) headers = headers and 'EBML' in schema if headers and 'EBML' not in (el.tag for el in xmlRoot): pos = ebmlFile.tell() cls = schema.document ebmlFile.write(cls.encodePayload(cls._createHeaders())) numBytes = ebmlFile.tell() - pos else: numBytes = 0 if xmlRoot.tag == schema.document.__name__: for el in xmlRoot: numBytes += xmlElement2ebml(el, ebmlFile, schema, sizeLength, unknown=unknown) else: numBytes += xmlElement2ebml(xmlRoot, ebmlFile, schema, sizeLength, unknown=unknown) if openedEbml: ebmlFile.close() return numBytes
'--clobber', action="store_true", help="Clobber (overwrite) existing files.") argparser.add_argument('-p', '--pretty', action="store_true", help="Generate 'pretty' XML with ebml2xml.") args = argparser.parse_args() if not os.path.exists(args.input): sys.stderr.write("Input file does not exist: %s\n" % args.input) exit(1) try: schema = core.loadSchema(args.schema) except IOError as err: errPrint("Error loading schema: %s\n" % err) if args.output: output = os.path.realpath(os.path.expanduser(args.output)) if os.path.exists(output) and not args.clobber: errPrint("Output file exists: %s" % args.output) out = open(output, 'wb') else: out = sys.stdout if args.mode == "xml2ebml": xml2ebml(args.input, out, schema) # , sizeLength=4, headers=True, unknown=True) elif args.mode == "ebml2xml":