diff --git a/charms/jupyter-controller/pyproject.toml b/charms/jupyter-controller/pyproject.toml index c17b2731..c81e3918 100644 --- a/charms/jupyter-controller/pyproject.toml +++ b/charms/jupyter-controller/pyproject.toml @@ -18,6 +18,7 @@ line-length = 99 target-version = ["py38"] [tool.isort] +line_length = 99 profile = "black" # Linting tools configuration @@ -29,12 +30,11 @@ exclude = [".git", "__pycache__", ".tox", "build", "dist", "*.egg_info", "venv"] select = ["E", "W", "F", "C", "N", "R", "D", "H"] # Ignore W503, E501 because using black creates errors with this # Ignore D107 Missing docstring in __init__ -# Ignore E231 missing whitespace after ':', which work against W291 trailing whitespace -ignore = ["W503", "E501", "D107", "E231"] +ignore = ["W503", "E501", "D107"] # D100, D101, D102, D103: Ignore missing docstrings in tests per-file-ignores = ["tests/*:D100,D101,D102,D103,D104"] docstring-convention = "google" # Check for properly formatted copyright header in each file copyright-check = "True" copyright-author = "Canonical Ltd." -copyright-regexp = "Copyright\\s\\d{4}([-,]\\d{4})*\\s+%(author)s" +copyright-regexp = "Copyright\\s\\d{4}([-,]\\d{4})*\\s+%(author)s" \ No newline at end of file diff --git a/charms/jupyter-controller/requirements-fmt.in b/charms/jupyter-controller/requirements-fmt.in new file mode 100644 index 00000000..7559a405 --- /dev/null +++ b/charms/jupyter-controller/requirements-fmt.in @@ -0,0 +1,2 @@ +black +isort diff --git a/charms/jupyter-controller/requirements-fmt.txt b/charms/jupyter-controller/requirements-fmt.txt new file mode 100644 index 00000000..c5c26c36 --- /dev/null +++ b/charms/jupyter-controller/requirements-fmt.txt @@ -0,0 +1,22 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile --resolver=backtracking ./charms/jupyter-controller/requirements-fmt.in +# +black==22.10.0 + # via -r ./charms/jupyter-controller/requirements-fmt.in +click==8.1.3 + # via black +isort==5.10.1 + # via -r ./charms/jupyter-controller/requirements-fmt.in +mypy-extensions==0.4.3 + # via black +pathspec==0.10.2 + # via black +platformdirs==2.5.4 + # via black +tomli==2.0.1 + # via black +typing-extensions==4.4.0 + # via black diff --git a/charms/jupyter-controller/requirements-integration.in b/charms/jupyter-controller/requirements-integration.in new file mode 100644 index 00000000..dadeff77 --- /dev/null +++ b/charms/jupyter-controller/requirements-integration.in @@ -0,0 +1,3 @@ +juju +pytest-operator +-r requirements.txt diff --git a/charms/jupyter-controller/requirements-integration.txt b/charms/jupyter-controller/requirements-integration.txt new file mode 100644 index 00000000..e5e69c22 --- /dev/null +++ b/charms/jupyter-controller/requirements-integration.txt @@ -0,0 +1,188 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile --resolver=backtracking ./charms/jupyter-controller/requirements-integration.in +# +asttokens==2.2.0 + # via stack-data +attrs==22.1.0 + # via pytest +backcall==0.2.0 + # via ipython +bcrypt==4.0.1 + # via paramiko +cachetools==5.2.0 + # via google-auth +certifi==2022.9.24 + # via + # kubernetes + # requests +cffi==1.15.1 + # via + # cryptography + # pynacl +charset-normalizer==2.1.1 + # via requests +cryptography==38.0.4 + # via paramiko +decorator==5.1.1 + # via + # ipdb + # ipython +exceptiongroup==1.0.4 + # via pytest +executing==1.2.0 + # via stack-data +google-auth==2.15.0 + # via kubernetes +idna==3.4 + # via requests +iniconfig==1.1.1 + # via pytest +ipdb==0.13.9 + # via pytest-operator +ipython==8.7.0 + # via ipdb +jedi==0.18.2 + # via ipython +jinja2==3.1.2 + # via pytest-operator +juju==3.0.4 + # via + # -r ./charms/jupyter-controller/requirements-integration.in + # pytest-operator +jujubundlelib==0.5.7 + # via theblues +kubernetes==25.3.0 + # via juju +macaroonbakery==1.3.1 + # via + # juju + # theblues +markupsafe==2.1.1 + # via jinja2 +matplotlib-inline==0.1.6 + # via ipython +mypy-extensions==0.4.3 + # via typing-inspect +oauthlib==3.2.2 + # via requests-oauthlib +oci-image==1.0.0 + # via -r ./charms/jupyter-controller/requirements.txt +ops==1.5.4 + # via -r ./charms/jupyter-controller/requirements.txt +packaging==21.3 + # via pytest +paramiko==2.12.0 + # via juju +parso==0.8.3 + # via jedi +pexpect==4.8.0 + # via ipython +pickleshare==0.7.5 + # via ipython +pluggy==1.0.0 + # via pytest +prompt-toolkit==3.0.33 + # via ipython +protobuf==3.20.3 + # via macaroonbakery +ptyprocess==0.7.0 + # via pexpect +pure-eval==0.2.2 + # via stack-data +pyasn1==0.4.8 + # via + # juju + # pyasn1-modules + # rsa +pyasn1-modules==0.2.8 + # via google-auth +pycparser==2.21 + # via cffi +pygments==2.13.0 + # via ipython +pymacaroons==0.13.0 + # via macaroonbakery +pynacl==1.5.0 + # via + # macaroonbakery + # paramiko + # pymacaroons +pyparsing==3.0.9 + # via packaging +pyrfc3339==1.1 + # via + # juju + # macaroonbakery +pytest==7.2.0 + # via + # pytest-asyncio + # pytest-operator +pytest-asyncio==0.20.2 + # via pytest-operator +pytest-operator==0.22.0 + # via -r ./charms/jupyter-controller/requirements-integration.in +python-dateutil==2.8.2 + # via kubernetes +pytz==2022.6 + # via pyrfc3339 +pyyaml==6.0 + # via + # -r ./charms/jupyter-controller/requirements.txt + # juju + # jujubundlelib + # kubernetes + # ops + # pytest-operator +requests==2.28.1 + # via + # kubernetes + # macaroonbakery + # requests-oauthlib + # theblues +requests-oauthlib==1.3.1 + # via kubernetes +rsa==4.9 + # via google-auth +six==1.16.0 + # via + # asttokens + # google-auth + # kubernetes + # macaroonbakery + # paramiko + # pymacaroons + # python-dateutil +stack-data==0.6.2 + # via ipython +theblues==0.5.2 + # via juju +toml==0.10.2 + # via ipdb +tomli==2.0.1 + # via pytest +toposort==1.7 + # via juju +traitlets==5.6.0 + # via + # ipython + # matplotlib-inline +typing-extensions==4.4.0 + # via typing-inspect +typing-inspect==0.8.0 + # via juju +urllib3==1.26.13 + # via + # kubernetes + # requests +wcwidth==0.2.5 + # via prompt-toolkit +websocket-client==1.4.2 + # via kubernetes +websockets==7.0 + # via juju + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/charms/jupyter-controller/requirements-lint.in b/charms/jupyter-controller/requirements-lint.in new file mode 100644 index 00000000..c77cd87f --- /dev/null +++ b/charms/jupyter-controller/requirements-lint.in @@ -0,0 +1,9 @@ +codespell +flake8<6 +flake8-builtins +# Pinned because `flake8-copyright==0.2.3` is incompatible with `flake8>=6`. Can unpin this +# when https://github.com/savoirfairelinux/flake8-copyright/pull/20 or a similar fix is released +flake8-copyright +pep8-naming +pyproject-flake8 +-r requirements-fmt.txt diff --git a/charms/jupyter-controller/requirements-lint.txt b/charms/jupyter-controller/requirements-lint.txt new file mode 100644 index 00000000..6cb8d751 --- /dev/null +++ b/charms/jupyter-controller/requirements-lint.txt @@ -0,0 +1,60 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile --resolver=backtracking ./charms/jupyter-controller/requirements-lint.in +# +black==22.10.0 + # via -r ./charms/jupyter-controller/requirements-fmt.txt +click==8.1.3 + # via + # -r ./charms/jupyter-controller/requirements-fmt.txt + # black +codespell==2.2.2 + # via -r ./charms/jupyter-controller/requirements-lint.in +flake8==5.0.4 + # via + # -r ./charms/jupyter-controller/requirements-lint.in + # flake8-builtins + # pep8-naming + # pyproject-flake8 +flake8-builtins==2.0.1 + # via -r ./charms/jupyter-controller/requirements-lint.in +flake8-copyright==0.2.3 + # via -r ./charms/jupyter-controller/requirements-lint.in +isort==5.10.1 + # via -r ./charms/jupyter-controller/requirements-fmt.txt +mccabe==0.7.0 + # via flake8 +mypy-extensions==0.4.3 + # via + # -r ./charms/jupyter-controller/requirements-fmt.txt + # black +pathspec==0.10.2 + # via + # -r ./charms/jupyter-controller/requirements-fmt.txt + # black +pep8-naming==0.13.2 + # via -r ./charms/jupyter-controller/requirements-lint.in +platformdirs==2.5.4 + # via + # -r ./charms/jupyter-controller/requirements-fmt.txt + # black +pycodestyle==2.9.1 + # via flake8 +pyflakes==2.5.0 + # via flake8 +pyproject-flake8==5.0.4.post1 + # via -r ./charms/jupyter-controller/requirements-lint.in +tomli==2.0.1 + # via + # -r ./charms/jupyter-controller/requirements-fmt.txt + # black + # pyproject-flake8 +typing-extensions==4.4.0 + # via + # -r ./charms/jupyter-controller/requirements-fmt.txt + # black + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/charms/jupyter-controller/requirements-unit.in b/charms/jupyter-controller/requirements-unit.in new file mode 100644 index 00000000..3d5c246d --- /dev/null +++ b/charms/jupyter-controller/requirements-unit.in @@ -0,0 +1,3 @@ +coverage +pytest +-r requirements.txt diff --git a/charms/jupyter-controller/requirements-unit.txt b/charms/jupyter-controller/requirements-unit.txt new file mode 100644 index 00000000..67dfc5de --- /dev/null +++ b/charms/jupyter-controller/requirements-unit.txt @@ -0,0 +1,32 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile --resolver=backtracking ./charms/jupyter-controller/requirements-unit.in +# +attrs==22.1.0 + # via pytest +coverage==6.5.0 + # via -r ./charms/jupyter-controller/requirements-unit.in +exceptiongroup==1.0.4 + # via pytest +iniconfig==1.1.1 + # via pytest +oci-image==1.0.0 + # via -r ./charms/jupyter-controller/requirements.txt +ops==1.5.4 + # via -r ./charms/jupyter-controller/requirements.txt +packaging==21.3 + # via pytest +pluggy==1.0.0 + # via pytest +pyparsing==3.0.9 + # via packaging +pytest==7.2.0 + # via -r ./charms/jupyter-controller/requirements-unit.in +pyyaml==6.0 + # via + # -r ./charms/jupyter-controller/requirements.txt + # ops +tomli==2.0.1 + # via pytest diff --git a/charms/jupyter-controller/requirements-update-packages.in b/charms/jupyter-controller/requirements-update-packages.in new file mode 100644 index 00000000..2c2a9f38 --- /dev/null +++ b/charms/jupyter-controller/requirements-update-packages.in @@ -0,0 +1 @@ +pip-tools diff --git a/charms/jupyter-controller/requirements-update-packages.txt b/charms/jupyter-controller/requirements-update-packages.txt new file mode 100644 index 00000000..53660fbe --- /dev/null +++ b/charms/jupyter-controller/requirements-update-packages.txt @@ -0,0 +1,28 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile --resolver=backtracking ./charms/jupyter-controller/requirements-update-packages.in +# +build==0.9.0 + # via pip-tools +click==8.1.3 + # via pip-tools +packaging==21.3 + # via build +pep517==0.13.0 + # via build +pip-tools==6.10.0 + # via -r ./charms/jupyter-controller/requirements-update-packages.in +pyparsing==3.0.9 + # via packaging +tomli==2.0.1 + # via + # build + # pep517 +wheel==0.38.4 + # via pip-tools + +# The following packages are considered to be unsafe in a requirements file: +# pip +# setuptools diff --git a/charms/jupyter-controller/requirements.in b/charms/jupyter-controller/requirements.in new file mode 100644 index 00000000..7a994037 --- /dev/null +++ b/charms/jupyter-controller/requirements.in @@ -0,0 +1,2 @@ +ops +oci-image diff --git a/charms/jupyter-controller/requirements.txt b/charms/jupyter-controller/requirements.txt index 8d92469a..1bf7260b 100644 --- a/charms/jupyter-controller/requirements.txt +++ b/charms/jupyter-controller/requirements.txt @@ -1,2 +1,12 @@ -ops==1.3.0 +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile --resolver=backtracking ./charms/jupyter-controller/requirements.in +# oci-image==1.0.0 + # via -r ./charms/jupyter-controller/requirements.in +ops==1.5.4 + # via -r ./charms/jupyter-controller/requirements.in +pyyaml==6.0 + # via ops diff --git a/charms/jupyter-controller/tox.ini b/charms/jupyter-controller/tox.ini index d8f691fc..e0fb8406 100644 --- a/charms/jupyter-controller/tox.ini +++ b/charms/jupyter-controller/tox.ini @@ -1,44 +1,52 @@ +# Copyright 2022 Canonical Ltd. +# See LICENSE file for licensing details. + +[flake8] +max-line-length = 100 + [tox] -skipsdist=True +skipsdist = True skip_missing_interpreters = True -envlist = lint, unit +envlist = fmt, lint, unit, integration [vars] +all_path = {[vars]src_path} {[vars]tst_path} src_path = {toxinidir}/src/ tst_path = {toxinidir}/tests/ -all_path = {[vars]src_path} {[vars]tst_path} [testenv] -setenv = - PYTHONPATH = {toxinidir}:{toxinidir}/lib:{[vars]src_path} - PYTHONBREAKPOINT=ipdb.set_trace - PY_COLORS=1 passenv = - PYTHONPATH - CHARM_BUILD_DIR - MODEL_SETTINGS + PYTHONPATH + CHARM_BUILD_DIR + MODEL_SETTINGS + KUBECONFIG +setenv = + PYTHONPATH = {toxinidir}:{toxinidir}/lib:{[vars]src_path} + PYTHONBREAKPOINT=ipdb.set_trace + PY_COLORS=1 -[testenv:fmt] -description = Apply coding style standards to code +[testenv:update-requirements] +allowlist_externals = + bash + find + pip-compile + xargs +commands = +; uses 'bash -c' because piping didn't work in regular tox commands + bash -c \'find . -type f -name "requirements*.in" | xargs --replace=\{\} pip-compile --resolver=backtracking \{\}' deps = - black - isort + -r requirements-update-packages.txt +description = Update requirements files by executing pip-compile on all requirements*.in files, including those in subdirs. + +[testenv:fmt] commands = isort {[vars]all_path} black {[vars]all_path} +deps = + -r requirements-fmt.txt +description = Apply coding style standards to code [testenv:lint] -description = Check code against coding style standards -deps = - black - flake8==4.0.1 - flake8-docstrings - flake8-copyright - flake8-builtins - pyproject-flake8 - pep8-naming - isort - codespell commands = # uncomment the following line if this charm owns a lib # codespell {[vars]lib_path} @@ -49,23 +57,21 @@ commands = pflake8 {[vars]all_path} isort --check-only --diff {[vars]all_path} black --check --diff {[vars]all_path} +deps = + -r requirements-lint.txt +description = Check code against coding style standards [testenv:unit] -description = Run unit tests -deps = - pytest - coverage[toml] - -r{toxinidir}/requirements.txt commands = coverage run --source={[vars]src_path} \ - -m pytest --ignore={[vars]tst_path}integration -v --tb native -s {posargs} + -m pytest --ignore={[vars]tst_path}integration -vv --tb native {posargs} coverage report +deps = + -r requirements-unit.txt +description = Run unit tests [testenv:integration] -description = Run integration tests +commands = pytest -v --tb native --asyncio-mode=auto {[vars]tst_path}integration --log-cli-level=INFO -s {posargs} deps = - juju - pytest-operator - -r{toxinidir}/requirements.txt -commands = - pytest -v --tb native --asyncio-mode=auto --ignore={[vars]tst_path}unit --log-cli-level=INFO -s {posargs} + -r requirements-integration.txt +description = Run integration tests diff --git a/charms/jupyter-ui/pyproject.toml b/charms/jupyter-ui/pyproject.toml new file mode 100644 index 00000000..c81e3918 --- /dev/null +++ b/charms/jupyter-ui/pyproject.toml @@ -0,0 +1,40 @@ +# Copyright 2022 Canonical Ltd. +# See LICENSE file for licensing details. + +# Testing tools configuration +[tool.coverage.run] +branch = true + +[tool.coverage.report] +show_missing = true + +[tool.pytest.ini_options] +minversion = "6.0" +log_cli_level = "INFO" + +# Formatting tools configuration +[tool.black] +line-length = 99 +target-version = ["py38"] + +[tool.isort] +line_length = 99 +profile = "black" + +# Linting tools configuration +[tool.flake8] +max-line-length = 99 +max-doc-length = 99 +max-complexity = 10 +exclude = [".git", "__pycache__", ".tox", "build", "dist", "*.egg_info", "venv"] +select = ["E", "W", "F", "C", "N", "R", "D", "H"] +# Ignore W503, E501 because using black creates errors with this +# Ignore D107 Missing docstring in __init__ +ignore = ["W503", "E501", "D107"] +# D100, D101, D102, D103: Ignore missing docstrings in tests +per-file-ignores = ["tests/*:D100,D101,D102,D103,D104"] +docstring-convention = "google" +# Check for properly formatted copyright header in each file +copyright-check = "True" +copyright-author = "Canonical Ltd." +copyright-regexp = "Copyright\\s\\d{4}([-,]\\d{4})*\\s+%(author)s" \ No newline at end of file diff --git a/charms/jupyter-ui/requirements-fmt.in b/charms/jupyter-ui/requirements-fmt.in new file mode 100644 index 00000000..7559a405 --- /dev/null +++ b/charms/jupyter-ui/requirements-fmt.in @@ -0,0 +1,2 @@ +black +isort diff --git a/charms/jupyter-ui/requirements-fmt.txt b/charms/jupyter-ui/requirements-fmt.txt new file mode 100644 index 00000000..2dfe3629 --- /dev/null +++ b/charms/jupyter-ui/requirements-fmt.txt @@ -0,0 +1,22 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile --resolver=backtracking ./charms/jupyter-ui/requirements-fmt.in +# +black==22.10.0 + # via -r ./charms/jupyter-ui/requirements-fmt.in +click==8.1.3 + # via black +isort==5.10.1 + # via -r ./charms/jupyter-ui/requirements-fmt.in +mypy-extensions==0.4.3 + # via black +pathspec==0.10.2 + # via black +platformdirs==2.5.4 + # via black +tomli==2.0.1 + # via black +typing-extensions==4.4.0 + # via black diff --git a/charms/jupyter-ui/requirements-lint.in b/charms/jupyter-ui/requirements-lint.in new file mode 100644 index 00000000..c77cd87f --- /dev/null +++ b/charms/jupyter-ui/requirements-lint.in @@ -0,0 +1,9 @@ +codespell +flake8<6 +flake8-builtins +# Pinned because `flake8-copyright==0.2.3` is incompatible with `flake8>=6`. Can unpin this +# when https://github.com/savoirfairelinux/flake8-copyright/pull/20 or a similar fix is released +flake8-copyright +pep8-naming +pyproject-flake8 +-r requirements-fmt.txt diff --git a/charms/jupyter-ui/requirements-lint.txt b/charms/jupyter-ui/requirements-lint.txt new file mode 100644 index 00000000..465175bf --- /dev/null +++ b/charms/jupyter-ui/requirements-lint.txt @@ -0,0 +1,60 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile --resolver=backtracking ./charms/jupyter-ui/requirements-lint.in +# +black==22.10.0 + # via -r ./charms/jupyter-ui/requirements-fmt.txt +click==8.1.3 + # via + # -r ./charms/jupyter-ui/requirements-fmt.txt + # black +codespell==2.2.2 + # via -r ./charms/jupyter-ui/requirements-lint.in +flake8==5.0.4 + # via + # -r ./charms/jupyter-ui/requirements-lint.in + # flake8-builtins + # pep8-naming + # pyproject-flake8 +flake8-builtins==2.0.1 + # via -r ./charms/jupyter-ui/requirements-lint.in +flake8-copyright==0.2.3 + # via -r ./charms/jupyter-ui/requirements-lint.in +isort==5.10.1 + # via -r ./charms/jupyter-ui/requirements-fmt.txt +mccabe==0.7.0 + # via flake8 +mypy-extensions==0.4.3 + # via + # -r ./charms/jupyter-ui/requirements-fmt.txt + # black +pathspec==0.10.2 + # via + # -r ./charms/jupyter-ui/requirements-fmt.txt + # black +pep8-naming==0.13.2 + # via -r ./charms/jupyter-ui/requirements-lint.in +platformdirs==2.5.4 + # via + # -r ./charms/jupyter-ui/requirements-fmt.txt + # black +pycodestyle==2.9.1 + # via flake8 +pyflakes==2.5.0 + # via flake8 +pyproject-flake8==5.0.4.post1 + # via -r ./charms/jupyter-ui/requirements-lint.in +tomli==2.0.1 + # via + # -r ./charms/jupyter-ui/requirements-fmt.txt + # black + # pyproject-flake8 +typing-extensions==4.4.0 + # via + # -r ./charms/jupyter-ui/requirements-fmt.txt + # black + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/charms/jupyter-ui/requirements-unit.in b/charms/jupyter-ui/requirements-unit.in new file mode 100644 index 00000000..3d5c246d --- /dev/null +++ b/charms/jupyter-ui/requirements-unit.in @@ -0,0 +1,3 @@ +coverage +pytest +-r requirements.txt diff --git a/charms/jupyter-ui/requirements-unit.txt b/charms/jupyter-ui/requirements-unit.txt new file mode 100644 index 00000000..147810ce --- /dev/null +++ b/charms/jupyter-ui/requirements-unit.txt @@ -0,0 +1,75 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile --resolver=backtracking ./charms/jupyter-ui/requirements-unit.in +# +attrs==22.1.0 + # via + # -r ./charms/jupyter-ui/requirements.txt + # jsonschema + # pytest +certifi==2022.9.24 + # via + # -r ./charms/jupyter-ui/requirements.txt + # requests +chardet==3.0.4 + # via + # -r ./charms/jupyter-ui/requirements.txt + # requests +coverage==6.5.0 + # via -r ./charms/jupyter-ui/requirements-unit.in +exceptiongroup==1.0.4 + # via pytest +idna==2.10 + # via + # -r ./charms/jupyter-ui/requirements.txt + # requests +iniconfig==1.1.1 + # via pytest +jsonschema==3.2.0 + # via + # -r ./charms/jupyter-ui/requirements.txt + # serialized-data-interface +oci-image==1.0.0 + # via -r ./charms/jupyter-ui/requirements.txt +ops==1.5.4 + # via + # -r ./charms/jupyter-ui/requirements.txt + # serialized-data-interface +packaging==21.3 + # via pytest +pluggy==1.0.0 + # via pytest +pyparsing==3.0.9 + # via packaging +pyrsistent==0.19.2 + # via + # -r ./charms/jupyter-ui/requirements.txt + # jsonschema +pytest==7.2.0 + # via -r ./charms/jupyter-ui/requirements-unit.in +pyyaml==5.4 + # via + # -r ./charms/jupyter-ui/requirements.txt + # ops + # serialized-data-interface +requests==2.25.0 + # via + # -r ./charms/jupyter-ui/requirements.txt + # serialized-data-interface +serialized-data-interface==0.3.5 + # via -r ./charms/jupyter-ui/requirements.txt +six==1.16.0 + # via + # -r ./charms/jupyter-ui/requirements.txt + # jsonschema +tomli==2.0.1 + # via pytest +urllib3==1.26.13 + # via + # -r ./charms/jupyter-ui/requirements.txt + # requests + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/charms/jupyter-ui/requirements-update-packages.in b/charms/jupyter-ui/requirements-update-packages.in new file mode 100644 index 00000000..2c2a9f38 --- /dev/null +++ b/charms/jupyter-ui/requirements-update-packages.in @@ -0,0 +1 @@ +pip-tools diff --git a/charms/jupyter-ui/requirements-update-packages.txt b/charms/jupyter-ui/requirements-update-packages.txt new file mode 100644 index 00000000..81f00cb4 --- /dev/null +++ b/charms/jupyter-ui/requirements-update-packages.txt @@ -0,0 +1,28 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile --resolver=backtracking ./charms/jupyter-ui/requirements-update-packages.in +# +build==0.9.0 + # via pip-tools +click==8.1.3 + # via pip-tools +packaging==21.3 + # via build +pep517==0.13.0 + # via build +pip-tools==6.10.0 + # via -r ./charms/jupyter-ui/requirements-update-packages.in +pyparsing==3.0.9 + # via packaging +tomli==2.0.1 + # via + # build + # pep517 +wheel==0.38.4 + # via pip-tools + +# The following packages are considered to be unsafe in a requirements file: +# pip +# setuptools diff --git a/charms/jupyter-ui/requirements.in b/charms/jupyter-ui/requirements.in new file mode 100644 index 00000000..5d666cd0 --- /dev/null +++ b/charms/jupyter-ui/requirements.in @@ -0,0 +1,4 @@ +ops +oci-image +serialized-data-interface<0.4 +# Unittest will fail without pinning diff --git a/charms/jupyter-ui/requirements.txt b/charms/jupyter-ui/requirements.txt index 4df0e5be..83f389f9 100644 --- a/charms/jupyter-ui/requirements.txt +++ b/charms/jupyter-ui/requirements.txt @@ -1,3 +1,39 @@ -ops==1.2.0 +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile --resolver=backtracking ./charms/jupyter-ui/requirements.in +# +attrs==22.1.0 + # via jsonschema +certifi==2022.9.24 + # via requests +chardet==3.0.4 + # via requests +idna==2.10 + # via requests +jsonschema==3.2.0 + # via serialized-data-interface oci-image==1.0.0 -serialized-data-interface<0.4 + # via -r ./charms/jupyter-ui/requirements.in +ops==1.5.4 + # via + # -r ./charms/jupyter-ui/requirements.in + # serialized-data-interface +pyrsistent==0.19.2 + # via jsonschema +pyyaml==5.4 + # via + # ops + # serialized-data-interface +requests==2.25.0 + # via serialized-data-interface +serialized-data-interface==0.3.5 + # via -r ./charms/jupyter-ui/requirements.in +six==1.16.0 + # via jsonschema +urllib3==1.26.13 + # via requests + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/charms/jupyter-ui/src/charm.py b/charms/jupyter-ui/src/charm.py index 34eb3a6a..3fec75c3 100755 --- a/charms/jupyter-ui/src/charm.py +++ b/charms/jupyter-ui/src/charm.py @@ -8,11 +8,7 @@ from ops.charm import CharmBase from ops.main import main from ops.model import ActiveStatus, BlockedStatus, MaintenanceStatus, WaitingStatus -from serialized_data_interface import ( - NoCompatibleVersions, - NoVersionsListed, - get_interfaces, -) +from serialized_data_interface import NoCompatibleVersions, NoVersionsListed, get_interfaces class CheckFailed(Exception): @@ -38,7 +34,7 @@ def __init__(self, *args): self.on.leader_elected, self.on.upgrade_charm, self.on.config_changed, - self.on['ingress'].relation_changed, + self.on["ingress"].relation_changed, ]: self.framework.observe(event, self.main) @@ -64,38 +60,45 @@ def main(self, event): "global": True, "rules": [ { - 'apiGroups': [''], - 'resources': ['namespaces'], - 'verbs': ['get', 'list', 'create', 'delete'], + "apiGroups": [""], + "resources": ["namespaces"], + "verbs": ["get", "list", "create", "delete"], }, { - 'apiGroups': ['authorization.k8s.io'], - 'resources': ['subjectaccessreviews'], - 'verbs': ['create'], + "apiGroups": ["authorization.k8s.io"], + "resources": ["subjectaccessreviews"], + "verbs": ["create"], }, { - 'apiGroups': ['kubeflow.org'], - 'resources': [ - 'notebooks', - 'notebooks/finalizers', - 'poddefaults', + "apiGroups": ["kubeflow.org"], + "resources": [ + "notebooks", + "notebooks/finalizers", + "poddefaults", + ], + "verbs": [ + "get", + "list", + "create", + "delete", + "patch", + "update", ], - 'verbs': ['get', 'list', 'create', 'delete', 'patch', 'update'], }, { - 'apiGroups': [''], - 'resources': ['persistentvolumeclaims'], - 'verbs': ['create', 'delete', 'get', 'list'], + "apiGroups": [""], + "resources": ["persistentvolumeclaims"], + "verbs": ["create", "delete", "get", "list"], }, { - 'apiGroups': [''], - 'resources': ['events', 'nodes'], - 'verbs': ['list'], + "apiGroups": [""], + "resources": ["events", "nodes"], + "verbs": ["list"], }, { - 'apiGroups': ['storage.k8s.io'], - 'resources': ['storageclasses'], - 'verbs': ['get', 'list', 'watch'], + "apiGroups": ["storage.k8s.io"], + "resources": ["storageclasses"], + "verbs": ["get", "list", "watch"], }, ], } @@ -105,15 +108,15 @@ def main(self, event): { "name": "jupyter-ui", "imageDetails": image_details, - 'ports': [{'name': 'http', 'containerPort': config['port']}], + "ports": [{"name": "http", "containerPort": config["port"]}], "envConfig": { - 'APP_PREFIX': config['url-prefix'], - 'APP_SECURE_COOKIES': str(config['secure-cookies']), - 'BACKEND_MODE': config['backend-mode'], - 'CLUSTER_DOMAIN': 'cluster.local', - 'UI': config['ui'], - 'USERID_HEADER': 'kubeflow-userid', - 'USERID_PREFIX': '', + "APP_PREFIX": config["url-prefix"], + "APP_SECURE_COOKIES": str(config["secure-cookies"]), + "BACKEND_MODE": config["backend-mode"], + "CLUSTER_DOMAIN": "cluster.local", + "UI": config["ui"], + "USERID_HEADER": "kubeflow-userid", + "USERID_PREFIX": "", }, "volumeConfig": [ { @@ -122,7 +125,7 @@ def main(self, event): "files": [ { "path": "spawner_ui_config.yaml", - "content": Path('src/spawner_ui_config.yaml').read_text(), + "content": Path("src/spawner_ui_config.yaml").read_text(), } ], }, @@ -135,8 +138,8 @@ def main(self, event): "content": content, } for name, content in yaml.safe_load( - Path('src/logos-configmap.yaml').read_text() - )['data'].items() + Path("src/logos-configmap.yaml").read_text() + )["data"].items() ], }, ], @@ -150,7 +153,7 @@ def _configure_mesh(self, interfaces): if interfaces["ingress"]: interfaces["ingress"].send_data( { - "prefix": self.model.config['url-prefix'] + '/', + "prefix": self.model.config["url-prefix"] + "/", "rewrite": "/", "service": self.model.app.name, "port": self.model.config["port"], diff --git a/charms/jupyter-ui/test-requirements.txt b/charms/jupyter-ui/test-requirements.txt deleted file mode 100644 index 90f4d537..00000000 --- a/charms/jupyter-ui/test-requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -pytest<6.3 -black -flake8<4.1 diff --git a/charms/jupyter-ui/tests/test_operator.py b/charms/jupyter-ui/tests/test_operator.py index 1a0b713b..8b89ae8e 100644 --- a/charms/jupyter-ui/tests/test_operator.py +++ b/charms/jupyter-ui/tests/test_operator.py @@ -1,9 +1,10 @@ import pytest import yaml -from charm import Operator from ops.model import ActiveStatus, BlockedStatus, WaitingStatus from ops.testing import Harness +from charm import Operator + @pytest.fixture def harness(): @@ -33,7 +34,7 @@ def test_no_relation(harness): ) harness.begin_with_initial_hooks() - assert harness.charm.model.unit.status == ActiveStatus('') + assert harness.charm.model.unit.status == ActiveStatus("") def test_with_relation(harness): diff --git a/charms/jupyter-ui/tox.ini b/charms/jupyter-ui/tox.ini index b9f205d6..7554ca2f 100644 --- a/charms/jupyter-ui/tox.ini +++ b/charms/jupyter-ui/tox.ini @@ -1,21 +1,72 @@ +# Copyright 2022 Canonical Ltd. +# See LICENSE file for licensing details. + [flake8] max-line-length = 100 [tox] skipsdist = True +skip_missing_interpreters = True +envlist = lint, unit, integration + +[vars] +all_path = {[vars]src_path} {[vars]tst_path} +src_path = {toxinidir}/src/ +tst_path = {toxinidir}/tests/ [testenv] +passenv = + PYTHONPATH + CHARM_BUILD_DIR + MODEL_SETTINGS + KUBECONFIG setenv = - PYTHONPATH={toxinidir}/src + PYTHONPATH = {toxinidir}:{toxinidir}/lib:{[vars]src_path} + PYTHONBREAKPOINT=ipdb.set_trace + PY_COLORS=1 + +[testenv:update-requirements] +allowlist_externals = + bash + find + pip-compile + xargs +commands = +; uses 'bash -c' because piping didn't work in regular tox commands + bash -c \'find . -type f -name "requirements*.in" | xargs --replace=\{\} pip-compile --resolver=backtracking \{\}' deps = - -rtest-requirements.txt - -rrequirements.txt + -r requirements-update-packages.txt +description = Update requirements files by executing pip-compile on all requirements*.in files, including those in subdirs. -[testenv:unit] +[testenv:fmt] commands = - pytest tests + isort {[vars]all_path} + black {[vars]all_path} +deps = + -r requirements-fmt.txt +description = Apply coding style standards to code [testenv:lint] commands = - flake8 {toxinidir}/src {toxinidir}/tests - black --check --diff {toxinidir}/src {toxinidir}/tests + # uncomment the following line if this charm owns a lib + # codespell {[vars]lib_path} + codespell {toxinidir}/. --skip {toxinidir}/.git --skip {toxinidir}/.tox \ + --skip {toxinidir}/build --skip {toxinidir}/lib --skip {toxinidir}/venv \ + --skip {toxinidir}/.mypy_cache \ + --skip {toxinidir}/icon.svg --skip *.json.tmpl + # pflake8 wrapper supports config from pyproject.toml + pflake8 {[vars]all_path} + isort --check-only --diff {[vars]all_path} + black --check --diff {[vars]all_path} +deps = + -r requirements-lint.txt +description = Check code against coding style standards + +[testenv:unit] +commands = + coverage run --source={[vars]src_path} \ + -m pytest --ignore={[vars]tst_path}integration -vv --tb native {posargs} + coverage report +deps = + -r requirements-unit.txt +description = Run unit tests diff --git a/juju-crashdump-2f2d0dd9-17a0-4141-824f-5d3159daa058.tar.xz b/juju-crashdump-2f2d0dd9-17a0-4141-824f-5d3159daa058.tar.xz new file mode 100644 index 00000000..ecd25f76 Binary files /dev/null and b/juju-crashdump-2f2d0dd9-17a0-4141-824f-5d3159daa058.tar.xz differ diff --git a/renovate.json b/renovate.json new file mode 100644 index 00000000..a8f7a844 --- /dev/null +++ b/renovate.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "rebaseWhen": "behind-base-branch", + "dependencyDashboard": false, + "pip-compile": { + "fileMatch": [ + "(^|/)requirements.*\\.in$" + ], + "lockFileMaintenance": { + "schedule": null + } + }, + "packageRules": [ + { + "groupName": "testing deps", + "matchPackagePatterns": [ + "^black$", + "codespell", + "flake8", + "flake8-builtins", + "flake8-copyright", + "flake8-docstrings", + "isort", + "pep8-naming", + "pyproject-flake8", + "pytest", + "pytest-asyncio", + "selenium", + "selenium-wire" + ], + "automerge": true + } + ] +} diff --git a/requirements-integration.in b/requirements-integration.in new file mode 100644 index 00000000..1a8b9d26 --- /dev/null +++ b/requirements-integration.in @@ -0,0 +1,9 @@ +juju +lightkube +pytest-operator +pytest +pyyaml +selenium-wire +selenium +tenacity +requests diff --git a/requirements-integration.txt b/requirements-integration.txt new file mode 100644 index 00000000..bba0e8e2 --- /dev/null +++ b/requirements-integration.txt @@ -0,0 +1,275 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile --resolver=backtracking ./requirements-integration.in +# +anyio==3.6.2 + # via httpcore +asttokens==2.2.0 + # via stack-data +async-generator==1.10 + # via + # trio + # trio-websocket +attrs==22.1.0 + # via + # outcome + # pytest + # trio +backcall==0.2.0 + # via ipython +bcrypt==4.0.1 + # via paramiko +blinker==1.5 + # via selenium-wire +brotli==1.0.9 + # via selenium-wire +cachetools==5.2.0 + # via google-auth +certifi==2022.9.24 + # via + # httpcore + # httpx + # kubernetes + # requests + # selenium + # selenium-wire +cffi==1.15.1 + # via + # cryptography + # pynacl +charset-normalizer==2.1.1 + # via requests +cryptography==38.0.4 + # via + # paramiko + # pyopenssl +decorator==5.1.1 + # via + # ipdb + # ipython +exceptiongroup==1.0.4 + # via + # pytest + # trio +executing==1.2.0 + # via stack-data +google-auth==2.15.0 + # via kubernetes +h11==0.14.0 + # via + # httpcore + # wsproto +h2==4.1.0 + # via selenium-wire +hpack==4.0.0 + # via h2 +httpcore==0.16.2 + # via httpx +httpx==0.23.1 + # via lightkube +hyperframe==6.0.1 + # via + # h2 + # selenium-wire +idna==3.4 + # via + # anyio + # requests + # rfc3986 + # trio +iniconfig==1.1.1 + # via pytest +ipdb==0.13.9 + # via pytest-operator +ipython==8.7.0 + # via ipdb +jedi==0.18.2 + # via ipython +jinja2==3.1.2 + # via pytest-operator +juju==3.0.4 + # via + # -r ./requirements-integration.in + # pytest-operator +jujubundlelib==0.5.7 + # via theblues +kaitaistruct==0.10 + # via selenium-wire +kubernetes==25.3.0 + # via juju +lightkube==0.11.0 + # via -r ./requirements-integration.in +lightkube-models==1.25.4.4 + # via lightkube +macaroonbakery==1.3.1 + # via + # juju + # theblues +markupsafe==2.1.1 + # via jinja2 +matplotlib-inline==0.1.6 + # via ipython +mypy-extensions==0.4.3 + # via typing-inspect +oauthlib==3.2.2 + # via requests-oauthlib +outcome==1.2.0 + # via trio +packaging==21.3 + # via pytest +paramiko==2.12.0 + # via juju +parso==0.8.3 + # via jedi +pexpect==4.8.0 + # via ipython +pickleshare==0.7.5 + # via ipython +pluggy==1.0.0 + # via pytest +prompt-toolkit==3.0.33 + # via ipython +protobuf==3.20.3 + # via macaroonbakery +ptyprocess==0.7.0 + # via pexpect +pure-eval==0.2.2 + # via stack-data +pyasn1==0.4.8 + # via + # juju + # pyasn1-modules + # rsa + # selenium-wire +pyasn1-modules==0.2.8 + # via google-auth +pycparser==2.21 + # via cffi +pygments==2.13.0 + # via ipython +pymacaroons==0.13.0 + # via macaroonbakery +pynacl==1.5.0 + # via + # macaroonbakery + # paramiko + # pymacaroons +pyopenssl==22.1.0 + # via selenium-wire +pyparsing==3.0.9 + # via + # packaging + # selenium-wire +pyrfc3339==1.1 + # via + # juju + # macaroonbakery +pysocks==1.7.1 + # via + # selenium-wire + # urllib3 +pytest==7.2.0 + # via + # -r ./requirements-integration.in + # pytest-asyncio + # pytest-operator +pytest-asyncio==0.20.2 + # via pytest-operator +pytest-operator==0.22.0 + # via -r ./requirements-integration.in +python-dateutil==2.8.2 + # via kubernetes +pytz==2022.6 + # via pyrfc3339 +pyyaml==6.0 + # via + # -r ./requirements-integration.in + # juju + # jujubundlelib + # kubernetes + # lightkube + # pytest-operator +requests==2.28.1 + # via + # -r ./requirements-integration.in + # kubernetes + # macaroonbakery + # requests-oauthlib + # theblues +requests-oauthlib==1.3.1 + # via kubernetes +rfc3986[idna2008]==1.5.0 + # via httpx +rsa==4.9 + # via google-auth +selenium==4.7.0 + # via + # -r ./requirements-integration.in + # selenium-wire +selenium-wire==5.1.0 + # via -r ./requirements-integration.in +six==1.16.0 + # via + # asttokens + # google-auth + # kubernetes + # macaroonbakery + # paramiko + # pymacaroons + # python-dateutil +sniffio==1.3.0 + # via + # anyio + # httpcore + # httpx + # trio +sortedcontainers==2.4.0 + # via trio +stack-data==0.6.2 + # via ipython +tenacity==8.1.0 + # via -r ./requirements-integration.in +theblues==0.5.2 + # via juju +toml==0.10.2 + # via ipdb +tomli==2.0.1 + # via pytest +toposort==1.7 + # via juju +traitlets==5.6.0 + # via + # ipython + # matplotlib-inline +trio==0.22.0 + # via + # selenium + # trio-websocket +trio-websocket==0.9.2 + # via selenium +typing-extensions==4.4.0 + # via typing-inspect +typing-inspect==0.8.0 + # via juju +urllib3[socks]==1.26.13 + # via + # kubernetes + # requests + # selenium +wcwidth==0.2.5 + # via prompt-toolkit +websocket-client==1.4.2 + # via kubernetes +websockets==7.0 + # via juju +wsproto==1.2.0 + # via + # selenium-wire + # trio-websocket +zstandard==0.19.0 + # via selenium-wire + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/requirements-update-packages.in b/requirements-update-packages.in new file mode 100644 index 00000000..2c2a9f38 --- /dev/null +++ b/requirements-update-packages.in @@ -0,0 +1 @@ +pip-tools diff --git a/requirements-update-packages.txt b/requirements-update-packages.txt new file mode 100644 index 00000000..3daa27df --- /dev/null +++ b/requirements-update-packages.txt @@ -0,0 +1,28 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile --resolver=backtracking ./requirements-update-packages.in +# +build==0.9.0 + # via pip-tools +click==8.1.3 + # via pip-tools +packaging==21.3 + # via build +pep517==0.13.0 + # via build +pip-tools==6.10.0 + # via -r ./requirements-update-packages.in +pyparsing==3.0.9 + # via packaging +tomli==2.0.1 + # via + # build + # pep517 +wheel==0.38.4 + # via pip-tools + +# The following packages are considered to be unsafe in a requirements file: +# pip +# setuptools diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index 70487667..00000000 --- a/test-requirements.txt +++ /dev/null @@ -1,11 +0,0 @@ -black -flake8<4.1 -juju==3.0.1 -lightkube<0.11 -pytest-operator<0.10 -pytest<6.3 -pyyaml<6.1 -selenium-wire<4.6 -selenium==3.141.0 -tenacity<8.1 -requests diff --git a/tox.ini b/tox.ini index 08383557..f0d1b497 100644 --- a/tox.ini +++ b/tox.ini @@ -6,7 +6,6 @@ skipsdist = True envlist = {controller,ui}-{unit,lint,integration},integration [testenv] -whitelist_externals = tox setenv = controller: CHARM = controller ui: CHARM = ui @@ -16,10 +15,24 @@ setenv = commands = tox -c charms/jupyter-{env:CHARM} -e {env:TYPE} +[testenv:update-requirements] +description = Update requirements files by executing pip-compile on all requirements*.in files, including those in subdirs. +deps = + -r requirements-update-packages.txt +allowlist_externals = + bash + find + pip-compile + xargs +commands = +; uses 'bash -c' because piping didn't work in regular tox commands + bash -c \'find . -type f -name "requirements*.in" | xargs --replace=\{\} pip-compile --resolver=backtracking \{\}' + [testenv:integration] +whitelist_externals = tox passenv = HOME DISPLAY deps = - -rtest-requirements.txt + -r requirements-integration.txt commands = pytest -vvs --tb native --show-capture=no --log-cli-level=INFO --asyncio-mode=auto {posargs} {toxinidir}/tests/