diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml new file mode 100644 index 0000000..97ef6ad --- /dev/null +++ b/.github/workflows/build-and-publish.yml @@ -0,0 +1,38 @@ +name: Build & Publish + +on: + workflow_call: + secrets: + PYPI_TOKEN: + required: true + +jobs: + + cd-job: + name: Continues Delivery + runs-on: ubuntu-latest + steps: + + - name: SCM Checkout + uses: actions/checkout@v3 + + - name: Setup Python & Poetry Environment + uses: exasol/python-toolbox/.github/actions/python-environment@0.5.0 + + - name: Build Artifacts + run: poetry build + + - name: PyPi Release + env: + POETRY_HTTP_BASIC_PYPI_USERNAME: "__token__" + POETRY_HTTP_BASIC_PYPI_PASSWORD: "${{ secrets.PYPI_TOKEN }}" + run: poetry publish + + - name: GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: > + gh release create ${GITHUB_REF_NAME} + --title ${GITHUB_REF_NAME} + --notes-file doc/changes/changes_${GITHUB_REF_NAME}.md + dist/* diff --git a/.github/workflows/check-release-tag.yml b/.github/workflows/check-release-tag.yml new file mode 100644 index 0000000..cedd32b --- /dev/null +++ b/.github/workflows/check-release-tag.yml @@ -0,0 +1,21 @@ +name: Check Release Tag + +on: workflow_call + +jobs: + + check-tag-version-job: + + name: Check Tag Version + runs-on: ubuntu-latest + + steps: + - name: SCM Checkout + uses: actions/checkout@v3 + + - name: Setup Python & Poetry Environment + uses: exasol/python-toolbox/.github/actions/python-environment@0.5.0 + + - name: Check Tag Version + # make sure the pushed/created tag matched the project version + run: "[[ `poetry version --short` == ${{ github.ref_name }} ]]" diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 0000000..b464065 --- /dev/null +++ b/.github/workflows/checks.yml @@ -0,0 +1,113 @@ +name: Checks + +on: workflow_call + +jobs: + + version-check-job: + name: Version Check + runs-on: ubuntu-latest + + steps: + - name: SCM Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Setup Python & Poetry Environment + uses: exasol/python-toolbox/.github/actions/python-environment@0.5.0 + + - name: Check Version(s) + run: poetry run version-check version.py + + build-documentation-job: + name: Build Documentation + needs: [version-check-job] + runs-on: ubuntu-latest + + steps: + - name: SCM Checkout + uses: actions/checkout@v3 + + - name: Setup Python & Poetry Environment + uses: exasol/python-toolbox/.github/actions/python-environment@0.5.0 + + - name: Build Documentation + run: | + poetry run python -m nox -s build-docs + + lint-job: + name: Linting (Python-${{ matrix.python-version }}) + needs: [version-check-job] + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.9"] + + steps: + - name: SCM Checkout + uses: actions/checkout@v3 + + - name: Setup Python & Poetry Environment + uses: exasol/python-toolbox/.github/actions/python-environment@0.5.0 + with: + python-version: ${{ matrix.python-version }} + + - name: Run Linter + run: poetry run nox -s lint + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: .lint.txt + path: .lint.txt + + type-check-job: + name: Type Checking (Python-${{ matrix.python-version }}) + needs: [version-check-job] + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.9"] + + steps: + - name: SCM Checkout + uses: actions/checkout@v3 + + - name: Setup Python & Poetry Environment + uses: exasol/python-toolbox/.github/actions/python-environment@0.5.0 + with: + python-version: ${{ matrix.python-version }} + + - name: Run Type check + run: poetry run nox -s type-check + + tests-job: + name: Tests (Python-${{ matrix.python-version }}, Exasol-${{ matrix.exasol-version}}) + needs: [build-documentation-job, lint-job, type-check-job] + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.9"] + exasol-version: ["7.1.9"] + + steps: + - name: SCM Checkout + uses: actions/checkout@v3 + + - name: Setup Python & Poetry Environment + uses: exasol/python-toolbox/.github/actions/python-environment@0.5.0 + with: + python-version: ${{ matrix.python-version }} + + - name: Calculate Test Coverage + run: poetry run nox -s coverage -- -- --db-version ${{ matrix.exasol-version }} + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: .coverage + path: .coverage diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml new file mode 100644 index 0000000..a1b9664 --- /dev/null +++ b/.github/workflows/ci-cd.yml @@ -0,0 +1,28 @@ +name: CI/CD + +on: + push: + tags: + - '**' + +jobs: + + check-tag-version-job: + name: Check Release Tag + uses: ./.github/workflows/check-release-tag.yml + + ci-job: + name: Checks + needs: [ check-tag-version-job ] + uses: ./.github/workflows/checks.yml + + cd-job: + name: Continuous Delivery + needs: [ ci-job ] + uses: ./.github/workflows/build-and-publish.yml + secrets: + PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} + + metrics: + needs: [ ci-job ] + uses: ./.github/workflows/report.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7af9378..f0dc9d1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,33 +3,22 @@ name: CI on: push: branches-ignore: + - "github-pages/*" + - "gh-pages/*" - "main" + - "master" + pull_request: + types: [opened, reopened] + schedule: + # “At 00:00 on every 7th day-of-month from 1 through 31.” (https://crontab.guru) + - cron: "0 0 1/7 * *" jobs: - tests-job: - name: Tests (Python-${{ matrix.python-version }}) - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - python-version: ["3.9"] - steps: - - uses: actions/checkout@v2 - - name: Install Poetry - run: | - pipx install poetry - - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - cache: 'poetry' - cache-dependency-path: poetry.lock - - uses: abatilo/actions-poetry@v2.1.4 - with: - poetry-version: 1.2.2 + ci-job: + name: Checks + uses: ./.github/workflows/checks.yml - - name: Install Project - run: poetry install - - - name: Run Tests - run: poetry run pytest tests + metrics: + needs: [ ci-job ] + uses: ./.github/workflows/report.yml diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml new file mode 100644 index 0000000..d2f1c68 --- /dev/null +++ b/.github/workflows/gh-pages.yml @@ -0,0 +1,27 @@ +name: Publish Documentation + +on: workflow_call + +jobs: + + documentation-job: + runs-on: ubuntu-latest + + steps: + - name: SCM Checkout + uses: actions/checkout@v3 + + - name: Setup Python & Poetry Environment + uses: exasol/python-toolbox/.github/actions/python-environment@0.5.0 + + - name: Build Documentation + run: | + poetry run python -m nox -s build-docs + + - name: Deploy + uses: JamesIves/github-pages-deploy-action@v4.4.1 + with: + branch: gh-pages + folder: .html-documentation + git-config-name: Github Action + git-config-email: opensource@exasol.com diff --git a/.github/workflows/pr-merge.yml b/.github/workflows/pr-merge.yml new file mode 100644 index 0000000..7a4fc86 --- /dev/null +++ b/.github/workflows/pr-merge.yml @@ -0,0 +1,21 @@ +name: PR-Merge + +on: + push: + branches: + - 'main' + - 'master' + +jobs: + + ci-job: + name: Checks + uses: ./.github/workflows/checks.yml + + publish-docs: + name: Publish Documentation + uses: ./.github/workflows/gh-pages.yml + + metrics: + needs: [ ci-job ] + uses: ./.github/workflows/report.yml diff --git a/.github/workflows/report.yml b/.github/workflows/report.yml new file mode 100644 index 0000000..c8d3043 --- /dev/null +++ b/.github/workflows/report.yml @@ -0,0 +1,53 @@ +name: Status Report + +on: + workflow_call: + secrets: + ALTERNATIVE_GITHUB_TOKEN: + required: false + +jobs: + + report: + name: Generate Status Report + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.ALTERNATIVE_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + + steps: + - name: SCM Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Setup Python & Poetry Environment + uses: exasol/python-toolbox/.github/actions/python-environment@0.5.0 + + - name: Download Artifacts + uses: actions/download-artifact@v3 + with: + path: ./artifacts + + - name: Copy Artifacts into Root Folder + working-directory: ./artifacts + run: | + cp .coverage/.coverage ../ + cp .lint.txt/.lint.txt ../ + + - name: Generate Report + run: poetry run nox -s report -- -- --format json | tee metrics.json + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: metrics.json + path: metrics.json + + - name: Generate GitHub Summary + run: | + echo -e "# Summary\n" >> $GITHUB_STEP_SUMMARY + poetry run nox -s report -- -- --format markdown >> $GITHUB_STEP_SUMMARY + echo -e "\n\n# Coverage\n" >> $GITHUB_STEP_SUMMARY + poetry run coverage report -- --format markdown >> $GITHUB_STEP_SUMMARY + echo -e "\n\n# Static Code Analysis\n" >> $GITHUB_STEP_SUMMARY + cat .lint.txt >> $GITHUB_STEP_SUMMARY diff --git a/.gitignore b/.gitignore index 9ce8408..f478513 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,7 @@ dist __pycache__/ /TAGS +/.coverage +/.lint.json +/.lint.txt +/.html-documentation/ diff --git a/tests/__init__.py b/artifacts/.placeholder similarity index 100% rename from tests/__init__.py rename to artifacts/.placeholder diff --git a/doc/changes/changes_0.0.1.md b/doc/changes/changes_0.0.1.md index b48a1ff..2a7520b 100644 --- a/doc/changes/changes_0.0.1.md +++ b/doc/changes/changes_0.0.1.md @@ -10,3 +10,4 @@ This release adds the initial implementation of the secret store * #4: Added python toolbox * #7: Refactored secret store to store simple key/value pairs * #5: Added test case to verify that plain access to secret store fails +* #8: Updated exasol python toolbox to version 0.5.0 diff --git a/doc/conf.py b/doc/conf.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/doc/conf.py @@ -0,0 +1 @@ + diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/doc/index.rst @@ -0,0 +1 @@ + diff --git a/exasol/secret_store.py b/exasol/secret_store.py index 0f7c292..23c3e8f 100644 --- a/exasol/secret_store.py +++ b/exasol/secret_store.py @@ -1,13 +1,13 @@ import contextlib import logging -import os -import pathlib -from pathlib import Path -from dataclasses import dataclass -from sqlcipher3 import dbapi2 as sqlcipher -from typing import List, Optional, Union from inspect import cleandoc +from pathlib import Path +from typing import ( + List, + Optional, +) +from sqlcipher3 import dbapi2 as sqlcipher # type: ignore _logger = logging.getLogger(__name__) TABLE_NAME = "secrets" @@ -28,12 +28,18 @@ def close(self) -> None: self._con.close() self._con = None - def connection(self) -> sqlcipher.Connection: + # disable error messages about unresolved types in type hints as + # sqlcipher is a c library and does not provide this information. + def connection( + self, + ) -> sqlcipher.Connection: # pylint: disable=E1101 if self._con is None: db_file_found = self.db_file.exists() if not db_file_found: - _logger.info(f"Creating file {self.db_file}") - self._con = sqlcipher.connect(self.db_file) + _logger.info("Creating file %s", self.db_file) + # fmt: off + self._con = sqlcipher.connect(self.db_file) # pylint: disable=E1101 + # fmt: on self._use_master_password() self._initialize(db_file_found) return self._con @@ -42,7 +48,7 @@ def _initialize(self, db_file_found: bool) -> None: if db_file_found: self._verify_access() return - _logger.info(f'Creating table "{TABLE_NAME}".') + _logger.info('Creating table "%s".', TABLE_NAME) with self._cursor() as cur: cur.execute(f"CREATE TABLE {TABLE_NAME} (key TEXT, value TEXT PRIMARY KEY)") @@ -60,22 +66,26 @@ def _verify_access(self): try: with self._cursor() as cur: cur.execute("SELECT * FROM sqlite_master") - except sqlcipher.DatabaseError as ex: - print(f'exception {ex}') + # fmt: off + except (sqlcipher.DatabaseError) as ex: # pylint: disable=E1101 + # fmt: on + print(f"exception {ex}") if str(ex) == "file is not a database": raise InvalidPassword( cleandoc( - f""" + f""" Cannot access database file {self.db_file}. This also happens if master password is incorrect. - """) + """ + ) ) from ex - else: - raise ex + raise ex @contextlib.contextmanager - def _cursor(self) -> sqlcipher.Cursor: + def _cursor( + self, + ) -> sqlcipher.Cursor: # pylint: disable=E1101 cur = self.connection().cursor() try: yield cur @@ -88,21 +98,18 @@ def _cursor(self) -> sqlcipher.Cursor: def save(self, key: str, value: str) -> "Secrets": """key represents a system, service, or application""" - def entry_exists(cur) -> None: - res = cur.execute( - f"SELECT * FROM {TABLE_NAME} WHERE key=?", - [key]) + + def entry_exists(cur) -> bool: + res = cur.execute(f"SELECT * FROM {TABLE_NAME} WHERE key=?", [key]) return res and res.fetchone() def update(cur) -> None: - cur.execute( - f"UPDATE {TABLE_NAME} SET value=? WHERE key=?", - [value, key]) + cur.execute(f"UPDATE {TABLE_NAME} SET value=? WHERE key=?", [value, key]) def insert(cur) -> None: cur.execute( - f"INSERT INTO {TABLE_NAME} (key,value) VALUES (?, ?)", - [key, value]) + f"INSERT INTO {TABLE_NAME} (key,value) VALUES (?, ?)", [key, value] + ) with self._cursor() as cur: if entry_exists(cur): @@ -113,8 +120,6 @@ def insert(cur) -> None: def get(self, key: str) -> Optional[List[str]]: with self._cursor() as cur: - res = cur.execute( - f"SELECT value FROM {TABLE_NAME} WHERE key=?", - [key]) + res = cur.execute(f"SELECT value FROM {TABLE_NAME} WHERE key=?", [key]) row = res.fetchone() if res else None return row[0] if row else None diff --git a/noxconfig.py b/noxconfig.py index 48fc4db..3f664d9 100644 --- a/noxconfig.py +++ b/noxconfig.py @@ -3,11 +3,13 @@ from typing import Iterable +ROOT_DIR = Path(__file__).parent + @dataclass(frozen=True) class Config: - root: Path = Path(__file__).parent - doc: Path = Path(__file__).parent / "doc" - version_file: Path = Path(__file__).parent / "exasol" / "toolbox" / "version.py" + root: Path = ROOT_DIR + doc: Path = ROOT_DIR / "doc" + version_file: Path = ROOT_DIR / "version.py" path_filters: Iterable[str] = ("dist", ".eggs", "venv") diff --git a/poetry.lock b/poetry.lock index f1f2be1..343c955 100644 --- a/poetry.lock +++ b/poetry.lock @@ -391,29 +391,31 @@ files = [ [[package]] name = "exasol-toolbox" -version = "0.4.0" +version = "0.5.0" description = "" optional = false python-versions = ">=3.8,<4.0" files = [ - {file = "exasol_toolbox-0.4.0-py3-none-any.whl", hash = "sha256:bfe112eeec85be607878425a39412311a15aa8a3f4e6e83bb640f4c4f5360150"}, - {file = "exasol_toolbox-0.4.0.tar.gz", hash = "sha256:049f7d23cbae3751c7b6f85b8df2f4797b43620017fba992c3362a6cc8928125"}, + {file = "exasol_toolbox-0.5.0-py3-none-any.whl", hash = "sha256:261986636ed1e8f5b5347803d28e49e2cfa1cc5639f8e430c15bb37e27c839eb"}, + {file = "exasol_toolbox-0.5.0.tar.gz", hash = "sha256:857c174651ad866846e9196524daedaf430621fb3e902396d579539c47627ab6"}, ] [package.dependencies] black = ">=23.1.0,<24.0.0" coverage = ">=6.4.4,<8.0.0" furo = ">=2022.9.15,<2023.0.0" +importlib-resources = ">=5.12.0,<6.0.0" isort = ">=5.12.0,<6.0.0" mypy = ">=0.971" nox = ">=2022.8.7,<2023.0.0" pre-commit = ">=3.1.1,<4.0.0" +prysk = ">=0.15.1,<0.16.0" pylint = ">=2.15.4,<3.0.0" pytest = ">=7.2.2,<8.0.0" pyupgrade = ">=2.38.2,<4.0.0" -rich = ">=13.3.2,<14.0.0" sphinx = ">=5.3,<7.0" sphinx-copybutton = ">=0.5.0,<0.6.0" +typer = {version = ">=0.7.0", extras = ["all"]} [[package]] name = "exceptiongroup" @@ -517,6 +519,24 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker perf = ["ipython"] testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] +[[package]] +name = "importlib-resources" +version = "5.13.0" +description = "Read resources from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_resources-5.13.0-py3-none-any.whl", hash = "sha256:9f7bd0c97b79972a6cce36a366356d16d5e13b09679c11a58f1014bfdf8e64b2"}, + {file = "importlib_resources-5.13.0.tar.gz", hash = "sha256:82d5c6cca930697dbbd86c93333bb2c2e72861d4789a11c2662b933e5ad2b528"}, +] + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + [[package]] name = "iniconfig" version = "2.0.0" @@ -883,6 +903,23 @@ nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" +[[package]] +name = "prysk" +version = "0.15.1" +description = "Functional tests for command line applications" +optional = false +python-versions = ">=3.7,<4.0.0" +files = [ + {file = "prysk-0.15.1-py3-none-any.whl", hash = "sha256:47f8ae0736d46cf3d895624776d92aa21633ca595496beff7b2f799c3bf2b8ca"}, + {file = "prysk-0.15.1.tar.gz", hash = "sha256:93efbbd7cab258256b342ee46a2d2376281f7c8b990ca320ccec5906594cbf71"}, +] + +[package.dependencies] +rich = ">=13.3.1,<14.0.0" + +[package.extras] +pytest-plugin = ["pytest (>=7.0.1)"] + [[package]] name = "pygments" version = "2.16.1" @@ -1105,6 +1142,17 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +[[package]] +name = "shellingham" +version = "1.5.3" +description = "Tool to Detect Surrounding Shell" +optional = false +python-versions = ">=3.7" +files = [ + {file = "shellingham-1.5.3-py2.py3-none-any.whl", hash = "sha256:419c6a164770c9c7cfcaeddfacb3d31ac7a8db0b0f3e9c1287679359734107e9"}, + {file = "shellingham-1.5.3.tar.gz", hash = "sha256:cb4a6fec583535bc6da17b647dd2330cf7ef30239e05d547d99ae3705fd0f7f8"}, +] + [[package]] name = "snowballstemmer" version = "2.2.0" @@ -1334,6 +1382,30 @@ files = [ {file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"}, ] +[[package]] +name = "typer" +version = "0.9.0" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +optional = false +python-versions = ">=3.6" +files = [ + {file = "typer-0.9.0-py3-none-any.whl", hash = "sha256:5d96d986a21493606a358cae4461bd8cdf83cbf33a5aa950ae629ca3b51467ee"}, + {file = "typer-0.9.0.tar.gz", hash = "sha256:50922fd79aea2f4751a8e0408ff10d2662bd0c8bbfa84755a699f3bada2978b2"}, +] + +[package.dependencies] +click = ">=7.1.1,<9.0.0" +colorama = {version = ">=0.4.3,<0.5.0", optional = true, markers = "extra == \"all\""} +rich = {version = ">=10.11.0,<14.0.0", optional = true, markers = "extra == \"all\""} +shellingham = {version = ">=1.3.0,<2.0.0", optional = true, markers = "extra == \"all\""} +typing-extensions = ">=3.7.4.3" + +[package.extras] +all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] +dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"] +doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"] +test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] + [[package]] name = "typing-extensions" version = "4.8.0" @@ -1484,4 +1556,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.8.0,<4.0" -content-hash = "a6f6bfe3d81408c5167c0ff73f81485f5eb73d1a46a7aa733d0f69636ee9ee02" +content-hash = "c1091176e0d57890b97b46111742ebccf0c9e847186d8a780fe2f53964bff588" diff --git a/pyproject.toml b/pyproject.toml index d5a2090..10b25d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,6 +2,7 @@ name = "notebook-connector" version = "0.0.1" description = "Components, tools, APIs, and configurations in order to connect Jupyter notebooks to various other systems." +packages = [ {include = "exasol"}, ] license = "MIT" @@ -12,7 +13,7 @@ authors = [ [tool.poetry.dependencies] python = ">=3.8.0,<4.0" sqlcipher3-binary = ">=0.5.0" -exasol-toolbox = "^0.4.0" +exasol-toolbox = "^0.5.0" [build-system] @@ -56,18 +57,18 @@ force_grid_wrap = 2 fail-under = 7.5 output-format = "colorized,json:.lint.json,text:.lint.txt" -[tool.pylint.format] -max-line-length = 88 -max-module-lines = 800 - - [[tool.mypy.overrides]] module = [ - "exasol.toolbox.sphinx.multiversion.*", - "test.unit.*", - "test.integration.*", -] + "exasol.toolbox.nox.tasks", + "test.conftest.*", + "test.*", + ] ignore_errors = true +ignore_missing_imports = true + +[tool.pylint.format] +max-line-length = 88 +max-module-lines = 800 [tool.poetry.scripts] tbx = 'exasol.toolbox.tools.tbx:CLI' diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/test/conftest.py similarity index 80% rename from tests/conftest.py rename to test/conftest.py index b087994..7a3351e 100644 --- a/tests/conftest.py +++ b/test/conftest.py @@ -1,5 +1,7 @@ -import pytest from pathlib import Path + +import pytest + from exasol.secret_store import Secrets @@ -9,5 +11,5 @@ def sample_file(tmp_path: Path) -> Path: @pytest.fixture -def secrets(sample_file) -> Path: +def secrets(sample_file) -> Path: # pylint: disable=W0621 return Secrets(sample_file, master_password="abc") diff --git a/test/integration/test_smoke.py b/test/integration/test_smoke.py new file mode 100644 index 0000000..7252c68 --- /dev/null +++ b/test/integration/test_smoke.py @@ -0,0 +1,2 @@ +def test_smoke(): + assert True diff --git a/tests/test_secret_store.py b/test/unit/test_secret_store.py similarity index 89% rename from tests/test_secret_store.py rename to test/unit/test_secret_store.py index f8b7566..860b65c 100644 --- a/tests/test_secret_store.py +++ b/test/unit/test_secret_store.py @@ -1,7 +1,12 @@ -import pytest import sqlite3 -from exasol.secret_store import InvalidPassword, Secrets -from sqlcipher3 import dbapi2 as sqlcipher + +import pytest + +from exasol.secret_store import ( + InvalidPassword, + Secrets, +) + def test_no_database_file(secrets): assert not secrets.db_file.exists() @@ -46,6 +51,6 @@ def test_plain_access_fails(sample_file): con = sqlite3.connect(sample_file) cur = con.cursor() with pytest.raises(sqlite3.DatabaseError) as ex: - res = cur.execute("SELECT * FROM sqlite_master") + cur.execute("SELECT * FROM sqlite_master") cur.close() assert str(ex.value) == "file is not a database" diff --git a/version.py b/version.py new file mode 100644 index 0000000..58270e0 --- /dev/null +++ b/version.py @@ -0,0 +1,10 @@ +# ATTENTION: +# This file is generated by exasol/toolbox/pre_commit_hooks/package_version.py when using: +# * either "poetry run nox -s fix" +# * or "poetry run version-check --fix" +# Do not edit this file manually! +# If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`. +MAJOR = 0 +MINOR = 0 +PATCH = 1 +VERSION = f"{MAJOR}.{MINOR}.{PATCH}"