From b43d15eb39101838626eaec19b1062da9fd68e79 Mon Sep 17 00:00:00 2001 From: Oleg Butuzov Date: Sun, 31 Dec 2023 17:00:31 +0200 Subject: [PATCH] docs: minor updates (#144) * docs: update docs dependencies * dev: update dev dependencies + Dockerimage * dev: minor refactoring * dev: remove `mypy` chekcs + workflow changes --- .github/workflows/main.yaml | 10 +-- Dockerfile | 7 +- deadlinks/__init__.py | 23 ++---- deadlinks/__main__.py | 19 ++--- deadlinks/clicker.py | 16 ++--- deadlinks/crawler.py | 24 +++---- deadlinks/exporters/__init__.py | 6 +- deadlinks/exporters/default.py | 13 ++-- deadlinks/exporters/export.py | 4 +- deadlinks/index.py | 22 +++--- deadlinks/link.py | 4 +- deadlinks/options.py | 6 +- deadlinks/request.py | 5 +- deadlinks/robots_txt.py | 3 +- deadlinks/serving/handler.py | 2 +- deadlinks/serving/options.py | 4 +- deadlinks/serving/router.py | 7 +- deadlinks/serving/simple_server.py | 13 ++-- deadlinks/settings.py | 37 ++++------ deadlinks/url.py | 29 ++++---- docs/conf.py | 6 +- make_brew_formula.py | 23 +++--- requirements.txt | 34 +++++---- setup.py | 8 +-- tests/components/tests_baseurl.py | 2 +- tests/components/tests_crawler.py | 31 ++++---- tests/components/tests_index.py | 6 +- tests/components/tests_links.py | 101 +++++++++++++-------------- tests/components/tests_settings.py | 22 +++--- tests/conftest.py | 10 +-- tests/features/tests_robots.py | 22 ++---- tests/features/tests_serving.py | 9 ++- tests/features/tests_termination.py | 7 +- tests/runners/brew.py | 8 +-- tests/runners/click.py | 8 +-- tests/runners/docker.py | 8 +-- tests/tests_cli_common.py | 4 +- tests/tests_cli_defaults.py | 20 +++--- tests/tests_cli_defaults_internal.py | 5 +- tests/utils/server.py | 10 +-- 40 files changed, 273 insertions(+), 325 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index f028586..931305f 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -20,7 +20,7 @@ jobs: - run: make dev-env - run: make pylint-full - - run: make mypy + # - run: make mypy Docs: runs-on: ubuntu-latest @@ -33,16 +33,16 @@ jobs: - run: make docs-build Build: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 needs: [ Static-Analysis, Docs ] strategy: fail-fast: false matrix: - python-version: [ "3.6", "3.7", "3.8", "3.9", "3.10", "3.11" ] + python-version: [ "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"] steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 @@ -55,6 +55,6 @@ jobs: - run: make tests - name: codecov.io - if: matrix.python-version == "3.11" + if: matrix.python-version == 3.11 run: bash <(curl -s https://codecov.io/bash) diff --git a/Dockerfile b/Dockerfile index f7867b5..b40cf16 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # initial builder -FROM docker.io/python:3.7-slim-stretch as BUILD +FROM docker.io/python:3.11-slim as BUILD COPY . /tmp WORKDIR /tmp @@ -18,13 +18,12 @@ RUN grep "# install" requirements.txt -A100 > docker.requirments.txt \ && sed -i 's/\/usr\/local/\/usr/g' /usr/local/bin/deadlinks -FROM gcr.io/distroless/python3:latest +FROM gcr.io/distroless/python3-debian12:debug LABEL maintainer "Oleg Butuzov " -ENV PYTHONPATH=/usr/local/lib/python3.7/site-packages +ENV PYTHONPATH=/usr/local/lib/python3.11/site-packages COPY --from=BUILD ${PYTHONPATH} ${PYTHONPATH} -# COPY --from=BUILD /usr/local/lib/libpython3.7m.so.1.0 /usr/lib/x86_64-linux-gnu/ COPY --from=BUILD /usr/local/bin/deadlinks /usr/local/bin/ WORKDIR /github/workspace diff --git a/deadlinks/__init__.py b/deadlinks/__init__.py index ce27a0c..a9c476e 100644 --- a/deadlinks/__init__.py +++ b/deadlinks/__init__.py @@ -24,30 +24,21 @@ # -- Imports ------------------------------------------------------------------- -from .url import URL -from .link import Link -from .index import Index +from .__version__ import __version__ as version from .baseurl import BaseURL from .crawler import Crawler +from .exceptions import (DeadlinksIgnoredURL, DeadlinksSettingsBase, DeadlinksSettingsChange, + DeadlinksSettingsDomains, DeadlinksSettingsPath, DeadlinksSettingsPathes, + DeadlinksSettingsRetry, DeadlinksSettingsRoot, DeadlinksSettingsThreads) +from .index import Index +from .link import Link from .request import request, user_agent from .settings import Settings from .status import Status - -from .__version__ import __version__ as version +from .url import URL # -- Exports ------------------------------------------------------------------ -from .exceptions import ( - DeadlinksIgnoredURL, - DeadlinksSettingsThreads, - DeadlinksSettingsBase, - DeadlinksSettingsRetry, - DeadlinksSettingsRoot, - DeadlinksSettingsChange, - DeadlinksSettingsDomains, - DeadlinksSettingsPathes, - DeadlinksSettingsPath, -) __all__ = [ 'version', diff --git a/deadlinks/__main__.py b/deadlinks/__main__.py index e7469d0..942ef44 100644 --- a/deadlinks/__main__.py +++ b/deadlinks/__main__.py @@ -26,26 +26,19 @@ import click -from .settings import Settings +# Version and App. +from .__version__ import __app_package__ as name +from .__version__ import __app_version__ as version +# CLI implementation related +from .clicker import Clicker, Options, register_exports, register_options, validate_url from .crawler import Crawler from .exceptions import DeadlinksException - -# CLI implementation related -from .clicker import (register_options, register_exports) -from .clicker import Options -from .clicker import (Clicker, validate_url) - # Exporters -from .exporters import Export #pylint: disable-msg=W0611 from .exporters import exporters - # Default and Specified Options from .options import default_options as general_options from .serving.options import default_options as serving_options - -# Version and App. -from .__version__ import __app_version__ as version -from .__version__ import __app_package__ as name +from .settings import Settings # -- Implementation ------------------------------------------------------------ diff --git a/deadlinks/clicker.py b/deadlinks/clicker.py index 645b5c9..ef1acc5 100644 --- a/deadlinks/clicker.py +++ b/deadlinks/clicker.py @@ -24,16 +24,16 @@ # -- Imports ------------------------------------------------------------------- -from typing import (Dict, List, Tuple, Union, Any, Callable, Sequence) -from textwrap import dedent from collections import OrderedDict +from textwrap import dedent +from typing import Any, Callable, Dict, List, Sequence, Tuple, Union -from click import Option, Argument -from click import Command, Context +from click import Argument, Command, Context from click import HelpFormatter as Formatter +from click import Option -from .link import Link from .__version__ import __app_package__ as app +from .link import Link # -- Typing Decorators -----~--------------------------------------------------- OptionsValues = Union[str, bool, int, List[str], List[Callable]] @@ -204,7 +204,7 @@ def format_examples( with formatter.section('Usage Examples'): formatter.write("\n") for line in self.EXAMPLES.split("\n"): - formatter.write(" {}\n".format(line)) + formatter.write(f" {line}\n") def modify(self, ctx: Context) -> None: """ Modifing params based on context. """ @@ -235,12 +235,12 @@ def validate_url(ctx: Context, param: Argument, value: str) -> str: url = Link(value) if not url.is_valid() and not url.scheme: - return "http://%s" % value + return f"http://{value}" if "@" in url.path: return value if not url.is_valid() and url.scheme and url.path: - return "http://%s:%s" % (url.scheme, url.path) + return f"http://{url.scheme}:{url.path}" return value diff --git a/deadlinks/crawler.py b/deadlinks/crawler.py index 3310bd1..64643fb 100644 --- a/deadlinks/crawler.py +++ b/deadlinks/crawler.py @@ -24,25 +24,20 @@ # -- Imports ------------------------------------------------------------------- -from typing import (List, Tuple, Optional, Dict) -from types import FrameType - -from threading import Thread -from signal import (signal, SIGINT) +from collections import defaultdict from queue import Queue +from signal import SIGINT, signal +from threading import Thread from time import sleep +from types import FrameType +from typing import Dict, List, Optional, Tuple -from .link import Link -from .status import Status +from .exceptions import DeadlinksIgnoredURL, DeadlinksRedirectionURL from .index import Index +from .link import Link from .robots_txt import RobotsTxt from .settings import Settings -from .exceptions import ( - DeadlinksIgnoredURL, - DeadlinksRedirectionURL, -) - -from collections import defaultdict +from .status import Status # -- Implementation ------------------------------------------------------------ @@ -259,7 +254,8 @@ def internal(self, links: List[Link]) -> List[Link]: return links domain = self.settings.base.domain - mapper = lambda x: x.url().replace(domain, 'internal') + def mapper(x): + return x.url().replace(domain, "internal") return list(map(Link, map(mapper, links))) diff --git a/deadlinks/exporters/__init__.py b/deadlinks/exporters/__init__.py index bc43ec0..98cdf1f 100644 --- a/deadlinks/exporters/__init__.py +++ b/deadlinks/exporters/__init__.py @@ -24,10 +24,10 @@ # -- Imports ------------------------------------------------------------------- -from typing import Dict #pylint: disable-msg=W0611 +from typing import Dict -from .export import Export from .default import Default +from .export import Export # -- Exports ------------------------------------------------------------------- @@ -36,6 +36,6 @@ 'Export', ] -exporters = { # type Dict[str, Export] +exporters: Dict[str, Export] = { 'default': Default, } diff --git a/deadlinks/exporters/default.py b/deadlinks/exporters/default.py index 309f842..8e1ee59 100644 --- a/deadlinks/exporters/default.py +++ b/deadlinks/exporters/default.py @@ -24,17 +24,16 @@ # -- Imports ------------------------------------------------------------------- -from typing import (Dict, Tuple, List, Sequence, Any) #pylint: disable-msg=W0611 - -from threading import Thread from os import name as os_name +from threading import Thread from time import sleep +from typing import Dict, List, Sequence, Tuple # pylint: disable-msg=W0611 import click -from .export import Export -from ..crawler import Crawler from ..clicker import OptionRaw +from ..crawler import Crawler +from .export import Export # -- Implementation ------------------------------------------------------------ @@ -180,7 +179,7 @@ def _generate(self, key: str) -> str: param_color = click.style(param, fg=self.params_colors[param]) - return '\n'.join(map(lambda x: "[ {} ] {}".format(param_color, x), links)) + return '\n'.join(map(lambda x: f"[ {param_color} ] {x}", links)) def report(self) -> None: @@ -217,7 +216,7 @@ def report(self) -> None: click.echo(("-"*split_line_len) + "\033[?25h") # show some url report(s) - show = list(self._opts.get('show', [])) # type: Sequence[str] + show: Sequence[str] = list(self._opts.get('show', [])) if 'none' in show: return diff --git a/deadlinks/exporters/export.py b/deadlinks/exporters/export.py index 69624ff..a9a34f5 100644 --- a/deadlinks/exporters/export.py +++ b/deadlinks/exporters/export.py @@ -24,11 +24,11 @@ # -- Imports ------------------------------------------------------------------- -from typing import (Dict, Tuple) from abc import ABC, abstractmethod +from typing import Dict, Tuple -from ..crawler import Crawler from ..clicker import OptionsList +from ..crawler import Crawler # -- Abstract ------------------------------------------------------------------ diff --git a/deadlinks/index.py b/deadlinks/index.py index 93701f5..ad64551 100644 --- a/deadlinks/index.py +++ b/deadlinks/index.py @@ -24,7 +24,7 @@ # -- Imports ------------------------------------------------------------------- -from typing import (Dict, List, Iterator, Callable) #pylint: disable-msg=W0611 +from typing import Callable, Dict, Iterator, List # pylint: disable-msg=W0611 from .link import Link from .status import Status @@ -69,38 +69,32 @@ def put(self, link: Link) -> None: def all(self) -> List[Link]: """ Return links in the index (but not UNDEFINED). """ - lmbd = lambda x: x.status != Status.UNDEFINED - return self._filter(lmbd) + return self._filter(lambda x: x.status != Status.UNDEFINED) def succeed(self) -> List[Link]: """ Filters succeed urls from index. """ - lmbd = lambda x: x.status == Status.FOUND - return self._filter(lmbd) + return self._filter(lambda x: x.status == Status.FOUND) def redirected(self) -> List[Link]: """ Filters succeed urls from index. """ - lmbd = lambda x: x.status == Status.REDIRECTION - return self._filter(lmbd) + return self._filter(lambda x: x.status == Status.REDIRECTION) def failed(self) -> List[Link]: """ Filters failed urls from index. """ - lmbd = lambda x: x.status == Status.NOT_FOUND - return self._filter(lmbd) + return self._filter(lambda x: x.status == Status.NOT_FOUND) def ignored(self) -> List[Link]: """ Filters failed urls from index. """ - lmbd = lambda x: x.status == Status.IGNORED - return self._filter(lmbd) + return self._filter(lambda x: x.status == Status.IGNORED) def undefined(self) -> List[Link]: """ Filters undefined urls from index. """ - lmbd = lambda x: x.status == Status.UNDEFINED - return self._filter(lmbd) + return self._filter(lambda x: x.status == Status.UNDEFINED) def update(self, url: Link, status: Status, message: str) -> None: """ wraps access to updating url status and gathering stats """ @@ -118,4 +112,4 @@ def get_stats(self) -> Dict[Status, int]: def _filter(self, lambda_func: Callable[[Link], bool]) -> List[Link]: """ Filters values according lambda. """ - return list(sorted(filter(lambda_func, self._index.values()))) # type: ignore + return list(sorted(filter(lambda_func, self._index.values()))) diff --git a/deadlinks/link.py b/deadlinks/link.py index ed47455..3e8450b 100644 --- a/deadlinks/link.py +++ b/deadlinks/link.py @@ -24,8 +24,8 @@ # -- Imports ------------------------------------------------------------------- -from typing import Union from functools import total_ordering +from typing import Union from .url import URL @@ -51,7 +51,7 @@ def is_external(self, url: Union[URL, str]) -> bool: if isinstance(url, str): url = URL(url) elif not isinstance(url, URL): - raise TypeError("url of type {}".format(type(url))) + raise TypeError(f"url of type {type(url)}") base_scheme, this_scheme = url.scheme, self.scheme base, this = url.domain, self.domain diff --git a/deadlinks/options.py b/deadlinks/options.py index 09d5702..96fd8f0 100644 --- a/deadlinks/options.py +++ b/deadlinks/options.py @@ -26,13 +26,13 @@ from typing import List -from click import IntRange, Choice +from click import Choice, IntRange -from .clicker import OptionRaw #pylint: disable-msg=W0611 +from .clicker import OptionRaw # -- Options ------------------------------------------------------------------- -default_options = [] # type: List[OptionRaw] +default_options: List[OptionRaw] = [] # Index External URLs ------------------------------------------------------ default_options.append(( diff --git a/deadlinks/request.py b/deadlinks/request.py index 4d5a600..979a698 100644 --- a/deadlinks/request.py +++ b/deadlinks/request.py @@ -24,9 +24,8 @@ # -- Imports ------------------------------------------------------------------- -from requests import Session, Response -from requests.adapters import HTTPAdapter -from urllib3.util.retry import Retry +from requests import Response, Session +from requests.adapters import HTTPAdapter, Retry from .__version__ import __app_package__ diff --git a/deadlinks/robots_txt.py b/deadlinks/robots_txt.py index 52ec190..83498cb 100644 --- a/deadlinks/robots_txt.py +++ b/deadlinks/robots_txt.py @@ -23,8 +23,7 @@ """ # -- Imports ------------------------------------------------------------------- -from typing import (Any, List, Tuple) - +from typing import Any, List, Tuple from urllib.robotparser import RobotFileParser from .request import user_agent diff --git a/deadlinks/serving/handler.py b/deadlinks/serving/handler.py index 116ae82..6ff1228 100644 --- a/deadlinks/serving/handler.py +++ b/deadlinks/serving/handler.py @@ -60,7 +60,7 @@ def do_GET(self) -> None: if code == 301: self.send_response(code) - self.send_header('Location', response) + self.send_header('Location', str(response)) self.end_headers() return diff --git a/deadlinks/serving/options.py b/deadlinks/serving/options.py index 1f56707..5c702d2 100644 --- a/deadlinks/serving/options.py +++ b/deadlinks/serving/options.py @@ -28,11 +28,11 @@ from click import Path -from ..clicker import OptionRaw, Options #pylint: disable-msg=W0611 +from ..clicker import OptionRaw # pylint: disable-msg=W0611 # -- Code ---------------------------------------------------------------------- -default_options = [] # type: List[OptionRaw] +default_options: List[OptionRaw] = [] # root, in case of URL, defaults to . (pwd or current directory) default_options.append(( ('root', '-R', '--root'), diff --git a/deadlinks/serving/router.py b/deadlinks/serving/router.py index eda205d..d67a4cc 100644 --- a/deadlinks/serving/router.py +++ b/deadlinks/serving/router.py @@ -24,10 +24,9 @@ # -- Imports ------------------------------------------------------------------- -from typing import (Union, Dict, Optional, Tuple) - -from pathlib import Path from collections import OrderedDict +from pathlib import Path +from typing import Dict, Optional, Tuple, Union from ..exceptions import DeadlinksSettingsRoot @@ -59,7 +58,7 @@ def __init__(self, siteroot: Union[Path, str]) -> None: raise DeadlinksSettingsRoot("This is not a directory") # redirects - self._redirects = OrderedDict() # type: Dict[str, str] + self._redirects: Dict[str, str] = OrderedDict() self.load_redirects() def load_redirects(self) -> None: diff --git a/deadlinks/serving/simple_server.py b/deadlinks/serving/simple_server.py index d1f7229..2bd278a 100644 --- a/deadlinks/serving/simple_server.py +++ b/deadlinks/serving/simple_server.py @@ -24,20 +24,19 @@ # -- Imports ------------------------------------------------------------------- -from typing import (Union, Optional) - from functools import partial +from typing import Union try: - from socketserver import ThreadingMixIn from http.server import HTTPServer + from socketserver import ThreadingMixIn except ModuleNotFoundError: from SocketServer import ThreadingMixIn # type: ignore from BaseHTTPServer import HTTPServer # type: ignore -from socket import (socket, SOCK_STREAM, AF_INET) -from threading import Thread from pathlib import Path +from socket import AF_INET, SOCK_STREAM, socket +from threading import Thread from .handler import Handler from .router import Router @@ -73,6 +72,7 @@ def start(self) -> None: # https://github.com/python/mypy/issues/1484 self._handler = partial(Handler, self.router) self._server = ThreadedHTTPServer(self._sa, self._handler) + server_thread = Thread(target=self._server.serve_forever, daemon=True) server_thread.start() @@ -83,4 +83,5 @@ def __str__(self) -> str: def url(self) -> str: """ Return URL of running server (including path). """ - return "http://{}:{}".format(self._sa[0], self._sa[1]) + + return f"http://{self._sa[0]}:{self._sa[1]}" diff --git a/deadlinks/settings.py b/deadlinks/settings.py index b0c5104..d7bd366 100644 --- a/deadlinks/settings.py +++ b/deadlinks/settings.py @@ -24,24 +24,15 @@ # -- Imports ------------------------------------------------------------------- -from typing import (Optional, List, Dict, Any, Union) - from pathlib import Path +from typing import Any, Dict, List, Optional, Union from .baseurl import BaseURL +from .exceptions import (DeadlinksSettingsBase, DeadlinksSettingsChange, DeadlinksSettingsDomains, + DeadlinksSettingsPath, DeadlinksSettingsPathes, DeadlinksSettingsRetry, + DeadlinksSettingsRoot, DeadlinksSettingsThreads) from .serving import Server -from .exceptions import ( - DeadlinksSettingsThreads, - DeadlinksSettingsBase, - DeadlinksSettingsRetry, - DeadlinksSettingsChange, - DeadlinksSettingsDomains, - DeadlinksSettingsPathes, - DeadlinksSettingsPath, - DeadlinksSettingsRoot, -) - # -- Implementation ------------------------------------------------------------ # TODO - Review, and may be somehow simplify arguments @@ -127,7 +118,7 @@ def root(self) -> str: @root.setter def root(self, value: Path) -> None: - if not (self._root is None): #pylint: disable-msg=C0325 + if self._root is not None: #pylint: disable-msg=C0325 error = "root is already set to {}" raise DeadlinksSettingsRoot(error.format(self._root)) @@ -156,7 +147,7 @@ def check_robots_txt(self) -> bool: @check_robots_txt.setter def check_robots_txt(self, value: bool) -> None: - if not (self._skip_robots is None): #pylint: disable-msg=C0325 + if self._skip_robots is not None: #pylint: disable-msg=C0325 error = "SkipRobotsTxt check already set {}" raise DeadlinksSettingsBase(error.format(self._skip_robots)) @@ -174,7 +165,7 @@ def base(self) -> BaseURL: @base.setter def base(self, value: BaseURL) -> None: - if not (self._base is None): #pylint: disable-msg=C0325 + if self._base is not None: #pylint: disable-msg=C0325 error = "BaseUrl is already set to {}" raise DeadlinksSettingsBase(error.format(self._base)) @@ -191,7 +182,7 @@ def domains(self) -> List[str]: @domains.setter def domains(self, values: List[str]) -> None: - if not (self._domains is None): #pylint: disable-msg=C0325 + if self._domains is not None: #pylint: disable-msg=C0325 error = "Ignored Domains is already defined" raise DeadlinksSettingsDomains(error) @@ -219,7 +210,7 @@ def pathes(self) -> List[str]: @pathes.setter def pathes(self, values: List[str]) -> None: - if not (self._pathes is None): #pylint: disable-msg=C0325 + if self._pathes is not None: #pylint: disable-msg=C0325 error = "Ignored Pathes is already defined." raise DeadlinksSettingsPathes(error) @@ -243,7 +234,7 @@ def stay_within_path(self) -> bool: @stay_within_path.setter def stay_within_path(self, value: bool) -> None: """ Getter for stay_within_path setting. """ - if not (self._stay_within_path is None): #pylint: disable-msg=C0325 + if self._stay_within_path is not None: #pylint: disable-msg=C0325 error = "Stay within path is already defined." raise DeadlinksSettingsPath(error) @@ -277,11 +268,11 @@ def stay_within_path(self, value: bool) -> None: @property def retry(self) -> int: """ Getter for retry information. """ - return self._retry + return int(self._retry) @retry.setter def retry(self, value: Optional[int]) -> None: - if not (self._retry is None): #pylint: disable-msg=C0325 + if self._retry is not None: #pylint: disable-msg=C0325 raise DeadlinksSettingsChange("Change not allowed") # retry validation @@ -314,7 +305,7 @@ def external(self) -> bool: @external.setter def external(self, value: bool) -> None: - if not (self._external is None): #pylint: disable-msg=C0325 + if self._external is not None: #pylint: disable-msg=C0325 raise DeadlinksSettingsChange("Change not allowed") self._external = bool(value) @@ -332,7 +323,7 @@ def threads(self) -> int: @threads.setter def threads(self, value: Optional[int]) -> None: - if not (self._threads is None): #pylint: disable-msg=C0325 + if self._threads is not None: #pylint: disable-msg=C0325 raise DeadlinksSettingsChange("Change not allowed") if value is None: diff --git a/deadlinks/url.py b/deadlinks/url.py index 9a43fe8..7c6563e 100644 --- a/deadlinks/url.py +++ b/deadlinks/url.py @@ -24,29 +24,30 @@ # -- Imports ------------------------------------------------------------------- -from typing import (List, Optional) #pylint: disable-msg=W0611 - -from urllib.parse import (urlparse, urljoin) from html import unescape from re import compile as _compile +from typing import List, Union # pylint: disable-msg=W0611 +from urllib.parse import urljoin, urlparse from requests import RequestException +from .exceptions import DeadlinksIgnoredURL, DeadlinksRedirectionURL from .request import request from .status import Status -from .exceptions import ( - DeadlinksIgnoredURL, - DeadlinksRedirectionURL, -) # -- Constants ----------------------------------------------------------------- __RE_LINKS__ = _compile(r']+)>') # pylint: disable=W1401 # filters -CLEANER = lambda x: x.strip("\"'\n ") # removes quotes, spaces and new lines -ANCHORS = lambda x: x.split("#")[0] # removed part after anchor -UNESCPE = lambda x: unescape(x) # pylint: disable=W0108 +def CLEANER(x:str) -> str: + """removes quotes, spaces and new lines""" + return x.strip("\"'\n ") +def ANCHORS(x:str) -> str: + """removes anschor""" + return x.split("#")[0] +def UNESCPE(x:str) -> str: + return unescape(x) class URL: @@ -59,7 +60,7 @@ def __init__(self, location: str) -> None: # some predefined states self._referrers = [] # type: List[str] - self._text = None # type: Optional[str] + self._text: Union[str, None] = None self._links = [] # type: List[str] # internal error or mesage field, used to store ignore message @@ -194,7 +195,7 @@ def __str__(self) -> str: def __repr__(self) -> str: """ Object stringer representation. """ - return "{}<{}>".format(self.__class__.__name__, self.url()) + return f"{self.__class__.__name__}<{self.url()}>" def _consume_links(self) -> None: """ Parse response text into list of links. """ @@ -207,12 +208,10 @@ def _consume_links(self) -> None: continue href = attr[pos + 5:].strip() - if not href: continue - link = "" # type: str - + link: str = "" quoted = href[0] in {'"', "'"} if quoted: end_pos = href[1:].find(href[0]) diff --git a/docs/conf.py b/docs/conf.py index 0fa55b3..dd09da1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- import sys -from os import path, getenv +from os import getenv, path + from recommonmark.parser import CommonMarkParser sys.path.append(path.dirname(getenv('PWD'))) @@ -96,6 +97,7 @@ 'sphinx_markdown_tables', ] +language = "en" class MyCommonMarkParser(CommonMarkParser): # remove this hack once upsteam RecommonMark supports inline code @@ -104,6 +106,8 @@ def visit_code(self, mdnode): n = nodes.literal(mdnode.literal, mdnode.literal) self.current_node.append(n) + def visit_document(self, node): + pass def setup(app): from recommonmark.transform import AutoStructify diff --git a/make_brew_formula.py b/make_brew_formula.py index 999ca49..9be69a3 100644 --- a/make_brew_formula.py +++ b/make_brew_formula.py @@ -4,13 +4,12 @@ brew py is brew formula generator for the deadlinks package """ -from typing import (Dict, Tuple, Optional, List) #pylint: disable-msg=W0611 - +import json from collections import defaultdict from pathlib import Path -from textwrap import dedent from re import compile as _compile -import json +from textwrap import dedent +from typing import Dict, List, Optional, Tuple # pylint: disable-msg=W0611 import requests from jinja2 import Template @@ -135,14 +134,14 @@ def build_formula(app, requirements, build_dev=False) -> str: def get_local_pacage(): - import hashlib, glob + import glob + import hashlib - sha256 = hashlib.sha256() files = glob.glob("dist/deadlinks-*.tar.gz") with open(files[0], "rb") as f: data = f.read() - return "http://localhost:8878/%s" % files[0], hashlib.sha256(data).hexdigest() + return f"http://localhost:8878/{files[0]}", hashlib.sha256(data).hexdigest() def clean_version(package) -> Tuple[str, str, str]: @@ -159,7 +158,7 @@ def clean_version(package) -> Tuple[str, str, str]: def info(pkg, cmp: Optional[str], version: Optional[str]) -> Tuple[str, str]: """ Return version of package on pypi.python.org using json. """ - package_info = 'https://pypi.python.org/pypi/{}/json'.format(pkg) + package_info = f'https://pypi.python.org/pypi/{pkg}/json' req = requests.get(package_info) if req.status_code != requests.codes.ok: @@ -170,7 +169,8 @@ def info(pkg, cmp: Optional[str], version: Optional[str]) -> Tuple[str, str]: versions = releases.keys() version = release(versions, cmp, version) - source = lambda x: x.get("python_version") == "source" + def source(x): + return x.get('python_version') == 'source' version = list(filter(source, releases[str(version)]))[0] return version['url'], version["digests"]['sha256'] @@ -179,7 +179,8 @@ def info(pkg, cmp: Optional[str], version: Optional[str]) -> Tuple[str, str]: def release(releases, pkg_cmp, pkg_ver): """ filter available release to pick one included in formula """ - not_prerelease = lambda x: not x.is_prerelease + def not_prerelease(x): + return not x.is_prerelease cmps = { '!=': lambda x: x != parse(pkg_ver), @@ -218,5 +219,5 @@ def release(releases, pkg_cmp, pkg_ver): if '--dev' in sys.argv[1:]: options['build_dev'] = True - with open("{}.rb".format(data['app_package']), 'w') as f: + with open(f"{data['app_package']}.rb", 'w') as f: print(build_formula(**options), file=f) diff --git a/requirements.txt b/requirements.txt index 2741496..a050bdc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,19 +4,27 @@ yapf>=0.28.0 mypy>=0.701 # tests -pytest>=4.4.1 -flaky>=3.6.1 -pytest-randomly>=3.1.0 -pytest-timeout>=1.3.3 -coverage>=4.5.3 -pytest-cov>=2.6.1 -pytest-xdist>=1.29.0 +pytest>=7.0; python_version >= '3.9' +pytest==7.0.0; python_version < '3.9' +flaky>=3.7.0 +pytest-randomly>=3.15.0; python_version >= '3.9' +pytest-randomly==3.10.0; python_version < '3.9' +pytest-timeout>=2.2.0; python_version >= '3.9' +pytest-timeout==2.1.0; python_version < '3.9' +coverage>=7.4.0; python_version >= '3.9' +coverage==6.2; python_version < '3.9' +pytest-cov>=4.1.0; python_version >= '3.9' +pytest-cov==4.0.0; python_version < '3.9' +pytest-xdist>=3.5.0; python_version >= '3.9' +pytest-xdist==3.0.2; python_version < '3.9' # docs -Sphinx==4.0.2 +Sphinx==7.2.6; python_version >= '3.9' +Sphinx==5.3.0; python_version < '3.9' recommonmark==0.7.1 -sphinx-rtd-theme==0.5.2 -sphinx-markdown-tables==0.0.15 +sphinx-rtd-theme==2.0.0 +sphinx-markdown-tables>=0.0.17; python_version >= '3.9' +sphinx-markdown-tables>=0.0.15; python_version < '3.9' # brew chardet>=3.0.4 @@ -24,9 +32,9 @@ certifi>=2019.9.11 idna>=2.8 # install -requests>=2.22.0 -click>=7.0 -urllib3>=1.25.6 +requests>=2.31.0; python_version >= '3.9' +requests>=2.27.0; python_version < '3.9' +click>=8.0 six==1.16.0 diff --git a/setup.py b/setup.py index f2708f2..cecd059 100755 --- a/setup.py +++ b/setup.py @@ -29,8 +29,8 @@ def read_data() -> Dict[str, str]: values = dict() # type: Dict[str, str] with open(init) as fh: content = "".join(fh.readlines()) - for match in DUNDER_REGEXP.findall(content): - values[match[1]] = match[2] + for str_match in DUNDER_REGEXP.findall(content): + values[str_match[1]] = str_match[2] return values @@ -95,9 +95,9 @@ def readme() -> str: data['app_version'] += os.environ.get('DEADLINKS_VERSION', None) elif tagged and not match(VERSION, tagged) and branch and commit: dev_version_file = Path(__file__).parent / "deadlinks" / "__develop__.py" - dev_version_str = ".{}.{}".format(branch, commit).rstrip("+") + dev_version_str = f".{branch}.{commit}".rstrip("+") with open(str(dev_version_file), "w") as f: - print("version = '{}'".format(dev_version_str), file=f) + print(f"version = '{dev_version_str}'", file=f) data['app_version'] += dev_version_str # -- Version Releases / End ~~ diff --git a/tests/components/tests_baseurl.py b/tests/components/tests_baseurl.py index b93271f..6123776 100644 --- a/tests/components/tests_baseurl.py +++ b/tests/components/tests_baseurl.py @@ -12,7 +12,7 @@ import pytest -from deadlinks import (Link, BaseURL) +from deadlinks import BaseURL, Link # -- Tests --------------------------------------------------------------------- diff --git a/tests/components/tests_crawler.py b/tests/components/tests_crawler.py index f9c946c..5eb67b8 100644 --- a/tests/components/tests_crawler.py +++ b/tests/components/tests_crawler.py @@ -15,13 +15,9 @@ import pytest from flaky import flaky -from ..utils import Page +from deadlinks import Crawler, DeadlinksIgnoredURL, DeadlinksSettingsBase, Settings -from deadlinks import (Settings, Crawler) -from deadlinks import ( - DeadlinksIgnoredURL, - DeadlinksSettingsBase, -) +from ..utils import Page # -- Tests --------------------------------------------------------------------- @@ -197,9 +193,14 @@ def test_defaults(server, threads): # there are 2*3 links on the page, and half of them are working links_number = 3 - HTML_FORMATTER = lambda x: "{{0}}".format(x) #pylint: disable-msg=W0108 - LINK_FORMATTER = lambda x: HTML_FORMATTER("link").format(x) - LIMK_FORMATTER = lambda x: HTML_FORMATTER("limk").format(x) + def HTML_FORMATTER(x): + return "{{0}}".format(x) + + def LINK_FORMATTER(x): + return HTML_FORMATTER('link').format(x) + + def LIMK_FORMATTER(x): + return HTML_FORMATTER('limk').format(x) index_html = "" index_html += " - ".join(map(LINK_FORMATTER, range(links_number))) # 10 good links @@ -257,7 +258,7 @@ def test_mailto(server): """ Extra mailto test. """ MAILTO = "mailto:name@example.org" - CONTENT = """ mail link""".format(MAILTO) + CONTENT = f""" mail link""" address = server.router({ '^/$': Page(CONTENT).exists(), @@ -290,7 +291,8 @@ def test_redirected_links(server): from random import sample pages = list(range(1, 51)) - format_link = lambda x: "link" % x + def format_link(x): + return f"link" routes = { '^/$': Page(" / ".join(map(format_link, sample(pages, 4)))).exists(), @@ -298,7 +300,7 @@ def test_redirected_links(server): } for step in pages: - route_key = '^/link-%s/$' % step + route_key = f'^/link-{step}/$' route_contents = Page(" / ".join(map(format_link, sample(pages, 4)))).exists() routes.update({route_key: route_contents}) @@ -319,14 +321,15 @@ def test_no_index_page(server): from random import sample pages = list(range(1, 51)) - format_link = lambda x: "link" % x + def format_link(x): + return f"link" routes = { '^/$': Page("").exists(), } for step in pages: - route_key = '^/link-%s/$' % step + route_key = f'^/link-{step}/$' route_contents = Page(" / ".join(map(format_link, sample(pages, 4)))).exists() routes.update({route_key: route_contents}) diff --git a/tests/components/tests_index.py b/tests/components/tests_index.py index 92d5e0a..2755866 100644 --- a/tests/components/tests_index.py +++ b/tests/components/tests_index.py @@ -10,9 +10,9 @@ # -- Imports ------------------------------------------------------------------- -from typing import (List) +from typing import List -from deadlinks import (Link, Index, Status) +from deadlinks import Index, Link, Status # -- Tests --------------------------------------------------------------------- @@ -23,7 +23,7 @@ def test_index(): assert len(index) == 0 - links = [] # type: List[Link] + links: List[Link] = [] links.append(Link("https://google.com")) links.append(Link("https://google.com")) diff --git a/tests/components/tests_links.py b/tests/components/tests_links.py index bc98219..8ccaf58 100644 --- a/tests/components/tests_links.py +++ b/tests/components/tests_links.py @@ -14,14 +14,11 @@ import pytest -from ..utils import Page - -from deadlinks import (Link, URL) +from deadlinks import URL, Link +from deadlinks.exceptions import DeadlinksIgnoredURL, DeadlinksRedirectionURL from deadlinks.status import Status -from deadlinks.exceptions import ( - DeadlinksIgnoredURL, - DeadlinksRedirectionURL, -) + +from ..utils import Page # -- Tests --------------------------------------------------------------------- @@ -129,12 +126,12 @@ def test_links(server): '^/$': Page('test').exists(), }) - l = Link(url) + link = Link(url) - assert l.exists() - assert len(l.links) == 1 - assert str(l) == url - assert l.url() == url + assert link.exists() + assert len(link.links) == 1 + assert str(link) == url + assert link.url() == url @pytest.mark.parametrize( @@ -199,20 +196,20 @@ def test_eq(): def test_referrer(): """ Test referrer. """ - l = Link("https://made.ua") + link = Link("https://made.ua") referrer = "https://example.com" - l.add_referrer(referrer) - l.add_referrer(referrer) + link.add_referrer(referrer) + link.add_referrer(referrer) - assert referrer in l.get_referrers() + assert referrer in link.get_referrers() def test_match_domain(): """ Domain matching. """ - l = Link("https://made.ua") - assert l.match_domains(["made.ua"]) - assert not l.match_domains(["example.com"]) + link = Link("https://made.ua") + assert link.match_domains(["made.ua"]) + assert not link.match_domains(["example.com"]) @pytest.mark.timeout(2) @@ -223,14 +220,14 @@ def test_existing_page(server): '^/$': Page("").slow().exists(), }) - l = Link(address) - assert l.status == Status.UNDEFINED - assert l.exists() - l.status = Status.FOUND - assert l.exists() + link = Link(address) + assert link.status == Status.UNDEFINED + assert link.exists() + link.status = Status.FOUND + assert link.exists() with pytest.raises(TypeError): - l.status = 1 + link.status = 1 @pytest.mark.timeout(3) @@ -241,19 +238,19 @@ def test_not_existing_page(server): '^/$': Page("").unlock_after(3).slow().exists(), }) - l = Link(address) - assert l.status == Status.UNDEFINED + link = Link(address) + assert link.status == Status.UNDEFINED # timed out - assert not l.exists(retries=2) + assert not link.exists(retries=2) # setting new status - l.status = Status.NOT_FOUND + link.status = Status.NOT_FOUND # page is unlocked, but response is cached! - assert not l.exists() + assert not link.exists() with pytest.raises(TypeError): - l.status = 2 + link.status = 2 def test_redirected_page(server): @@ -262,13 +259,13 @@ def test_redirected_page(server): '^/$': Page("").redirects(pattern="https://example.com/?%s"), }) - l = Link(address) - assert l.status == Status.UNDEFINED + link = Link(address) + assert link.status == Status.UNDEFINED with pytest.raises(DeadlinksRedirectionURL): - l.exists() + link.exists() with pytest.raises(TypeError): - l.status = 0 + link.status = 0 def test_ignored_page(server): @@ -277,15 +274,15 @@ def test_ignored_page(server): '^/$': Page("").exists(), }) - l = Link(address) - assert l.status == Status.UNDEFINED - l.status = Status.IGNORED - assert l.status == Status.IGNORED + link = Link(address) + assert link.status == Status.UNDEFINED + link.status = Status.IGNORED + assert link.status == Status.IGNORED with pytest.raises(DeadlinksIgnoredURL): - l.exists() + link.exists() with pytest.raises(TypeError): - l.status = 3 + link.status = 3 def test_same_url(server): @@ -297,18 +294,18 @@ def test_same_url(server): '^/$': Page(page.format(*addr)).exists(), '^/link$': Page("ok").exists(), }) - l = Link(address) - assert l.exists() - assert address in l.links + link = Link(address) + assert link.exists() + assert address in link.links def test_not_available_page(): """ ok server, but ip with error """ - l = Link("http://127.0.0.1:79") - assert l.status == Status.UNDEFINED - assert not l.exists() - assert "Failed to establish a new connection" in l.message + link = Link("http://127.0.0.1:79") + assert link.status == Status.UNDEFINED + assert not link.exists() + assert "Failed to establish a new connection" in link.message def test_link_nl(server): @@ -319,9 +316,9 @@ def test_link_nl(server): '^/link$': Page("ok").exists(), }) - l = Link(address) - l.exists() - assert "/link" in l.links + link = Link(address) + link.exists() + assert "/link" in link.links @pytest.fixture( @@ -336,7 +333,7 @@ def params_l1_lt_l2(request): def test_order_neq(params_l1_lt_l2): - from operator import lt, gt + from operator import gt, lt l1, l2 = params_l1_lt_l2 assert l1 < l2 diff --git a/tests/components/tests_settings.py b/tests/components/tests_settings.py index ee1838b..fb31e35 100644 --- a/tests/components/tests_settings.py +++ b/tests/components/tests_settings.py @@ -14,17 +14,11 @@ import pytest -from deadlinks import (Settings, Link) -from deadlinks.exceptions import ( - DeadlinksSettingsPathes, - DeadlinksSettingsPath, - DeadlinksSettingsThreads, - DeadlinksSettingsBase, - DeadlinksSettingsRoot, - DeadlinksSettingsRetry, - DeadlinksSettingsChange, - DeadlinksSettingsDomains, -) +from deadlinks import Link, Settings +from deadlinks.exceptions import (DeadlinksSettingsBase, DeadlinksSettingsChange, + DeadlinksSettingsDomains, DeadlinksSettingsPath, + DeadlinksSettingsPathes, DeadlinksSettingsRetry, + DeadlinksSettingsRoot, DeadlinksSettingsThreads) # -- Tests --------------------------------------------------------------------- @@ -277,18 +271,18 @@ def test_internal_root(tmpdir): def test_robots_txt_defaults(settings): """ simple settings test for robots.txt """ - assert settings.check_robots_txt ==True + assert settings.check_robots_txt is True def test_robots_txt_turn_on(): """ simple settings test for robots.txt """ settings = Settings("http://localhost", check_robots_txt=True) - assert settings.check_robots_txt ==True + assert settings.check_robots_txt is True def test_robots_txt_turn_off(): """ simple settings test for robots.txt """ settings = Settings("http://localhost", check_robots_txt=False) - assert settings.check_robots_txt == False + assert settings.check_robots_txt is False diff --git a/tests/conftest.py b/tests/conftest.py index 0a80092..efd1db9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,15 +8,15 @@ :license: Apache2, see LICENSE for more details. """ -import pytest - -from textwrap import dedent from collections import OrderedDict +from textwrap import dedent -from .utils import Server, Page +import pytest + +from .runners.brew import BrewRunner from .runners.click import ClickRunner from .runners.docker import DockerRunner -from .runners.brew import BrewRunner +from .utils import Page, Server runners = OrderedDict({ 'click': ClickRunner, diff --git a/tests/features/tests_robots.py b/tests/features/tests_robots.py index 776f71c..6edb6b1 100644 --- a/tests/features/tests_robots.py +++ b/tests/features/tests_robots.py @@ -10,19 +10,17 @@ # -- Imports ------------------------------------------------------------------- -import pytest - from copy import deepcopy as copy from typing import Dict -from ..utils import Page +import pytest -from deadlinks import (Settings, Crawler) +from deadlinks import Crawler, DeadlinksIgnoredURL, Settings -from deadlinks import DeadlinksIgnoredURL +from ..utils import Page server_pages = { - '^/$': Page("".join(["%s" % (x, x) for x in range(1, 101)])).exists(), + '^/$': Page("".join([f"{x}" for x in range(1, 101)])).exists(), '^/link-\d{1,}$': Page("ok").exists().redirects(pattern='%s/'), '^/link-\d{1,}/$': Page("ok").exists(), } @@ -92,8 +90,8 @@ def test_failed_domain(): from random import choice from string import ascii_lowercase - domain = "http://%s.com/" % ''.join(choice(ascii_lowercase) for x in range(42)) - c = Crawler(Settings(domain)) + rand_str = "".join(choice(ascii_lowercase) for _ in range(42)) + c = Crawler(Settings(f"http://{rand_str}.com/")) c.start() assert len(c.failed) == 1 @@ -115,11 +113,3 @@ def test_failed_google(): c.start() assert len(c.succeed) == 1 - - -def test_gobyexample(): - """ special case - aws substitute robots.txt """ - - with pytest.raises(DeadlinksIgnoredURL): - c = Crawler(Settings("https://gobyexample.com")) - c.start() diff --git a/tests/features/tests_serving.py b/tests/features/tests_serving.py index ed24841..25344b2 100644 --- a/tests/features/tests_serving.py +++ b/tests/features/tests_serving.py @@ -12,10 +12,9 @@ import pytest -from deadlinks.serving.simple_server import SimpleServer -from deadlinks.serving.router import Router - from deadlinks import DeadlinksSettingsRoot +from deadlinks.serving.router import Router +from deadlinks.serving.simple_server import SimpleServer # -- Tests --------------------------------------------------------------------- @@ -48,7 +47,7 @@ def test_router(tmpdir): sitemap_txt_request = r('/sitemap.xml') assert sitemap_txt_request[0] == 404 - assert sitemap_txt_request[1] == None + assert sitemap_txt_request[1] is None index_request = r('/index.html') assert index_request[0] == 301 @@ -60,7 +59,7 @@ def test_router(tmpdir): none_request = r('/nope.html') assert none_request[0] == 404 - assert none_request[1] == None + assert none_request[1] is None def test_router_dir_non_exists(tmpdir): diff --git a/tests/features/tests_termination.py b/tests/features/tests_termination.py index 7ac3d12..8438cb5 100644 --- a/tests/features/tests_termination.py +++ b/tests/features/tests_termination.py @@ -10,16 +10,15 @@ # -- Imports ------------------------------------------------------------------- -import pytest -from flaky import flaky - import multiprocessing as mp -from threading import Timer from os import kill from signal import SIGINT +from threading import Timer from time import sleep from click.testing import CliRunner +from flaky import flaky + from deadlinks.__main__ import main from ..utils import Page diff --git a/tests/runners/brew.py b/tests/runners/brew.py index c52a07a..1b37eb4 100644 --- a/tests/runners/brew.py +++ b/tests/runners/brew.py @@ -10,15 +10,15 @@ # -- Imports ------------------------------------------------------------------- -import pytest - import sys -from typing import List from functools import partial from subprocess import PIPE +from typing import List + +import pytest -from .utils.runner import Runner from .utils.driver import Driver +from .utils.runner import Runner # -- Implementation ------------------------------------------------------------ diff --git a/tests/runners/click.py b/tests/runners/click.py index 143cdf9..f0df0c3 100644 --- a/tests/runners/click.py +++ b/tests/runners/click.py @@ -9,16 +9,16 @@ """ # -- Imports ------------------------------------------------------------------- -import pytest - -from typing import List from functools import partial +from typing import List +import pytest from click.testing import CliRunner -from .utils.runner import Runner from deadlinks.__main__ import main +from .utils.runner import Runner + # -- Implementation ------------------------------------------------------------------- diff --git a/tests/runners/docker.py b/tests/runners/docker.py index 5178375..c1dc51f 100644 --- a/tests/runners/docker.py +++ b/tests/runners/docker.py @@ -9,14 +9,14 @@ """ # -- Imports ------------------------------------------------------------------- -import pytest - -from typing import List from functools import partial from subprocess import PIPE +from typing import List + +import pytest -from .utils.runner import Runner from .utils.driver import Driver +from .utils.runner import Runner # -- Implementation ------------------------------------------------------------ diff --git a/tests/tests_cli_common.py b/tests/tests_cli_common.py index d093300..0bf551d 100644 --- a/tests/tests_cli_common.py +++ b/tests/tests_cli_common.py @@ -27,7 +27,7 @@ def test_default_dsn_with_issues(runner, dsn): assert result['code'] == 2 - assert "Error: URL {} is not valid".format(dsn) in result['output'] + assert f"Error: URL {dsn} is not valid" in result['output'] def test_default_url_no_scheme_issue(server, runner): @@ -40,7 +40,7 @@ def test_default_url_no_scheme_issue(server, runner): result = runner(args) assert result['code'] == 0 - assert "{}//{}".format(scheme, address) in result['output'] + assert f"{scheme}//{address}" in result['output'] def test_help(runner): diff --git a/tests/tests_cli_defaults.py b/tests/tests_cli_defaults.py index dba773e..ea4f191 100644 --- a/tests/tests_cli_defaults.py +++ b/tests/tests_cli_defaults.py @@ -10,18 +10,16 @@ # -- Imports ------------------------------------------------------------------- -import pytest - -from typing import Dict - from collections import Counter -from random import choice from copy import deepcopy as copy +from random import choice +from typing import Dict -from .utils import Page - +import pytest from click import unstyle +from .utils import Page + # -- Helpers ------------------------------------------------------------------ def make_params(external, threads, domains, pathes): @@ -60,10 +58,10 @@ def test_version(runner): assert result['code'] == 0 - from deadlinks.__version__ import __app_version__ as version from deadlinks.__version__ import __app_package__ as package + from deadlinks.__version__ import __app_version__ as version - expected_main_version = "{}: v{}".format(package, version) + expected_main_version = f"{package}: v{version}" assert result["output"].rstrip("\n").startswith(expected_main_version) @@ -157,7 +155,7 @@ def test_redirection(servers, runner): }) site_to_index = servers[1].router({ - '^/$': Page("{0}".format(linked_domain)).exists(), + '^/$': Page(f"{linked_domain}").exists(), }) args = [site_to_index, '-e', '-s', 'all'] @@ -300,7 +298,7 @@ def test_cli_details(site_with_links, runner, external, threads, domains, pathes @pytest.fixture def pages(): - index = "".join(["%s" % (x, x) for x in range(1, 11)]) + index = "".join([f"{x}" for x in range(1, 11)]) return { '^/$': Page(index).exists(), '^/link-\d{1,}$': Page("ok").exists().redirects(pattern='%s/'), diff --git a/tests/tests_cli_defaults_internal.py b/tests/tests_cli_defaults_internal.py index 5483cb5..ce9680c 100644 --- a/tests/tests_cli_defaults_internal.py +++ b/tests/tests_cli_defaults_internal.py @@ -10,11 +10,10 @@ # -- Imports ------------------------------------------------------------------- -import pytest - -import sys from textwrap import dedent +import pytest + # -- Tests ------------------------------------------------------------------- # TODO - Do same tests for updated docker runner with shared volume. diff --git a/tests/utils/server.py b/tests/utils/server.py index 0139c06..463d5e3 100644 --- a/tests/utils/server.py +++ b/tests/utils/server.py @@ -10,19 +10,15 @@ # -- Imports ------------------------------------------------------------------ -from typing import (Optional, Dict) - +import socket from functools import partial -from time import sleep from http.server import HTTPServer - -import socket - from threading import Thread +from typing import Dict, Optional -from .router import Router from .handler import Handler from .page import Page +from .router import Router # -- Implementation -----------------------------------------------------------