diff --git a/docs/Dockerfile b/docs/Dockerfile index 36da88bc8..c64aa572a 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -17,28 +17,28 @@ RUN pip install --upgrade pip # Install IDOM # ------------ -ADD requirements ./requirements +COPY requirements ./requirements RUN pip install -r requirements/build-docs.txt -ADD src ./src -ADD scripts ./scripts -ADD setup.py ./ -ADD setup.cfg ./ -ADD MANIFEST.in ./ -ADD README.md ./ +COPY src ./src +COPY scripts ./scripts +COPY setup.py ./ +COPY pyproject.toml ./ +COPY MANIFEST.in ./ +COPY README.md ./ RUN pip install -e .[all] -# Add License +# COPY License # ----------- -Add LICENSE /app/ +COPY LICENSE /app/ # Build the Docs # -------------- -ADD docs/__init__.py ./docs/ -ADD docs/app.py ./docs/ -ADD docs/examples.py ./docs/ -ADD docs/source ./docs/source -ADD branding ./branding +COPY docs/__init__.py ./docs/ +COPY docs/app.py ./docs/ +COPY docs/examples.py ./docs/ +COPY docs/source ./docs/source +COPY branding ./branding RUN sphinx-build -v -W -b html docs/source docs/build # Define Entrypoint diff --git a/noxfile.py b/noxfile.py index a50ba1912..65aa4a52c 100644 --- a/noxfile.py +++ b/noxfile.py @@ -180,17 +180,21 @@ def test_python_suite(session: Session) -> None: session.env["IDOM_DEBUG_MODE"] = "1" install_requirements_file(session, "test-env") session.run("playwright", "install", "chromium") - posargs = session.posargs - posargs += ["--reruns", "3", "--reruns-delay", "1"] + args = ["pytest", "--reruns", "3", "--reruns-delay", "1", *session.posargs] - if "--no-cov" in session.posargs: + check_cov = "--no-cov" not in session.posargs + if check_cov: + args = ["coverage", "run", "--source=src/idom", "--module", *args] + install_idom_dev(session) + else: + args.remove("--no-cov") session.log("Coverage won't be checked") session.install(".[all]") - else: - posargs += ["--cov=src/idom", "--cov-report", "term"] - install_idom_dev(session) - session.run("pytest", *posargs) + session.run(*args) + + if check_cov: + session.run("coverage", "report") @nox.session @@ -209,14 +213,7 @@ def test_python_style(session: Session) -> None: """Check that Python style guidelines are being followed""" install_requirements_file(session, "check-style") session.run("flake8", "src/idom", "tests", "docs") - black_default_exclude = r"\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist" - session.run( - "black", - ".", - "--check", - "--exclude", - rf"/({black_default_exclude}|venv|node_modules)/", - ) + session.run("black", ".", "--check") session.run("isort", ".", "--check-only") diff --git a/pyproject.toml b/pyproject.toml index 18a77f5a7..32f0fb5dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,3 +10,46 @@ ensure_newline_before_comments = "True" include_trailing_comma = "True" line_length = 88 lines_after_imports = 2 + +[tool.mypy] +ignore_missing_imports = true +warn_unused_configs = true +warn_redundant_casts = true +warn_unused_ignores = true + +[tool.pytest.ini_options] +testpaths = "tests" +xfail_strict = true +markers = ["slow: marks tests as slow (deselect with '-m \"not slow\"')"] +python_files = "*asserts.py test_*.py" +asyncio_mode = "auto" + +[tool.coverage.report] +fail_under = 100 +show_missing = true +skip_covered = true +sort = "Name" +exclude_lines = [ + "pragma: no cover", + '\.\.\.', + "raise NotImplementedError", +] + +[tool.pydocstyle] +inherit = false +match = '.*\.py' +convention = "google" +add_ignore = ["D100", "D101", "D102", "D103", "D104", "D105", "D107", "D412", "D415"] + +[tool.flake8] +ignore = ["E203", "E266", "E501", "W503", "F811", "N802", "N806"] +per-file-ignores = [ + # sometimes this is required in order to hide setup for an example + "docs/*/_examples/*.py:E402", +] +max-line-length = 88 +max-complexity = 18 +select = ["B", "C", "E", "F", "W", "T4", "B9", "N", "ROH"] +exclude = ["**/node_modules/*", ".eggs/*", ".tox/*"] +# -- flake8-tidy-imports -- +ban-relative-imports = "parents" diff --git a/requirements/check-style.txt b/requirements/check-style.txt index 4a6e0c421..eff7b3164 100644 --- a/requirements/check-style.txt +++ b/requirements/check-style.txt @@ -1,5 +1,6 @@ -black +black[jupyter] flake8 +flake8-pyproject flake8-idom-hooks >=0.5.0 flake8-print flake8-tidy-imports diff --git a/requirements/test-env.txt b/requirements/test-env.txt index 7e5ab1955..aa007c295 100644 --- a/requirements/test-env.txt +++ b/requirements/test-env.txt @@ -1,9 +1,10 @@ pytest pytest-asyncio>=0.17 -pytest-cov pytest-mock pytest-rerunfailures pytest-timeout + +coverage responses playwright diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 293907987..000000000 --- a/setup.cfg +++ /dev/null @@ -1,55 +0,0 @@ -[bdist_wheel] -universal=1 - -[mypy] -ignore_missing_imports = True -warn_unused_configs = True -warn_redundant_casts = True -warn_unused_ignores = True - -[flake8] -ignore = E203, E266, E501, W503, F811, N802, N806 -per-file-ignores = - # sometimes this is required in order to hide setup for an example - docs/*/_examples/*.py:E402 -max-line-length = 88 -max-complexity = 18 -select = B,C,E,F,W,T4,B9,N,ROH -exclude = - **/node_modules/* - .eggs/* - .tox/* -# -- flake8-tidy-imports -- -ban-relative-imports = parents - -[tool:pytest] -testpaths = tests -xfail_strict = True -markers = - slow: marks tests as slow (deselect with '-m "not slow"') -python_files = *asserts.py test_*.py -asyncio_mode = auto - -[coverage:report] -fail_under = 100 -show_missing = True -skip_covered = True -sort = Name -exclude_lines = - pragma: no cover - \.\.\. - raise NotImplementedError -omit = - src/idom/__main__.py - src/idom/core/_fixed_jsonpatch.py - -[build_sphinx] -all-files = true -source-dir = docs/source -build-dir = docs/build - -[pydocstyle] -inherit = false -match = .*\.py -convention = google -add_ignore = D100,D101,D102,D103,D104,D105,D107,D412,D415 diff --git a/src/idom/_option.py b/src/idom/_option.py index 3d2295f16..7fb1b7ecd 100644 --- a/src/idom/_option.py +++ b/src/idom/_option.py @@ -1,9 +1,11 @@ from __future__ import annotations import os -import warnings +from inspect import currentframe from logging import getLogger -from typing import Any, Callable, Generic, TypeVar, cast +from types import FrameType +from typing import Any, Callable, Generic, Iterator, TypeVar, cast +from warnings import warn _O = TypeVar("_O") @@ -129,12 +131,32 @@ def __init__(self, new_opt: Option[_O], name: str) -> None: @property # type: ignore def _current(self) -> _O: - warnings.warn( + warn( f"{self.name!r} has been renamed to {self._new_opt.name!r}", DeprecationWarning, + stacklevel=_frame_depth_in_module() + 1, ) return self._new_opt.current @_current.setter def _current(self, new: _O) -> None: self._new_opt.current = new + + +def _frame_depth_in_module() -> int: + depth = 0 + for frame in _iter_frames(2): + if frame.f_globals.get("__name__") != __name__: + break + depth += 1 + return depth + + +def _iter_frames(index: int = 1) -> Iterator[FrameType]: + frame = currentframe() + while frame is not None: + if index == 0: + yield frame + else: + index -= 1 + frame = frame.f_back