././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1690837173.550363 python-libdiscid-2.0.3/0000755000175100001730000000000014462020266014364 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/CHANGELOG.md0000644000175100001730000000657414462020247016210 0ustar00runnerdocker# Changelog ## 2.0.3 (2023-07-31) * Bump required Python version to 3.8. * Fix compatibility with Sphinx 7. ## 2.0.2 (2022-11-01) * Remove long deprecated `libdiscid.DEFAULT_DEVICE`. * Bump required Python version to 3.7. ## 2.0.1 (2021-02-11) * Fix `python_requires` in setup.cfg. A typo caused the information not to be included in PKG-INFO. ## 2.0 (2021-02-10) * Remove `compat` module for the 0.x style interface. * Add type annotations. * Internal changes: - Modernize build system: move build dependencies to `pyproject.toml`. - Use relative imports ## 1.2 (2021-01-24) * Bump required Python version to 3.6. * Replaced use of `unicode` with `str`. ## 1.1 (2019-11-10) * Remove support for Python 2. * Note Fedora package availability. Thanks to Ville Skyttä. * Fix the build without `pkgconfig` module. Thanks to Philipp Wolfer. ## 1.0 (2016-12-29) * Fix compatibility issues with Cython 0.23. * Add support for Python 3.4, 3.5, and 3.6. * Drop (active) support for Python 2.6, 3.2 and 3.3. This change only affects the test suite. * Fix various spelling mistakes. * Internal changes: - Use `pkgconfig` to detect discid. - Use Travis-CI. ## 0.4.1 (2014-01-03) * Fix typo in `test_read_not_implemented` test. * `libdiscid.compat.discid`: Add `toc_string property` for compatibility with python-discid 1.1.0. Thanks to Johannes Dewender. * Internal changes: - Move test data to common location for deduplication. ## 0.4 (2013-10-03) * Add support for libdiscid's `discid_get_toc_string` introduced in 0.6.0. * Add sectors_to_seconds to libdiscid. * Use shipped C source to build `libdiscid._discid` if Cython is not available. * Internal changes: - Release resources acquired from libdiscid earlier. After a successful read or put all the information is stored in the returned object and no further calls to libdiscid are necessary to access the data. ## 0.3.1 (2013-09-09) * Fix handling of `None` in `libdiscid.compat.discid.read`. ## 0.3 (2013-07-04) * The device used to read the data is now stored in `DiscId`'s device property. * Make `DiscError` available as `libdiscid.DiscError`. * `libdiscid.compat.discid`: - Fix features handling. - Try to decode devices with the filesystem's encoding and features with ascii on a best effort basis. - Thanks to Andreas Stührk for the hints. * Internal changes: - Move most of the API documentation from the rst files back to the code. - Name the extension module as `libdiscid._discid` and move some bits that don't require Cython away. ## 0.2.0 (2013-06-30) * Add `libdiscid.compat.discid` module that provides the same interface as the `discid` module from python-discid. This allows devlopers to write applications that work with both python-libdiscid and python-discid without much effort. * Deprecate `libdiscid.DEFAULT_DEVICE` in favor of `libdiscid.default_device`. The default device might change one some platforms during the runtime, so it should not be a constant. ## 0.1.2 (2013-05-09) * Fix issues with Cython 0.19. * Don't fail tests if MCN or ISCR is not available on the platform. ## 0.1.1 (2013-04-3) * Fix issues with symbol names if python-libdiscid was built against a libdiscid version prior to 0.5.0 and then used with 0.5.0. ## 0.1 (2013-04-11) * Initial release. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/LICENSE0000644000175100001730000000210714462020247015370 0ustar00runnerdockerCopyright (C) 2013-2023 Sebastian Ramacher Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/MANIFEST.in0000644000175100001730000000031114462020247016114 0ustar00runnerdockerinclude libdiscid/discid-wrapper.h include libdiscid/cdiscid.pxd libdiscid/_discid.pyx libdiscid/_discid.pyi libdiscid/py.typed include LICENSE README.md CHANGELOG.md recursive-include docs *.py *.rst ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1690837173.550363 python-libdiscid-2.0.3/PKG-INFO0000644000175100001730000000433214462020266015463 0ustar00runnerdockerMetadata-Version: 2.1 Name: python-libdiscid Version: 2.0.3 Summary: Python bindings for libdiscid Home-page: https://github.com/sebastinas/python-libdiscid Author: Sebastian Ramacher Author-email: sebastian@ramacher.at License: MIT Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Multimedia :: Sound/Audio :: CD Audio :: CD Ripping Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=3.8 Description-Content-Type: text/markdown License-File: LICENSE # libdiscid Python bindings python-libdiscid implements Python >= 3.6 bindings for libdiscid using Cython. ## Dependencies * libdiscid * Cython (>= 0.15, optional) * pkgconfig (optional) Note that the tarballs come with pre-built C source for the Cython module. So Cython is only required if one builds python-libdiscid from the git repository or if one wants to change anything in the Cython module. If pkgconfig is installed, setup.py uses libdiscid's pkg-config information to set include directories, libraries to link, etc. ## Quick installation guide python-libdiscid is available in some distributions: * Debian/Ubuntu: `apt-get install python3-libdiscid` (Python 3) * Fedora: `dnf install python3-libdiscid` (Python 3) python-libdiscid can be installed via `pip`: ``` $ pip install python-libdiscid ``` or by running: ``` $ python3 setup.py install ``` If you just want to try it locally, run: ``` $ python3 setup.py build_ext -i ``` and hack right away. You can also run: ``` $ python3 setup.py build ``` but please make sure that `build/lib.*` is in `sys.path` before the source folder. ## A note for Windows users There are eggs available from PyPI that don't require the extension module to be built. If these are used, it is still required to drop a working discid.dll in `C:\WINDOWS\system32` (or wherever it can be found). ## Usage ```python3 from libdiscid import read disc = read("/dev/cdrom") print("id: {}".format(disc.id)) ``` ## License python-libdiscid is released under the MIT license. Check LICENSE for details. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/README.md0000644000175100001730000000302314462020247015640 0ustar00runnerdocker# libdiscid Python bindings python-libdiscid implements Python >= 3.6 bindings for libdiscid using Cython. ## Dependencies * libdiscid * Cython (>= 0.15, optional) * pkgconfig (optional) Note that the tarballs come with pre-built C source for the Cython module. So Cython is only required if one builds python-libdiscid from the git repository or if one wants to change anything in the Cython module. If pkgconfig is installed, setup.py uses libdiscid's pkg-config information to set include directories, libraries to link, etc. ## Quick installation guide python-libdiscid is available in some distributions: * Debian/Ubuntu: `apt-get install python3-libdiscid` (Python 3) * Fedora: `dnf install python3-libdiscid` (Python 3) python-libdiscid can be installed via `pip`: ``` $ pip install python-libdiscid ``` or by running: ``` $ python3 setup.py install ``` If you just want to try it locally, run: ``` $ python3 setup.py build_ext -i ``` and hack right away. You can also run: ``` $ python3 setup.py build ``` but please make sure that `build/lib.*` is in `sys.path` before the source folder. ## A note for Windows users There are eggs available from PyPI that don't require the extension module to be built. If these are used, it is still required to drop a working discid.dll in `C:\WINDOWS\system32` (or wherever it can be found). ## Usage ```python3 from libdiscid import read disc = read("/dev/cdrom") print("id: {}".format(disc.id)) ``` ## License python-libdiscid is released under the MIT license. Check LICENSE for details. ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1690837173.550363 python-libdiscid-2.0.3/docs/0000755000175100001730000000000014462020266015314 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/docs/api.compat.rst0000644000175100001730000000041514462020247020100 0ustar00runnerdockerlibdiscid.compat package ^^^^^^^^^^^^^^^^^^^^^^^^ :mod:`discid` module ~~~~~~~~~~~~~~~~~~~~ The `discid` module provides the same interface as :py:mod:`discid`. Please have a look at its `documentation`__. .. __: https://python-discid.readthedocs.org/en/v1.0.2/api/ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/docs/api.rst0000644000175100001730000000026314462020247016617 0ustar00runnerdockerlibdiscid package ----------------- :mod:`libdiscid` module ^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: libdiscid :members: Subpackages ^^^^^^^^^^^ .. toctree:: api.compat ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/docs/conf.py0000644000175100001730000001330714462020247016616 0ustar00runnerdocker# python-libdiscid documentation build configuration file, created by # sphinx-quickstart on Thu Apr 11 14:36:37 2013. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os import distutils.command.build from distutils.dist import Distribution b = distutils.command.build.build(Distribution()) b.initialize_options() b.finalize_options() sys.path.insert(0, os.path.abspath(os.path.join("../", b.build_lib))) import libdiscid # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ["sphinx.ext.autodoc", "sphinx.ext.intersphinx"] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # The suffix of source filenames. source_suffix = ".rst" # The encoding of source files. source_encoding = "UTF-8" # The master toctree document. master_doc = "index" # General information about the project. project = "python-libdiscid" copyright = "2013-2023, Sebastian Ramacher" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = libdiscid.__version__ # The full version, including alpha/beta/rc tags. release = libdiscid.__version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = "alabaster" # 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 = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. html_show_sourcelink = False # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = "python-libdisciddoc" intersphinx_mapping = { "python": ("http://docs.python.org/", None), "pydiscid": ("https://python-discid.readthedocs.org/en/latest/", None), } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/docs/index.rst0000644000175100001730000000077714462020247017167 0ustar00runnerdockerpython-libdiscid |release| ========================== `python-libdiscid` provides Python 3 bindings for libdiscid_. `libdiscid`'s main purpose is the calculation of Disc ID for audio discs to use for the MusicBrainz_ database. `python-libdiscid` is released under the :ref:`MIT license `. Contents ^^^^^^^^ .. toctree:: installation usage misc api license Index ^^^^^ * :ref:`genindex` .. _libdiscid: https://musicbrainz.org/doc/libdiscid .. _MusicBrainz: http://musicbrainz.org ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/docs/installation.rst0000644000175100001730000000566514462020247020562 0ustar00runnerdockerInstallation ------------ Dependencies ^^^^^^^^^^^^ `python-libdiscid` depends on the following components: * libdiscid_ * `Cython`__ (>= 0.15) * `pkgconfig`__ Note that `Cython` is only required if one builds `python-libdiscid` from the repository. The released tarballs ship with pre-built C source files for the extension mdoules. If `pkgconfig` is installed, `setup.py` uses `libdiscid`'s `pkg-config` information to set include directories, libraries to link, etc. On Debian based systems, the dependencies are only an `apt-get` away:: apt-get install cython3 libdiscid-dev python3-pkgconfig `Cython` and `pkgconfig` are also available via `PyPI`__:: pip install cython pip install pkgconfig .. __: http://www.cython.org/ .. __: https://github.com/matze/pkgconfig .. __: https://pypi.python.org Known supported distributions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `python-libdiscid` is available in some distributions: * `Debian `_ * `Ubuntu `_ * `Fedora `_ PyPI ^^^^ `python-libdiscid` is available from `PyPI`__:: pip install python-libdiscid You can also download the tarball from `PyPI`__ manually, unpack it and run:: python setup.py install A note for Windows users ~~~~~~~~~~~~~~~~~~~~~~~~ There are eggs available from the same source too. With these eggs, the extension module comes pre-built. However, you still need to fetch `discid.dll` from libdiscid_ and copy the DLL to somewhere it can be found, e.g. to ``C:\WINDOWS\system32``. .. __: https://pypi.python.org/pypi/python-libdiscid/ .. __: https://pypi.python.org/pypi/python-libdiscid/ Building python-libdiscid locally ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If you just want to try `python-libdiscid` without installing, please note that per default `setuptools` will build the extension module in ``build/lib.*`` and doesn't copy it to ``libdiscid``. There are many possible ways to work with this limitation: * Running:: python3 setup.py build_ext -i will copy the extension modules to ``libdiscid`` and one can hack right away. * Use `setuptools` ``develop`` command. Please read `setuptools`'s `documentation`__ for further information. * If you build with ``python3 setup.py build``, It is also possible to put ``build/lib.*`` before the source directory of `python-libdiscid` in ``sys.path``. Assuming that `python-libdiscid` is built on a 64 bit Linux and for `Python` 3.4, one can use the following lines to achieve that:: import sys, os sys.path.insert(0, os.path.abspath('build/lib.linux-x86_64-3.4')) import libdiscid Please note that modification to any file in the ``libdiscid`` directory will only be available after another run of ``python setup.py build``. .. _libdiscid: https://musicbrainz.org/doc/libdiscid .. __: http://pythonhosted.org/distribute/setuptools.html#development-mode ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/docs/license.rst0000644000175100001730000000010414462020247017462 0ustar00runnerdocker.. _license: License ------- .. include:: ../LICENSE :literal: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/docs/misc.rst0000644000175100001730000000223714462020247017004 0ustar00runnerdockerMiscellaneous ------------- Bugs ^^^^ Please report bugs to the project's issue tracker at `GitHub`_. Supported libdiscid features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `python-libdiscid` supports all the features introduced by `libdiscid` up to version 0.6.0, that is: * retrieval of the disc's Media Catalogue Number and retrieving the International Standard Recording Code (ISRC) of the tracks if you are using `libdiscid` 0.4.0 and above. * selective reading support if you are using `libdiscid` 0.5.0 and above. * fuzzy TOC lookup if you are using `libdiscid` 0.6.0 and above. Please note that if `python-libdiscid` was built against versions of `libdiscid` prior to 0.4.0 or 0.5.0, `python-libdiscid` has to be rebuilt against the newer version to detect the features of the newer `libdiscid`. Other Python bindings ^^^^^^^^^^^^^^^^^^^^^ There are other Python bindings available. `python-discid`__ is the most prominent one. For a full list of bindings (including bindings for other languages) check libdiscid_. .. _GitHub: https://github.com/sebastinas/python-libdiscid .. _libdiscid: https://musicbrainz.org/doc/libdiscid .. __: https://github.com/JonnyJD/python-discid ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/docs/usage.rst0000644000175100001730000000473114462020247017156 0ustar00runnerdockerUsage ----- Disc ID computation from a disc ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :func:`libdiscid.read` provides everything needed to read the information from a disc and compute the disc id:: from libdiscid import read disc = read() print("id: {}".format(disc.id)) If no additional arguments are passed to :func:`libdiscid.read`, it will read from :func:`libdiscid.default_device`. If reading is not supported on your platform, :py:exc:`NotImplementedError` will be raised. If anything goes wrong while reading from the device, :exc:`libdiscid.DiscError` will be raised. To read from a different device than the default one, you can set ``device`` accordingly:: from libdiscid import read disc = read(device=u'/dev/cdrom1') print("id: {}".format(disc.id)) Starting with `libdiscid` 0.5.0, it is possible to explicitly state what should be read. For example, to read the MCN, one would use:: from libdiscid import read, FEATURE_MCN disc = read(features=FEATURE_MCN) # disc.id will be available print("id: {}".format(disc.id)) # if the disc has a MCN and libdiscid is 0.4.0 or later and libdiscid # supports reading the MCN on this platform, disc.mcn will be non-empty. try: print("MCN: {}".format(disc.mcn)) except NotImplementedError: print("MCN reading not supported on this platform/with this libdiscid") If you only want to get the disc id and do not care about the MCN and the ISCRs, you can tell that to :func:`libdiscid.read` by passing ``0`` or :data:`libdiscid.FEATURE_READ` to ``features``:: from libdiscid import read disc = read(features=0) Disc ID computation from data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :func:`libdiscid.put` can be used to compute the disc ID based on the first and last track, the number of total sectors and track offsets:: from libdiscid import put disc = put(first_track, last_track, num_sectors, offsets) print("id: {}".format(disc.id)) Please note that :attr:`libdiscid.DiscId.mcn` and :attr:`libdiscid.DiscId.track_isrcs` will be empty after a call to :func:`libdiscid.put`. python-discid compat module ^^^^^^^^^^^^^^^^^^^^^^^^^^^ :mod:`libdiscid.compat.discid` provides the same API as :py:mod:`discid` from `python-discid` version 1.0.2. This allows applications to only care about one API and be usable with either of `python-libdiscid` or `python-discid` installed. Just use the following code to import the module:: try: from libdiscid.compat import discid except ImportError: import discid and then use the :py:mod:`discid` interface. ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1690837173.550363 python-libdiscid-2.0.3/libdiscid/0000755000175100001730000000000014462020266016312 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/__init__.py0000644000175100001730000002320014462020247020417 0ustar00runnerdocker# Copyright 2013-2023 Sebastian Ramacher # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. """Python bindings for libdiscid libdiscid is a library to calculate MusicBrainz Disc IDs. This module provides Python-bindings for libdiscid. >>> disc = libdiscid.read() >>> disc.id is not None True """ from . import _discid from .exceptions import DiscError from typing import Optional, Union, List, Tuple import re import warnings __version__ = "2.0.3" __author__ = "Sebastian Ramacher" __license__ = "MIT" __copyright__ = f"(C) 2013-2023 {__author__}" FEATURES = _discid.FEATURES """Tuple of all available features supported by libdiscid on this platform. """ FEATURE_READ = _discid.FEATURE_READ """Read the TOC of the disc to get the disc ID. This feature is always enabled. """ FEATURE_MCN = _discid.FEATURE_MCN """Read the Media Catalogue Number of the disc. """ FEATURE_ISRC = _discid.FEATURE_ISRC """Read International Standard Recording Codes (ISRC) of all the tracks. """ FEATURES_MAPPING = _discid.FEATURES_MAPPING """Mapping between the constants representing a feature and their string representation. """ __discid_version__ = _discid.__discid_version__ """The version of the underlying libdiscid. """ class DiscId: """Disc information Class holding all the information obtained from a disc. """ def __init__(self, cdiscid: _discid.DiscId) -> None: self._id = cdiscid.id self._freedb_id = cdiscid.freedb_id self._submission_url = cdiscid.submission_url self._webservice_url = cdiscid.webservice_url self._first_track = cdiscid.first_track self._last_track = cdiscid.last_track self._sectors = cdiscid.sectors self._track_offsets = cdiscid.track_offsets self._track_lengths = cdiscid.track_lengths self._mcn = cdiscid.mcn self._track_isrcs = cdiscid.track_isrcs self._device = cdiscid.device self._toc = cdiscid.toc @property def id(self) -> str: """The MusicBrainz Disc ID.""" return self._id @property def freedb_id(self) -> str: """The FreeDB Disc ID (without category).""" return self._freedb_id @property def submission_url(self) -> str: """Disc ID / TOC Submission URL for MusicBrainz With this url you can submit the current TOC as a new MusicBrainz Disc ID. """ return self._submission_url @property def webservice_url(self) -> str: """The web service URL for info about the CD With this url you can retrieve information about the CD in XML from the MusicBrainz web service. """ warnings.warn( "webservice_url is deprecated since it points to the old " "webservice. Please use python-musicbrainz-ngs to access " "the webservice.", DeprecationWarning, ) return self._webservice_url @property def first_track(self) -> int: """Number of the first audio track.""" return self._first_track @property def last_track(self) -> int: """Number of the last audio track.""" return self._last_track @property def sectors(self) -> int: """Total sector count.""" return self._sectors @property def leadout_track(self) -> int: """Leadout track.""" return self.sectors @property def track_offsets(self) -> Tuple[int]: """Tuple of all track offsets (in sectors). The first element corresponds to the offset of the track denoted by :attr:`first_track` and so on. """ return self._track_offsets @property def pregap(self) -> int: """Pregap of the first track (in sectors).""" return self.track_offsets[0] @property def track_lengths(self) -> Tuple[int]: """Tuple of all track lengths (in sectors). The first element corresponds to the length of the track denoted by :attr:`first_track` and so on. """ return self._track_lengths @property def mcn(self) -> str: """Media Catalogue Number of the disc. :raises NotImplementedError: reading MCN is not supported on this platform """ if self._mcn is None: raise NotImplementedError( "MCN is not available with this version " "of libdiscid and/or platform" ) return self._mcn @property def track_isrcs(self) -> Tuple[str]: """Tuple of ISRCs of all tracks. The first element of the list corresponds to the ISRC of the :attr:`first_track` and so on. :raises NotImplementedError: reading ISRCs is not supported on this platform """ if self._track_isrcs is None: raise NotImplementedError( "ISRC is not available with this version " "of libdiscid and/or platform" ) return self._track_isrcs @property def device(self) -> Optional[str]: """The device the data was read from. If it is ``None``, :func:`libdiscid.put` was called to create the instance. """ return self._device @property def toc(self) -> str: """String representing the CD's Table of Contents (TOC). :raises ValueError: extracting TOC string from the submission URL failed """ if self._toc is None: # extract TOC string from submission URL match = re.match(r".*toc=([0-9+]+)$", self.submission_url) if match is None: raise ValueError("Failed to extract TOC from submission URL") self._toc = match.group(1).replace("+", " ") return self._toc def read(device: Optional[Union[str, bytes]] = None, features: Optional[int] = None): """Reads the TOC from the device given as string. If *device* is ``None``, :func:`default_device` is used to determine the device. *features* can be any combination of :data:`FEATURE_MCN` and :data:`FEATURE_ISRC` and :data:`FEATURE_READ`. Note that prior to libdiscid version 0.5.0 *features* has no effect and that :data:`FEATURE_READ` is always assumed, even if not given. :param device: device to read from :type device: unicode or None :param features: selected features, possible values are :data:`FEATURE_READ` \ :data:`FEATURE_MCN`, :data:`FEATURE_ISRC` and any of these values combined \ with bitwise or. :type features: integer or None :raises libdiscid.DiscError: reading the disc failed :raises NotImplementedError: reading discs is not supported :raises MemoryError: failed to allocate the internal DiscId object :rtype: :class:`DiscId` object """ disc = _discid.DiscId() if features is None: disc.read(device) else: disc.read(device, features) return DiscId(disc) def put( first: int, last, sectors: int, offsets: Union[List[int], Tuple[int]] ) -> DiscId: """Creates a TOC based on the given offsets. Takes the *first* and *last* audio track, as well as the number of *sectors* and a list of *offsets* as in :attr:`track_offsets`. :param first: number of the first audio track :type first: integer :param last: number of the last audio track :type last: integer :param sectors: total number of sectors on the disc :type sectors: integer :param offsets: offsets of each track :type offsets: list or tuple of integers :raises libdiscid.DiscError: operation failed for some reason :raises MemoryError: failed to allocated memory to store the offsets or the \ internal DiscId object :rtype: :class:`DiscId` object """ disc = _discid.DiscId() disc.put(first, last, sectors, offsets) return DiscId(disc) def default_device() -> str: """The default device on this platform. The default device can change during the run-time of the program. This can happen with removable devices for example. :rtype: str """ return _discid.default_device() def sectors_to_seconds(sectors: int) -> int: """Convert sectors to seconds rounded to the nearest second. :param sectors: number of sectors :type sectors: integer :rtype: integer """ SECTORS_PER_SECOND = 75 remainder = sectors % SECTORS_PER_SECOND return sectors // SECTORS_PER_SECOND + ( 1 if remainder > SECTORS_PER_SECOND // 2 else 0 ) __all__ = ( "read", "put", "default_device", "sectors_to_seconds", "__version__", "__discid_version__", "FEATURES", "FEATURES_MAPPING", "FEATURE_READ", "FEATURE_MCN", "FEATURE_ISRC", "DEFAULT_DEVICE", "DiscId", "DiscError", ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/_discid.pyi0000644000175100001730000000440314462020247020433 0ustar00runnerdocker# Copyright 2013-2021 Sebastian Ramacher # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. from typing import Optional, Union, List, Tuple, Mapping class DiscId: def __init__(self) -> None: ... def read(self, device: Optional[Union[str, bytes]], features: int = 0) -> None: ... def put( self, first: int, last: int, sectors: int, offsets: Union[List[int], Tuple[int]] ) -> None: ... @property def id(self) -> str: ... @property def freedb_id(self) -> str: ... @property def submission_url(self) -> str: ... @property def webservice_url(self) -> str: ... @property def first_track(self) -> int: ... @property def last_track(self) -> int: ... @property def sectors(self) -> int: ... @property def track_offsets(self) -> Tuple[int]: ... @property def track_lengths(self) -> Tuple[int]: ... @property def mcn(self) -> str: ... @property def track_isrcs(self) -> Tuple[str]: ... @property def device(self) -> Optional[str]: ... @property def toc(self) -> Optional[str]: ... def default_device() -> str: ... FEATURES_MAPPING: Mapping[int, str] FEATURES: Tuple[str] FEATURE_READ: int FEATURE_MCN: int FEATURE_ISRC: int __discid_version__: str ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/_discid.pyx0000644000175100001730000002104514462020247020453 0ustar00runnerdocker# Copyright 2013-2021 Sebastian Ramacher # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # cython: language_level=3, warn.unused=True from . cimport cdiscid cimport cpython from libc cimport limits from libc.stdlib cimport malloc, free from cpython cimport bool from libdiscid.exceptions import DiscError cdef bool _has_feature(int feature): return cdiscid.wrap_has_feature(feature) == 1 cdef str _to_str(char* s): return s.decode('UTF-8', 'strict') cdef class DiscId: """Class to calculate MusicBrainz Disc IDs. >>> d = DiscId() >>> d.read() >>> d.id is not None True Note that all the properties are only set after an successful call to :func:`DiscId.read` or :func:`DiscId.put`. """ cdef cdiscid.DiscId *_c_discid cdef bool _have_read cdef str _device def __cinit__(self): self._c_discid = cdiscid.discid_new() if self._c_discid is NULL: raise MemoryError('Failed to allocate DiscId object') self._have_read = False self._device = None def __dealloc__(self): if self._c_discid is not NULL: cdiscid.discid_free(self._c_discid) cdef _read(self, char* device, unsigned int features): if not _has_feature(cdiscid.DISCID_FEATURE_READ): raise NotImplementedError( "read is not available with this version of libdiscid and/or platform" ) if not cdiscid.wrap_read_sparse(self._c_discid, device, features): raise DiscError(self._get_error_msg()) self._have_read = True def read(self, str device=None, unsigned int features=limits.UINT_MAX): """Reads the TOC from the device given as string. If *device* is ``None``, :func:`libdiscid.default_device` is used. *features* can be any combination of :data:`FEATURE_MCN` and :data:`FEATURE_ISRC` and :data:`FEATURE_READ`. Note that prior to libdiscid version 0.5.0 *features* has no effect and that :data:`FEATURE_READ` is always assumed, even if not given. A :exc:`libdiscid.DiscError` exception is raised when reading fails, and :py:exc:`NotImplementedError` when libdiscid does not support reading discs on the current platform. """ if device is None: device = default_device() py_byte_device = device.encode('UTF-8') cdef char* cdevice = py_byte_device self._read(cdevice, features) self._device = device cdef _put(self, int first, int last, int* offsets): if not cdiscid.discid_put(self._c_discid, first, last, offsets): raise DiscError(self._get_error_msg()) self._device = None self._have_read = True def put(self, int first, int last, int sectors, offsets): """Creates a TOC based on the given offsets. Takes the *first* and *last* audio track, as well as the number of *sectors* and a list of *offsets* as in :attr:`DiscId.track_offsets`. If the operation fails for some reason, a :exc:`libdiscid.DiscError` exception is raised. """ cdef int* coffsets = malloc((len(offsets) + 1) * sizeof(int)) if coffsets is NULL: raise MemoryError('Failed to allocate memory to store offsets') try: coffsets[0] = sectors for (i, v) in enumerate(offsets): coffsets[i + 1] = v return self._put(first, last, coffsets) finally: free(coffsets) cdef str _get_error_msg(self): return _to_str(cdiscid.discid_get_error_msg(self._c_discid)) @property def id(self): """The MusicBrainz Disc ID. """ return _to_str(cdiscid.discid_get_id(self._c_discid)) @property def freedb_id(self): """The FreeDB Disc ID (without category). """ return _to_str(cdiscid.discid_get_freedb_id(self._c_discid)) @property def submission_url(self): """Disc ID / TOC Submission URL for MusicBrainz With this url you can submit the current TOC as a new MusicBrainz Disc ID. """ return _to_str(cdiscid.discid_get_submission_url(self._c_discid)) @property def webservice_url(self): """The web service URL for info about the CD With this url you can retrieve information about the CD in XML from the MusicBrainz web service. """ return _to_str(cdiscid.discid_get_webservice_url(self._c_discid)) @property def first_track(self): """Number of the first audio track. """ return cdiscid.discid_get_first_track_num(self._c_discid) @property def last_track(self): """Number of the last audio track. """ return cdiscid.discid_get_last_track_num(self._c_discid) @property def sectors(self): """Total sector count. """ return cdiscid.discid_get_sectors(self._c_discid) @property def track_offsets(self): """Tuple of all track offsets (in sectors). The first element corresponds to the offset of the track denoted by :attr:`first_track` and so on. """ return tuple( cdiscid.discid_get_track_offset(self._c_discid, track) for track in range(self.first_track, self.last_track + 1) ) @property def track_lengths(self): """Tuple of all track lengths (in sectors). The first element corresponds to the length of the track denoted by :attr:`first_track` and so on. """ return tuple( cdiscid.discid_get_track_length(self._c_discid, track) for track in range(self.first_track, self.last_track + 1) ) @property def mcn(self): """Media Catalogue Number of the disc. """ if not _has_feature(cdiscid.DISCID_FEATURE_MCN): return None return _to_str(cdiscid.wrap_get_mcn(self._c_discid)) @property def track_isrcs(self): """Tuple of ISRCs of all tracks. The first element of the list corresponds to the ISRC of the :attr:`first_track` and so on. """ if not _has_feature(cdiscid.DISCID_FEATURE_ISRC): return None return tuple( _to_str(cdiscid.wrap_get_track_isrc(self._c_discid, track)) for track in range(self.first_track, self.last_track + 1) ) @property def device(self): """The device the data was read from. If it is ``None``, :func:`libdiscid.put` was called to create the instance. """ return self._device @property def toc(self): """String representing the CD's Table of Contents (TOC). """ assert self._have_read cdef char* tocstr = cdiscid.wrap_get_toc(self._c_discid) if tocstr is not NULL: return _to_str(tocstr) return None FEATURES_MAPPING = { cdiscid.DISCID_FEATURE_READ: _to_str(cdiscid.DISCID_FEATURE_STR_READ), cdiscid.DISCID_FEATURE_MCN: _to_str(cdiscid.DISCID_FEATURE_STR_MCN), cdiscid.DISCID_FEATURE_ISRC: _to_str(cdiscid.DISCID_FEATURE_STR_ISRC) } cdef _feature_list(): return tuple(s for f, s in FEATURES_MAPPING.items() if _has_feature(f)) def default_device(): """The default device on this platform. """ return _to_str(cdiscid.discid_get_default_device()) FEATURES = _feature_list() FEATURE_READ = cdiscid.DISCID_FEATURE_READ FEATURE_MCN = cdiscid.DISCID_FEATURE_MCN FEATURE_ISRC = cdiscid.DISCID_FEATURE_ISRC __discid_version__ = _to_str(cdiscid.wrap_get_version_string()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/cdiscid.pxd0000644000175100001730000000445314462020247020436 0ustar00runnerdocker# Copyright 2013-2021 Sebastian Ramacher # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. from libc.string cimport const_char cdef extern from "discid-wrapper.h": ctypedef void* DiscId DiscId* discid_new() void discid_free(DiscId* d) int wrap_read_sparse(DiscId *d, const_char* device, unsigned int features) int discid_put(DiscId *d, int first, int last, int *offsets) char *discid_get_error_msg(DiscId *d) char *discid_get_id(DiscId *d) char *discid_get_freedb_id(DiscId *d) char *discid_get_submission_url(DiscId *d) char *discid_get_webservice_url(DiscId *d) char *discid_get_default_device() int discid_get_first_track_num(DiscId *d) int discid_get_last_track_num(DiscId *d) int discid_get_sectors(DiscId *d) int discid_get_track_offset(DiscId *d, int track_num) int discid_get_track_length(DiscId *d, int track_num) cdef enum discid_feature: DISCID_FEATURE_READ DISCID_FEATURE_MCN DISCID_FEATURE_ISRC char* DISCID_FEATURE_STR_READ char* DISCID_FEATURE_STR_MCN char* DISCID_FEATURE_STR_ISRC int wrap_has_feature(int feature) char* wrap_get_version_string() char* wrap_get_mcn(DiscId *d) char* wrap_get_track_isrc(DiscId *d, int track_num) char* wrap_get_toc(DiscId *d) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1690837173.550363 python-libdiscid-2.0.3/libdiscid/compat/0000755000175100001730000000000014462020266017575 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/compat/__init__.py0000644000175100001730000000000014462020247021673 0ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/compat/discid.py0000644000175100001730000001430114462020247021404 0ustar00runnerdocker# Copyright 2013-2021 Sebastian Ramacher # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. """python-discid compat layer This module provides a compatible layer so that python-libdiscid can be used as a replacement for python-discid. It provides an interface compatible with python-discid version 1.0.2. """ import libdiscid import operator import functools import sys _INVERSE_FEATURES = { libdiscid.FEATURES_MAPPING[libdiscid.FEATURE_READ]: libdiscid.FEATURE_READ, libdiscid.FEATURES_MAPPING[libdiscid.FEATURE_MCN]: libdiscid.FEATURE_MCN, libdiscid.FEATURES_MAPPING[libdiscid.FEATURE_ISRC]: libdiscid.FEATURE_ISRC, } class _NoneHelper: def __getattr__(self, name): if name in ( "id", "freedb_id", "submission_url", "toc", "first_track", "last_track", "sectors", "mcn", ): return None return super().__getattr__(name) def _decode(string, encoding=None): # Let's do the same thing discid is doing. It always accepts both strings and # bytes objects and encodes/decodes them as it sees fit. libdiscid always # wants string objects, so let's decode it here on a best effort basis. if not isinstance(string, str): if encoding is None: encoding = sys.getfilesystemencoding() or "ascii" return string.decode(encoding) return string # exceptions defined in discid DiscError = libdiscid.DiscError class TOCError(Exception): pass # classes defined in discid class Track: def __init__(self, disc, number): self.disc = disc self.number = number def __str__(self): return str(self.number) @property def offset(self): return self.disc.track_offsets[self.number - self.disc.first_track] @property def sectors(self): return self.disc.track_lengths[self.number - self.disc.first_track] length = sectors @property def seconds(self): return libdiscid.sectors_to_seconds(self.sectors) @property def isrc(self): try: value = self.disc.track_isrcs[self.number - self.disc.first_track] except NotImplementedError: return None return value if value != "" else None class Disc: def __init__(self): self.disc = _NoneHelper() self.tracks = [] def read(self, device, features=[]): self.disc = libdiscid.read( device, functools.reduce( operator.or_, ( _INVERSE_FEATURES[feature] for feature in features if feature in FEATURES ), 0, ), ) self.tracks = [ Track(self.disc, numb) for numb in range(self.disc.first_track, self.disc.last_track + 1) ] return True def put(self, first, last, disc_sectors, track_offsets): try: self.disc = libdiscid.put(first, last, disc_sectors, track_offsets) except DiscError as disc_error: raise TOCError(str(disc_error)) self.tracks = [ Track(self.disc, num) for num in range(self.disc.first_track, self.disc.last_track + 1) ] return True @property def id(self): return self.disc.id @property def freedb_id(self): return self.disc.freedb_id @property def submission_url(self): return self.disc.submission_url @property def toc_string(self): return self.disc.toc @property def first_track_num(self): return self.disc.first_track @property def last_track_num(self): return self.disc.last_track @property def sectors(self): return self.disc.sectors length = sectors @property def seconds(self): return ( libdiscid.sectors_to_seconds(self.sectors) if self.sectors is not None else None ) @property def mcn(self): try: value = self.disc.mcn except NotImplementedError: return None return value if value != "" else None # functions defined in discid get_default_device = libdiscid.default_device def read(device=None, features=[]): disc = Disc() disc.read( _decode(device) if device is not None else None, map(lambda feature: _decode(feature, "ascii"), features), ) return disc def put(first, last, disc_sectors, track_offsets): disc = Disc() disc.put(first, last, disc_sectors, track_offsets) return disc # constants defined in discid __version__ = "1.1.0 (compat layer from python-libdiscid %s)" % (libdiscid.__version__,) """This is the version of python-discid this layer is compatible with. """ LIBDISCID_VERSION_STRING = libdiscid.__discid_version__ FEATURES = libdiscid.FEATURES FEATURES_IMPLEMENTED = ( libdiscid.FEATURE_READ, libdiscid.FEATURE_MCN, libdiscid.FEATURE_ISRC, ) __all__ = ( "read", "put", "get_default_device", "__version__", "LIBDISCID_VERSION_STRING", "FEATURES", "FEATURES_IMPLEMENTED", "Disc", "DiscError", "TOCError", ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/discid-wrapper.c0000644000175100001730000000573714462020247021406 0ustar00runnerdocker/* Copyright 2013-2021 Sebastian Ramacher * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "discid-wrapper.h" #include #ifndef UNUSED # if defined(__GNUC__) || defined(__CLANG__) # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) # elif defined(__LCLINT__) # define UNUSED(x) /*@unused@*/ x # else # define UNUSED(x) x # endif #endif #ifndef DISCID_FEATURE_LENGTH char* wrap_get_version_string(void) { return "libdiscid < 0.4.0"; } int wrap_has_feature(enum discid_feature feature) { /* except for GNU Hurd, read is available for all platforms */ #ifndef __GNU__ if (feature == DISCID_FEATURE_READ) return 1; else #endif return 0; } char* wrap_get_mcn(DiscId* UNUSED(d)) { return NULL; } char* wrap_get_track_isrc(DiscId* UNUSED(d), int UNUSED(track_num)) { return NULL; } #else char* wrap_get_version_string(void) { return discid_get_version_string(); } int wrap_has_feature(enum discid_feature feature) { return discid_has_feature(feature); } char* wrap_get_mcn(DiscId* d) { return discid_get_mcn(d); } char* wrap_get_track_isrc(DiscId* d, int track_num) { return discid_get_track_isrc(d, track_num); } #endif /* libdiscid < 0.4.0 */ /* discid_read_sparse appeared in 0.5.0 and 0.5.0 finally introduced defines for * the version */ #if !defined(DISCID_VERSION_MAJOR) || \ (DISCID_VERSION_MAJOR == 0 && DISCID_VERSION_MINOR < 5) int wrap_read_sparse(DiscId *d, const char *device, unsigned int UNUSED(features)) { return discid_read(d, device); } #else int wrap_read_sparse(DiscId *d, const char *device, unsigned int features) { return discid_read_sparse(d, device, features); } #endif /* libdiscid < 0.5.0 */ /* discid_get_toc_string appeared in 0.6.0 */ #if !defined(DISCID_VERSION_MAJOR) || \ (DISCID_VERSION_MAJOR == 0 && DISCID_VERSION_MINOR < 6) char* wrap_get_toc(DiscId* d) { return NULL; } #else char* wrap_get_toc(DiscId* d) { return discid_get_toc_string(d); } #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/discid-wrapper.h0000644000175100001730000000465514462020247021411 0ustar00runnerdocker/* Copyright 2013-2021 Sebastian Ramacher * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef DISCID_WRAPPER_H #define DISCID_WRAPPER_H #include #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) # define INTERNAL __attribute__((visibility("hidden"))) #elif defined(__SUNPRO_C) # define INTERNAL __hidden #else # define INTERNAL #endif /* use the availability of DISCID_FEATURE_LENGTH to detect libdiscid < 0.4.0 */ #ifndef DISCID_FEATURE_LENGTH enum discid_feature { DISCID_FEATURE_READ = 1, DISCID_FEATURE_MCN = 2, DISCID_FEATURE_ISRC = 4 }; #define DISCID_FEATURE_STR_READ "read" #define DISCID_FEATURE_STR_MCN "mcn" #define DISCID_FEATURE_STR_ISRC "isrc" #endif /* libdiscid < 0.4.0 */ int wrap_has_feature(enum discid_feature feature) INTERNAL; char* wrap_get_version_string(void) INTERNAL; /* discid_get_mcn and discid_get_track_isrc were introduced in 0.3.0 but there * is no way to reliable detect if the current platform supports mcn and isrc, * so let's assume they are not available and replace them with placeholders */ char* wrap_get_mcn(DiscId* d) INTERNAL; char* wrap_get_track_isrc(DiscId* d, int track_num) INTERNAL; /* discid_read_sparse appeared in 0.5.0 */ int wrap_read_sparse(DiscId *d, const char *device, unsigned int features) INTERNAL; /* discid_get_toc_string appeared in 0.6.0 */ char* wrap_get_toc(DiscId* d) INTERNAL; #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/exceptions.py0000644000175100001730000000247014462020247021047 0ustar00runnerdocker# Copyright 2013-2021 Sebastian Ramacher # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. """Module containing all the exceptions from libdiscid """ class DiscError(IOError): """:func:`libdiscid.read` and :func:`libdiscid.put` will raise this exception when an error occurred. """ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/py.typed0000644000175100001730000000000014462020247017776 0ustar00runnerdocker././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1690837173.550363 python-libdiscid-2.0.3/libdiscid/tests/0000755000175100001730000000000014462020266017454 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/tests/__init__.py0000644000175100001730000000000014462020247021552 0ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/tests/common.py0000644000175100001730000000427114462020247021321 0ustar00runnerdocker# Copyright 2013-2021 Sebastian Ramacher # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. """Tests for the libdiscid module """ class PutSuccess: first = 1 last = 15 sectors = 258725 seconds = 3450 offsets = ( 150, 17510, 33275, 45910, 57805, 78310, 94650, 109580, 132010, 149160, 165115, 177710, 203325, 215555, 235590, ) track_seconds = ( 231, 210, 168, 159, 273, 218, 199, 299, 229, 213, 168, 342, 163, 267, 308, ) disc_id = "TqvKjMu7dMliSfmVEBtrL7sBSno-" freedb_id = "b60d770f" toc = " ".join(map(str, [first, last, sectors] + list(offsets))) class _PutFail: sectors = 200 offsets = (1, 2, 3, 4, 5, 6, 7) class PutFail1(_PutFail): first = 13 last = 1 class PutFail2(_PutFail): first = 0 last = 10 class PutFail2_2(_PutFail): first = 100 last = 200 class PutFail3(_PutFail): first = 0 last = 0 class PutFail3_2(_PutFail): first = 1 last = 100 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/tests/test_compat_discid.py0000644000175100001730000001275514462020247023700 0ustar00runnerdocker# Copyright 2013-2021 Sebastian Ramacher # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. """Tests for the libdiscid.compat.discid module """ import unittest import libdiscid from libdiscid.compat import discid from libdiscid.compat.discid import DiscError, TOCError from . import common class TestCompatDiscID(unittest.TestCase): def test_default_device(self): self.assertIsNotNone(discid.get_default_device()) def test_features(self): self.assertIsNotNone(discid.FEATURES) def test_features_implementes(self): self.assertIsNotNone(discid.FEATURES_IMPLEMENTED) def test_empty_is_none(self): disc = discid.Disc() self.assertIsNone(disc.id) self.assertIsNone(disc.freedb_id) self.assertIsNone(disc.submission_url) self.assertIsNone(disc.toc_string) self.assertIsNone(disc.first_track_num) self.assertIsNone(disc.last_track_num) self.assertIsNone(disc.sectors) self.assertIsNone(disc.seconds) self.assertEqual(len(disc.tracks), 0) @unittest.skipIf( libdiscid.FEATURES_MAPPING[libdiscid.FEATURE_READ] not in libdiscid.FEATURES, "not available on this platform", ) def test_read_fail(self): self.assertRaises(DiscError, discid.read, "/does/not/exist") def test_read_None(self): try: discid.read() except (DiscError, NotImplementedError): pass @unittest.skipIf( libdiscid.FEATURES_MAPPING[libdiscid.FEATURE_READ] not in libdiscid.FEATURES, "not available on this platform", ) def test_encoded_device(self): self.assertRaises(DiscError, discid.read, "/does/not/exist") @unittest.skipIf( libdiscid.FEATURES_MAPPING[libdiscid.FEATURE_READ] not in libdiscid.FEATURES, "not available on this platform", ) def test_byte_device(self): self.assertRaises(DiscError, discid.read, b"/does/not/exist") def test_put(self): testdata = common.PutSuccess disc = discid.put( testdata.first, testdata.last, testdata.sectors, testdata.offsets ) self.assertIsNotNone(disc) self.assertEqual(disc.id, testdata.disc_id) self.assertEqual(disc.freedb_id, testdata.freedb_id) self.assertIsNotNone(disc.submission_url) self.assertEqual(disc.toc_string, testdata.toc) self.assertEqual(disc.first_track_num, testdata.first) self.assertEqual(disc.last_track_num, testdata.last) self.assertEqual(disc.sectors, testdata.sectors) self.assertEqual(disc.seconds, testdata.seconds) self.assertEqual(len(disc.tracks), len(testdata.offsets)) for track, offset, sec in zip( disc.tracks, testdata.offsets, testdata.track_seconds ): self.assertEqual(track.offset, offset) self.assertEqual(track.seconds, sec) # ISRCs are not available if one calls put for track in disc.tracks: self.assertIsNone(track.isrc) # MCN is not available if one calls put self.assertIsNone(disc.mcn) def test_put_fail_1(self): # !(first < last) testdata = common.PutFail1 self.assertRaises( TOCError, discid.put, testdata.first, testdata.last, testdata.sectors, testdata.offsets, ) def test_put_fail_2(self): # !(first >= 1) testdata = common.PutFail2 self.assertRaises( TOCError, discid.put, testdata.first, testdata.last, testdata.sectors, testdata.offsets, ) # !(first < 100) testdata = common.PutFail2_2 self.assertRaises( TOCError, discid.put, testdata.first, testdata.last, testdata.sectors, testdata.offsets, ) def test_put_fail_3(self): # !(last >= 1) testdata = common.PutFail3 self.assertRaises( TOCError, discid.put, testdata.first, testdata.last, testdata.sectors, testdata.offsets, ) # !(last < 100) testdata = common.PutFail3_2 self.assertRaises( TOCError, discid.put, testdata.first, testdata.last, testdata.sectors, testdata.offsets, ) if __name__ == "__main__": unittest.main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/libdiscid/tests/test_libdiscid.py0000644000175100001730000001323114462020247023012 0ustar00runnerdocker# Copyright 2013-2021 Sebastian Ramacher # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. """Tests for the libdiscid module """ import unittest import libdiscid from libdiscid import DiscError from . import common class TestLibDiscId(unittest.TestCase): def test_version(self): self.assertIsNotNone(libdiscid.__version__) self.assertIsNotNone(libdiscid.__discid_version__) def test_default_device(self): self.assertIsNotNone(libdiscid.default_device()) def test_features(self): self.assertIsNotNone(libdiscid.FEATURES) self.assertIsNotNone(libdiscid.FEATURE_READ) self.assertIsNotNone(libdiscid.FEATURE_MCN) self.assertIsNotNone(libdiscid.FEATURE_ISRC) self.assertIsNotNone(libdiscid.FEATURES_MAPPING) @unittest.skipIf( libdiscid.FEATURES_MAPPING[libdiscid.FEATURE_READ] not in libdiscid.FEATURES, "not available on this platform", ) def test_read_fail(self): self.assertRaises(DiscError, libdiscid.read, "/does/not/exist") def test_read_None(self): try: libdiscid.read() except (DiscError, NotImplementedError): pass @unittest.skipIf( libdiscid.FEATURES_MAPPING[libdiscid.FEATURE_READ] in libdiscid.FEATURES, "available on this platform", ) def test_read_not_implemented(self): self.assertRaises(NotImplementedError, libdiscid.read) def test_put(self): testdata = common.PutSuccess disc = libdiscid.put( testdata.first, testdata.last, testdata.sectors, testdata.offsets ) self.assertIsNotNone(disc) self.assertIsNone(disc.device) self.assertEqual(disc.id, testdata.disc_id) self.assertEqual(disc.freedb_id, testdata.freedb_id) self.assertIsNotNone(disc.submission_url) self.assertEqual(disc.first_track, testdata.first) self.assertEqual(disc.last_track, testdata.last) self.assertEqual(disc.sectors, testdata.sectors) self.assertEqual(disc.pregap, testdata.offsets[0]) self.assertEqual(disc.leadout_track, testdata.sectors) self.assertEqual(disc.toc, testdata.toc) self.assertEqual(len(disc.track_offsets), len(testdata.offsets)) for read_offset, expected_offset in zip(disc.track_offsets, testdata.offsets): self.assertEqual(read_offset, expected_offset) # ISRCs are not available if one calls put if libdiscid.FEATURES_MAPPING[libdiscid.FEATURE_ISRC] in libdiscid.FEATURES: self.assertEqual(len(disc.track_isrcs), 15) for read_isrc in disc.track_isrcs: self.assertEqual(read_isrc, "") # MCN is not available if one calls put if libdiscid.FEATURES_MAPPING[libdiscid.FEATURE_MCN] in libdiscid.FEATURES: self.assertEqual(disc.mcn, "") def test_put_fail_1(self): # !(first < last) testdata = common.PutFail1 self.assertRaises( DiscError, libdiscid.put, testdata.first, testdata.last, testdata.sectors, testdata.offsets, ) def test_put_fail_2(self): # !(first >= 1) testdata = common.PutFail2 self.assertRaises( DiscError, libdiscid.put, testdata.first, testdata.last, testdata.sectors, testdata.offsets, ) # !(first < 100) testdata = common.PutFail2_2 self.assertRaises( DiscError, libdiscid.put, testdata.first, testdata.last, testdata.sectors, testdata.offsets, ) def test_put_fail_3(self): # !(last >= 1) testdata = common.PutFail3 self.assertRaises( DiscError, libdiscid.put, testdata.first, testdata.last, testdata.sectors, testdata.offsets, ) # !(last < 100) testdata = common.PutFail3_2 self.assertRaises( DiscError, libdiscid.put, testdata.first, testdata.last, testdata.sectors, testdata.offsets, ) def test_sectors_to_seconds(self): # there are 75 sectors per second for sectors in range(38): # round down for sectors in the first half self.assertEqual(libdiscid.sectors_to_seconds(sectors), 0) for sectors in range(38, 76): # round up for sectors in the second half self.assertEqual(libdiscid.sectors_to_seconds(sectors), 1) if __name__ == "__main__": unittest.main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/pyproject.toml0000644000175100001730000000045414462020247017302 0ustar00runnerdocker[build-system] requires = ["setuptools >= 43", "Cython (>= 0.15)", "pkgconfig"] build-backend = "setuptools.build_meta" [tool.black] target_version = ["py38"] include = '\.pyi?$' exclude = ''' /( \.git | \.hg | \.eggs | \.mypy_cache | \.tox | venv | _build | build | dist )/ ''' ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1690837173.550363 python-libdiscid-2.0.3/python_libdiscid.egg-info/0000755000175100001730000000000014462020266021405 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837173.0 python-libdiscid-2.0.3/python_libdiscid.egg-info/PKG-INFO0000644000175100001730000000433214462020265022503 0ustar00runnerdockerMetadata-Version: 2.1 Name: python-libdiscid Version: 2.0.3 Summary: Python bindings for libdiscid Home-page: https://github.com/sebastinas/python-libdiscid Author: Sebastian Ramacher Author-email: sebastian@ramacher.at License: MIT Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Multimedia :: Sound/Audio :: CD Audio :: CD Ripping Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=3.8 Description-Content-Type: text/markdown License-File: LICENSE # libdiscid Python bindings python-libdiscid implements Python >= 3.6 bindings for libdiscid using Cython. ## Dependencies * libdiscid * Cython (>= 0.15, optional) * pkgconfig (optional) Note that the tarballs come with pre-built C source for the Cython module. So Cython is only required if one builds python-libdiscid from the git repository or if one wants to change anything in the Cython module. If pkgconfig is installed, setup.py uses libdiscid's pkg-config information to set include directories, libraries to link, etc. ## Quick installation guide python-libdiscid is available in some distributions: * Debian/Ubuntu: `apt-get install python3-libdiscid` (Python 3) * Fedora: `dnf install python3-libdiscid` (Python 3) python-libdiscid can be installed via `pip`: ``` $ pip install python-libdiscid ``` or by running: ``` $ python3 setup.py install ``` If you just want to try it locally, run: ``` $ python3 setup.py build_ext -i ``` and hack right away. You can also run: ``` $ python3 setup.py build ``` but please make sure that `build/lib.*` is in `sys.path` before the source folder. ## A note for Windows users There are eggs available from PyPI that don't require the extension module to be built. If these are used, it is still required to drop a working discid.dll in `C:\WINDOWS\system32` (or wherever it can be found). ## Usage ```python3 from libdiscid import read disc = read("/dev/cdrom") print("id: {}".format(disc.id)) ``` ## License python-libdiscid is released under the MIT license. Check LICENSE for details. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837173.0 python-libdiscid-2.0.3/python_libdiscid.egg-info/SOURCES.txt0000644000175100001730000000133414462020265023271 0ustar00runnerdockerCHANGELOG.md LICENSE MANIFEST.in README.md pyproject.toml setup.cfg setup.py docs/api.compat.rst docs/api.rst docs/conf.py docs/index.rst docs/installation.rst docs/license.rst docs/misc.rst docs/usage.rst libdiscid/__init__.py libdiscid/_discid.pyi libdiscid/_discid.pyx libdiscid/cdiscid.pxd libdiscid/discid-wrapper.c libdiscid/discid-wrapper.h libdiscid/exceptions.py libdiscid/py.typed libdiscid/compat/__init__.py libdiscid/compat/discid.py libdiscid/tests/__init__.py libdiscid/tests/common.py libdiscid/tests/test_compat_discid.py libdiscid/tests/test_libdiscid.py python_libdiscid.egg-info/PKG-INFO python_libdiscid.egg-info/SOURCES.txt python_libdiscid.egg-info/dependency_links.txt python_libdiscid.egg-info/top_level.txt././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837173.0 python-libdiscid-2.0.3/python_libdiscid.egg-info/dependency_links.txt0000644000175100001730000000000114462020265025452 0ustar00runnerdocker ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837173.0 python-libdiscid-2.0.3/python_libdiscid.egg-info/top_level.txt0000644000175100001730000000001214462020265024127 0ustar00runnerdockerlibdiscid ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1690837173.550363 python-libdiscid-2.0.3/setup.cfg0000644000175100001730000000144214462020266016206 0ustar00runnerdocker[metadata] name = python-libdiscid version = 2.0.3 author = Sebastian Ramacher author_email = sebastian@ramacher.at url = https://github.com/sebastinas/python-libdiscid description = Python bindings for libdiscid long_description = file: README.md long_description_content_type = text/markdown license = MIT license_files = LICENSE classifiers = Development Status :: 5 - Production/Stable Intended Audience :: Developers License :: OSI Approved :: MIT License Operating System :: OS Independent Programming Language :: Python :: 3 Topic :: Multimedia :: Sound/Audio :: CD Audio :: CD Ripping Topic :: Software Development :: Libraries :: Python Modules [options] python_requires = >=3.8 [build_sphinx] source-dir = docs build-dir = build all_files = 1 [egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1690837159.0 python-libdiscid-2.0.3/setup.py0000755000175100001730000000327114462020247016103 0ustar00runnerdocker#!/usr/bin/python3 import os.path import os import sys from setuptools import setup, Extension try: import pkgconfig have_pkgconfig = True def pkgconfig_exists(package): try: return pkgconfig.exists(package) except OSError: return False except ImportError: have_pkgconfig = False if have_pkgconfig and pkgconfig_exists("libdiscid"): flags = pkgconfig.parse("libdiscid") define_macros = flags["define_macros"] include_dirs = flags["include_dirs"] library_dirs = flags["library_dirs"] libraries = list(flags["libraries"]) else: define_macros = [] include_dirs = [] library_dirs = [] libraries = ["discid"] # TODO: Solve this properly by passing CFLAGS and LDFLAGS via CIBW_ENVIRONMENT. For some reason, # CFLAGS and LDFLAGS seem to be ignored when built through cibuildwheel. LIBDISCID_HOME = os.environ.get("LIBDISCID_HOME", None) if LIBDISCID_HOME is not None: library_dirs.append(os.path.join(LIBDISCID_HOME, "libdiscid-0.6.1-win32")) include_dirs.append( os.path.join( LIBDISCID_HOME, "libdiscid-0.6.1-win32", "libdiscid-0.6.1", "include" ) ) setup( ext_modules=[ Extension( "libdiscid._discid", ["libdiscid/_discid.pyx", "libdiscid/discid-wrapper.c"], define_macros=define_macros, include_dirs=include_dirs, library_dirs=library_dirs, libraries=libraries, ) ], packages=["libdiscid", "libdiscid.tests", "libdiscid.compat"], package_data={ "libdiscid": ["_discid.pyi", "py.typed"], }, test_suite="libdiscid.tests", )