diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..1626cb6 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 + +updates: + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..53c24fc --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,67 @@ +--- +name: Tests + +on: + pull_request: ~ + push: + branches: [ main ] + + # Allow job to be triggered manually. + workflow_dispatch: + +# Cancel in-progress jobs when pushing to the same branch. +concurrency: + cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + +jobs: + + tests: + + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest"] + python-version: ["3.11"] + + env: + OS: ${{ matrix.os }} + PYTHON: ${{ matrix.python-version }} + + name: Python ${{ matrix.python-version }} on OS ${{ matrix.os }} + steps: + + - name: Acquire sources + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + architecture: x64 + cache: 'pip' + cache-dependency-path: 'pyproject.toml' + + - name: Setup project + run: | + + # `setuptools 0.64.0` adds support for editable install hooks (PEP 660). + # https://github.com/pypa/setuptools/blob/main/CHANGES.rst#v6400 + pip install "setuptools>=64" --upgrade + + # Install package in editable mode. + pip install --use-pep517 --prefer-binary --editable=.[test,develop] + + - name: Run linter and software tests + run: | + poe check + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + files: ./coverage.xml + flags: unittests + env_vars: OS,PYTHON + name: codecov-umbrella + fail_ci_if_error: false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7c76566 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +__pycache__ +.idea +.venv* +*.egg-info +.coverage +coverage.xml +*.pyc +dist diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000..938633b --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,7 @@ +# Changes for pueblo + + +## Unreleased + +## 2023-10-30 0.0.1 +- Initial thing diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..1eeef06 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +prune tests diff --git a/README.md b/README.md new file mode 100644 index 0000000..5c05397 --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# Pueblo - a Python toolbox library + +[![Tests](https://github.com/pyveci/pueblo/actions/workflows/main.yml/badge.svg)](https://github.com/pyveci/pueblo/actions/workflows/main.yml) +[![Test coverage](https://img.shields.io/codecov/c/gh/pyveci/pueblo.svg)](https://codecov.io/gh/pyveci/pueblo/) +[![Python versions](https://img.shields.io/pypi/pyversions/pueblo.svg)](https://pypi.org/project/pueblo/) + +[![License](https://img.shields.io/github/license/pyveci/pueblo.svg)](https://github.com/pyveci/pueblo/blob/main/LICENSE) +[![Status](https://img.shields.io/pypi/status/pueblo.svg)](https://pypi.org/project/pueblo/) +[![PyPI](https://img.shields.io/pypi/v/pueblo.svg)](https://pypi.org/project/pueblo/) +[![Downloads](https://pepy.tech/badge/pueblo/month)](https://pypi.org/project/pueblo/) + + + + +» [Changelog] +| [PyPI] +| [Issues] +| [Source code] +| [License] + +[Changelog]: https://github.com/pyveci/pueblo/blob/main/CHANGES.md +[Documentation]: https://pueblo.readthedocs.io/ +[Issues]: https://github.com/pyveci/pueblo/issues +[License]: https://github.com/pyveci/pueblo/blob/main/LICENSE +[PyPI]: https://pypi.org/project/pueblo/ +[Source code]: https://github.com/pyveci/pueblo + + +## About + +- A Python toolbox library. +- Contains Python code duplicated too often elsewhere. +- Finally, it is in one place. +- Here be dragons and gems. + + +## Setup + +```shell +pip install --upgrade pueblo +``` + +After installation, you can verify if it was successful. +```shell +pueblo --version +``` + + +## Usage + +Read the source. + + +## Prior Art + +- https://pypi.org/project/boltons/ diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..4ccde74 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,221 @@ +# ================== +# Project definition +# ================== + +# Derived from https://peps.python.org/pep-0621/ + +[build-system] +build-backend = "setuptools.build_meta" +requires = [ + "setuptools>=42", # At least v42 of setuptools required. + "versioningit", +] + +[tool.versioningit.vcs] +method = "git" +default-tag = "0.0.0" + +[project] +name = "pueblo" +description = "Pueblo - a Python toolbox library." +readme = "README.md" +requires-python = ">=3.8" +license = { text = "LGPL 3, EUPL 1.2" } +keywords = [ + "pueblo", + "general purpose", + "library", + "mixed", +] +authors = [ + {name = "Andreas Motl", email = "andreas.motl@panodata.org"}, +] +classifiers = [ + "Development Status :: 3 - Alpha", + "Environment :: Console", + "Intended Audience :: Customer Service", + "Intended Audience :: Developers", + "Intended Audience :: Education", + "Intended Audience :: Information Technology", + "Intended Audience :: Telecommunications Industry", + "License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2)", + "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", + "Operating System :: MacOS :: MacOS X", + "Operating System :: POSIX :: Linux", + "Operating System :: Unix", + "Programming Language :: Python", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Communications", + "Topic :: Education", + "Topic :: Software Development :: Libraries", + "Topic :: Text Processing", + "Topic :: Utilities", +] + +dynamic = [ + "version", +] + +dependencies = [ +] + +[project.optional-dependencies] +cli = [ + "click<9", + "click-aliases<2", + "colorlog<7", +] +env = [ + "python-dotenv<2", +] +develop = [ + "black<24", + "mypy==1.5.1", + "poethepoet<1", + "pyproject-fmt<1.2", + "ruff==0.0.291", + "validate-pyproject<0.15", +] +release = [ + "build<2", + "twine<5", +] +test = [ + "nbclient<0.9", + "pytest<8", + "pytest-cov<5", + "pytest-mock<4", +] +[project.scripts] +pueblo = "pueblo.cli:cli" +[tool.setuptools] +# https://setuptools.pypa.io/en/latest/userguide/package_discovery.html +packages = ["pueblo"] + +[project.urls] +changelog = "https://github.com/pyveci/pueblo/blob/main/CHANGES.md" +documentation = "https://github.com/pyveci/pueblo" +homepage = "https://github.com/pyveci/pueblo" +repository = "https://github.com/pyveci/pueblo" +[tool.black] +line-length = 120 + +# extend-exclude = "" + +[tool.isort] +profile = "black" +skip_glob = "**/site-packages/**" +skip_gitignore = false + +[tool.pytest.ini_options] +minversion = "2.0" +addopts = """ + -rfEX -p pytester --strict-markers --verbosity=3 + --cov --cov-report=term-missing --cov-report=xml + """ +log_level = "DEBUG" +log_cli_level = "DEBUG" +testpaths = ["tests"] +xfail_strict = true +markers = [ +] + +[tool.coverage.run] +branch = false +source = ["pueblo"] +omit = [ + "tests/*", +] + +[tool.coverage.report] +fail_under = 0 +show_missing = true + +[tool.mypy] +packages = ["pueblo"] +exclude = [ +] +check_untyped_defs = true +ignore_missing_imports = true +implicit_optional = true +install_types = true +no_implicit_optional = true +non_interactive = true +show_error_codes = true +strict_equality = true +warn_unused_ignores = true +warn_redundant_casts = true + +[tool.ruff] +line-length = 120 + +select = [ + # Bandit + "S", + # Bugbear + "B", + # Builtins + "A", + # comprehensions + "C4", + # eradicate + "ERA", + # flake8-2020 + "YTT", + # isort + "I", + # pandas-vet + "PD", + # print + "T20", + # Pycodestyle + "E", + "W", + # Pyflakes + "F", + # return + "RET", +] + +extend-exclude = [ + "example_*", +] + +[tool.ruff.per-file-ignores] +"tests/*" = ["S101"] # Use of `assert` detected + + +# =================== +# Tasks configuration +# =================== + +[tool.poe.tasks] +format = [ + { cmd = "black ." }, + # Configure Ruff not to auto-fix (remove!): + # Ignore unused imports (F401), unused variables (F841), `print` statements (T201), and commented-out code (ERA001). + { cmd = "ruff --fix --ignore=ERA --ignore=F401 --ignore=F841 --ignore=T20 --ignore=ERA001 ." }, + { cmd = "pyproject-fmt pyproject.toml" }, +] + +lint = [ + { cmd = "ruff ." }, + { cmd = "black --check ." }, + { cmd = "validate-pyproject pyproject.toml" }, + { cmd = "mypy" }, +] +test = [ + { cmd = "pytest" }, +] +build = { cmd = "python -m build" } +check = ["lint", "test"] + +release = [ + { cmd = "python -m build" }, + { cmd = "twine upload --skip-existing dist/*.tar.gz dist/*.whl" }, +]