diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9d85dab --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,35 @@ +name: CI + +on: + - push + +jobs: + build: + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + permissions: + contents: read + runs-on: ubuntu-latest + strategy: + matrix: + python-version: + - "3.11" + - "3.12" + steps: + - uses: actions/checkout@v4 + - name: Set up project using python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + cache: pip + python-version: ${{ matrix.python-version }} + # Run all pre-commit hooks on all the files. + # Getting only staged files can be tricky in case a new PR is opened + # since the action is run on a branch in detached head state + - name: Install and run pre-commit + uses: pre-commit/action@v3.0.1 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install tox tox-gh-actions + - name: Test with tox + run: tox -r diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c547bd0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,319 @@ +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +del.txt +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +coverage/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +junitxml_report/* +/**/junitxml_report/* + +# Translations +*.mo +*.pot + +# Django stuff: +staticfiles/ + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# pyenv +.python-version + +# Environments +.venv +venv/ +ENV/ + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + + +### Node template +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + + +### Linux template +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + + +### VisualStudioCode template +.vscode/* + +# Local History for Visual Studio Code +.history/ + + +# Provided default Pycharm Run/Debug Configurations should be tracked by git +# In case of local modifications made by Pycharm, use update-index command +# for each changed file, like this: +# git update-index --assume-unchanged .idea/fahari.iml +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + + +# CMake +cmake-build-debug/ + + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +.idea/* +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + + + +### Windows template +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + + +### macOS template +# General +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +### SublimeText template +# Cache files for Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# Workspace files are user-specific +*.sublime-workspace + +# Project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using Sublime Text +# *.sublime-project + +# SFTP configuration file +sftp-config.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + + +### Vim template +# Swap +[._]*.s[a-v][a-z] +[._]*.sw[a-p] +[._]s[a-v][a-z] +[._]sw[a-p] + +# Session +Session.vim + +# Ruff cache +.ruff_cache + +# Temporary +.netrwhist +.~lock.* + +# Auto-generated tag files +tags + +### Project template +dist/* +docs/api +.pytest_cache/ +.ipython/ +.env +.envs/* +!.envs/.local/ +config.toml +config.yaml +local.sh +logs/* +!logs/.gitkeep +secrets/* +cloud_sql_proxy +*.prof diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..5bc2665 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,35 @@ +--- +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-added-large-files + - id: check-toml + - id: check-vcs-permalinks + - id: check-yaml + + - repo: https://github.com/asottile/pyupgrade + rev: v3.15.2 + hooks: + - id: pyupgrade + args: + - --py311-plus + + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.3.6 + hooks: + - id: ruff + args: + - --fix + - --exit-non-zero-on-fix + - id: ruff-format + +# sets up .pre-commit-ci.yaml to ensure pre-commit dependencies stay up to date +ci: + autoupdate_schedule: weekly + skip: [] + submodules: false diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8dd8c91 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Savannah Informatics Global Health Institute + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e3b9fcc --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +

SGHI ETL Runtime

+

An executor/runner of SGHI ETL Workflows.

+

+ + Checked with pyright + + + Ruff + + + pre-commit + + + GitHub License + +

+

+ + CI + + + Coverage Status + +

