Mailinglist Archive: opensuse-commit (1903 mails)

< Previous Next >
commit python-pymediainfo for openSUSE:Factory
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 <aloisio@xxxxxxx>
+
+- 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")


< Previous Next >
This Thread
  • No further messages