From f18549d698a6239ffaca5921f6d420d5a81e2e19 Mon Sep 17 00:00:00 2001 From: Evan Goode Date: Fri, 19 Nov 2021 23:27:59 -0500 Subject: [PATCH] Start work on packaging for distribution - Package using poetry and pyproject.toml - Require modules to have a `name` in ModuleInformation (shouldn't rely on just the python package name any more) - Installed modules matching "orpheus_module_*" will be loaded. For now, modules in "modules/" will still be loaded too. - settings.json moved to $XDG_CONFIG_HOME/orpheusdl/settings.json (or an equivalent cross-platform location). config/settings.json will still be loaded for now if it is present - loginstorage.bin moved to $XDG_CACHE_HOME/orpheusdl/loginstorage.bin (or equivalent). config/loginstorage.bin will still be loaded for now if it is present. --- .gitignore | 3 +- modules/example/interface.py | 7 +- moduletesting.py | 4 +- {orpheus => orpheusdl}/__init__.py | 0 {orpheus => orpheusdl}/core.py | 92 +++++-- {orpheus => orpheusdl}/housekeeping.py | 0 {orpheus => orpheusdl}/music_downloader.py | 10 +- orpheus.py => orpheusdl/orpheus.py | 10 +- {orpheus => orpheusdl}/tagging.py | 4 +- {utils => orpheusdl/utils}/__init__.py | 0 {utils => orpheusdl/utils}/exceptions.py | 0 {utils => orpheusdl/utils}/models.py | 5 +- {utils => orpheusdl/utils}/utils.py | 0 poetry.lock | 306 +++++++++++++++++++++ pyproject.toml | 24 ++ 15 files changed, 422 insertions(+), 43 deletions(-) rename {orpheus => orpheusdl}/__init__.py (100%) rename {orpheus => orpheusdl}/core.py (86%) rename {orpheus => orpheusdl}/housekeeping.py (100%) rename {orpheus => orpheusdl}/music_downloader.py (99%) rename orpheus.py => orpheusdl/orpheus.py (99%) rename {orpheus => orpheusdl}/tagging.py (98%) rename {utils => orpheusdl/utils}/__init__.py (100%) rename {utils => orpheusdl/utils}/exceptions.py (100%) rename {utils => orpheusdl/utils}/models.py (98%) rename {utils => orpheusdl/utils}/utils.py (100%) create mode 100644 poetry.lock create mode 100644 pyproject.toml diff --git a/.gitignore b/.gitignore index b7e54b7..c4296d0 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ downloads/ temp/ .python-version modules/ -extensions/ \ No newline at end of file +extensions/ +dist/ diff --git a/modules/example/interface.py b/modules/example/interface.py index dbe17bd..8167a5f 100755 --- a/modules/example/interface.py +++ b/modules/example/interface.py @@ -1,8 +1,9 @@ -from utils.models import * -from utils.utils import create_temp_filename +from orpheusdl.utils.models import * +from orpheusdl.utils.utils import create_temp_filename module_information = ModuleInformation( # Only service_name and module_supported_modes are mandatory + name = 'example', service_name = 'Example', module_supported_modes = ModuleModes.download | ModuleModes.lyrics | ModuleModes.covers | ModuleModes.credits, flags = ModuleFlags.hidden, @@ -183,4 +184,4 @@ def search(self, query_type: DownloadTypeEnum, query: str, track_info: TrackInfo # get_track_credits, get_track_cover, get_track_lyrics in the case of other modules using this module just for those. # therefore, it's recommended to choose something generic like 'data' rather than specifics like 'cover_info' # or, you could use both, keeping a data field just in case track data is given, while keeping the specifics, but that's overcomplicated - ) for i in results] \ No newline at end of file + ) for i in results] diff --git a/moduletesting.py b/moduletesting.py index 136cbb9..a841459 100644 --- a/moduletesting.py +++ b/moduletesting.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import argparse, cProfile, pstats -from orpheus.core import Orpheus +from orpheusdl.core import Orpheus def main(): parser = argparse.ArgumentParser(description='Orpheus Module Testing Tool') @@ -42,4 +42,4 @@ def main(): main() except KeyboardInterrupt: print('\n\t^C pressed - abort') - exit() \ No newline at end of file + exit() diff --git a/orpheus/__init__.py b/orpheusdl/__init__.py similarity index 100% rename from orpheus/__init__.py rename to orpheusdl/__init__.py diff --git a/orpheus/core.py b/orpheusdl/core.py similarity index 86% rename from orpheus/core.py rename to orpheusdl/core.py index d92d157..bb4f03d 100644 --- a/orpheus/core.py +++ b/orpheusdl/core.py @@ -1,10 +1,12 @@ -import importlib, json, logging, os, pickle, requests, urllib3, base64, shutil +import importlib, json, logging, os, pickle, requests, urllib3, base64, shutil, pkgutil from datetime import datetime -from orpheus.music_downloader import Downloader -from utils.models import * -from utils.utils import * -from utils.exceptions import * +from orpheusdl.music_downloader import Downloader +from orpheusdl.utils.models import * +from orpheusdl.utils.utils import * +from orpheusdl.utils.exceptions import * + +from appdirs import AppDirs os.environ['CURL_CA_BUNDLE'] = '' # Hack to disable SSL errors for requests module for easier debugging urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # Make SSL warnings hidden @@ -27,7 +29,13 @@ def true_current_utc_timestamp(): class Orpheus: def __init__(self, private_mode=False): - self.extensions, self.extension_list, self.module_list, self.module_settings, self.module_netloc_constants, self.loaded_modules = {}, set(), set(), {}, {}, {} + self.extensions = {} + self.extension_list = set() + self.module_list = set() + self.module_packages = {} + self.module_settings = {} + self.module_netloc_constants = {} + self.loaded_modules = {} self.default_global_settings = { "general": { @@ -87,18 +95,33 @@ def __init__(self, private_mode=False): } } - self.settings_location = 'config/settings.json' - self.session_storage_location = 'config/loginstorage.bin' + dirs = AppDirs('orpheusdl', 'orpheusdl') + + if os.path.isfile('./config/settings.json'): + self.settings_location = './config/settings.json' + else: + os.makedirs(dirs.user_config_dir, exist_ok=True) + self.settings_location = os.path.join(dirs.user_config_dir, 'settings.json') + print(f'Using settings file at {self.settings_location}') + + if os.path.isfile('./config/loginstorage.bin'): + self.session_storage_location = 'config/loginstorage.bin' + else: + os.makedirs(dirs.user_cache_dir, exist_ok=True) + self.session_storage_location = os.path.join(dirs.user_cache_dir, 'loginstorage.bin') - if not os.path.exists('config'): os.makedirs('config') - self.settings = json.loads(open(self.settings_location, 'r').read()) if os.path.exists(self.settings_location) else {} + try: + with open(self.settings_location, 'rb') as fp: + self.settings = json.load(fp) + except FileNotFoundError: + self.settings = {} try: if self.settings['global']['advanced']['debug_mode']: logging.basicConfig(level=logging.DEBUG) except KeyError: pass - if not os.path.exists('extensions'): os.makedirs('extensions') + os.makedirs('extensions', exist_ok=True) for extension in os.listdir('extensions'): # Loading extensions if os.path.isdir(f'extensions/{extension}') and os.path.exists(f'extensions/{extension}/interface.py'): class_ = getattr(importlib.import_module(f'extensions.{extension}.interface'), 'OrpheusExtension', None) @@ -109,21 +132,34 @@ def __init__(self, private_mode=False): raise Exception('Error loading extension: "{extension}"') # Module preparation (not loaded yet for performance purposes) - if not os.path.exists('modules'): os.makedirs('modules') - module_list = [module.lower() for module in os.listdir('modules') if os.path.exists(f'modules/{module}/interface.py')] - if not module_list or module_list == ['example']: + + # Load modules from installed packages matching "orpheusdl_module_*" + module_packages = [ + module_package for _, module_package, _ in pkgutil.iter_modules() if module_package.startswith('orpheusdl_module_') + ] + + # Load modules from the local "modules" directory + os.makedirs('modules', exist_ok=True) + module_packages.extend(f"modules.{module}" for module in os.listdir('modules') if os.path.exists(f'modules/{module}/interface.py')) + + if not module_packages or set(module_packages) == {"modules.example"}: print('No modules are installed, quitting') exit() - logging.debug('Orpheus: Modules detected: ' + ", ".join(module_list)) + logging.debug('Orpheus: Modules detected: ' + ", ".join(module_packages)) - for module in module_list: # Loading module information into module_settings - module_information: ModuleInformation = getattr(importlib.import_module(f'modules.{module}.interface'), 'module_information', None) + for module_package in module_packages: # Loading module information into module_settings + module_information: ModuleInformation = getattr(importlib.import_module(f'{module_package}.interface'), 'module_information', None) if module_information and not ModuleFlags.private in module_information.flags and not private_mode: - self.module_list.add(module) - self.module_settings[module] = module_information - logging.debug(f'Orpheus: {module} added as a module') + if module_information.name: + module_name = module_information.name + else: + module_name = module_package.split(".")[-1].split("_")[-1] + self.module_list.add(module_name) + self.module_packages[module_name] = module_package + self.module_settings[module_name] = module_information + logging.debug(f'Orpheus: {module_name} added as a module') else: - raise Exception(f'Error loading module information from module: "{module}"') # TODO: replace with InvalidModuleError + raise Exception(f'Error loading module information from module: "{module_package}"') # TODO: replace with InvalidModuleError duplicates = set() for module in self.module_list: # Detecting duplicate url constants @@ -161,7 +197,8 @@ def load_module(self, module: str): if module not in self.module_list: raise Exception(f'"{module}" does not exist in modules.') # TODO: replace with InvalidModuleError if module not in self.loaded_modules: - class_ = getattr(importlib.import_module(f'modules.{module}.interface'), 'ModuleInterface', None) + module_package = self.module_packages[module] + class_ = getattr(importlib.import_module(f'{module_package}.interface'), 'ModuleInterface', None) if class_: class ModuleError(Exception): # TODO: get rid of this, as it is deprecated def __init__(self, message): @@ -267,7 +304,14 @@ def update_module_storage(self): # Should be refactored eventually new_settings['modules'] = module_settings ## Sessions - sessions = pickle.load(open(self.session_storage_location, 'rb')) if os.path.exists(self.session_storage_location) else {} + try: + sessions = pickle.load(open(self.session_storage_location, 'rb')) + except FileNotFoundError: + sessions = {} + except Exception: + print("Session store was invalid, resetting sessions.") + sessions = {} + if not ('advancedmode' in sessions and 'modules' in sessions and sessions['advancedmode'] == advanced_login_mode): sessions = {'advancedmode': advanced_login_mode, 'modules':{}} @@ -375,4 +419,4 @@ def orpheus_core_download(orpheus_session: Orpheus, media_to_download, third_par raise Exception(f'\tUnknown media type "{mediatype}"') print() - if os.path.exists('temp'): shutil.rmtree('temp') \ No newline at end of file + if os.path.exists('temp'): shutil.rmtree('temp') diff --git a/orpheus/housekeeping.py b/orpheusdl/housekeeping.py similarity index 100% rename from orpheus/housekeeping.py rename to orpheusdl/housekeeping.py diff --git a/orpheus/music_downloader.py b/orpheusdl/music_downloader.py similarity index 99% rename from orpheus/music_downloader.py rename to orpheusdl/music_downloader.py index 0b21a6d..7cb1e61 100644 --- a/orpheus/music_downloader.py +++ b/orpheusdl/music_downloader.py @@ -1,10 +1,10 @@ import logging, os, ffmpeg from dataclasses import asdict -from orpheus.tagging import tag_file -from utils.models import * -from utils.utils import * -from utils.exceptions import * +from orpheusdl.tagging import tag_file +from orpheusdl.utils.models import * +from orpheusdl.utils.utils import * +from orpheusdl.utils.exceptions import * class Downloader: @@ -473,4 +473,4 @@ def set_indent_number(self, number: int): def oprint(self, input: str, drop_level: int = 0): if self.printing_enabled: - print(' ' * (self.indent_number - drop_level * self.multiplier) + input) \ No newline at end of file + print(' ' * (self.indent_number - drop_level * self.multiplier) + input) diff --git a/orpheus.py b/orpheusdl/orpheus.py similarity index 99% rename from orpheus.py rename to orpheusdl/orpheus.py index a5c1e45..6dd9e0b 100755 --- a/orpheus.py +++ b/orpheusdl/orpheus.py @@ -3,7 +3,7 @@ import argparse, re from urllib.parse import urlparse -from orpheus.core import * +from orpheusdl.core import * def main(): @@ -195,10 +195,12 @@ def main(): orpheus_core_download(orpheus, media_to_download, tpm, sdm, path) - -if __name__ == "__main__": +def run(): try: main() except KeyboardInterrupt: print('\n\t^C pressed - abort') - exit() \ No newline at end of file + exit() + +if __name__ == "__main__": + run() diff --git a/orpheus/tagging.py b/orpheusdl/tagging.py similarity index 98% rename from orpheus/tagging.py rename to orpheusdl/tagging.py index dae7fdd..04ee379 100644 --- a/orpheus/tagging.py +++ b/orpheusdl/tagging.py @@ -11,8 +11,8 @@ from mutagen.id3 import PictureType, APIC, USLT from PIL import Image -from utils.models import ContainerEnum, TrackInfo -from utils.exceptions import * +from orpheusdl.utils.models import ContainerEnum, TrackInfo +from orpheusdl.utils.exceptions import * # Needed for Windows tagging support MP4Tags._padding = 0 diff --git a/utils/__init__.py b/orpheusdl/utils/__init__.py similarity index 100% rename from utils/__init__.py rename to orpheusdl/utils/__init__.py diff --git a/utils/exceptions.py b/orpheusdl/utils/exceptions.py similarity index 100% rename from utils/exceptions.py rename to orpheusdl/utils/exceptions.py diff --git a/utils/models.py b/orpheusdl/utils/models.py similarity index 98% rename from utils/models.py rename to orpheusdl/utils/models.py index 05c9d3f..e188f84 100644 --- a/utils/models.py +++ b/orpheusdl/utils/models.py @@ -3,7 +3,7 @@ from types import ClassMethodDescriptorType, FunctionType from typing import Optional -from utils.utils import read_temporary_setting, set_temporary_setting +from orpheusdl.utils.utils import read_temporary_setting, set_temporary_setting class CodecEnum(Flag): @@ -108,6 +108,7 @@ class ManualEnum(Flag): class ModuleInformation: service_name: str module_supported_modes: ModuleModes + name: Optional[str] = None global_settings: Optional[dict] = field(default_factory=dict) global_storage_variables: Optional[list] = None session_settings: Optional[dict] = field(default_factory=dict) @@ -275,4 +276,4 @@ class TrackDownloadInfo: download_type: DownloadEnum file_url: Optional[str] = None file_url_headers: Optional[dict] = None - temp_file_path: Optional[str] = None \ No newline at end of file + temp_file_path: Optional[str] = None diff --git a/utils/utils.py b/orpheusdl/utils/utils.py similarity index 100% rename from utils/utils.py rename to orpheusdl/utils/utils.py diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..edc9f22 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,306 @@ +[[package]] +name = "appdirs" +version = "1.4.4" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "certifi" +version = "2021.10.8" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "charset-normalizer" +version = "2.0.7" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.5.0" + +[package.extras] +unicode_backport = ["unicodedata2"] + +[[package]] +name = "colorama" +version = "0.4.4" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "ffmpeg-python" +version = "0.2.0" +description = "Python bindings for FFmpeg - with complex filtering support" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +future = "*" + +[package.extras] +dev = ["future (==0.17.1)", "numpy (==1.16.4)", "pytest-mock (==1.10.4)", "pytest (==4.6.1)", "Sphinx (==2.1.0)", "tox (==3.12.1)"] + +[[package]] +name = "future" +version = "0.18.2" +description = "Clean single-source support for Python 3 and 2" +category = "main" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "idna" +version = "3.3" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "mutagen" +version = "1.45.1" +description = "read and write audio tags for many formats" +category = "main" +optional = false +python-versions = ">=3.5, <4" + +[[package]] +name = "pillow" +version = "8.4.0" +description = "Python Imaging Library (Fork)" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "protobuf" +version = "3.19.1" +description = "Protocol Buffers" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "pycryptodomex" +version = "3.11.0" +description = "Cryptographic library for Python" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "requests" +version = "2.26.0" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} +idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] + +[[package]] +name = "tqdm" +version = "4.62.3" +description = "Fast, Extensible Progress Meter" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +dev = ["py-make (>=0.1.0)", "twine", "wheel"] +notebook = ["ipywidgets (>=6)"] +telegram = ["requests"] + +[[package]] +name = "urllib3" +version = "1.26.7" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" + +[package.extras] +brotli = ["brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[metadata] +lock-version = "1.1" +python-versions = "^3.7" +content-hash = "b3e79e4a5fc07093ad767892c856415c8ec7982298f68d0439dc089da5631437" + +[metadata.files] +appdirs = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] +certifi = [ + {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, + {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, +] +charset-normalizer = [ + {file = "charset-normalizer-2.0.7.tar.gz", hash = "sha256:e019de665e2bcf9c2b64e2e5aa025fa991da8720daa3c1138cadd2fd1856aed0"}, + {file = "charset_normalizer-2.0.7-py3-none-any.whl", hash = "sha256:f7af805c321bfa1ce6714c51f254e0d5bb5e5834039bc17db7ebe3a4cec9492b"}, +] +colorama = [ + {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, + {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, +] +defusedxml = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] +ffmpeg-python = [ + {file = "ffmpeg-python-0.2.0.tar.gz", hash = "sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127"}, + {file = "ffmpeg_python-0.2.0-py3-none-any.whl", hash = "sha256:ac441a0404e053f8b6a1113a77c0f452f1cfc62f6344a769475ffdc0f56c23c5"}, +] +future = [ + {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, +] +idna = [ + {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, + {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, +] +mutagen = [ + {file = "mutagen-1.45.1-py3-none-any.whl", hash = "sha256:9c9f243fcec7f410f138cb12c21c84c64fde4195481a30c9bfb05b5f003adfed"}, + {file = "mutagen-1.45.1.tar.gz", hash = "sha256:6397602efb3c2d7baebd2166ed85731ae1c1d475abca22090b7141ff5034b3e1"}, +] +pillow = [ + {file = "Pillow-8.4.0-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:81f8d5c81e483a9442d72d182e1fb6dcb9723f289a57e8030811bac9ea3fef8d"}, + {file = "Pillow-8.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f97cfb1e5a392d75dd8b9fd274d205404729923840ca94ca45a0af57e13dbe6"}, + {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb9fc393f3c61f9054e1ed26e6fe912c7321af2f41ff49d3f83d05bacf22cc78"}, + {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d82cdb63100ef5eedb8391732375e6d05993b765f72cb34311fab92103314649"}, + {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc1afda735a8d109007164714e73771b499768b9bb5afcbbee9d0ff374b43f"}, + {file = "Pillow-8.4.0-cp310-cp310-win32.whl", hash = "sha256:e3dacecfbeec9a33e932f00c6cd7996e62f53ad46fbe677577394aaa90ee419a"}, + {file = "Pillow-8.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:620582db2a85b2df5f8a82ddeb52116560d7e5e6b055095f04ad828d1b0baa39"}, + {file = "Pillow-8.4.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:1bc723b434fbc4ab50bb68e11e93ce5fb69866ad621e3c2c9bdb0cd70e345f55"}, + {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72cbcfd54df6caf85cc35264c77ede902452d6df41166010262374155947460c"}, + {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70ad9e5c6cb9b8487280a02c0ad8a51581dcbbe8484ce058477692a27c151c0a"}, + {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25a49dc2e2f74e65efaa32b153527fc5ac98508d502fa46e74fa4fd678ed6645"}, + {file = "Pillow-8.4.0-cp36-cp36m-win32.whl", hash = "sha256:93ce9e955cc95959df98505e4608ad98281fff037350d8c2671c9aa86bcf10a9"}, + {file = "Pillow-8.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2e4440b8f00f504ee4b53fe30f4e381aae30b0568193be305256b1462216feff"}, + {file = "Pillow-8.4.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:8c803ac3c28bbc53763e6825746f05cc407b20e4a69d0122e526a582e3b5e153"}, + {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8a17b5d948f4ceeceb66384727dde11b240736fddeda54ca740b9b8b1556b29"}, + {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1394a6ad5abc838c5cd8a92c5a07535648cdf6d09e8e2d6df916dfa9ea86ead8"}, + {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:792e5c12376594bfcb986ebf3855aa4b7c225754e9a9521298e460e92fb4a488"}, + {file = "Pillow-8.4.0-cp37-cp37m-win32.whl", hash = "sha256:d99ec152570e4196772e7a8e4ba5320d2d27bf22fdf11743dd882936ed64305b"}, + {file = "Pillow-8.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7b7017b61bbcdd7f6363aeceb881e23c46583739cb69a3ab39cb384f6ec82e5b"}, + {file = "Pillow-8.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:d89363f02658e253dbd171f7c3716a5d340a24ee82d38aab9183f7fdf0cdca49"}, + {file = "Pillow-8.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585"}, + {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b7bb9de00197fb4261825c15551adf7605cf14a80badf1761d61e59da347779"}, + {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72b9e656e340447f827885b8d7a15fc8c4e68d410dc2297ef6787eec0f0ea409"}, + {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5a4532a12314149d8b4e4ad8ff09dde7427731fcfa5917ff16d0291f13609df"}, + {file = "Pillow-8.4.0-cp38-cp38-win32.whl", hash = "sha256:82aafa8d5eb68c8463b6e9baeb4f19043bb31fefc03eb7b216b51e6a9981ae09"}, + {file = "Pillow-8.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76"}, + {file = "Pillow-8.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:5503c86916d27c2e101b7f71c2ae2cddba01a2cf55b8395b0255fd33fa4d1f1a"}, + {file = "Pillow-8.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4acc0985ddf39d1bc969a9220b51d94ed51695d455c228d8ac29fcdb25810e6e"}, + {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b052a619a8bfcf26bd8b3f48f45283f9e977890263e4571f2393ed8898d331b"}, + {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:493cb4e415f44cd601fcec11c99836f707bb714ab03f5ed46ac25713baf0ff20"}, + {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8831cb7332eda5dc89b21a7bce7ef6ad305548820595033a4b03cf3091235ed"}, + {file = "Pillow-8.4.0-cp39-cp39-win32.whl", hash = "sha256:5e9ac5f66616b87d4da618a20ab0a38324dbe88d8a39b55be8964eb520021e02"}, + {file = "Pillow-8.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:3eb1ce5f65908556c2d8685a8f0a6e989d887ec4057326f6c22b24e8a172c66b"}, + {file = "Pillow-8.4.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ddc4d832a0f0b4c52fff973a0d44b6c99839a9d016fe4e6a1cb8f3eea96479c2"}, + {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a3e5ddc44c14042f0844b8cf7d2cd455f6cc80fd7f5eefbe657292cf601d9ad"}, + {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c70e94281588ef053ae8998039610dbd71bc509e4acbc77ab59d7d2937b10698"}, + {file = "Pillow-8.4.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:3862b7256046fcd950618ed22d1d60b842e3a40a48236a5498746f21189afbbc"}, + {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4901622493f88b1a29bd30ec1a2f683782e57c3c16a2dbc7f2595ba01f639df"}, + {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84c471a734240653a0ec91dec0996696eea227eafe72a33bd06c92697728046b"}, + {file = "Pillow-8.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:244cf3b97802c34c41905d22810846802a3329ddcb93ccc432870243211c79fc"}, + {file = "Pillow-8.4.0.tar.gz", hash = "sha256:b8e2f83c56e141920c39464b852de3719dfbfb6e3c99a2d8da0edf4fb33176ed"}, +] +protobuf = [ + {file = "protobuf-3.19.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d80f80eb175bf5f1169139c2e0c5ada98b1c098e2b3c3736667f28cbbea39fc8"}, + {file = "protobuf-3.19.1-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a529e7df52204565bcd33738a7a5f288f3d2d37d86caa5d78c458fa5fabbd54d"}, + {file = "protobuf-3.19.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28ccea56d4dc38d35cd70c43c2da2f40ac0be0a355ef882242e8586c6d66666f"}, + {file = "protobuf-3.19.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8b30a7de128c46b5ecb343917d9fa737612a6e8280f440874e5cc2ba0d79b8f6"}, + {file = "protobuf-3.19.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5935c8ce02e3d89c7900140a8a42b35bc037ec07a6aeb61cc108be8d3c9438a6"}, + {file = "protobuf-3.19.1-cp36-cp36m-win32.whl", hash = "sha256:74f33edeb4f3b7ed13d567881da8e5a92a72b36495d57d696c2ea1ae0cfee80c"}, + {file = "protobuf-3.19.1-cp36-cp36m-win_amd64.whl", hash = "sha256:038daf4fa38a7e818dd61f51f22588d61755160a98db087a046f80d66b855942"}, + {file = "protobuf-3.19.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e51561d72efd5bd5c91490af1f13e32bcba8dab4643761eb7de3ce18e64a853"}, + {file = "protobuf-3.19.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:6e8ea9173403219239cdfd8d946ed101f2ab6ecc025b0fda0c6c713c35c9981d"}, + {file = "protobuf-3.19.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db3532d9f7a6ebbe2392041350437953b6d7a792de10e629c1e4f5a6b1fe1ac6"}, + {file = "protobuf-3.19.1-cp37-cp37m-win32.whl", hash = "sha256:615b426a177780ce381ecd212edc1e0f70db8557ed72560b82096bd36b01bc04"}, + {file = "protobuf-3.19.1-cp37-cp37m-win_amd64.whl", hash = "sha256:d8919368410110633717c406ab5c97e8df5ce93020cfcf3012834f28b1fab1ea"}, + {file = "protobuf-3.19.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:71b0250b0cfb738442d60cab68abc166de43411f2a4f791d31378590bfb71bd7"}, + {file = "protobuf-3.19.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:3cd0458870ea7d1c58e948ac8078f6ba8a7ecc44a57e03032ed066c5bb318089"}, + {file = "protobuf-3.19.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:655264ed0d0efe47a523e2255fc1106a22f6faab7cc46cfe99b5bae085c2a13e"}, + {file = "protobuf-3.19.1-cp38-cp38-win32.whl", hash = "sha256:b691d996c6d0984947c4cf8b7ae2fe372d99b32821d0584f0b90277aa36982d3"}, + {file = "protobuf-3.19.1-cp38-cp38-win_amd64.whl", hash = "sha256:e7e8d2c20921f8da0dea277dfefc6abac05903ceac8e72839b2da519db69206b"}, + {file = "protobuf-3.19.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fd390367fc211cc0ffcf3a9e149dfeca78fecc62adb911371db0cec5c8b7472d"}, + {file = "protobuf-3.19.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d83e1ef8cb74009bebee3e61cc84b1c9cd04935b72bca0cbc83217d140424995"}, + {file = "protobuf-3.19.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36d90676d6f426718463fe382ec6274909337ca6319d375eebd2044e6c6ac560"}, + {file = "protobuf-3.19.1-cp39-cp39-win32.whl", hash = "sha256:e7b24c11df36ee8e0c085e5b0dc560289e4b58804746fb487287dda51410f1e2"}, + {file = "protobuf-3.19.1-cp39-cp39-win_amd64.whl", hash = "sha256:77d2fadcf369b3f22859ab25bd12bb8e98fb11e05d9ff9b7cd45b711c719c002"}, + {file = "protobuf-3.19.1-py2.py3-none-any.whl", hash = "sha256:e813b1c9006b6399308e917ac5d298f345d95bb31f46f02b60cd92970a9afa17"}, + {file = "protobuf-3.19.1.tar.gz", hash = "sha256:62a8e4baa9cb9e064eb62d1002eca820857ab2138440cb4b3ea4243830f94ca7"}, +] +pycryptodomex = [ + {file = "pycryptodomex-3.11.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:7abfd84a362e4411f7c5f5758c18cbf377a2a2be64b9232e78544d75640c677e"}, + {file = "pycryptodomex-3.11.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:6a76d7821ae43df8a0e814cca32114875916b9fc2158603b364853de37eb9002"}, + {file = "pycryptodomex-3.11.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:1580db5878b1d16a233550829f7c189c43005f7aa818f2f95c7dddbd6a7163cc"}, + {file = "pycryptodomex-3.11.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:c825611a951baad63faeb9ef1517ef96a20202d6029ae2485b729152cc703fab"}, + {file = "pycryptodomex-3.11.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:7cc5ee80b2d5ee8f59a761741cfb916a068c97cac5e700c8ce01e1927616aa2f"}, + {file = "pycryptodomex-3.11.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:fbe09e3ae95f47c7551a24781d2e348974cde4a0b33bc3b1566f6216479db2b1"}, + {file = "pycryptodomex-3.11.0-cp27-cp27m-win32.whl", hash = "sha256:9eace1e5420abc4f9e76de01e49caca349b7c80bda9c1643193e23a06c2a332c"}, + {file = "pycryptodomex-3.11.0-cp27-cp27m-win_amd64.whl", hash = "sha256:adc25aa8cfc537373dd46ae97863f16fd955edee14bf54d3eb52bde4e4ac8c7b"}, + {file = "pycryptodomex-3.11.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cf30b5e03d974874185b989839c396d799f6e2d4b4d5b2d8bd3ba464eb3cc33f"}, + {file = "pycryptodomex-3.11.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:c91772cf6808cc2d80279e80b491c48cb688797b6d914ff624ca95d855c24ee5"}, + {file = "pycryptodomex-3.11.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:c391ec5c423a374a36b90f7c8805fdf51a0410a2b5be9cebd8990e0021cb6da4"}, + {file = "pycryptodomex-3.11.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:64a83ab6f54496ab968a6f21a41a620afe0a742573d609fd03dcab7210645153"}, + {file = "pycryptodomex-3.11.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:252ac9c1e1ae1c256a75539e234be3096f2d100b9f4bae42ef88067787b9b249"}, + {file = "pycryptodomex-3.11.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:bf2ea67eaa1fff0aecef6da881144f0f91e314b4123491f9a4fa8df0598e48fe"}, + {file = "pycryptodomex-3.11.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:fe2b8c464ba335e71aed74f830bf2b2881913f8905d166f9c0fe06ca44a1cb5e"}, + {file = "pycryptodomex-3.11.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:ff0826f3886e85708a0e8ef7ec47020723b998cfed6ae47962d915fcb89ec780"}, + {file = "pycryptodomex-3.11.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:1d4d13c59d2cfbc0863c725f5812d66ff0d6836ba738ef26a52e1291056a1c7c"}, + {file = "pycryptodomex-3.11.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:2b586d13ef07fa6197b6348a48dbbe9525f4f496205de14edfa4e91d99e69672"}, + {file = "pycryptodomex-3.11.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:f35ccfa44a1dd267e392cd76d8525cfcfabee61dd070e15ad2119c54c0c31ddf"}, + {file = "pycryptodomex-3.11.0-cp35-abi3-win32.whl", hash = "sha256:5baf690d27f39f2ba22f06e8e32c5f1972573ca65db6bdbb8b2c7177a0112dab"}, + {file = "pycryptodomex-3.11.0-cp35-abi3-win_amd64.whl", hash = "sha256:919cadcedad552e78349d1626115cfd246fc03ad469a4a62c91a12204f0f0d85"}, + {file = "pycryptodomex-3.11.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:c10b2f6bcbaa9aa51fe08207654100074786d423b03482c0cbe44406ca92d146"}, + {file = "pycryptodomex-3.11.0-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:91662b27f5aa8a6d2ad63be9a7d1a403e07bf3c2c5b265a7cc5cbadf6f988e06"}, + {file = "pycryptodomex-3.11.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:207e53bdbf3a26de6e9dcf3ebaf67ba70a61f733f84c464eca55d278211c1b71"}, + {file = "pycryptodomex-3.11.0-pp27-pypy_73-win32.whl", hash = "sha256:1dd4271d8d022216533c3547f071662b44d703fd5dbb632c4b5e77b3ee47567f"}, + {file = "pycryptodomex-3.11.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c43ddcff251e8b427b3e414b026636617276e008a9d78a44a9195d4bdfcaa0fe"}, + {file = "pycryptodomex-3.11.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:ef25d682d0d9ab25c5022a298b5cba9084c7b148a3e71846df2c67ea664eacc7"}, + {file = "pycryptodomex-3.11.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:4c7c6418a3c08b2ebfc2cf50ce52de267618063b533083a2c73b40ec54a1b6f5"}, + {file = "pycryptodomex-3.11.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:15d25c532de744648f0976c56bd10d07b2a44b7eb2a6261ffe2497980b1102d8"}, + {file = "pycryptodomex-3.11.0.tar.gz", hash = "sha256:0398366656bb55ebdb1d1d493a7175fc48ade449283086db254ac44c7d318d6d"}, +] +requests = [ + {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"}, + {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"}, +] +tqdm = [ + {file = "tqdm-4.62.3-py2.py3-none-any.whl", hash = "sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c"}, + {file = "tqdm-4.62.3.tar.gz", hash = "sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"}, +] +urllib3 = [ + {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"}, + {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"}, +] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..fa643b2 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,24 @@ +[tool.poetry] +name = "orpheusdl" +version = "0.1.0" +description = "A modular music archival program" +authors = ["yarrm80s", "Dniel97"] + +[tool.poetry.scripts] +orpheus = "orpheusdl.orpheus:run" + +[tool.poetry.dependencies] +python = "^3.7" +defusedxml = "^0.7.1" +protobuf = "^3.19.1" +pycryptodomex = "^3.11.0" +requests = "^2.26.0" +Pillow = "^8.4.0" +tqdm = "^4.62.3" +mutagen = "^1.45.1" +ffmpeg-python = "^0.2.0" +appdirs = "^1.4.4" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api"