+ +--- + +This project is part of [SGHI ETL](https://github.com/savannahghi/sghi-etl-core/) +projects. Specifically, this is an executor/runner of SGHI ETL Workflows. It is designed to be used both as a CLI tool and as a library where it can be embedded into other applications. + +## Contribute + +Clone the project and run the following command to install dependencies: + +```bash +pip install -e .[dev,test,docs] +``` + +Set up pre-commit hooks: +```bash +pre-commit install +``` + +## License + +[MIT License](https://github.com/savannahghi/sghi-etl-runtime/blob/main/LICENSE) + +Copyright (c) 2024, Savannah Informatics Global Health Institute diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..a8e33a4 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,149 @@ +# ruff: noqa + +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +import os +import sys +from datetime import datetime + +sys.path.insert(0, os.path.abspath("src")) + + +# ----------------------------------------------------------------------------- +# Project information +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +# ----------------------------------------------------------------------------- + +author = "Savannah Global Health Institute" +copyright = f"{datetime.today().year}, Savannah Global Health Institute" +project = "sghi-etl-runtime" + + +# ----------------------------------------------------------------------------- +# General configuration +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration +# ----------------------------------------------------------------------------- + +extensions = ["sphinx.ext.autodoc", "sphinx.ext.autosummary"] + +# Preserve authored syntax for defaults +autodoc_preserve_defaults = True + +autodoc_default_flags = { + "inherited-members": True, + "show-inheritance": True, + "special-members": ( + "__enter__", + "__exit__", + "__call__", + "__getattr__", + "__setattr_", + ), +} + +autodoc_member_order = "groupwise" + +autoapi_python_use_implicit_namespaces = True + +autosummary_generate = True # Turn on sphinx.ext.autosummary + +exclude_patterns = [] + +# Be strict about any broken references +nitpicky = True + +nitpick_ignore = [] + +templates_path = ["templates"] + +root_doc = "index" + + +# ----------------------------------------------------------------------------- +# Options for HTML output +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output +# ----------------------------------------------------------------------------- + +html_logo = "images/sghi_globe.png" + +html_static_path = ["static"] + +html_theme = "furo" + +html_theme_options = { + "sidebar_hide_name": True, + "light_css_variables": { + "color-brand-primary": "#0474AC", # "blue" + "color-brand-content": "#0474AC", + }, + "dark_css_variables": { + "color-brand-primary": "#C1368C", # "purple" + "color-brand-content": "#C1368C", + }, +} + + +# ----------------------------------------------------------------------------- +# Include Python intersphinx mapping to prevent failures +# jaraco/skeleton#51 +# ----------------------------------------------------------------------------- + +extensions += ["sphinx.ext.intersphinx"] +intersphinx_mapping = { + "peps": ("https://peps.python.org/", None), + "python": ("https://docs.python.org/3", None), + "pypackage": ("https://packaging.python.org/en/latest/", None), + "importlib-resources": ( + "https://importlib-resources.readthedocs.io/en/latest", + None, + ), + "django": ( + "http://docs.djangoproject.com/en/dev/", + "http://docs.djangoproject.com/en/dev/_objects/", + ), +} + + +# ----------------------------------------------------------------------------- +# Support tooltips on references +# ----------------------------------------------------------------------------- + +extensions += ["hoverxref.extension"] +hoverxref_auto_ref = True +hoverxref_intersphinx = [ + "python", + "pip", + "pypackage", + "importlib-resources", + "django", +] + + +# ----------------------------------------------------------------------------- +# Add support for nice Not Found 404 pages +# ----------------------------------------------------------------------------- + +extensions += ["notfound.extension"] + + +# ----------------------------------------------------------------------------- +# Add icons (aka "favicons") to documentation +# ----------------------------------------------------------------------------- + +extensions += ["sphinx_favicon"] +html_static_path += ["images"] # should contain the folder with icons + +# List of dicts with HTML attributes +# static-file points to files in the html_static_path (href is computed) + +favicons = [ + { + "rel": "icon", + "type": "image/png", + "static-file": "sghi_globe.png", + "sizes": "any", + }, +] diff --git a/docs/images/sghi_globe.png b/docs/images/sghi_globe.png new file mode 100644 index 0000000..525a893 Binary files /dev/null and b/docs/images/sghi_globe.png differ diff --git a/docs/images/sghi_logo.webp b/docs/images/sghi_logo.webp new file mode 100644 index 0000000..3b6cedc Binary files /dev/null and b/docs/images/sghi_logo.webp differ diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..bc6b9ce --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,44 @@ +.. sghi-etl-runtime documentation master file, created by sphinx-quickstart on + Tue Apr 16 22:17:18 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +.. image:: images/sghi_logo.webp + :align: center + +SGHI ETL Runtime +================ + +This project is part of `SGHI ETL `_ projects. Specifically, +this is a executor/runner of SGHI ETL Workflows. It is designed to be used +both as a CLI tool and as a library where it can be embedded into other +applications. + +Installation +------------ + +We recommend using the latest version of Python. Python 3.11 and newer is +supported. We also recommend using a `virtual environment`_ in order +to isolate your project dependencies from other projects and the system. + +Install the latest sghi-etl-runtime version using pip: + +.. code-block:: bash + + pip install sghi-etl-runtime + + +API Reference +------------- + +.. autosummary:: + :template: module.rst + :toctree: api + :caption: API + :recursive: + + sghi.etl.runtime + + +.. _sghi-etl-core: https://github.com/savannahghi/sghi-etl-core/ +.. _virtual environment: https://packaging.python.org/tutorials/installing-packages/#creating-virtual-environments diff --git a/docs/static/.gitkeep b/docs/static/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/templates/class.rst b/docs/templates/class.rst new file mode 100644 index 0000000..ca179e6 --- /dev/null +++ b/docs/templates/class.rst @@ -0,0 +1,45 @@ +{{ fullname | escape | underline}} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + :members: + :special-members: __contains__, __delitem__, __enter__, __exit__, __call__, __getattr__, __setattr__, __getitem__, __setitem__ + :show-inheritance: + :inherited-members: + :member-order: groupwise + + {% if methods or attributes %} + ---- + {% endif %} + + {% block methods %} + {% if methods %} + .. rubric:: {{ _('Methods') }} + + .. autosummary:: + {% for item in methods %} + ~{{ name }}.{{ item }} + {%- endfor %} + + {% endif %} + {% endblock %} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Attributes') }} + + .. autosummary:: + {% for item in attributes %} + ~{{ name }}.{{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% if methods or attributes %} + ---- + {% endif %} + + {% block constructor %} + .. automethod:: __init__ + {% endblock %} diff --git a/docs/templates/exception.rst b/docs/templates/exception.rst new file mode 100644 index 0000000..5bad225 --- /dev/null +++ b/docs/templates/exception.rst @@ -0,0 +1,44 @@ +{{ fullname | escape | underline}} + +.. currentmodule:: {{ module }} + +.. autoexception:: {{ objname }} + :members: + :show-inheritance: + :inherited-members: + :member-order: groupwise + + {% if methods or attributes %} + ---- + {% endif %} + + {% block methods %} + {% if methods %} + .. rubric:: {{ _('Methods') }} + + .. autosummary:: + {% for item in methods %} + ~{{ name }}.{{ item }} + {%- endfor %} + + {% endif %} + {% endblock %} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Attributes') }} + + .. autosummary:: + {% for item in attributes %} + ~{{ name }}.{{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% if methods or attributes %} + ---- + {% endif %} + + {% block constructor %} + .. automethod:: __init__ + {% endblock %} diff --git a/docs/templates/module.rst b/docs/templates/module.rst new file mode 100644 index 0000000..b5195e9 --- /dev/null +++ b/docs/templates/module.rst @@ -0,0 +1,67 @@ +{{ fullname | escape | underline}} + +.. automodule:: {{ fullname }} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Module Attributes') }} + + .. autosummary:: + :toctree: + {% for item in attributes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block functions %} + {% if functions %} + .. rubric:: {{ _('Functions') }} + + .. autosummary:: + :toctree: + {% for item in functions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block classes %} + {% if classes %} + .. rubric:: {{ _('Classes') }} + + .. autosummary:: + :toctree: + :template: class.rst + {% for item in classes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block exceptions %} + {% if exceptions %} + .. rubric:: {{ _('Exceptions') }} + + .. autosummary:: + :toctree: + :template: exception.rst + {% for item in exceptions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + +{% block modules %} +{% if modules %} +.. rubric:: Modules + +.. autosummary:: + :toctree: + :template: module.rst + :recursive: +{% for item in modules %} + {{ item }} +{%- endfor %} +{% endif %} +{% endblock %} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..ab5bc28 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,335 @@ +[build-system] +build-backend = "setuptools.build_meta" +requires = [ + "setuptools>=69.2.0", + "setuptools_scm>=8.0.4", +] + +[project] +authors = [ + {name = "Savannah Informatics Global Health Institute"} +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Intended Audience :: Developers", + "License :: Freeware", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Operating System :: POSIX", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Topic :: Utilities", + "Typing :: Typed" +] +dependencies = [ + "typing-extensions>=4.10.0", + "sghi-commons @ git+https://github.com/savannahghi/sghi-commons.git@v1.4.0", + "sghi-etl-core @ git+https://github.com/savannahghi/sghi-etl-core.git@v1.1.1", + "sghi-etl-commons @ git+https://github.com/savannahghi/sghi-etl-commons.git@v1.0.0", +] +description = "An executor/runner of SGHI ETL Workflows." +dynamic = ["version"] +keywords = ["sghi", "etl", "pipeline", "util", "utils"] +license = {file = "LICENSE"} +maintainers = [ + {name = "Kennedy Kori", email = "kennedykori47@gmail.com"}, + {name = "Salad Guyo", email = "saladguyo60@gmail.com"} +] +name = "sghi-etl-runtime" +readme = "README.md" +requires-python = ">=3.11" # Support Python 3.10+. + +[project.optional-dependencies] +dev = [ + "pre-commit~=3.7.0", +] + +docs = [ + "furo==2024.1.29", + "jaraco.packaging~=9.5.0", + "rst.linker~=2.4.0", + "Sphinx~=7.2.6", + "sphinx-favicon~=1.0.1", + "sphinx-hoverxref~=1.3.0", + "sphinx-inline-tabs~=2023.4.21", + "sphinx-lint~=0.9.1", + "sphinx-notfound-page~=1.0.0", +] + +test = [ + "coverage~=6.5.0", + "coveralls~=3.3.1", + "packaging", + "pyright>=1.1.358", + "pytest~=8.1.1", + "pytest-cov~=5.0.0", + "pytest-forked~=1.6.0", + "pytest-sugar~=1.0.0", + "pytest-xdist~=3.5.0", + "ruff~=0.3.6", + "tox~=4.14.2", + "tox-gh-actions~=3.2.0", +] + +[project.urls] +changelog = "https://github.com/savannahghi/sghi-etl-runtime/blob/develop/docs/CHANGELOG.md" +documentation = "https://github.com/savannahghi/sghi-etl-runtime/blob/develop/README.md" +homepage = "https://github.com/savannahghi/sghi-etl-runtime/" +repository = "https://github.com/savannahghi/sghi-etl-runtime.git" + +[tool.black] +extend-exclude = """ +# A regex preceded with ^/ will apply only to files and directories +# in the root of the project. +( + ^/docs/_*.py +) +""" +include = ["src", "test"] +line-length = 79 +target-version = ["py311", "py312"] + +[tool.coverage.html] +directory = "coverage" + +[tool.coverage.report] +exclude_lines = [ + # Have to re-enable the standard pragma: + "pragma: no branch", + "pragma: nocover", + "pragma: no cover", + + # Don't complain if tests don't hit defensive assertion code: + "raise AssertionError", + "raise NotImplementedError", + + # Don't complain about abstract methods, they aren't run: + '@(abc\.)?abstractmethod', + + # Don't complain about conditional TYPE_CHECKING blocks: + 'if (typing\.)?TYPE_CHECKING:', + + # Don't complain about overloads: + '@(typing\.)?overload', +] +show_missing = true + +[tool.coverage.run] +branch = true +omit = [".tox/*", "docs/*", "test/*"] + +[tool.isort] +extend_skip = "docs" +extend_skip_glob = ["*/build/*", "*/docs/*"] +known_first_party = ["sghi", "test"] +line_length = 79 +multi_line_output = 3 +profile = "black" + +[tool.pyright] +analyzeUnannotatedFunctions = true +enableTypeIgnoreComments = true +exclude = [ + "**/.*", + "**/node_modules", + "**/__pycache__", + "build", +] +reportConstantRedefinition = "error" +reportDeprecated = "warning" +reportDuplicateImport = "error" +reportGeneralTypeIssues = "error" +reportIncompatibleMethodOverride = "error" +reportIncompatibleVariableOverride = "error" +reportMissingSuperCall = "warning" +reportMissingTypeStubs = "information" +reportOverlappingOverload = "warning" +reportPrivateUsage = "error" +reportPropertyTypeMismatch = "error" +reportUnnecessaryTypeIgnoreComment = "error" +reportUnusedClass = "warning" +reportUnusedFunction = "warning" +reportUnusedImport = "error" +reportUnusedVariable = "warning" +reportWildcardImportFromLibrary = "warning" +strictDictionaryInference = true +strictListInference = true +strictParameterNoneValue = true +strictSetInference = true +typeCheckingMode = "basic" + +[tool.pytest.ini_options] +addopts = "--cov=src/sghi --cov-fail-under=100 --cov-report=html --cov-report=term-missing -n auto --junitxml='junitxml_report/report.xml' -vv --durations=10 --cache-clear" +console_output_style = "progress" +log_cli = 1 +log_cli_date_format = "%Y-%m-%d %H:%M:%S" +log_cli_format = "[%(levelname)8s]-%(asctime)s (%(filename)s:%(lineno)s) - %(message)s" +log_cli_level = "WARNING" +python_files = ["*test.py", "*tests.py", "test_*.py"] +norecursedirs = "node_modules venv build env bin .cache .tox" + +[tool.ruff] +exclude = [ + ".eggs", + ".git", + ".mypy_cache", + ".nox", + ".pytype", + ".ruff_cache", + ".tox", + ".venv", + "__pycache__", + "__pypackages__", + "_build", + "build", + "dist", + "docs", + "node_modules", + "venv", +] +line-length = 79 +src = ["src", "test"] +target-version = "py311" + +[tool.ruff.format] +docstring-code-format = true +indent-style = "space" +quote-style = "double" +skip-magic-trailing-comma = false + +[tool.ruff.lint] +ignore = [ + "ANN002", + "ANN003", + "ANN101", + "ANN102", + "ANN204", + "COM812", + "D203", + "D213", + "ISC001", + "S101", +] +select = [ + "A", # flake8-builtins + "ANN", # flake8-annotations + "B", # flake8-bugbear + "BLE", # flake8-blind-except + "C4", # flake8-comprehensions + "C90", # mccabe + "COM", # flake8-commas + "D", # pydocstyle + "E", # pycodestyle Error + "EM", # flake8-errmsg + "ERA", # eradicate + "F", # pyflakes + "G", # flake8-logging-format + "I", # isort + "ISC", # flake8-implicit-str-concat + "N", # pep8 Naming + "PD", # pandas-vet + "PT", # flake8-pytest-style + "PYI", # flake8-pyi + "Q", # flake8-quotes + "RET", # flake8-return + "RUF", # Ruff-specific rules + "S", # flake8-bandit + "SIM", # flake8-simplify + "T10", # flake8-debugger + "T20", # flake8-print + "TCH", # flake8-type-checking + "UP", # pyupgrade + "W", # pycodestyle Warning + "YTT", # flake8-2020 +] + +[tool.ruff.lint.flake8-quotes] +inline-quotes = "double" +docstring-quotes = "double" + +[tool.ruff.lint.isort] +known-first-party = ["src", "test"] + +[tool.ruff.lint.mccabe] +max-complexity = 10 + +[tool.setuptools] +package-dir = {"" = "src"} + +[tool.setuptools.packages.find] +namespaces = true +where = ["src"] + +[tool.setuptools_scm] +root = "." + +[tool.tox] +legacy_tox_ini = """ + [tox] + env_list = {py311, py312}, coveralls, docs, package + isolated_build = true + no_package = false + requires = + tox>4 + skip_missing_interpreters = true + + + [gh-actions] + python = + 3.11: py311 + 3.12: py312, coveralls, docs, package + + + [testenv] + commands = + ruff check . + ruff format --check . + pyright . + coverage erase + pytest {posargs:.} + coverage html + deps = + . + description = test and lint the project + download = true + extras = + test + set_env = + PYTHONPATH = {toxinidir}/src + PYRIGHT_PYTHON_FORCE_VERSION = latest + + + ;If running outside Github, ensure that the the `COVERALLS_REPO_TOKEN` + ;environment variable is set. + [testenv:coveralls] + commands = + coveralls --service=github + description = submit coverage results to coverall.io + extras = + test + pass_env = + COVERALLS_REPO_TOKEN + GITHUB_* + + + [testenv:docs] + changedir = docs + commands = + sphinx-build -EW --keep-going -b html . {toxinidir}/docs/build/html + sphinx-lint -i api + description = build sphinx documentation + extras = + docs + + + [testenv:package] + commands = + python -c "import shutil; shutil.rmtree('dist', ignore_errors=True)" + python -m build + depends = testenv + deps = + build + description = build the library + skip_install = true +"""