Hello community, here is the log from the commit of package python-pymediainfo for openSUSE:Factory checked in at 2019-04-23 14:36:10 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pymediainfo (Old) and /work/SRC/openSUSE:Factory/.python-pymediainfo.new.5536 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pymediainfo" Tue Apr 23 14:36:10 2019 rev:4 rq:696774 version:4.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pymediainfo/python-pymediainfo.changes 2018-09-13 12:14:06.514118215 +0200 +++ /work/SRC/openSUSE:Factory/.python-pymediainfo.new.5536/python-pymediainfo.changes 2019-04-23 14:36:13.533479678 +0200 @@ -1,0 +2,29 @@ +Mon Apr 22 13:56:26 UTC 2019 - Luigi Baldoni <[email protected]> + +- Update to version 4.0 + * Drop Python 2.6 compatibility + * Allow pickling of Track instances (#68) + * Remove xml attributes from Track and MediaInfo objects, + populate the tracks attribute immediately (03f6242) + * Implement __eq__ forTrack and MediaInfo objects + * Add an option to obtain MediaInfo's text output (#66) + * Add an option to return non-complete MediaInfo (#66) + * Disable LegacyStreamDisplay explicitly by default, make it + configurable (see 9aa65d8 for details) + version 3.2.1: + * Generate sdists on Linux instead of OSX (#67) + version 3.2: + * Publish wheels containing libmediainfo (#59, thanks to + @bgermann) + version 3.1: + * Add an option to control parsing speed (#65) + version 3.0: + * Do not ignore exceptions when invalid XML is passed (#53) + * Raise RuntimeError if parsing fails + * Add an option to ignore UTF-8 encoding errors, fixes (#54) + * Use proper XPath to detect track elements in XML (#55) + * Fix handling of non-existent files + * Fix tests with libmediainfo ≥ 18.08 (#58) + * Try to load libmediainfo from the module folder + +------------------------------------------------------------------- Old: ---- pymediainfo-2.3.0.tar.gz New: ---- pymediainfo-4.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pymediainfo.spec ++++++ --- /var/tmp/diff_new_pack.dXqGpK/_old 2019-04-23 14:36:14.057480027 +0200 +++ /var/tmp/diff_new_pack.dXqGpK/_new 2019-04-23 14:36:14.061480030 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-pymediainfo # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -12,13 +12,13 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-pymediainfo -Version: 2.3.0 +Version: 4.0 Release: 0 Summary: Python wrapper for the mediainfo library License: MIT ++++++ pymediainfo-2.3.0.tar.gz -> pymediainfo-4.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymediainfo-2.3.0/PKG-INFO new/pymediainfo-4.0/PKG-INFO --- old/pymediainfo-2.3.0/PKG-INFO 2018-05-14 16:15:37.000000000 +0200 +++ new/pymediainfo-4.0/PKG-INFO 2019-04-04 17:46:38.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: pymediainfo -Version: 2.3.0 +Version: 4.0 Summary: A Python wrapper for the mediainfo library. Home-page: https://github.com/sbraz/pymediainfo Author: Louis Sautier @@ -15,6 +15,9 @@ .. image:: https://img.shields.io/pypi/pyversions/pymediainfo.svg :target: https://pypi.org/project/pymediainfo + .. image:: https://repology.org/badge/tiny-repos/python:pymediainfo.svg + :target: https://repology.org/metapackage/python:pymediainfo + .. image:: https://img.shields.io/pypi/implementation/pymediainfo.svg :target: https://pypi.org/project/pymediainfo @@ -27,17 +30,17 @@ This small package is a wrapper around the MediaInfo library. - It works on Linux, Mac OS X and Windows and is tested with Python 2.6, 2.7, 3.4, 3.5, 3.6, PyPy and PyPy3. + It works on Linux, Mac OS X and Windows and is tested with Python 2.7, 3.4, 3.5, 3.6, 3.7, PyPy and PyPy3. See https://pymediainfo.readthedocs.io/ for more information. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable -Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Operating System :: POSIX :: Linux diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymediainfo-2.3.0/README.rst new/pymediainfo-4.0/README.rst --- old/pymediainfo-2.3.0/README.rst 2018-05-14 16:15:08.000000000 +0200 +++ new/pymediainfo-4.0/README.rst 2019-04-04 17:46:33.000000000 +0200 @@ -7,6 +7,9 @@ .. image:: https://img.shields.io/pypi/pyversions/pymediainfo.svg :target: https://pypi.org/project/pymediainfo +.. image:: https://repology.org/badge/tiny-repos/python:pymediainfo.svg + :target: https://repology.org/metapackage/python:pymediainfo + .. image:: https://img.shields.io/pypi/implementation/pymediainfo.svg :target: https://pypi.org/project/pymediainfo @@ -19,6 +22,6 @@ This small package is a wrapper around the MediaInfo library. -It works on Linux, Mac OS X and Windows and is tested with Python 2.6, 2.7, 3.4, 3.5, 3.6, PyPy and PyPy3. +It works on Linux, Mac OS X and Windows and is tested with Python 2.7, 3.4, 3.5, 3.6, 3.7, PyPy and PyPy3. See https://pymediainfo.readthedocs.io/ for more information. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymediainfo-2.3.0/appveyor.yml new/pymediainfo-4.0/appveyor.yml --- old/pymediainfo-2.3.0/appveyor.yml 2018-05-14 16:15:08.000000000 +0200 +++ new/pymediainfo-4.0/appveyor.yml 2019-04-04 17:46:33.000000000 +0200 @@ -1,26 +1,32 @@ environment: + MEDIAINFO_VERSION: 18.12 + TWINE_PASSWORD: + secure: /EO8CxTxhQVNsGNZZvU51jjHwPW524rgddNlwOAyLoA= matrix: - PYTHON: "C:/Python27" - PYTHON: "C:/Python34" - PYTHON: "C:/Python35" - PYTHON: "C:/Python36" + - PYTHON: "C:/Python37" - PYTHON: "C:/Python27-x64" - PYTHON: "C:/Python34-x64" - PYTHON: "C:/Python35-x64" - PYTHON: "C:/Python36-x64" + - PYTHON: "C:/Python37-x64" install: - "SET PATH=%PYTHON%;%PYTHON%/Scripts;%PATH%" - "python --version" - "IF %PYTHON:~-4% == -x64 (SET ARCH=x64) ELSE (SET ARCH=i386)" - - ps: "Start-FileDownload https://mediaarea.net/download/binary/mediainfo/18.05/MediaInfo_CLI_18.05_Windows_${Env:ARCH}.zip" - - ps: "unzip -o MediaInfo_CLI_18.05_Windows_${Env:ARCH}.zip" - - ps: "Start-FileDownload https://mediaarea.net/download/binary/libmediainfo0/18.05/MediaInfo_DLL_18.05_Windows_${Env:ARCH}_WithoutInstaller.7z" - - ps: "7z -y x MediaInfo_DLL_18.05_Windows_${Env:ARCH}_WithoutInstaller.7z" - - "pip install pytest" - # see https://phabricator.wikimedia.org/T186991 - # and https://github.com/wikimedia/pywikibot/commit/c503a9bb225933066f2b9f40b061b0279c7f6ad3 - - "IF %PYTHON:~0,11% == C:/Python34 (pip install pytest-runner==3.0) ELSE (pip install pytest-runner)" + - ps: "Start-FileDownload https://mediaarea.net/download/binary/mediainfo/${Env:MEDIAINFO_VERSION}/MediaInfo_CLI_${Env:MEDIAINFO_VERSION}_Windows_${Env:ARCH}.zip" + - ps: "unzip -o MediaInfo_CLI_${Env:MEDIAINFO_VERSION}_Windows_${Env:ARCH}.zip LIBCURL.DLL" + - ps: "Start-FileDownload https://mediaarea.net/download/binary/libmediainfo0/${Env:MEDIAINFO_VERSION}/MediaInfo_DLL_${Env:MEDIAINFO_VERSION}_Windows_${Env:ARCH}_WithoutInstaller.7z" + - ps: "7z -y x MediaInfo_DLL_${Env:MEDIAINFO_VERSION}_Windows_${Env:ARCH}_WithoutInstaller.7z MediaInfo.dll Developers/License.html" + - "move MediaInfo.dll pymediainfo" + - "move Developers\\License.html docs" + - "pip install --upgrade setuptools pytest pytest-runner twine wheel" build_script: - - "python setup.py build" + - "python setup.py bdist_wheel" test_script: - "python setup.py test" +deploy_script: + - ps: If ($env:APPVEYOR_REPO_TAG -eq "true") { Invoke-Expression "twine upload --skip-existing -u sbraz dist/*" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymediainfo-2.3.0/docs/conf.py new/pymediainfo-4.0/docs/conf.py --- old/pymediainfo-2.3.0/docs/conf.py 2018-05-14 16:15:08.000000000 +0200 +++ new/pymediainfo-4.0/docs/conf.py 2019-04-04 17:46:33.000000000 +0200 @@ -113,7 +113,10 @@ # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +html_theme_options = { + "page_width": "auto", + "fixed_sidebar": True +} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymediainfo-2.3.0/docs/index.rst new/pymediainfo-4.0/docs/index.rst --- old/pymediainfo-2.3.0/docs/index.rst 2018-05-14 16:15:08.000000000 +0200 +++ new/pymediainfo-4.0/docs/index.rst 2019-04-04 17:46:33.000000000 +0200 @@ -15,6 +15,10 @@ This is a simple wrapper around the MediaInfo library, which you can find at https://mediaarea.net/en/MediaInfo +Binary wheels containing the library are provided for Windows and Mac OS X. + +Packages are available for `several Linux distributions <https://repology.org/metapackage/python:pymediainfo>`_. + =============== Using MediaInfo =============== @@ -28,7 +32,7 @@ media_info = MediaInfo.parse('my_video_file.mov') for track in media_info.tracks: if track.track_type == 'Video': - print track.bit_rate, track.bit_rate_mode, track.codec + print(track.bit_rate, track.bit_rate_mode, track.codec) # output: 46033920 CBR DV @@ -56,12 +60,14 @@ media_info = MediaInfo.parse('my_video_file.mov') for track in media_info.tracks: if track.bit_rate is not None: - print "%s: %s" % (track.track_type, track.bit_rate) + print("{}: {}".format(track.track_type, track.bit_rate)) else: - print """%s tracks do not have bit rate - associated with them.""" % track.track_type + print("""{} tracks do not have bit rate + associated with them.""".format(track.track_type)) + +Output: -Output:: +.. code-block:: text General tracks do not have bit rate associated with them. Video: 46033920 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymediainfo-2.3.0/pymediainfo/__init__.py new/pymediainfo-4.0/pymediainfo/__init__.py --- old/pymediainfo-2.3.0/pymediainfo/__init__.py 2018-05-14 16:15:08.000000000 +0200 +++ new/pymediainfo-4.0/pymediainfo/__init__.py 2019-04-04 17:46:33.000000000 +0200 @@ -1,11 +1,12 @@ +# vim: set fileencoding=utf-8 : import os import re import locale import json +import ctypes import sys from pkg_resources import get_distribution, DistributionNotFound import xml.etree.ElementTree as ET -from ctypes import * try: import pathlib @@ -47,16 +48,21 @@ All available attributes can be obtained by calling :func:`to_data`. """ + def __eq__(self, other): + return self.__dict__ == other.__dict__ def __getattribute__(self, name): try: return object.__getattribute__(self, name) except: pass return None + def __getstate__(self): + return self.__dict__ + def __setstate__(self, state): + self.__dict__ = state def __init__(self, xml_dom_fragment): - self.xml_dom_fragment = xml_dom_fragment self.track_type = xml_dom_fragment.attrib['type'] - for el in self.xml_dom_fragment: + for el in xml_dom_fragment: node_name = el.tag.lower().strip().strip('_') if node_name == 'id': node_name = 'track_id' @@ -84,7 +90,7 @@ except: pass def __repr__(self): - return("<Track track_id='{0}', track_type='{1}'>".format(self.track_id, self.track_type)) + return("<Track track_id='{}', track_type='{}'>".format(self.track_id, self.track_type)) def to_data(self): """ Returns a dict representation of the track attributes. @@ -117,42 +123,87 @@ >>> pymediainfo.MediaInfo.parse("/path/to/file.mp4") Alternatively, objects may be created from MediaInfo's XML output. - XML output can be obtained using the `XML` output format on versions older than v17.10 - and the `OLDXML` format on newer versions. + Such output can be obtained using the ``XML`` output format on versions older than v17.10 + and the ``OLDXML`` format on newer versions. Using such an XML file, we can create a :class:`MediaInfo` object: >>> with open("output.xml") as f: ... mi = pymediainfo.MediaInfo(f.read()) - :param str xml: XML output obtained from MediaInfo - """ - def __init__(self, xml): - self.xml_dom = MediaInfo._parse_xml_data_into_dom(xml) + :param str xml: XML output obtained from MediaInfo. + :param str encoding_errors: option to pass to :func:`str.encode`'s `errors` + parameter before parsing `xml`. + :raises xml.etree.ElementTree.ParseError: if passed invalid XML. + :var tracks: A list of :py:class:`Track` objects which the media file contains. + For instance: - @staticmethod - def _parse_xml_data_into_dom(xml_data): - try: - return ET.fromstring(xml_data.encode("utf-8")) - except: - return None + >>> mi = pymediainfo.MediaInfo.parse("/path/to/file.mp4") + >>> for t in mi.tracks: + ... print(t) + <Track track_id='None', track_type='General'> + <Track track_id='1', track_type='Text'> + """ + def __eq__(self, other): + return self.tracks == other.tracks + def __init__(self, xml, encoding_errors="strict"): + xml_dom = ET.fromstring(xml.encode("utf-8", encoding_errors)) + self.tracks = [] + # This is the case for libmediainfo < 18.03 + # https://github.com/sbraz/pymediainfo/issues/57 + # https://github.com/MediaArea/MediaInfoLib/commit/575a9a32e6960ea34adb3bc982c64edfa06e95eb + if xml_dom.tag == "File": + xpath = "track" + else: + xpath = "File/track" + for xml_track in xml_dom.iterfind(xpath): + self.tracks.append(Track(xml_track)) @staticmethod def _get_library(library_file=None): os_is_nt = os.name in ("nt", "dos", "os2", "ce") - if library_file is not None: + if os_is_nt: + lib_type = ctypes.WinDLL + else: + lib_type = ctypes.CDLL + if library_file is None: if os_is_nt: - return WinDLL(library_file) + library_names = ("MediaInfo.dll",) + elif sys.platform == "darwin": + library_names = ("libmediainfo.0.dylib", "libmediainfo.dylib") else: - return CDLL(library_file) - elif os_is_nt: - return windll.MediaInfo - elif sys.platform == "darwin": + library_names = ("libmediainfo.so.0",) + script_dir = os.path.dirname(__file__) + # Look for the library file in the script folder + for library in library_names: + lib_path = os.path.join(script_dir, library) + if os.path.isfile(lib_path): + # If we find it, don't try any other filename + library_names = (lib_path,) + break + else: + library_names = (library_file,) + for i, library in enumerate(library_names, start=1): try: - return CDLL("libmediainfo.0.dylib") + lib = lib_type(library) + # Define arguments and return types + lib.MediaInfo_Inform.restype = ctypes.c_wchar_p + lib.MediaInfo_New.argtypes = [] + lib.MediaInfo_New.restype = ctypes.c_void_p + lib.MediaInfo_Option.argtypes = [ctypes.c_void_p, ctypes.c_wchar_p, ctypes.c_wchar_p] + lib.MediaInfo_Option.restype = ctypes.c_wchar_p + lib.MediaInfo_Inform.argtypes = [ctypes.c_void_p, ctypes.c_size_t] + lib.MediaInfo_Inform.restype = ctypes.c_wchar_p + lib.MediaInfo_Open.argtypes = [ctypes.c_void_p, ctypes.c_wchar_p] + lib.MediaInfo_Open.restype = ctypes.c_size_t + lib.MediaInfo_Delete.argtypes = [ctypes.c_void_p] + lib.MediaInfo_Delete.restype = None + lib.MediaInfo_Close.argtypes = [ctypes.c_void_p] + lib.MediaInfo_Close.restype = None + return lib except OSError: - return CDLL("libmediainfo.dylib") - else: - return CDLL("libmediainfo.so.0") + # If we've tried all possible filenames + if i == len(library_names): + raise @classmethod def can_parse(cls, library_file=None): """ @@ -166,7 +217,9 @@ except: return False @classmethod - def parse(cls, filename, library_file=None, cover_data=False): + def parse(cls, filename, library_file=None, cover_data=False, + encoding_errors="strict", parse_speed=0.5, text=False, + full=True, legacy_stream_display=False): """ Analyze a media file using libmediainfo. If libmediainfo is located in a non-standard location, the `library_file` parameter can be used: @@ -175,38 +228,46 @@ ... library_file="/path/to/libmediainfo.dylib") :param filename: path to the media file which will be analyzed. + A URL can also be used if libmediainfo was compiled + with CURL support. :param str library_file: path to the libmediainfo library, this should only be used if the library cannot be auto-detected. :param bool cover_data: whether to retrieve cover data as base64. + :param str encoding_errors: option to pass to :func:`str.encode`'s `errors` + parameter before parsing MediaInfo's XML output. + :param float parse_speed: passed to the library as `ParseSpeed`, + this option takes values between 0 and 1. + A higher value will yield more precise results in some cases + but will also increase parsing time. + :param bool text: if ``True``, MediaInfo's text output will be returned instead + of a :class:`MediaInfo` object. + :param bool full: display additional tags, including computer-readable values + for sizes and durations. + :param bool legacy_stream_display: display additional information about streams. :type filename: str or pathlib.Path - :rtype: MediaInfo + :rtype: str if `text` is ``True``. + :rtype: :class:`MediaInfo` otherwise. + :raises FileNotFoundError: if passed a non-existent file + (Python ≥ 3.3), does not work on Windows. + :raises IOError: if passed a non-existent file (Python < 3.3), + does not work on Windows. + :raises RuntimeError: if parsing fails, this should not + happen unless libmediainfo itself fails. """ lib = cls._get_library(library_file) if pathlib is not None and isinstance(filename, pathlib.PurePath): filename = str(filename) + url = False else: url = urlparse.urlparse(filename) - # Test whether the filename is actually a URL - if url.scheme is None: - # Test whether the file is readable - with open(filename, "rb"): - pass - # Define arguments and return types - lib.MediaInfo_Inform.restype = c_wchar_p - lib.MediaInfo_New.argtypes = [] - lib.MediaInfo_New.restype = c_void_p - lib.MediaInfo_Option.argtypes = [c_void_p, c_wchar_p, c_wchar_p] - lib.MediaInfo_Option.restype = c_wchar_p - lib.MediaInfo_Inform.argtypes = [c_void_p, c_size_t] - lib.MediaInfo_Inform.restype = c_wchar_p - lib.MediaInfo_Open.argtypes = [c_void_p, c_wchar_p] - lib.MediaInfo_Open.restype = c_size_t - lib.MediaInfo_Delete.argtypes = [c_void_p] - lib.MediaInfo_Delete.restype = None - lib.MediaInfo_Close.argtypes = [c_void_p] - lib.MediaInfo_Close.restype = None + # Try to open the file (if it's not a URL) + # Doesn't work on Windows because paths are URLs + if not (url and url.scheme): + # Test whether the file is readable + with open(filename, "rb"): + pass # Obtain the library version lib_version = lib.MediaInfo_Option(None, "Info_Version", "") - lib_version = tuple(int(_) for _ in re.search("^MediaInfoLib - v(\S+)", lib_version).group(1).split(".")) + lib_version = tuple(int(_) for _ in re.search("^MediaInfoLib - v(\\S+)", lib_version).group(1).split(".")) # The XML option was renamed starting with version 17.10 if lib_version >= (17, 10): xml_option = "OLDXML" @@ -225,38 +286,21 @@ if (sys.version_info < (3,) and os.name == "posix" and locale.getlocale() == (None, None)): locale.setlocale(locale.LC_CTYPE, locale.getdefaultlocale()) - lib.MediaInfo_Option(None, "Inform", xml_option) - lib.MediaInfo_Option(None, "Complete", "1") - lib.MediaInfo_Open(handle, filename) - xml = lib.MediaInfo_Inform(handle, 0) + lib.MediaInfo_Option(None, "Inform", "" if text else xml_option) + lib.MediaInfo_Option(None, "Complete", "1" if full else "") + lib.MediaInfo_Option(None, "ParseSpeed", str(parse_speed)) + lib.MediaInfo_Option(None, "LegacyStreamDisplay", "1" if legacy_stream_display else "") + if lib.MediaInfo_Open(handle, filename) == 0: + raise RuntimeError("An eror occured while opening {}" + " with libmediainfo".format(filename)) + output = lib.MediaInfo_Inform(handle, 0) # Delete the handle lib.MediaInfo_Close(handle) lib.MediaInfo_Delete(handle) - return cls(xml) - def _populate_tracks(self): - if self.xml_dom is None: - return - iterator = "getiterator" if sys.version_info < (2, 7) else "iter" - for xml_track in getattr(self.xml_dom, iterator)("track"): - self._tracks.append(Track(xml_track)) - @property - def tracks(self): - """ - A list of :py:class:`Track` objects which the media file contains. - - For instance: - - >>> mi = pymediainfo.MediaInfo.parse("/path/to/file.mp4") - >>> for t in mi.tracks: - ... print(t) - <Track track_id='None', track_type='General'> - <Track track_id='1', track_type='Text'> - """ - if not hasattr(self, "_tracks"): - self._tracks = [] - if len(self._tracks) == 0: - self._populate_tracks() - return self._tracks + if text: + return output + else: + return cls(output, encoding_errors) def to_data(self): """ Returns a dict representation of the object's :py:class:`Tracks <Track>`. @@ -269,7 +313,7 @@ return data def to_json(self): """ - Returns a json representation of the object's :py:class:`Tracks <Track>`. + Returns a JSON representation of the object's :py:class:`Tracks <Track>`. :rtype: str """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymediainfo-2.3.0/pymediainfo.egg-info/PKG-INFO new/pymediainfo-4.0/pymediainfo.egg-info/PKG-INFO --- old/pymediainfo-2.3.0/pymediainfo.egg-info/PKG-INFO 2018-05-14 16:15:37.000000000 +0200 +++ new/pymediainfo-4.0/pymediainfo.egg-info/PKG-INFO 2019-04-04 17:46:38.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: pymediainfo -Version: 2.3.0 +Version: 4.0 Summary: A Python wrapper for the mediainfo library. Home-page: https://github.com/sbraz/pymediainfo Author: Louis Sautier @@ -15,6 +15,9 @@ .. image:: https://img.shields.io/pypi/pyversions/pymediainfo.svg :target: https://pypi.org/project/pymediainfo + .. image:: https://repology.org/badge/tiny-repos/python:pymediainfo.svg + :target: https://repology.org/metapackage/python:pymediainfo + .. image:: https://img.shields.io/pypi/implementation/pymediainfo.svg :target: https://pypi.org/project/pymediainfo @@ -27,17 +30,17 @@ This small package is a wrapper around the MediaInfo library. - It works on Linux, Mac OS X and Windows and is tested with Python 2.6, 2.7, 3.4, 3.5, 3.6, PyPy and PyPy3. + It works on Linux, Mac OS X and Windows and is tested with Python 2.7, 3.4, 3.5, 3.6, 3.7, PyPy and PyPy3. See https://pymediainfo.readthedocs.io/ for more information. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable -Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Operating System :: POSIX :: Linux diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymediainfo-2.3.0/pymediainfo.egg-info/SOURCES.txt new/pymediainfo-4.0/pymediainfo.egg-info/SOURCES.txt --- old/pymediainfo-2.3.0/pymediainfo.egg-info/SOURCES.txt 2018-05-14 16:15:37.000000000 +0200 +++ new/pymediainfo-4.0/pymediainfo.egg-info/SOURCES.txt 2019-04-04 17:46:38.000000000 +0200 @@ -19,9 +19,12 @@ pymediainfo.egg-info/requires.txt pymediainfo.egg-info/top_level.txt tests/test_pymediainfo.py +tests/data/aac_he_v2.aac tests/data/accentué.txt tests/data/invalid.xml +tests/data/issue55.flv tests/data/sample.mkv tests/data/sample.mp4 tests/data/sample.xml -tests/data/sample_with_cover.mp3 \ No newline at end of file +tests/data/sample_with_cover.mp3 +tests/data/vbr_requires_parsespeed_1.mp4 \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymediainfo-2.3.0/setup.cfg new/pymediainfo-4.0/setup.cfg --- old/pymediainfo-2.3.0/setup.cfg 2018-05-14 16:15:37.000000000 +0200 +++ new/pymediainfo-4.0/setup.cfg 2019-04-04 17:46:38.000000000 +0200 @@ -12,6 +12,12 @@ [aliases] test = pytest +[tool:pytest] +addopts = -vv + +[bdist_wheel] +universal = 1 + [egg_info] tag_build = tag_date = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymediainfo-2.3.0/setup.py new/pymediainfo-4.0/setup.py --- old/pymediainfo-2.3.0/setup.py 2018-05-14 16:15:08.000000000 +0200 +++ new/pymediainfo-4.0/setup.py 2019-04-04 17:46:33.000000000 +0200 @@ -1,9 +1,36 @@ #!/usr/bin/env python +import os from setuptools import setup, find_packages with open("README.rst") as f: long_description = f.read() +data_files = [] +bin_files = [] +cmdclass = {} + +bin_license = 'docs/License.html' +if os.path.exists(bin_license): + data_files.append(('docs', [bin_license])) + bin_files.extend(['MediaInfo.dll', 'libmediainfo.*']) + try: + from wheel.bdist_wheel import bdist_wheel + + class platform_bdist_wheel(bdist_wheel): + def finalize_options(self): + bdist_wheel.finalize_options(self) + # Force the wheel to be marked as platform-specific + self.root_is_pure = False + def get_tag(self): + python, abi, plat = bdist_wheel.get_tag(self) + # The python code works for any Python version, + # not just the one we are running to build the wheel + return 'py2.py3', 'none', plat + + cmdclass['bdist_wheel'] = platform_bdist_wheel + except ImportError: + pass + setup( name='pymediainfo', author='Louis Sautier', @@ -16,17 +43,20 @@ include_package_data=True, zip_safe=False, license='MIT', + data_files=data_files, use_scm_version=True, setup_requires=["setuptools_scm"], install_requires=["setuptools"], tests_require=["pytest", "pytest-runner"], + package_data={'pymediainfo': bin_files}, + cmdclass=cmdclass, classifiers=[ "Development Status :: 5 - Production/Stable", - "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Operating System :: POSIX :: Linux", Binary files old/pymediainfo-2.3.0/tests/data/aac_he_v2.aac and new/pymediainfo-4.0/tests/data/aac_he_v2.aac differ Binary files old/pymediainfo-2.3.0/tests/data/issue55.flv and new/pymediainfo-4.0/tests/data/issue55.flv differ Binary files old/pymediainfo-2.3.0/tests/data/vbr_requires_parsespeed_1.mp4 and new/pymediainfo-4.0/tests/data/vbr_requires_parsespeed_1.mp4 differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymediainfo-2.3.0/tests/test_pymediainfo.py new/pymediainfo-4.0/tests/test_pymediainfo.py --- old/pymediainfo-2.3.0/tests/test_pymediainfo.py 2018-05-14 16:15:08.000000000 +0200 +++ new/pymediainfo-4.0/tests/test_pymediainfo.py 2019-04-04 17:46:33.000000000 +0200 @@ -3,11 +3,20 @@ import os import sys import unittest +import xml +import pickle import pytest from pymediainfo import MediaInfo +os_is_nt = os.name in ("nt", "dos", "os2", "ce") + +if sys.version_info < (3, 3): + FileNotFoundError = IOError +if sys.version_info < (3, 2): + unittest.TestCase.assertRegex = unittest.TestCase.assertRegexpMatches + data_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data") class MediaInfoTest(unittest.TestCase): @@ -46,12 +55,12 @@ with open(os.path.join(data_dir, 'invalid.xml'), 'r') as f: self.xml_data = f.read() def test_parse_invalid_xml(self): - mi = MediaInfo(MediaInfo._parse_xml_data_into_dom(self.xml_data)) - self.assertEqual(len(mi.tracks), 0) + self.assertRaises(xml.etree.ElementTree.ParseError, MediaInfo, self.xml_data) class MediaInfoLibraryTest(unittest.TestCase): def setUp(self): self.mi = MediaInfo.parse(os.path.join(data_dir, "sample.mp4")) + self.non_full_mi = MediaInfo.parse(os.path.join(data_dir, "sample.mp4"), full=False) def test_can_parse_true(self): self.assertTrue(MediaInfo.can_parse()) def test_track_count(self): @@ -60,10 +69,13 @@ self.assertEqual(self.mi.tracks[1].track_type, "Video") self.assertEqual(self.mi.tracks[2].track_type, "Audio") def test_track_details(self): - self.assertEqual(self.mi.tracks[1].codec, "AVC") - self.assertEqual(self.mi.tracks[2].codec, "AAC LC") + self.assertEqual(self.mi.tracks[1].format, "AVC") + self.assertEqual(self.mi.tracks[2].format, "AAC") self.assertEqual(self.mi.tracks[1].duration, 958) self.assertEqual(self.mi.tracks[2].duration, 980) + def test_full_option(self): + self.assertEqual(self.mi.tracks[0].footersize, "59") + self.assertEqual(self.non_full_mi.tracks[0].footersize, None) class MediaInfoUnicodeXMLTest(unittest.TestCase): def setUp(self): @@ -90,11 +102,21 @@ class MediaInfoPathlibTest(unittest.TestCase): def setUp(self): - pathlib = pytest.importorskip("pathlib") - self.path = pathlib.Path(data_dir) / "sample.mp4" + self.pathlib = pytest.importorskip("pathlib") def test_parse_pathlib_path(self): - mi = MediaInfo.parse(self.path) + path = self.pathlib.Path(data_dir) / "sample.mp4" + mi = MediaInfo.parse(path) self.assertEqual(len(mi.tracks), 3) + @pytest.mark.skipif(os_is_nt, reason="Windows paths are URLs") + def test_parse_non_existent_path_pathlib(self): + path = self.pathlib.Path(data_dir) / "this file does not exist" + self.assertRaises(FileNotFoundError, MediaInfo.parse, path) + +class MediaInfoTestParseNonExistentFile(unittest.TestCase): + @pytest.mark.skipif(os_is_nt, reason="Windows paths are URLs") + def test_parse_non_existent_path(self): + path = os.path.join(data_dir, "this file does not exist") + self.assertRaises(FileNotFoundError, MediaInfo.parse, path) class MediaInfoCoverDataTest(unittest.TestCase): def setUp(self): @@ -108,3 +130,54 @@ "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACXBIWXMAAAAAAA" "AAAQCEeRdzAAAADUlEQVR4nGP4x8DwHwAE/AH+QSRCQgAAAABJRU5ErkJggg==" ) + +class MediaInfoTrackParsingTest(unittest.TestCase): + def test_track_parsing(self): + mi = MediaInfo.parse(os.path.join(data_dir, "issue55.flv")) + self.assertEqual(len(mi.tracks), 2) + +class MediaInfoRuntimeErrorTest(unittest.TestCase): + def test_parse_invalid_url(self): + # This is the easiest way to cause a parsing error + # since non-existent files return a different exception + self.assertRaises(RuntimeError, MediaInfo.parse, + "unsupportedscheme://") + +class MediaInfoSlowParseTest(unittest.TestCase): + def setUp(self): + self.mi = MediaInfo.parse( + os.path.join(data_dir, "vbr_requires_parsespeed_1.mp4"), + parse_speed=1 + ) + def test_slow_parse_speed(self): + self.assertEqual(self.mi.tracks[2].stream_size, "3353 / 45") + +class MediaInfoEqTest(unittest.TestCase): + def setUp(self): + self.mp3_mi = MediaInfo.parse(os.path.join(data_dir, "sample_with_cover.mp3")) + self.mp3_other_mi = MediaInfo.parse(os.path.join(data_dir, "sample_with_cover.mp3")) + self.mp4_mi = MediaInfo.parse(os.path.join(data_dir, "sample.mp4")) + def test_eq(self): + self.assertEqual(self.mp3_mi.tracks[0], self.mp3_other_mi.tracks[0]) + self.assertEqual(self.mp3_mi, self.mp3_other_mi) + self.assertNotEqual(self.mp3_mi.tracks[0], self.mp4_mi.tracks[0]) + self.assertNotEqual(self.mp3_mi, self.mp4_mi) + def test_pickle_unpickle(self): + pickled_track = pickle.dumps(self.mp4_mi.tracks[0]) + self.assertEqual(self.mp4_mi.tracks[0], pickle.loads(pickled_track)) + pickled_mi = pickle.dumps(self.mp4_mi) + self.assertEqual(self.mp4_mi, pickle.loads(pickled_mi)) + +class MediaInfoTextOutputTest(unittest.TestCase): + def setUp(self): + self.mi = MediaInfo.parse(os.path.join(data_dir, "sample.mp4"), text=True) + def test_text_output(self): + self.assertRegex(self.mi, r"Stream size\s+: 373836\b") + +class MediaInfoLegacyStreamDisplayTest(unittest.TestCase): + def setUp(self): + self.mi = MediaInfo.parse(os.path.join(data_dir, "aac_he_v2.aac")) + self.legacy_mi = MediaInfo.parse(os.path.join(data_dir, "aac_he_v2.aac"), legacy_stream_display=True) + def test_legacy_stream_display(self): + self.assertEqual(self.mi.tracks[1].channel_s, 2) + self.assertEqual(self.legacy_mi.tracks[1].channel_s, "2 / 1 / 1")
