From 27f6c057885a4aba24dd118166e9d0e97b230c1f Mon Sep 17 00:00:00 2001 From: Labrys of Knossos Date: Mon, 19 Dec 2022 15:13:03 -0500 Subject: [PATCH] Fix lint errors --- .flake8 | 62 ++++++++++++++ .pre-commit-config.yaml | 37 ++++++++- .pylintrc.ini => .pylintrc | 131 +++++++++++++++--------------- TorrentToMedia.py | 12 +-- azure-pipelines.yml | 14 ++++ dev-requirements.txt | 7 +- nzb2media/__init__.py | 20 +---- nzb2media/auto_process/games.py | 2 +- nzb2media/auto_process/movies.py | 4 +- nzb2media/auto_process/music.py | 4 +- nzb2media/auto_process/tv.py | 20 ++--- nzb2media/configuration.py | 5 +- nzb2media/extractor/__init__.py | 8 +- nzb2media/github_api.py | 8 +- nzb2media/main_db.py | 6 +- nzb2media/managers/sickbeard.py | 9 +- nzb2media/processor/manual.py | 2 +- nzb2media/processor/nzb.py | 2 +- nzb2media/processor/sab.py | 1 + nzb2media/scene_exceptions.py | 2 +- nzb2media/transcoder.py | 33 ++++---- nzb2media/user_scripts.py | 4 +- nzb2media/utils/encoding.py | 3 +- nzb2media/utils/identification.py | 2 +- nzb2media/utils/links.py | 5 +- nzb2media/utils/naming.py | 8 +- nzb2media/utils/parsers.py | 2 +- nzb2media/utils/paths.py | 6 +- nzb2media/utils/processes.py | 8 +- nzb2media/utils/torrent.py | 30 +++---- nzb2media/version_check.py | 39 ++++----- nzbToMedia.py | 2 +- tests/transcoder_test.py | 9 +- tox.ini | 91 +-------------------- 34 files changed, 313 insertions(+), 285 deletions(-) create mode 100644 .flake8 rename .pylintrc.ini => .pylintrc (98%) diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..77a9a30a --- /dev/null +++ b/.flake8 @@ -0,0 +1,62 @@ +[flake8] +max-line-length = 79 +max-doc-length = 79 +verbose = 2 +statistics = True +min-version = 2.7 +require-code = True +exclude = + .github/ + .pytest_cache/ + .tox/ + .venv*/ + build/ + htmlcov/ + logs/ +ignore = +; -- flake8 -- +; E501 line too long +; E722 do not use bare 'except' (duplicates B001) +; W503 line break before binary operator +; W505 doc line too long + E501, E722, W503, W505 + +; -- flake8-docstrings -- +; D100 Missing docstring in public module +; D101 Missing docstring in public class +; D102 Missing docstring in public method +; D103 Missing docstring in public function +; D104 Missing docstring in public package +; D105 Missing docstring in magic method +; D107 Missing docstring in __init__ +; D200 One-line docstring should fit on one line with quotes +; D202 No blank lines allowed after function docstring +; D205 1 blank line required between summary line and description +; D400 First line should end with a period +; D401 First line should be in imperative mood +; D402 First line should not be the function's "signature" + D100, D101, D102, D103, D104, D105, D107 + +; -- flake8-future-import -- +; x = 1 for missing, 5 for present +; FIx6 nested_scopes 2.2 +; FIx7 generators 2.3 +; FIx2 with_statement 2.6 +; FIx1 absolute_import 3.0 +; FIx0 division 3.0 +; FIx3 print_function 3.0 +; FIx4 unicode_literals 3.0 +; FIx5 generator_stop 3.7 +; FIx8 annotations 4.0 +; FI90 __future__ import does not exist + FI10, FI11, FI13, FI14, FI58 + +per-file-ignores = +; F401 imported but unused +; E402 module level import not at top of file +; nzbTo*.py: E265, E266, E402 +; TorrentToMedia.py: E402 +; nzb2media/__init__.py: E402, F401 +; nzb2media/utils/__init__.py: F401 +; nzb2media/plugins/downloaders/configuration.py: F401 +; nzb2media/plugins/downloaders/utils.py: F401 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9328ea82..26d1a63c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,10 +5,45 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml + - id: check-json + - id: check-toml + - id: check-xml + - id: check-case-conflict - id: debug-statements + - id: detect-private-key - id: double-quote-string-fixer + - id: fix-byte-order-marker - id: name-tests-test - id: requirements-txt-fixer +- repo: https://github.com/pycqa/flake8 + rev: '6.0.0' + hooks: + - id: flake8 + name: Flake8 primary tests + additional_dependencies: + - flake8-bugbear + - flake8-commas + - flake8-comprehensions + - flake8-docstrings + - flake8-future-import + - id: flake8 + name: Flake8 selective tests + args: [ + # ** SELECTIVE TESTS ** + # Run flake8 tests (with plugins) for specific optional codes defined below + # -- flake8 -- + # E123 closing bracket does not match indentation of opening bracket’s line + # E226 missing whitespace around arithmetic operator + # E241 multiple spaces after ‘,’ + # E242 tab after ‘,’ + # E704 multiple statements on one line + # W504 line break after binary operator + # W505 doc line too long + # -- flake8-bugbear -- + # B902 Invalid first argument used for instance method. + # B903 Data class should be immutable or use __slots__ to save memory. + '--select=B902,B903,E123,E226,E241,E242,E704,W504,W505' + ] - repo: https://github.com/asottile/add-trailing-comma rev: v2.4.0 hooks: @@ -34,5 +69,5 @@ repos: [ "-rn", # Only display messages "-sn", # Disable score - "--rcfile=.pylintrc.ini", # Link to your config file + "--rcfile=.pylintrc", # Link to your config file ] diff --git a/.pylintrc.ini b/.pylintrc similarity index 98% rename from .pylintrc.ini rename to .pylintrc index cc89f12c..f983f23e 100644 --- a/.pylintrc.ini +++ b/.pylintrc @@ -38,6 +38,70 @@ load-plugins= # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" +# See below for a list of codes + +disable= + E1101, # no-member + + W0141, # bad-builtin + W0149, # while-used + W0160, # consider-ternary-expression + W0201, # attribute-defined-outside-init + W0212, # protected-access + W0511, # fixme + W0601, # global-variable-undefined + W0602, # global-variable-not-assigned + W0603, # global-statement + W0612, # unused-variable + W0621, # redefined-outer-name + W0631, # undefined-loop-variable + W0703, # broad-except + W0717, # too-many-try-statements + W1202, # logging-format-interpolation + W1203, # logging-fstring-interpolation + W1404, # implicit-str-concat + W2901, # redefined-loop-name + W3101, # missing-timeout + W6001, # deprecated-typing-alias + + C0103, # invalid-name + C0114, # missing-module-docstring + C0115, # missing-class-docstring + C0116, # missing-function-docstring + C0201, # consider-iterating-dictionary + C0206, # consider-using-dict-items + C0301, # line-too-long + C0415, # import-outside-toplevel + + R0204, # redifined-variable-type + R0401, # cyclic-import + R0801, # duplicate-code + R0903, # too-few-public-methods + R0902, # too-many-instance-attributes + R0911, # too-many-return-statements + R0912, # too-many-branches + R0913, # too-many-arguments + R0914, # too-many-locals + R0915, # too-many-statements + R0916, # too-many-boolean-expressions + R1260, # too-complex + R1702, # too-many-nested-blocks + R1704, # redefined-argument-from-local + R1710, # inconsistent-return-statements + R5601, # confusing-consecutive-elif + R6103, # consider-using-assignment-expr + + I0011, # locally-disabled + I0020, # suppressed-message + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable= + + +# ------------------------ CODES ------------------------ ; # --- FATAL --------- ; F0001, # fatal ; F0002, # astroid-error @@ -459,70 +523,3 @@ load-plugins= ; I0022, # deprecated-pragma ; I0023, # use-symbolic-message-instead ; I1101, # c-extension-no-member - -disable= - E1101, # no-member - - W0141, # bad-builtin - W0149, # while-used - W0160, # consider-ternary-expression - W0201, # attribute-defined-outside-init - W0212, # protected-access - W0511, # fixme - W0601, # global-variable-undefined - W0602, # global-variable-not-assigned - W0603, # global-statement - W0612, # unused-variable - W0621, # redefined-outer-name - W0631, # undefined-loop-variable - W0703, # broad-except - W0717, # too-many-try-statements - W1202, # logging-format-interpolation - W1203, # logging-fstring-interpolation - W1404, # implicit-str-concat - W2901, # redefined-loop-name - W3101, # missing-timeout - W6001, # deprecated-typing-alias - W9016, # missing-type-do - - C0103, # invalid-name - C0114, # missing-module-docstring - C0115, # missing-class-docstring - C0116, # missing-function-docstring - C0199, # docstring-first-line-empty - C0201, # consider-iterating-dictionary - C0206, # consider-using-dict-items - C0301, # line-too-long - C0415, # import-outside-toplevel - C1901, # compare-to-empty-string - C2001, # compare-to-zero - - R0204, # redifined-variable-type - R0401, # cyclic-import - R0801, # duplicate-code - R0903, # too-few-public-methods - R0902, # too-many-instance-attributes - R0911, # too-many-return-statements - R0912, # too-many-branches - R0913, # too-many-arguments - R0914, # too-many-locals - R0915, # too-many-statements - R0916, # too-many-boolean-expressions - R1260, # too-complex - R1702, # too-many-nested-blocks - R1704, # redefined-argument-from-local - R1710, # inconsistent-return-statements - R5501, # else-if-used - R5601, # confusing-consecutive-elif - R6003, # consider-alternative-union-syntax - R6102, # consider-using-tuple - R6103, # consider-using-assignment-expr - - I0011, # locally-disabled - I0020, # suppressed-message - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). See also the "--disable" option for examples. -enable= diff --git a/TorrentToMedia.py b/TorrentToMedia.py index b8b367e5..965d1b44 100755 --- a/TorrentToMedia.py +++ b/TorrentToMedia.py @@ -53,7 +53,7 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp input_directory, input_name, input_category, root, nzb2media.CATEGORIES, ) - if input_category == '': + if not input_category: input_category = 'UNCAT' usercat = input_category @@ -132,7 +132,7 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp input_files = nzb2media.list_media_files(input_directory, archives=False, other=True, otherext=extensions) else: input_files = nzb2media.list_media_files(input_directory, other=True, otherext=extensions) - if len(input_files) == 0 and os.path.isfile(input_directory): + if not input_files and os.path.isfile(input_directory): input_files = [input_directory] log.debug(f'Found 1 file to process: {input_directory}') else: @@ -173,7 +173,7 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp else: continue # This file has not been recently moved or created, skip it - if torrent_no_link == 0: + if not torrent_no_link: try: nzb2media.copy_link(input_file, target_file, nzb2media.USE_LINK) nzb2media.remove_read_only(target_file) @@ -246,7 +246,7 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp plex_update(input_category) - if result.status_code != 0: + if result.status_code: if not nzb2media.TORRENT_RESUME_ON_FAILURE: log.error( 'A problem was reported in the autoProcess* script. ' @@ -344,11 +344,11 @@ def main(args): dir_name, input_name, subsection, input_hash or None, input_id or None, client_agent, ) - if results.status_code != 0: + if results.status_code: log.error(f'A problem was reported when trying to perform a manual run for {section}:{subsection}.') result = results - if result.status_code == 0: + if not result.status_code: log.info(f'The {args[0]} script completed successfully.') else: log.error(f'A problem was reported in the {args[0]} script.') diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c51472ed..9315f174 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -7,6 +7,20 @@ trigger: - master jobs: +- job: 'Lint' + pool: + vmImage: 'Ubuntu-latest' + + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.x' + architecture: 'x64' + + - script: | + pip install pre-commit pylint -r requirements.txt + pre-commit run --all-files + displayName: 'Run pre-commit tests' - job: 'Test' pool: diff --git a/dev-requirements.txt b/dev-requirements.txt index b05affb1..aff42463 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,10 @@ -black bump2version +flake8 +flake8-bugbear +flake8-commas +flake8-comprehensions +flake8-docstrings +flake8-future-import mypy pre-commit pylint[spelling] diff --git a/nzb2media/__init__.py b/nzb2media/__init__.py index d4332f0e..6d5f4795 100644 --- a/nzb2media/__init__.py +++ b/nzb2media/__init__.py @@ -11,11 +11,11 @@ import subprocess import sys import time import typing -from subprocess import PIPE, DEVNULL +from subprocess import DEVNULL -from nzb2media import tool from nzb2media import databases from nzb2media import main_db +from nzb2media import tool from nzb2media import version_check from nzb2media.configuration import Config from nzb2media.nzb.configuration import configure_nzbs @@ -29,22 +29,6 @@ from nzb2media.utils.processes import restart log = logging.getLogger(__name__) log.addHandler(logging.NullHandler()) -try: - import win32event -except ImportError: - if sys.platform == 'win32': - sys.exit('Please install pywin32') - - -def which(name) -> pathlib.Path | None: - with subprocess.Popen(['which', name], stdout=PIPE) as proc: - try: - proc_out, proc_err = proc.communicate() - except Exception: - return None - else: - location = proc_out.strip().decode() - return pathlib.Path(location) def module_path(module=__file__): diff --git a/nzb2media/auto_process/games.py b/nzb2media/auto_process/games.py index cb3a0c7e..9679c841 100644 --- a/nzb2media/auto_process/games.py +++ b/nzb2media/auto_process/games.py @@ -41,7 +41,7 @@ def process(*, section: str, dir_name: str, input_name: str = '', status: int = input_name, dir_name = convert_to_ascii(input_name, dir_name) fields = input_name.split('-') gamez_id = fields[0].replace('[', '').replace(']', '').replace(' ', '') - download_status = 'Downloaded' if status == 0 else 'Wanted' + download_status = 'Downloaded' if not status else 'Wanted' params = {'api_key': apikey, 'mode': 'UPDATEREQUESTEDSTATUS', 'db_id': gamez_id, 'status': download_status} log.debug(f'Opening URL: {url}') try: diff --git a/nzb2media/auto_process/movies.py b/nzb2media/auto_process/movies.py index 5c217677..273c95a6 100644 --- a/nzb2media/auto_process/movies.py +++ b/nzb2media/auto_process/movies.py @@ -151,10 +151,10 @@ def process(*, section: str, dir_name: str, input_name: str = '', status: int = status = 1 if 'NZBOP_VERSION' in os.environ and os.environ['NZBOP_VERSION'][0:5] >= '14.0': print('[NZB] MARK=BAD') - if status == 0: + if not status: if nzb2media.TRANSCODE == 1: result, new_dir_name = transcoder.transcode_directory(dir_name) - if result == 0: + if not result: log.debug(f'Transcoding succeeded for files in {dir_name}') dir_name = new_dir_name log.debug(f'Config setting \'chmodDirectory\' currently set to {oct(chmod_directory)}') diff --git a/nzb2media/auto_process/music.py b/nzb2media/auto_process/music.py index 8353e375..3fbbd605 100644 --- a/nzb2media/auto_process/music.py +++ b/nzb2media/auto_process/music.py @@ -69,7 +69,7 @@ def process(*, section: str, dir_name: str, input_name: str = '', status: int = # if listMediaFiles(dir_name, media=False, audio=True, meta=False, archives=False) and status: # logger.info('Status shown as failed from Downloader, but valid video files found. Setting as successful.', SECTION) # status = 0 - if status == 0 and section == 'HeadPhones': + if not status and section == 'HeadPhones': params = {'apikey': apikey, 'cmd': 'forceProcess', 'dir': remote_dir(dir_name) if remote_path else dir_name} res = force_process(params, url, apikey, input_name, dir_name, section, wait_for) if res.status_code in {0, 1}: @@ -81,7 +81,7 @@ def process(*, section: str, dir_name: str, input_name: str = '', status: int = # The status hasn't changed. uTorrent can resume seeding now. log.warning(f'The music album does not appear to have changed status after {wait_for} minutes. Please check your Logs') return ProcessResult.failure(f'{section}: Failed to post-process - No change in wanted status') - if status == 0 and section == 'Lidarr': + if not status and section == 'Lidarr': route = f'{web_root}/api/v1/command' url = nzb2media.utils.common.create_url(scheme, host, port, route) headers = {'X-Api-Key': apikey} diff --git a/nzb2media/auto_process/tv.py b/nzb2media/auto_process/tv.py index 66ef4fa6..a5827260 100644 --- a/nzb2media/auto_process/tv.py +++ b/nzb2media/auto_process/tv.py @@ -130,10 +130,10 @@ def process(*, section: str, dir_name: str, input_name: str = '', status: int = import_subs(video) rename_subs(dir_name) if num_files > 0: - if valid_files == num_files and not status == 0: + if valid_files == num_files and status: log.info('Found Valid Videos. Setting status Success') status = 0 - if valid_files < num_files and status == 0: + if valid_files < num_files and not status: log.info('Found corrupt videos. Setting status Failed') status = 1 if 'NZBOP_VERSION' in os.environ and os.environ['NZBOP_VERSION'][0:5] >= '14.0': @@ -150,7 +150,7 @@ def process(*, section: str, dir_name: str, input_name: str = '', status: int = return ProcessResult.success() elif nzb_extraction_by == 'Destination': log.info('Check for media files ignored because nzbExtractionBy is set to Destination.') - if status == 0: + if not status: log.info('Setting Status Success.') else: log.info('Downloader reported an error during download or verification. Processing this as a failed download.') @@ -160,9 +160,10 @@ def process(*, section: str, dir_name: str, input_name: str = '', status: int = status = 1 if 'NZBOP_VERSION' in os.environ and os.environ['NZBOP_VERSION'][0:5] >= '14.0': print('[NZB] MARK=BAD') - if status == 0 and nzb2media.TRANSCODE == 1: # only transcode successful downloads + if not status and nzb2media.TRANSCODE == 1: + # only transcode successful downloads result, new_dir_name = transcoder.transcode_directory(dir_name) - if result == 0: + if not result: log.debug(f'SUCCESS: Transcoding succeeded for files in {dir_name}') dir_name = new_dir_name log.debug(f'Config setting \'chmodDirectory\' currently set to {oct(chmod_directory)}') @@ -230,7 +231,7 @@ def process(*, section: str, dir_name: str, input_name: str = '', status: int = for key, val in list(fork_params.items()): if val is None: del fork_params[key] - if status == 0: + if not status: if section == 'NzbDrone' and not apikey: log.info('No Sonarr apikey entered. Processing completed.') return ProcessResult.success(f'{section}: Successfully post-processed {input_name}') @@ -338,9 +339,8 @@ def process(*, section: str, dir_name: str, input_name: str = '', status: int = elif section == 'SiCKRAGE': if api_version >= 2: success = True - else: - if response.json()['result'] == 'success': - success = True + elif response.json()['result'] == 'success': + success = True elif section == 'NzbDrone': try: res = response.json() @@ -351,7 +351,7 @@ def process(*, section: str, dir_name: str, input_name: str = '', status: int = log.warning(f'No scan id was returned due to: {error}') scan_id = None started = False - if status != 0 and delete_failed and not os.path.dirname(dir_name) == dir_name: + if status and delete_failed and not os.path.dirname(dir_name) == dir_name: log.debug(f'Deleting failed files and folder {dir_name}') remove_dir(dir_name) if success: diff --git a/nzb2media/configuration.py b/nzb2media/configuration.py index ebce7c1b..19b23bd2 100644 --- a/nzb2media/configuration.py +++ b/nzb2media/configuration.py @@ -73,9 +73,8 @@ class Section(configobj.Section): if key in options: return options[key] del subsections[subsection] - else: - if section not in key: - del to_return[section] + elif section not in key: + del to_return[section] # cleanout empty sections and subsections for key in [k for (k, v) in to_return.items() if not v]: del to_return[key] diff --git a/nzb2media/extractor/__init__.py b/nzb2media/extractor/__init__.py index 5e6b8772..327b09f4 100644 --- a/nzb2media/extractor/__init__.py +++ b/nzb2media/extractor/__init__.py @@ -113,21 +113,21 @@ def extract(file_path, output_destination): cmd2.append('-p-') # don't prompt for password. with Popen(cmd2, stdout=DEVNULL, stderr=DEVNULL, startupinfo=info) as proc: res = proc.wait() # should extract files fine. - if res == 0: # Both Linux and Windows return 0 for successful. + if not res: # Both Linux and Windows return 0 for successful. log.info(f'EXTRACTOR: Extraction was successful for {file_path} to {output_destination}') success = 1 elif len(passwords) > 0 and 'gunzip' not in cmd: log.info('EXTRACTOR: Attempting to extract with passwords') for password in passwords: - if password == '': # if edited in windows or otherwise if blank lines. - continue + if not password: + continue # if edited in windows or otherwise if blank lines. cmd2 = cmd # append password here. passcmd = f'-p{password}' cmd2.append(passcmd) with Popen(cmd2, stdout=DEVNULL, stderr=DEVNULL, startupinfo=info) as proc: res = proc.wait() # should extract files fine. - if (res >= 0 and platform == 'Windows') or res == 0: + if not res or (res >= 0 and platform == 'Windows'): log.info(f'EXTRACTOR: Extraction was successful for {file_path} to {output_destination} using password: {password}') success = 1 break diff --git a/nzb2media/github_api.py b/nzb2media/github_api.py index beeced0b..c45a1591 100644 --- a/nzb2media/github_api.py +++ b/nzb2media/github_api.py @@ -20,8 +20,8 @@ class GitHub: return data.json() if data.ok else [] def commits(self): - """ - Get the 100 most recent commits from the specified user/repo/branch, starting from HEAD. + """Get the 100 most recent commits from the specified user/repo/branch, starting from HEAD. + user: The github username of the person whose repo you're querying repo: The repo name to query branch: Optional, the branch name to show commits from @@ -30,8 +30,8 @@ class GitHub: return self._access_api(['repos', self.github_repo_user, self.github_repo, 'commits'], params={'per_page': 100, 'sha': self.branch}) def compare(self, base, head, per_page=1): - """ - Get compares between base and head. + """Get compares between base and head. + user: The github username of the person whose repo you're querying repo: The repo name to query base: Start compare from branch diff --git a/nzb2media/main_db.py b/nzb2media/main_db.py index 373de1b6..e842e988 100644 --- a/nzb2media/main_db.py +++ b/nzb2media/main_db.py @@ -11,9 +11,9 @@ log = logging.getLogger(__name__) log.addHandler(logging.NullHandler()) -def db_filename(filename='nzbtomedia.db', suffix=None): - """ - Return the correct location of the database file. +def db_filename(filename: str = 'nzbtomedia.db', suffix: str | None = None): + """Return the correct location of the database file. + @param filename: The sqlite database filename to use. If not specified, will be made to be nzbtomedia.db @param suffix: The suffix to append to the filename. A '.' will be added automatically, i.e. suffix='v0' will make dbfile.db.v0 diff --git a/nzb2media/managers/sickbeard.py b/nzb2media/managers/sickbeard.py index f245afcd..e1d84cd2 100644 --- a/nzb2media/managers/sickbeard.py +++ b/nzb2media/managers/sickbeard.py @@ -17,6 +17,7 @@ log.addHandler(logging.NullHandler()) class InitSickBeard: """SickBeard init class. + Used to determine which SickBeard fork object to initialize. """ @@ -204,7 +205,9 @@ class InitSickBeard: def _init_fork(self): # These need to be imported here, to prevent a circular import. - from .pymedusa import PyMedusa, PyMedusaApiV1, PyMedusaApiV2 + from .pymedusa import PyMedusa + from .pymedusa import PyMedusaApiV1 + from .pymedusa import PyMedusaApiV2 mapped_forks = {'Medusa': PyMedusa, 'Medusa-api': PyMedusaApiV1, 'Medusa-apiv2': PyMedusaApiV2} log.debug(f'Create object for fork {self.fork}') @@ -243,7 +246,8 @@ class SickBeard: self.success = False def initialize(self, dir_name, input_name=None, failed=False, client_agent='manual'): - """We need to call this explicitely because we need some variables. + """We need to call this explicitly because we need some variables. + We can't pass these directly through the constructor. """ self.dir_name = dir_name @@ -358,6 +362,7 @@ class SickBeard: def process_response(self, response: requests.Response) -> ProcessResult: """Iterate over the lines returned, and log. + :param response: Streamed Requests response object. This method will need to be overwritten in the forks, for alternative response handling. """ diff --git a/nzb2media/processor/manual.py b/nzb2media/processor/manual.py index c272bbd4..c4b46d23 100644 --- a/nzb2media/processor/manual.py +++ b/nzb2media/processor/manual.py @@ -38,7 +38,7 @@ def process(): continue input_name = os.path.basename(dir_name) results = nzb.process(dir_name, input_name, 0, client_agent=client_agent, download_id=download_id or None, input_category=subsection) - if results.status_code != 0: + if results.status_code: log.error(f'A problem was reported when trying to perform a manual run for {section}:{subsection}.') result = results return result diff --git a/nzb2media/processor/nzb.py b/nzb2media/processor/nzb.py index 156fee7c..93ac9f7d 100644 --- a/nzb2media/processor/nzb.py +++ b/nzb2media/processor/nzb.py @@ -85,7 +85,7 @@ def process(input_directory, input_name=None, status=0, client_agent='manual', d processor = process_map[section_name] result = processor(section=section_name, dir_name=input_directory, input_name=input_name, status=status, client_agent=client_agent, download_id=download_id, input_category=input_category, failure_link=failure_link) plex_update(input_category) - if result.status_code == 0: + if not result.status_code: if client_agent != 'manual': # update download status in our DB update_download_info_status(input_name, 1) diff --git a/nzb2media/processor/sab.py b/nzb2media/processor/sab.py index b965dc84..eb85bb62 100644 --- a/nzb2media/processor/sab.py +++ b/nzb2media/processor/sab.py @@ -18,6 +18,7 @@ def process_script(): def process(args): """Process job from SABnzb. + SABnzbd arguments: 1. The final directory of the job (full path) 2. The original name of the NZB file diff --git a/nzb2media/scene_exceptions.py b/nzb2media/scene_exceptions.py index 47079fe5..04f48d08 100644 --- a/nzb2media/scene_exceptions.py +++ b/nzb2media/scene_exceptions.py @@ -164,7 +164,7 @@ def par2(dirname): result = proc.returncode except Exception: log.error(f'par2 file processing for {parfile} has failed') - if result == 0: + if not result: log.info('par2 file processing succeeded') os.chdir(pwd) diff --git a/nzb2media/transcoder.py b/nzb2media/transcoder.py index b7c9347f..bcaa4f95 100644 --- a/nzb2media/transcoder.py +++ b/nzb2media/transcoder.py @@ -11,7 +11,8 @@ import shutil import subprocess import sys import time -from subprocess import PIPE, DEVNULL +from subprocess import DEVNULL +from subprocess import PIPE from babelfish import Language @@ -30,7 +31,7 @@ def is_video_good(video: pathlib.Path, status, require_lan=None): disable = True else: test_details, res = get_video_details(nzb2media.TEST_FILE) - if res != 0 or test_details.get('error'): + if res or test_details.get('error'): disable = True log.info('DISABLED: ffprobe failed to analyse test file. Stopping corruption check.') if test_details.get('streams'): @@ -47,7 +48,7 @@ def is_video_good(video: pathlib.Path, status, require_lan=None): return True log.info(f'Checking [{video.name}] for corruption, please stand by ...') video_details, result = get_video_details(video) - if result != 0: + if result: log.error(f'FAILED: [{video.name}] is corrupted!') return False if video_details.get('error'): @@ -125,7 +126,7 @@ def get_video_details(videofile, img=None): def check_vid_file(video_details, result): - if result != 0: + if result: return False if video_details.get('error'): return False @@ -381,7 +382,7 @@ def build_commands(file, new_dir, movie_name): audio_cmd2.extend([f'-c:a:{used_audio}', 'copy']) elif audio3: # wrong language, wrong codec just pick the default audio track - _inded = audio3[0]['index'] + _index = audio3[0]['index'] map_cmd.extend(['-map', f'0:{_index}']) a_mapped.extend([audio3[0]['index']]) bitrate = int(float(audio3[0].get('bit_rate', 0))) / 1000 @@ -423,11 +424,10 @@ def build_commands(file, new_dir, movie_name): channels = int(float(audio.get('channels', 0))) if audio['codec_name'] in nzb2media.ACODEC3_ALLOW: audio_cmd3.extend([f'-c:a:{used_audio}', 'copy']) + elif nzb2media.ACODEC3: + audio_cmd3.extend([f'-c:a:{used_audio}', nzb2media.ACODEC3]) else: - if nzb2media.ACODEC3: - audio_cmd3.extend([f'-c:a:{used_audio}', nzb2media.ACODEC3]) - else: - audio_cmd3.extend([f'-c:a:{used_audio}', 'copy']) + audio_cmd3.extend([f'-c:a:{used_audio}', 'copy']) if nzb2media.ACHANNELS3 and channels and channels > nzb2media.ACHANNELS3: audio_cmd3.extend([f'-ac:a:{used_audio}', str(nzb2media.ACHANNELS3)]) if audio_cmd3[1] == 'copy': @@ -519,11 +519,10 @@ def build_commands(file, new_dir, movie_name): map_cmd.extend(['-map', f'{num}:0']) if not nzb2media.ALLOWSUBS or (not s_mapped and not num): sub_cmd.extend(['-sn']) + elif nzb2media.SCODEC: + sub_cmd.extend(['-c:s', nzb2media.SCODEC]) else: - if nzb2media.SCODEC: - sub_cmd.extend(['-c:s', nzb2media.SCODEC]) - else: - sub_cmd.extend(['-c:s', 'copy']) + sub_cmd.extend(['-c:s', 'copy']) command.extend(map_cmd) command.extend(video_cmd) command.extend(audio_cmd) @@ -586,7 +585,7 @@ def extract_subs(file, newfile_path): result = proc.returncode except Exception: log.error('Extracting subtitle has failed') - if result == 0: + if not result: try: shutil.copymode(file, output_file) except Exception: @@ -888,7 +887,7 @@ def transcode_directory(dir_name): result = proc.returncode except Exception: log.error(f'Transcoding of video {newfile_path} has failed') - if nzb2media.SUBSDIR and result == 0 and isinstance(file, str): + if nzb2media.SUBSDIR and not result and isinstance(file, str): for sub in get_subs(file): name = os.path.splitext(os.path.split(file)[1])[0] subname = os.path.split(sub)[1] @@ -896,7 +895,7 @@ def transcode_directory(dir_name): newpath = os.path.join(nzb2media.SUBSDIR, subname.replace(name, newname)) if not os.path.isfile(newpath): os.rename(sub, newpath) - if result == 0: + if not result: try: shutil.copymode(file, newfile_path) except Exception: @@ -920,7 +919,7 @@ def transcode_directory(dir_name): time.sleep(5) os.rmdir(nzb2media.MOUNTED) nzb2media.MOUNTED = None - if final_result == 0 and not nzb2media.DUPLICATE: + if not final_result and not nzb2media.DUPLICATE: for file in rem_list: try: os.unlink(file) diff --git a/nzb2media/user_scripts.py b/nzb2media/user_scripts.py index 6262ca59..6755c36d 100644 --- a/nzb2media/user_scripts.py +++ b/nzb2media/user_scripts.py @@ -108,9 +108,9 @@ def external_script(output_destination, torrent_name, torrent_label, settings): file_name, file_extension = os.path.splitext(file) if file_extension in nzb2media.USER_SCRIPT_MEDIAEXTENSIONS or nzb2media.USER_SCRIPT_MEDIAEXTENSIONS == 'ALL': num_files_new += 1 - if nzb2media.USER_SCRIPT_CLEAN == int(1) and num_files_new == 0 and final_result == 0: + if nzb2media.USER_SCRIPT_CLEAN == 1 and not num_files_new and not final_result: log.info(f'All files have been processed. Cleaning outputDirectory {output_destination}') remove_dir(output_destination) - elif nzb2media.USER_SCRIPT_CLEAN == int(1) and num_files_new != 0: + elif nzb2media.USER_SCRIPT_CLEAN == 1 and num_files_new: log.info(f'{num_files} files were processed, but {num_files_new} still remain. outputDirectory will not be cleaned.') return ProcessResult(status_code=final_result, message='User Script Completed') diff --git a/nzb2media/utils/encoding.py b/nzb2media/utils/encoding.py index 20400066..fead1705 100644 --- a/nzb2media/utils/encoding.py +++ b/nzb2media/utils/encoding.py @@ -59,7 +59,8 @@ def char_replace(name_in): def convert_to_ascii(input_name, dir_name): ascii_convert = int(nzb2media.CFG['ASCII']['convert']) - if ascii_convert == 0 or os.name == 'nt': # just return if we don't want to convert or on windows os and '\' is replaced!. + if not ascii_convert or os.name == 'nt': + # just return if we don't want to convert or on windows os and '\' is replaced!. return input_name, dir_name encoded, input_name = char_replace(input_name) directory, base = os.path.split(dir_name) diff --git a/nzb2media/utils/identification.py b/nzb2media/utils/identification.py index 424c31b6..03b84aa0 100644 --- a/nzb2media/utils/identification.py +++ b/nzb2media/utils/identification.py @@ -32,7 +32,7 @@ def find_imdbid(dir_name, input_name, omdb_api_key) -> str: return imdbid if 'NZBPR__DNZB_MOREINFO' in os.environ: dnzb_more_info = os.environ.get('NZBPR__DNZB_MOREINFO', '') - if dnzb_more_info != '': + if dnzb_more_info: regex = re.compile(r'^http://www.imdb.com/title/(tt[0-9]+)/$', re.IGNORECASE) match = regex.match(dnzb_more_info) if match: diff --git a/nzb2media/utils/links.py b/nzb2media/utils/links.py index 39e98272..ddff1273 100644 --- a/nzb2media/utils/links.py +++ b/nzb2media/utils/links.py @@ -12,11 +12,12 @@ log = logging.getLogger(__name__) log.addHandler(logging.NullHandler()) try: - from jaraco.windows.filesystem import islink, readlink + from jaraco.windows.filesystem import islink + from jaraco.windows.filesystem import readlink except ImportError: if os.name != 'nt': - from os.path import islink from os import readlink + from os.path import islink else: raise diff --git a/nzb2media/utils/naming.py b/nzb2media/utils/naming.py index acecdfd4..4f1454f6 100644 --- a/nzb2media/utils/naming.py +++ b/nzb2media/utils/naming.py @@ -4,8 +4,8 @@ import re def sanitize_name(name): - """ - Remove bad chars from the filename. + """Remove bad chars from the filename. + >>> sanitize_name('a/b/c') 'a-b-c' >>> sanitize_name('abc') @@ -23,8 +23,8 @@ def sanitize_name(name): def clean_file_name(filename): - """ - Clean up nzb name by removing any . and _ characters and trailing hyphens. + """Clean up nzb name by removing any . and _ characters and trailing hyphens. + Is basically equivalent to replacing all _ and . with a space, but handles decimal numbers in string, for example: """ diff --git a/nzb2media/utils/parsers.py b/nzb2media/utils/parsers.py index b85f1a68..b73aa6fa 100644 --- a/nzb2media/utils/parsers.py +++ b/nzb2media/utils/parsers.py @@ -101,7 +101,7 @@ def parse_synods(): log.error('unable to find download details in Synology DS') # Syno paths appear to be relative. Let's test to see if the returned path exists, and if not append to /volume1/ if not os.path.isdir(input_directory): - for root in ['/volume1/', '/volume2/', '/volume3/', '/volume4/']: + for root in ('/volume1/', '/volume2/', '/volume3/', '/volume4/'): if os.path.isdir(os.path.join(root, input_directory)): input_directory = os.path.join(root, input_directory) break diff --git a/nzb2media/utils/paths.py b/nzb2media/utils/paths.py index b1928a58..c8c965dd 100644 --- a/nzb2media/utils/paths.py +++ b/nzb2media/utils/paths.py @@ -14,8 +14,8 @@ log.addHandler(logging.NullHandler()) def onerror(func, path, exc_info): - """ - Error handler for ``shutil.rmtree``. + """Error handler for ``shutil.rmtree``. + If the error is due to an access error (read only file) it attempts to add write permission and then retries. If the error is for another reason it re-raises the error. @@ -83,7 +83,7 @@ def remove_empty_folders(path, remove_root=True): remove_empty_folders(fullpath) # if folder empty, delete it files = os.listdir(path) - if len(files) == 0 and remove_root: + if not files and remove_root: log.debug(f'Removing empty folder:{path}') os.rmdir(path) diff --git a/nzb2media/utils/processes.py b/nzb2media/utils/processes.py index 6cbe2681..742ae241 100644 --- a/nzb2media/utils/processes.py +++ b/nzb2media/utils/processes.py @@ -10,14 +10,12 @@ import typing import nzb2media if os.name == 'nt': - # pylint: disable-next=no-name-in-module - from win32event import CreateMutex - # pylint: disable-next=no-name-in-module from win32api import CloseHandle - # pylint: disable-next=no-name-in-module from win32api import GetLastError + # pylint: disable-next=no-name-in-module + from win32event import CreateMutex from winerror import ERROR_ALREADY_EXISTS log = logging.getLogger(__name__) @@ -96,6 +94,8 @@ class PosixProcess: self.pidpath.unlink() +# Alternative union syntax using | fails on Python < 3.10 +# pylint: disable-next=consider-alternative-union-syntax ProcessType = typing.Type[typing.Union[PosixProcess, WindowsProcess]] if os.name == 'nt': RunningProcess: ProcessType = WindowsProcess diff --git a/nzb2media/utils/torrent.py b/nzb2media/utils/torrent.py index e136efa9..f0b49179 100644 --- a/nzb2media/utils/torrent.py +++ b/nzb2media/utils/torrent.py @@ -30,15 +30,15 @@ def create_torrent_class(client_agent) -> object | None: def pause_torrent(client_agent, input_hash, input_id, input_name): log.debug(f'Stopping torrent {input_name} in {client_agent} while processing') try: - if client_agent == 'utorrent' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'utorrent' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.stop(input_hash) - if client_agent == 'transmission' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'transmission' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.stop_torrent(input_id) - if client_agent == 'synods' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'synods' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.pause_task(input_id) - if client_agent == 'deluge' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'deluge' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.core.pause_torrent([input_id]) - if client_agent == 'qbittorrent' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'qbittorrent' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.pause(input_hash) time.sleep(5) except Exception: @@ -50,15 +50,15 @@ def resume_torrent(client_agent, input_hash, input_id, input_name): return log.debug(f'Starting torrent {input_name} in {client_agent}') try: - if client_agent == 'utorrent' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'utorrent' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.start(input_hash) - if client_agent == 'transmission' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'transmission' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.start_torrent(input_id) - if client_agent == 'synods' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'synods' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.resume_task(input_id) - if client_agent == 'deluge' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'deluge' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.core.resume_torrent([input_id]) - if client_agent == 'qbittorrent' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'qbittorrent' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.resume(input_hash) time.sleep(5) except Exception: @@ -69,16 +69,16 @@ def remove_torrent(client_agent, input_hash, input_id, input_name): if nzb2media.DELETE_ORIGINAL == 1 or nzb2media.USE_LINK == 'move': log.debug(f'Deleting torrent {input_name} from {client_agent}') try: - if client_agent == 'utorrent' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'utorrent' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.removedata(input_hash) nzb2media.TORRENT_CLASS.remove(input_hash) - if client_agent == 'transmission' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'transmission' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.remove_torrent(input_id, True) - if client_agent == 'synods' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'synods' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.delete_task(input_id) - if client_agent == 'deluge' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'deluge' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.core.remove_torrent(input_id, True) - if client_agent == 'qbittorrent' and nzb2media.TORRENT_CLASS != '': + if client_agent == 'qbittorrent' and nzb2media.TORRENT_CLASS: nzb2media.TORRENT_CLASS.delete_permanently(input_hash) time.sleep(5) except Exception: diff --git a/nzb2media/version_check.py b/nzb2media/version_check.py index c4707913..12135631 100644 --- a/nzb2media/version_check.py +++ b/nzb2media/version_check.py @@ -11,7 +11,8 @@ import stat import subprocess import tarfile import traceback -from subprocess import PIPE, STDOUT +from subprocess import PIPE +from subprocess import STDOUT from urllib.request import urlretrieve import nzb2media @@ -40,8 +41,8 @@ class CheckVersion: @staticmethod def find_install_type(): - """ - Determine how this copy of SB was installed. + """Determine how this copy of SB was installed. + returns: type of installation. Possible values are: 'win': any compiled windows build 'git': running from source using git @@ -55,8 +56,8 @@ class CheckVersion: return install_type def check_for_new_version(self, force=False): - """ - Check the internet for a newer version. + """Check the internet for a newer version. + returns: bool, True for new version or False for no new version. force: if true the VERSION_NOTIFY setting will be ignored and a check will be forced """ @@ -114,7 +115,7 @@ class GitUpdateManager(UpdateManager): main_git = 'git' log.debug(f'Checking if we can use git commands: {main_git} {test_cmd}') output, err, exit_status = self._run_git(main_git, test_cmd) - if exit_status == 0: + if not exit_status: log.debug(f'Using: {main_git}') return main_git log.debug(f'Not using: {main_git}') @@ -131,7 +132,7 @@ class GitUpdateManager(UpdateManager): for cur_git in alternative_git: log.debug(f'Checking if we can use git commands: {cur_git} {test_cmd}') output, err, exit_status = self._run_git(cur_git, test_cmd) - if exit_status == 0: + if not exit_status: log.debug(f'Using: {cur_git}') return cur_git log.debug(f'Not using: {cur_git}') @@ -160,7 +161,7 @@ class GitUpdateManager(UpdateManager): log.error(f'Command {cmd} didn\'t work') proc_status = 1 proc_status = 128 if ('fatal:' in result) or proc_err else proc_status - if proc_status == 0: + if not proc_status: log.debug(f'{cmd} : returned successful') proc_status = 0 elif nzb2media.LOG_GIT and proc_status in {1, 128}: @@ -172,13 +173,13 @@ class GitUpdateManager(UpdateManager): return result, proc_err, proc_status def _find_installed_version(self): - """ - Attempt to find the currently installed version of Sick Beard. + """Attempt to find the currently installed version of Sick Beard. + Uses git show to get commit version. Returns: True for success or False for failure """ output, err, exit_status = self._run_git(self._git_path, 'rev-parse HEAD') - if exit_status == 0 and output: + if not exit_status and output: cur_commit_hash = output.strip() if not re.match('^[a-z0-9]+$', cur_commit_hash): log.error('Output doesn\'t look like a hash, not using it') @@ -192,7 +193,7 @@ class GitUpdateManager(UpdateManager): def _find_git_branch(self): nzb2media.NZBTOMEDIA_BRANCH = self.get_github_branch() branch_info, err, exit_status = self._run_git(self._git_path, 'symbolic-ref -q HEAD') - if exit_status == 0 and branch_info: + if not exit_status and branch_info: branch = branch_info.strip().replace('refs/heads/', '', 1) if branch: nzb2media.NZBTOMEDIA_BRANCH = branch @@ -200,8 +201,8 @@ class GitUpdateManager(UpdateManager): return nzb2media.GIT_BRANCH def _check_github_for_update(self): - """ - Check Github for a new version. + """Check Github for a new version. + Uses git commands to check if there is a newer version than the provided commit hash. If there is a newer version it sets _num_commits_behind. @@ -211,12 +212,12 @@ class GitUpdateManager(UpdateManager): self._num_commits_ahead = 0 # get all new info from github output, err, exit_status = self._run_git(self._git_path, 'fetch origin') - if not exit_status == 0: + if exit_status: log.error('Unable to contact github, can\'t check for update') return # get latest commit_hash from remote output, err, exit_status = self._run_git(self._git_path, 'rev-parse --verify --quiet \'@{upstream}\'') - if exit_status == 0 and output: + if not exit_status and output: cur_commit_hash = output.strip() if not re.match('^[a-z0-9]+$', cur_commit_hash): log.debug('Output doesn\'t look like a hash, not using it') @@ -227,7 +228,7 @@ class GitUpdateManager(UpdateManager): return # get number of commits behind and ahead (option --count not supported git < 1.7.2) output, err, exit_status = self._run_git(self._git_path, 'rev-list --left-right \'@{upstream}\'...HEAD') - if exit_status == 0 and output: + if not exit_status and output: try: self._num_commits_behind = int(output.count('<')) self._num_commits_ahead = int(output.count('>')) @@ -267,7 +268,7 @@ class GitUpdateManager(UpdateManager): Returns a bool depending on the call's success. """ output, err, exit_status = self._run_git(self._git_path, f'pull origin {self.branch}') - if exit_status == 0: + if not exit_status: return True return False @@ -308,7 +309,7 @@ class SourceUpdateManager(UpdateManager): return False def _check_github_for_update(self): - """ Check Github for a new version. + """Check Github for a new version. Uses pygithub to ask github if there is a newer version than the provided commit hash. If there is a newer version it sets diff --git a/nzbToMedia.py b/nzbToMedia.py index 385ca0f3..dac1898f 100755 --- a/nzbToMedia.py +++ b/nzbToMedia.py @@ -46,7 +46,7 @@ def main(args, section=None): else: manual.process() - if result.status_code == 0: + if not result.status_code: log.info(f'The {args[0]} script completed successfully.') if result.message: print(result.message + '!') diff --git a/tests/transcoder_test.py b/tests/transcoder_test.py index 7ddfc6eb..457f9856 100644 --- a/tests/transcoder_test.py +++ b/tests/transcoder_test.py @@ -1,9 +1,16 @@ -#! /usr/bin/env python from __future__ import annotations +import sys + +import pytest + import nzb2media from nzb2media import transcoder +@pytest.mark.xfail( + sys.platform == 'win32' and sys.version_info < (3, 8), + reason='subprocess.Popen does not support pathlib.Path commands in Python 3.7', +) def test_transcoder_check(): assert transcoder.is_video_good(nzb2media.TEST_FILE, 1) is True diff --git a/tox.ini b/tox.ini index 3a9471b1..53186bdc 100644 --- a/tox.ini +++ b/tox.ini @@ -27,98 +27,15 @@ deps = pytest-cov -rrequirements.txt commands = - {posargs:pytest -vvv --cov --cov-report=term-missing --cov-branch tests} - -[flake8] -max-line-length = 79 -max-doc-length = 79 -verbose = 2 -statistics = True -min-version = 2.7 -require-code = True -exclude = - .github/ - .pytest_cache/ - .tox/ - .venv*/ - build/ - htmlcov/ - logs/ -ignore = -; -- flake8 -- -; E501 line too long -; E722 do not use bare 'except' (duplicates B001) -; W503 line break before binary operator -; W505 doc line too long - E501, E722, W503, W505 - -; -- flake8-docstrings -- -; D100 Missing docstring in public module -; D101 Missing docstring in public class -; D102 Missing docstring in public method -; D103 Missing docstring in public function -; D104 Missing docstring in public package -; D105 Missing docstring in magic method -; D107 Missing docstring in __init__ -; D200 One-line docstring should fit on one line with quotes -; D202 No blank lines allowed after function docstring -; D205 1 blank line required between summary line and description -; D400 First line should end with a period -; D401 First line should be in imperative mood -; D402 First line should not be the function's "signature" - D100, D101, D102, D103, D104, D105, D107 - -; -- flake8-future-import -- -; x = 1 for missing, 5 for present -; FIx6 nested_scopes 2.2 -; FIx7 generators 2.3 -; FIx2 with_statement 2.6 -; FIx1 absolute_import 3.0 -; FIx0 division 3.0 -; FIx3 print_function 3.0 -; FIx4 unicode_literals 3.0 -; FIx5 generator_stop 3.7 -; FIx8 annotations 4.0 -; FI90 __future__ import does not exist - FI10, FI11, FI13, FI14, FI58 - -per-file-ignores = -; F401 imported but unused -; E402 module level import not at top of file - nzbTo*.py: E265, E266, E402 - TorrentToMedia.py: E402 - nzb2media/__init__.py: E402, F401 - nzb2media/utils/__init__.py: F401 - nzb2media/plugins/downloaders/configuration.py: F401 - nzb2media/plugins/downloaders/utils.py: F401 + {posargs:pytest -vvv -rA --cov --cov-report=term-missing --cov-branch tests} [testenv:check] deps = - flake8 - flake8-bugbear - flake8-commas - flake8-comprehensions - flake8-docstrings - flake8-future-import + pre-commit skip_install = true commands = -; ** PRIMARY TESTS ** -; Run flake8 tests (with plugins) using default test selections - flake8 -; ** SELECTIVE TESTS ** -; Run flake8 tests (with plugins) for specific optional codes defined below -; -- flake8 -- -; E123 closing bracket does not match indentation of opening bracket’s line -; E226 missing whitespace around arithmetic operator -; E241 multiple spaces after ‘,’ -; E242 tab after ‘,’ -; E704 multiple statements on one line -; W504 line break after binary operator -; W505 doc line too long -; -- flake8-bugbear -- -; B902 Invalid first argument used for instance method. -; B903 Data class should be immutable or use __slots__ to save memory. - flake8 --select=B902,B903,E123,E226,E241,E242,E704,W504,W505 + pre-commit autoupdate + pre-commit run --all-files [coverage:run]