From 0d6687cc36c16ae625a2bb7ae9df89fcfae07472 Mon Sep 17 00:00:00 2001 From: Miles Graham Date: Thu, 16 May 2024 14:26:12 +0100 Subject: [PATCH] Initial commit --- .copier-answers.yml | 11 +++ .github/ISSUE_TEMPLATE.md | 15 ++++ .github/TEST_FAIL_TEMPLATE.md | 12 +++ .github/dependabot.yml | 10 +++ .github/workflows/ci.yml | 108 +++++++++++++++++++++++++ .gitignore | 111 +++++++++++++++++++++++++ .pre-commit-config.yaml | 37 +++++++++ LICENSE | 28 +++++++ README.md | 9 +++ pyproject.toml | 148 ++++++++++++++++++++++++++++++++++ src/ttmask/__init__.py | 10 +++ src/ttmask/py.typed | 5 ++ tests/test_ttmask.py | 2 + 13 files changed, 506 insertions(+) create mode 100644 .copier-answers.yml create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/TEST_FAIL_TEMPLATE.md create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 pyproject.toml create mode 100644 src/ttmask/__init__.py create mode 100644 src/ttmask/py.typed create mode 100644 tests/test_ttmask.py diff --git a/.copier-answers.yml b/.copier-answers.yml new file mode 100644 index 0000000..186f8d9 --- /dev/null +++ b/.copier-answers.yml @@ -0,0 +1,11 @@ +# Do not edit - changes here will be overwritten by Copier +_commit: v1 +_src_path: gh:pydev-guide/pyrepo-copier +author_email: miles.graham@balliol.ox.ac.uk +author_name: Miles Graham +github_username: teamtomo +mode: tooling +module_name: ttmask +project_name: ttmask +project_short_description: CLI tool for mask creation in cryo-EM/ET + diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..8791834 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,15 @@ +* ttmask version: +* Python version: +* Operating System: + +### Description + +Describe what you were trying to get done. +Tell us what happened, what went wrong, and what you expected to happen. + +### What I Did + +``` +Paste the command(s) you ran and the output. +If there was a crash, please include the traceback here. +``` diff --git a/.github/TEST_FAIL_TEMPLATE.md b/.github/TEST_FAIL_TEMPLATE.md new file mode 100644 index 0000000..3512972 --- /dev/null +++ b/.github/TEST_FAIL_TEMPLATE.md @@ -0,0 +1,12 @@ +--- +title: "{{ env.TITLE }}" +labels: [bug] +--- +The {{ workflow }} workflow failed on {{ date | date("YYYY-MM-DD HH:mm") }} UTC + +The most recent failing test was on {{ env.PLATFORM }} py{{ env.PYTHON }} +with commit: {{ sha }} + +Full run: https://github.com/{{ repo }}/actions/runs/{{ env.RUN_ID }} + +(This post will be updated if another test fails, as long as this issue remains open.) diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..96505a9 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: "ci(dependabot):" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a2d54c6 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,108 @@ +name: CI + +on: + push: + branches: + - main + tags: + - "v*" + pull_request: + workflow_dispatch: + schedule: + # run every week (for --pre release tests) + - cron: "0 0 * * 0" + +# cancel in-progress runs that use the same workflow and branch +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + check-manifest: + # check-manifest is a tool that checks that all files in version control are + # included in the sdist (unless explicitly excluded) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: pipx run check-manifest + + test: + name: ${{ matrix.platform }} (${{ matrix.python-version }}) + runs-on: ${{ matrix.platform }} + strategy: + fail-fast: false + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + platform: [ubuntu-latest, macos-latest, windows-latest] + + steps: + - uses: actions/checkout@v4 + + - name: ๐Ÿ Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache-dependency-path: "pyproject.toml" + cache: "pip" + + - name: Install Dependencies + run: | + python -m pip install -U pip + # if running a cron job, we add the --pre flag to test against pre-releases + python -m pip install .[test] ${{ github.event_name == 'schedule' && '--pre' || '' }} + + - name: ๐Ÿงช Run Tests + run: pytest --color=yes --cov --cov-report=xml --cov-report=term-missing + + # If something goes wrong with --pre tests, we can open an issue in the repo + - name: ๐Ÿ“ Report --pre Failures + if: failure() && github.event_name == 'schedule' + uses: JasonEtco/create-an-issue@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PLATFORM: ${{ matrix.platform }} + PYTHON: ${{ matrix.python-version }} + RUN_ID: ${{ github.run_id }} + TITLE: "[test-bot] pip install --pre is failing" + with: + filename: .github/TEST_FAIL_TEMPLATE.md + update_existing: true + + - name: Coverage + uses: codecov/codecov-action@v3 + + deploy: + name: Deploy + needs: test + if: success() && startsWith(github.ref, 'refs/tags/') && github.event_name != 'schedule' + runs-on: ubuntu-latest + + permissions: + # IMPORTANT: this permission is mandatory for trusted publishing on PyPi + # see https://docs.pypi.org/trusted-publishers/ + id-token: write + # This permission allows writing releases + contents: write + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: ๐Ÿ Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.x" + + - name: ๐Ÿ‘ท Build + run: | + python -m pip install build + python -m build + + - name: ๐Ÿšข Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + + - uses: softprops/action-gh-release@v1 + with: + generate_release_notes: true + files: './dist/*' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..13afad0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,111 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +.DS_Store + +# 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/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# ruff +.ruff_cache/ + +# IDE settings +.vscode/ +.idea/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..f56a5e9 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,37 @@ +# enable pre-commit.ci at https://pre-commit.ci/ +# it adds: +# 1. auto fixing pull requests +# 2. auto updating the pre-commit configuration +ci: + autoupdate_schedule: monthly + autofix_commit_msg: "style(pre-commit.ci): auto fixes [...]" + autoupdate_commit_msg: "ci(pre-commit.ci): autoupdate" + +repos: + - repo: https://github.com/abravalheri/validate-pyproject + rev: v0.16 + hooks: + - id: validate-pyproject + + - repo: https://github.com/crate-ci/typos + rev: v1.20.9 + hooks: + - id: typos + args: [--force-exclude] # omitting --write-changes + + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.4.1 + hooks: + - id: ruff + args: [--fix] # may also add '--unsafe-fixes' + - id: ruff-format + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.9.0 + hooks: + - id: mypy + files: "^src/" + # # you have to add the things you want to type check against here + # additional_dependencies: + # - numpy + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..43a213b --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +BSD 3-Clause License + +Copyright (c) 2023, Miles Graham + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7d918d9 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# ttmask + +[![License](https://img.shields.io/pypi/l/ttmask.svg?color=green)](https://github.com/teamtomo/ttmask/raw/main/LICENSE) +[![PyPI](https://img.shields.io/pypi/v/ttmask.svg?color=green)](https://pypi.org/project/ttmask) +[![Python Version](https://img.shields.io/pypi/pyversions/ttmask.svg?color=green)](https://python.org) +[![CI](https://github.com/teamtomo/ttmask/actions/workflows/ci.yml/badge.svg)](https://github.com/teamtomo/ttmask/actions/workflows/ci.yml) +[![codecov](https://codecov.io/gh/teamtomo/ttmask/branch/main/graph/badge.svg)](https://codecov.io/gh/teamtomo/ttmask) + +CLI tool for mask creation in cryo-EM/ET diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b450781 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,148 @@ +# https://peps.python.org/pep-0517/ +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" + +# https://hatch.pypa.io/latest/config/metadata/ +[tool.hatch.version] +source = "vcs" + +# read more about configuring hatch at: +# https://hatch.pypa.io/latest/config/build/ +[tool.hatch.build.targets.wheel] +only-include = ["src"] +sources = ["src"] + +# https://peps.python.org/pep-0621/ +[project] +name = "ttmask" +dynamic = ["version"] +description = "CLI tool for mask creation in cryo-EM/ET" +readme = "README.md" +requires-python = ">=3.8" +license = { text = "BSD-3-Clause" } +authors = [{ name = "Miles Graham", email = "miles.graham@balliol.ox.ac.uk" }] +# https://pypi.org/classifiers/ +classifiers = [ + "Development Status :: 3 - Alpha", + "License :: OSI Approved :: BSD License", + "Programming Language :: Python :: 3", + "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", + "Typing :: Typed", +] +# add your package dependencies here +dependencies = [] + +# https://peps.python.org/pep-0621/#dependencies-optional-dependencies +# "extras" (e.g. for `pip install .[test]`) +[project.optional-dependencies] +# add dependencies used for testing here +test = ["pytest", "pytest-cov"] +# add anything else you like to have in your dev environment here +dev = [ + "ipython", + "mypy", + "pdbpp", # https://github.com/pdbpp/pdbpp + "pre-commit", + "rich", # https://github.com/Textualize/rich + "ruff", +] + +[project.urls] +homepage = "https://github.com/teamtomo/ttmask" +repository = "https://github.com/teamtomo/ttmask" + +# Entry points +# https://peps.python.org/pep-0621/#entry-points +# same as console_scripts entry point +# [project.scripts] +# ttmask-cli = "ttmask:main_cli" + +# [project.entry-points."some.group"] +# tomatoes = "ttmask:main_tomatoes" + +# https://docs.astral.sh/ruff +[tool.ruff] +line-length = 88 +target-version = "py38" +src = ["src"] + +# https://docs.astral.sh/ruff/rules +[tool.ruff.lint] +pydocstyle = { convention = "numpy" } +select = [ + "E", # style errors + "W", # style warnings + "F", # flakes + "D", # pydocstyle + "D417", # Missing argument descriptions in Docstrings + "I", # isort + "UP", # pyupgrade + "C4", # flake8-comprehensions + "B", # flake8-bugbear + "A001", # flake8-builtins + "RUF", # ruff-specific rules + "TCH", # flake8-type-checking + "TID", # flake8-tidy-imports +] +ignore = [ + "D401", # First line should be in imperative mood (remove to opt in) +] + +[tool.ruff.lint.per-file-ignores] +"tests/*.py" = ["D", "S"] + +# https://docs.astral.sh/ruff/formatter/ +[tool.ruff.format] +docstring-code-format = true +skip-magic-trailing-comma = false # default is false + +# https://mypy.readthedocs.io/en/stable/config_file.html +[tool.mypy] +files = "src/**/" +strict = true +disallow_any_generics = false +disallow_subclassing_any = false +show_error_codes = true +pretty = true + +# # module specific overrides +# [[tool.mypy.overrides]] +# module = ["numpy.*",] +# ignore_errors = true + +# https://docs.pytest.org/ +[tool.pytest.ini_options] +minversion = "7.0" +testpaths = ["tests"] +filterwarnings = ["error"] + +# https://coverage.readthedocs.io/ +[tool.coverage.report] +show_missing = true +exclude_lines = [ + "pragma: no cover", + "if TYPE_CHECKING:", + "@overload", + "except ImportError", + "\\.\\.\\.", + "raise NotImplementedError()", + "pass", +] + +[tool.coverage.run] +source = ["ttmask"] + +# https://github.com/mgedmin/check-manifest#configuration +# add files that you want check-manifest to explicitly ignore here +# (files that are in the repo but shouldn't go in the package) +[tool.check-manifest] +ignore = [ + ".pre-commit-config.yaml", + ".ruff_cache/**/*", + "tests/**/*", +] diff --git a/src/ttmask/__init__.py b/src/ttmask/__init__.py new file mode 100644 index 0000000..6ee4d29 --- /dev/null +++ b/src/ttmask/__init__.py @@ -0,0 +1,10 @@ +"""CLI tool for mask creation in cryo-EM/ET""" + +from importlib.metadata import PackageNotFoundError, version + +try: + __version__ = version("ttmask") +except PackageNotFoundError: + __version__ = "uninstalled" +__author__ = "Miles Graham" +__email__ = "miles.graham@balliol.ox.ac.uk" diff --git a/src/ttmask/py.typed b/src/ttmask/py.typed new file mode 100644 index 0000000..07d3fbd --- /dev/null +++ b/src/ttmask/py.typed @@ -0,0 +1,5 @@ +You may remove this file if you don't intend to add types to your package + +Details at: + +https://mypy.readthedocs.io/en/stable/installed_packages.html#creating-pep-561-compatible-packages diff --git a/tests/test_ttmask.py b/tests/test_ttmask.py new file mode 100644 index 0000000..363b3e2 --- /dev/null +++ b/tests/test_ttmask.py @@ -0,0 +1,2 @@ +def test_something(): + pass