diff --git a/namer/configuration_utils.py b/namer/configuration_utils.py index 77ecf86b..2f39a3e5 100644 --- a/namer/configuration_utils.py +++ b/namer/configuration_utils.py @@ -6,6 +6,7 @@ import os import random import re +import sys import tempfile from configparser import ConfigParser from datetime import timedelta @@ -167,3 +168,10 @@ def default_config() -> NamerConfig: default_locations = [Path("./namer.cfg")] config.read(default_locations) return from_config(config) + + +def configure_logging_verifier(configuration: NamerConfig, formatter: PartialFormatter) -> bool: + logger.remove() + logger.add(sys.stdout, format="{time} {level} {message}", level="INFO", diagnose=False) + logger.info(str(configuration)) + return verify_configuration(configuration, formatter) diff --git a/poetry.lock b/poetry.lock index 1a088507..92b758e7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -146,6 +146,23 @@ sdist = ["setuptools_rust (>=0.11.4)"] ssh = ["bcrypt (>=3.1.5)"] test = ["pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] +[[package]] +name = "dependency-injector" +version = "4.39.1" +description = "Dependency injection framework for Python" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = ">=1.7.0,<=1.16.0" + +[package.extras] +aiohttp = ["aiohttp"] +flask = ["flask"] +pydantic = ["pydantic"] +yaml = ["pyyaml"] + [[package]] name = "entrypoints" version = "0.4" @@ -348,7 +365,7 @@ colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} [package.extras] -dev = ["sphinx-rtd-theme (>=0.4.3)", "sphinx-autobuild (>=0.7.1)", "Sphinx (>=4.1.1)", "isort (>=5.1.1)", "black (>=19.10b0)", "pytest-cov (>=2.7.1)", "pytest (>=4.6.2)", "tox (>=3.9.0)", "flake8 (>=3.7.7)", "docutils (==0.16)", "colorama (>=0.3.4)"] +dev = ["colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "tox (>=3.9.0)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "black (>=19.10b0)", "isort (>=5.1.1)", "Sphinx (>=4.1.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)"] [[package]] name = "lxml" @@ -420,7 +437,7 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" [[package]] name = "pathvalidate" -version = "2.5.0" +version = "2.5.1" description = "pathvalidate is a Python library to sanitize/validate a string such as filenames/file-paths/etc." category = "main" optional = false @@ -450,8 +467,8 @@ optional = false python-versions = ">=3.6" [package.extras] -testing = ["pytest-benchmark", "pytest"] -dev = ["tox", "pre-commit"] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] [[package]] name = "py" @@ -561,7 +578,7 @@ coverage = {version = ">=5.2.1", extras = ["toml"]} pytest = ">=4.6" [package.extras] -testing = ["virtualenv", "pytest-xdist", "six", "process-tests", "hunter", "fields"] +testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] [[package]] name = "python-dotenv" @@ -862,7 +879,7 @@ optional = false python-versions = ">=3.5" [package.extras] -dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] +dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"] [[package]] name = "wsproto" @@ -890,7 +907,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest- [metadata] lock-version = "1.1" python-versions = ">=3.8,<3.11" -content-hash = "345b5004b868098c7a1b4e0f1049dfc1a62d7eb8cd0e56dfe80f8ece28c5b3bb" +content-hash = "ff54fa3bad6c8a90f5ade8954cfb40dffb53060380905cec47308f7e7f824573" [metadata.files] appdirs = [ @@ -904,9 +921,7 @@ async-generator = [ {file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"}, {file = "async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"}, ] -atomicwrites = [ - {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"}, -] +atomicwrites = [] attrs = [ {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, @@ -1128,6 +1143,44 @@ cryptography = [ {file = "cryptography-37.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4c590ec31550a724ef893c50f9a97a0c14e9c851c85621c5650d699a7b88f7ab"}, {file = "cryptography-37.0.4.tar.gz", hash = "sha256:63f9c17c0e2474ccbebc9302ce2f07b55b3b3fcb211ded18a42d5764f5c10a82"}, ] +dependency-injector = [ + {file = "dependency-injector-4.39.1.tar.gz", hash = "sha256:9ab76dc5e19b2692aaca49e00f9b41a087138d139b0ec985f92ff0498f038772"}, + {file = "dependency_injector-4.39.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c788a3d5482e63b5fd55e14fc258f1ff0b51b411927ab132ef0f689cb5d1183f"}, + {file = "dependency_injector-4.39.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0832e0457a360725cd1d1037b77b85478aeeaacc60e85ecceeb8020409e7b62"}, + {file = "dependency_injector-4.39.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d51998fff9704fd01d11c3c48f4e88d8506cb6afa1ee41409a881a5a51dae3fc"}, + {file = "dependency_injector-4.39.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea484cd13fc62966bf5582df0816205feee072d18f228aac75f7807b43f223ae"}, + {file = "dependency_injector-4.39.1-cp310-cp310-win32.whl", hash = "sha256:17389e53ec29ca13570319cf2065dcc4c2f6d36db5dd792bb1e8f2c39a9f146b"}, + {file = "dependency_injector-4.39.1-cp310-cp310-win_amd64.whl", hash = "sha256:55b0988489267c5a580f419133770ffe293057f2064da1c9ad6a2cc69666739b"}, + {file = "dependency_injector-4.39.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b297c3e79d3633cc56366386ae1f7dbce1587673cca2f559c368c1e936a1fa94"}, + {file = "dependency_injector-4.39.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2728827c5abb2420c5811e218262ae1b77a48e76cc9eebc6b4f55fee48a1a18d"}, + {file = "dependency_injector-4.39.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:029e42b064ab8cb5b2559be040ff682c7aa81592f1654a82355475956df17803"}, + {file = "dependency_injector-4.39.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:305e3db3f4bf40f64caaa1303e03005174e78d2339d2ae517b34c011ec2300f9"}, + {file = "dependency_injector-4.39.1-cp36-cp36m-win32.whl", hash = "sha256:a661dd23a5e4e2f6bf4a729de7fadbe148c9a4a298dbcadfc5a94584b6930970"}, + {file = "dependency_injector-4.39.1-cp36-cp36m-win_amd64.whl", hash = "sha256:340d6e7af5c4729d20c837d6d1e8a2626c24a05259dff746406cc823e26ba1e7"}, + {file = "dependency_injector-4.39.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a1553dac1c95f0de1f910b0025ee4570ea078a07d576bcdc2168990e719cea50"}, + {file = "dependency_injector-4.39.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c7baaa64d93359ee08c15d68579cc803e11d9becaf961f5a66b94ff627248e1"}, + {file = "dependency_injector-4.39.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7a27bf1951a066cf347b886cc7ab0f37dcbd1ad59bffcfe721c8c12a189a150d"}, + {file = "dependency_injector-4.39.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:da6e2d685f7d0c65257f08133b68d9bf74ec319b90a0f21b4f629d168ce5f68f"}, + {file = "dependency_injector-4.39.1-cp37-cp37m-win32.whl", hash = "sha256:a8ddd03ca86e67e9d3cc038793d34fbfccab12e6145df813e72bf14f9371f2ea"}, + {file = "dependency_injector-4.39.1-cp37-cp37m-win_amd64.whl", hash = "sha256:e01a319ea05cd86b520201386dcb53a81a5400cb82fcc2f006bd7e92c0c51a0a"}, + {file = "dependency_injector-4.39.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4704804bde25b694aa65201927937a9d82d8bc055cb3dadc68eb05988bd34fa9"}, + {file = "dependency_injector-4.39.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0935d50b263169e7b0826a2fb6be80d6a4f2a7c59e6dd9876f86da3243bea9eb"}, + {file = "dependency_injector-4.39.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3c34aa5abb1826b6189f47daf6e469d4293c1d01693233da2c1b923816270cc5"}, + {file = "dependency_injector-4.39.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:db64904c9b9a88756cfece3e3ed078a2b57127642711dd08af342dba8abf9667"}, + {file = "dependency_injector-4.39.1-cp38-cp38-win32.whl", hash = "sha256:66ebe728194adc8720dbc4d662edbbfa55659ff23c9c493fb2dae0bfd4df5734"}, + {file = "dependency_injector-4.39.1-cp38-cp38-win_amd64.whl", hash = "sha256:4349974620f630d6726808e1291ec99713b64d449b84eb01581ee807a5a5c224"}, + {file = "dependency_injector-4.39.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d87cad0899b05cd08931bfb68ddf7be77711a67b0649c37f2045d7808977b082"}, + {file = "dependency_injector-4.39.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8efd965e5cfdd9f339ec895e73c119569851adedc175088d34a670f5206fea63"}, + {file = "dependency_injector-4.39.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:27f69485ca6b85c31d162ee86cf6ef71bb71dce9cd2b5d0745425dfc551eefa1"}, + {file = "dependency_injector-4.39.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a25b63de59dff04ec78f5161f00c0222a04a23def5d1f0eda14e389a32baf428"}, + {file = "dependency_injector-4.39.1-cp39-cp39-win32.whl", hash = "sha256:a14274f50d125b4579314c355e22af07def1a96641ca94bd75edcf1400b89477"}, + {file = "dependency_injector-4.39.1-cp39-cp39-win_amd64.whl", hash = "sha256:9950039d00625f9252cd26378a4406342b256886bb61e4db8b65e9f01270f53e"}, + {file = "dependency_injector-4.39.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6d7f39cd54678741e132e13da3a1367ac18058cbda61fe39d61c8583aa6fd757"}, + {file = "dependency_injector-4.39.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2368c7ba3c9ffaf816ea0f2d14c78d481491b805f62ac8496a78a51397d4689"}, + {file = "dependency_injector-4.39.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:84e32407bb16c58aa0d4b5ed8485537bc66ccc14cfffae7022f1204e35ec939a"}, + {file = "dependency_injector-4.39.1-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f2d80a42c546e1f934d427b071630d86653cd4a60c74b570c4ffb03025c1f1f9"}, + {file = "dependency_injector-4.39.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ca126bbed370b8c002c859ebeb76f6d83eba2d7fb5d66f37f47cfc19661d2889"}, +] entrypoints = [ {file = "entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f"}, {file = "entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4"}, @@ -1431,8 +1484,8 @@ packaging = [ {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] pathvalidate = [ - {file = "pathvalidate-2.5.0-py3-none-any.whl", hash = "sha256:e5b2747ad557363e8f4124f0553d68878b12ecabd77bcca7e7312d5346d20262"}, - {file = "pathvalidate-2.5.0.tar.gz", hash = "sha256:119ba36be7e9a405d704c7b7aea4b871c757c53c9adc0ed64f40be1ed8da2781"}, + {file = "pathvalidate-2.5.1-py3-none-any.whl", hash = "sha256:8dbbc64e78e874ddff049ac187499d8bf34f890adb8b7f657e134a842832d3b9"}, + {file = "pathvalidate-2.5.1.tar.gz", hash = "sha256:bbc27e653335aba7935a2ade2299622e76a9487bc9004cdcf1441ce8d2ff4a54"}, ] pillow = [ {file = "Pillow-9.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:a9c9bc489f8ab30906d7a85afac4b4944a572a7432e00698a7239f44a44e6efb"}, diff --git a/pyproject.toml b/pyproject.toml index 5779432b..92842b83 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,6 +25,7 @@ Pillow = "^9.1.1" requests-cache = "^0.9.4" ffmpeg-python = "^0.2.0" ImageHash = "^4.2.1" +dependency-injector = "^4.39.1" [tool.poetry.dev-dependencies] pytest = "^7.0.0" diff --git a/test/namer_container_test.py b/test/namer_container_test.py new file mode 100644 index 00000000..998845bd --- /dev/null +++ b/test/namer_container_test.py @@ -0,0 +1,95 @@ +from pathlib import Path +import shutil +import unittest + +from namer.filenameparts import parse_file_name +from namer.ffmpeg import ffprobe +from namer.name_formatter import PartialFormatter +from namer.configuration_utils import default_config, configure_logging_verifier + +from test.utils import environment + +from dependency_injector import containers, providers + + +class Services(containers.DeclarativeContainer): + + # Namer's external configuration - perhaps redundant or highly coupled, or both + namer_configuration = providers.Singleton( + default_config + ) + + # The formatter that can convert FileNameParts to a full name + name_formatter = providers.Singleton( + PartialFormatter + ) + + properly_configured = providers.Singleton( + configure_logging_verifier, + configuration=namer_configuration, + formatter=name_formatter, + ) + + +class WorkItem(containers.DeclarativeContainer): + + config = providers.Configuration() + + services = providers.Container( + Services, + ) + + target_file = providers.Singleton( + str, + config.get("file") + ) + + target_path = providers.Singleton( + Path, + target_file + ) + + ffprobe_results = providers.Singleton( + ffprobe, + target_path + ) + + file_name_parts = providers.Singleton( + parse_file_name, + filename=target_file, + # TODO: regex_config=services.namer_configuration.name_parser + ) + + +class UnitTestAsTheDefaultExecution(unittest.TestCase): + """ + Always test first. + """ + def test_get_resolution(self): + with environment() as (tempdir, _parrot, config): + container = Services() + container.namer_configuration.override(providers.Object(config)) + for provider in container.traverse(): + print(provider) + print(container) + + container.load_config() + container.check_dependencies() + container.init_resources() + + self.assertTrue(container.properly_configured()) + item_container = WorkItem() + + test_dir = Path(__file__).resolve().parent + target_file = (tempdir / "DorcelClub - 2021-12-23 - Aya.Benetti.Megane.Lopez.And.Bella.Tina.mp4") + shutil.copy(test_dir / "Site.22.01.01.painful.pun.XXX.720p.xpost.mp4", target_file) + + item_container = WorkItem() + item_container.assign_parent(container) + item_container.target_file.override(providers.Object(str(target_file))) + ffprobe_results = item_container.ffprobe_results() + file_name_parts = item_container.file_name_parts() + self.assertIsNotNone(ffprobe_results) + self.assertIsNotNone(file_name_parts) + + print("okay") diff --git a/test/utils.py b/test/utils.py index 2ec03543..9f79a5bc 100644 --- a/test/utils.py +++ b/test/utils.py @@ -126,6 +126,14 @@ def environment(config: NamerConfig = sample_config()): with tempfile.TemporaryDirectory(prefix="test") as tmpdir: with FakeTPDB() as fakeTpdb: tempdir = Path(tmpdir) + config.watch_dir = tempdir / "watch" + config.watch_dir.mkdir(parents=True, exist_ok=True) + config.failed_dir = tempdir / "failed" + config.failed_dir.mkdir(parents=True, exist_ok=True) + config.dest_dir = tempdir / "dest" + config.dest_dir.mkdir(parents=True, exist_ok=True) + config.work_dir = tempdir / "working" + config.work_dir.mkdir(parents=True, exist_ok=True) config.override_tpdb_address = fakeTpdb.get_url() yield tempdir, fakeTpdb, config