diff --git a/.bumpversion.cfg b/.bumpversion.cfg deleted file mode 100644 index 7c940ea..0000000 --- a/.bumpversion.cfg +++ /dev/null @@ -1,32 +0,0 @@ -[bumpversion] -current_version = 0.5.7-dev -commit = True -tag = False -parse = (?P\d+)\.(?P\d+)\.(?P\d+)(?:-(?P[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+(?P[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))? -serialize = - {major}.{minor}.{patch}-{release}+{build} - {major}.{minor}.{patch}+{build} - {major}.{minor}.{patch}-{release} - {major}.{minor}.{patch} - -[bumpversion:part:release] -optional_value = production -first_value = dev -values = - dev - production - -[bumpverion:part:build] -values = [0-9A-Za-z-]+ - -[bumpversion:file:setup.cfg] -search = version = {current_version} -replace = version = {new_version} - -[bumpversion:file:docs/source/conf.py] -search = release = '{current_version}' -replace = release = '{new_version}' - -[bumpversion:file:src/pystow/version.py] -search = VERSION = "{current_version}" -replace = VERSION = "{new_version}" diff --git a/.cruft.json b/.cruft.json new file mode 100644 index 0000000..451b04b --- /dev/null +++ b/.cruft.json @@ -0,0 +1,26 @@ +{ + "template": "https://github.com/cthoyt/cookiecutter-snekpack", + "commit": "12edfcfa5f519467b5d834f0d4e706fb7cf4f065", + "checkout": null, + "context": { + "cookiecutter": { + "package_name": "pystow", + "package_name_stylized": "PyStow", + "short_description": "Easily pick a place to store data for your Python code", + "author_name": "Charles Tapley Hoyt", + "author_email": "cthoyt@gmail.com", + "github_organization_name": "cthoyt", + "github_repository_name": "pystow", + "command_line_interface": true, + "gitlab": false, + "runner": "tox", + "__runner": "tox -e", + "__runner_uv": "--with tox-uv tox -e", + "__runner_pip": "tox tox-uv", + "__runner_tests": "py", + "__gh_slug": "cthoyt/pystow", + "_template": "https://github.com/cthoyt/cookiecutter-snekpack" + } + }, + "directory": null +} diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..bbcc13d --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +cthoyt@gmail.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..2f95b83 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,116 @@ +# Contributing + +Contributions to this repository are welcomed and encouraged. + +## Code Contribution + +This project uses the [GitHub Flow](https://guides.github.com/introduction/flow) +model for code contributions. Follow these steps: + +1. [Create a fork](https://help.github.com/articles/fork-a-repo) of the upstream + repository + at [`cthoyt/pystow`](https://github.com/cthoyt/pystow) + on your GitHub account (or in one of your organizations) +2. [Clone your fork](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) + with `git clone https://github.com//pystow.git` +3. Make and commit changes to your fork with `git commit` +4. Push changes to your fork with `git push` +5. Repeat steps 3 and 4 as needed +6. Submit a pull request back to the upstream repository + +### Merge Model + +This repository +uses [squash merges](https://docs.github.com/en/github/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#squash-and-merge-your-pull-request-commits) +to group all related commits in a given pull request into a single commit upon +acceptance and merge into the main branch. This has several benefits: + +1. Keeps the commit history on the main branch focused on high-level narrative +2. Enables people to make lots of small commits without worrying about muddying + up the commit history +3. Commits correspond 1-to-1 with pull requests + +### Code Style + +This project uses `tox` for running code quality checks. Start by installing +it with `pip install tox tox-uv`. + +This project encourages the use of optional static typing. It +uses [`mypy`](http://mypy-lang.org/) as a type checker. You can check if +your code passes `mypy` with `tox -e mypy`. + +This project uses [`ruff`](https://docs.astral.sh/ruff/) to automatically +enforce a consistent code style. You can apply `ruff format` and other pre-configured +formatters with `tox -e format`. + +This project uses [`ruff`](https://docs.astral.sh/ruff/) and several plugins for +additional checks of documentation style, security issues, good variable +nomenclature, and more (see `pyproject.toml` for a list of Ruff plugins). You can check if your +code passes `ruff check` with `tox -e lint`. + +Each of these checks are run on each commit using GitHub Actions as a continuous +integration service. Passing all of them is required for accepting a +contribution. If you're unsure how to address the feedback from one of these +tools, please say so either in the description of your pull request or in a +comment, and we will help you. + +### Logging + +Python's builtin `print()` should not be used (except when writing to files), +it's checked by the +[`flake8-print` (T20)](https://docs.astral.sh/ruff/rules/#flake8-print-t20) plugin to `ruff`. If +you're in a command line setting or `main()` function for a module, you can use +`click.echo()`. Otherwise, you can use the builtin `logging` module by adding +`logger = logging.getLogger(__name__)` below the imports at the top of your +file. + +### Documentation + +All public functions (i.e., not starting with an underscore `_`) must be +documented using +the [sphinx documentation format](https://sphinx-rtd-tutorial.readthedocs.io/en/latest/docstrings.html#the-sphinx-docstring-format). +The [`darglint2`](https://github.com/akaihola/darglint2) tool +reports on functions that are not fully documented. + +This project uses [`sphinx`](https://www.sphinx-doc.org) to automatically build +documentation into a narrative structure. You can check that the documentation +builds properly in an isolated environment with `tox -e docs-test` and actually +build it locally with `tox -e docs`. + +### Testing + +Functions in this repository should be unit tested. These can either be written +using the `unittest` framework in the `tests/` directory or as embedded +doctests. You can check that the unit tests pass with `tox -e py` +and that the doctests pass with `tox -e doctests`. These tests are required to pass for +accepting a contribution. + +### Syncing your fork + +If other code is updated before your contribution gets merged, you might need to +resolve conflicts against the main branch. After cloning, you should add the +upstream repository with + +```shell +$ git remote add cthoyt https://github.com/cthoyt/pystow.git +``` + +Then, you can merge upstream code into your branch. You can also use the GitHub +UI to do this by +following [this tutorial](https://docs.github.com/en/github/collaborating-with-pull-requests/working-with-forks/syncing-a-fork). + +### Python Version Compatibility + +This project aims to support all versions of Python that have not passed their +end-of-life dates. After end-of-life, the version will be removed from the Trove +qualifiers in the `pyproject.toml` and from the GitHub Actions testing +configuration. + +See https://endoflife.date/python for a timeline of Python release and +end-of-life dates. + +## Acknowledgements + +These code contribution guidelines are derived from +the [cthoyt/cookiecutter-snekpack](https://github.com/cthoyt/cookiecutter-snekpack) +Python package template. They're free to reuse and modify as long as they're properly acknowledged. diff --git a/.github/codecov.yml b/.github/codecov.yml new file mode 100644 index 0000000..180cf44 --- /dev/null +++ b/.github/codecov.yml @@ -0,0 +1,4 @@ +# see https://docs.codecov.com/v4.6/docs/codecov-yaml +ignore: + - "src/pystow/__main__.py" + - "src/pystow/cli.py" diff --git a/.github/workflows/cruft.yml b/.github/workflows/cruft.yml new file mode 100644 index 0000000..7442c9f --- /dev/null +++ b/.github/workflows/cruft.yml @@ -0,0 +1,79 @@ +# from https://cruft.github.io/cruft/#automating-updates-with-github-actions + +name: Update repository with Cruft + +permissions: + contents: write + pull-requests: write + +on: + workflow_dispatch: + schedule: + - cron: "0 2 * * 1" # Every Monday at 2am + +jobs: + update: + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + include: + - add-paths: . + body: Use this to merge the changes to this repository. + branch: cruft/update + commit-message: "chore: accept new Cruft update" + title: New updates detected with Cruft + - add-paths: .cruft.json + body: Use this to reject the changes in this repository. + branch: cruft/reject + commit-message: "chore: reject new Cruft update" + title: Reject new updates detected with Cruft + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Install Cruft + run: pip3 install cruft + + - name: Check if update is available + continue-on-error: false + id: check + run: | + CHANGES=0 + if [ -f .cruft.json ]; then + if ! cruft check; then + CHANGES=1 + fi + else + echo "No .cruft.json file" + fi + + echo "has_changes=$CHANGES" >> "$GITHUB_OUTPUT" + + - name: Run update if available + if: steps.check.outputs.has_changes == '1' + run: | + git config --global user.email "you@example.com" + git config --global user.name "GitHub" + + cruft update --skip-apply-ask --refresh-private-variables + git restore --staged . + + - name: Create pull request + if: steps.check.outputs.has_changes == '1' + uses: peter-evans/create-pull-request@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + add-paths: ${{ matrix.add-paths }} + commit-message: ${{ matrix.commit-message }} + branch: ${{ matrix.branch }} + delete-branch: true + branch-suffix: timestamp + title: ${{ matrix.title }} + body: | + This is an autogenerated PR. ${{ matrix.body }} + + [Cruft](https://cruft.github.io/cruft/) has detected updates from the Cookiecutter repository. diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f5823a4..ebf81a3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,3 +1,7 @@ +# This file configures the continuous integration (CI) system on GitHub. +# Introductory materials can be found here: https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions. +# Documentation for editing this file can be found here: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions + name: Tests on: @@ -8,71 +12,67 @@ on: jobs: lint: - name: Lint + name: Code Quality runs-on: ubuntu-latest strategy: matrix: python-version: [ "3.12", "3.9" ] + tox-command: ["manifest", "lint", "pyroma", "mypy"] steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - name: "Install uv" + uses: "astral-sh/setup-uv@v3" with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: pip install tox tox-uv - - name: Check manifest - run: tox -e manifest - - name: Check code quality with flake8 - run: tox -e format,lint - - name: Check package metadata with Pyroma - run: tox -e pyroma - - name: Check static typing with MyPy - run: tox -e mypy + enable-cache: true + cache-dependency-glob: "pyproject.toml" + - name: "Run command" + run: | + uvx -p ${{ matrix.python-version }} --with tox-uv tox -e ${{ matrix.tox-command }} + docs: name: Documentation runs-on: ubuntu-latest strategy: matrix: + # We only test documentation on the latest version + # sphinx 8.0 / sphinx-rtd-theme 3.0 discontinued Python 3.9 support + # a year early, which prompted re-thinking about this. python-version: [ "3.12" ] steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - name: "Install uv" + uses: "astral-sh/setup-uv@v3" with: - python-version: ${{ matrix.python-version }} + enable-cache: true + cache-dependency-glob: "pyproject.toml" - name: Install dependencies - run: pip install tox tox-uv + run: | + sudo apt-get install graphviz - name: Check RST conformity with doc8 - run: tox -e doc8 + run: uvx -p ${{ matrix.python-version }} --with tox-uv tox -e doc8 - name: Check docstring coverage - run: tox -e docstr-coverage + run: uvx -p ${{ matrix.python-version }} --with tox-uv tox -e docstr-coverage - name: Check documentation build with Sphinx - run: tox -e docs-test + run: uvx -p ${{ matrix.python-version }} --with tox-uv tox -e docs-test tests: name: Tests runs-on: ${{ matrix.os }} strategy: matrix: - os: [ ubuntu-latest, windows-latest, macos-latest ] - python-version: [ "3.9", "3.10", "3.11", "3.12" ] + os: [ ubuntu-latest ] + python-version: [ "3.12", "3.9" ] steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - name: "Install uv" + uses: "astral-sh/setup-uv@v3" with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: pip install tox tox-uv - - name: Test with pytest - run: - tox -e py - - name: Build codecov file - if: success() + enable-cache: true + cache-dependency-glob: "pyproject.toml" + - name: Test with pytest and generate coverage file run: - tox -e coverage-xml + uvx -p ${{ matrix.python-version }} --with tox-uv tox -e py - name: Upload coverage report to codecov - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v4 if: success() with: file: coverage.xml diff --git a/.gitignore b/.gitignore index c57b880..fefaf5f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,296 @@ +# Created by https://www.toptal.com/developers/gitignore/api/macos,linux,windows,python,jupyternotebooks,jetbrains,pycharm,vim,emacs,visualstudiocode,visualstudio +# Edit at https://www.toptal.com/developers/gitignore?templates=macos,linux,windows,python,jupyternotebooks,jetbrains,pycharm,vim,emacs,visualstudiocode,visualstudio + +### Emacs ### +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +# network security +/network-security.data + + +### JetBrains ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### JetBrains Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +### JupyterNotebooks ### +# gitignore template for Jupyter Notebooks +# website: http://jupyter.org/ + +.ipynb_checkpoints +*/.ipynb_checkpoints/* + +# IPython +profile_default/ +ipython_config.py + +# Remove previous ipynb_checkpoints +# git rm -r .ipynb_checkpoints/ + +### Linux ### + +# 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* + +### macOS ### +# 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 + +### PyCharm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff + +# AWS User-specific + +# Generated files + +# Sensitive or high-churn files + +# Gradle + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake + +# Mongo Explorer plugin + +# File-based project format + +# IntelliJ + +# mpeltonen/sbt-idea plugin + +# JIRA plugin + +# Cursive Clojure plugin + +# SonarLint plugin + +# Crashlytics plugin (for Android Studio and IntelliJ) + +# Editor-based Rest Client + +# Android studio 3.1+ serialized cache file + +### PyCharm Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream + +### Python ### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -10,7 +303,6 @@ __pycache__/ .Python build/ develop-eggs/ -dist/ downloads/ eggs/ .eggs/ @@ -20,7 +312,6 @@ parts/ sdist/ var/ wheels/ -pip-wheel-metadata/ share/python-wheels/ *.egg-info/ .installed.cfg @@ -50,6 +341,7 @@ coverage.xml *.py,cover .hypothesis/ .pytest_cache/ +cover/ # Translations *.mo @@ -70,19 +362,21 @@ instance/ # Sphinx documentation docs/_build/ +docs/build +docs/source/api # PyBuilder +.pybuilder/ target/ # Jupyter Notebook -.ipynb_checkpoints # IPython -profile_default/ -ipython_config.py # pyenv -.python-version +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. @@ -91,6 +385,13 @@ ipython_config.py # install all needed dependencies. #Pipfile.lock +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ @@ -128,8 +429,473 @@ dmypy.json # Pyre type checker .pyre/ -# Auto-generated docs -docs/source/api/ -tests/resources/test_1.db -tests/resources/test_1.json.bz2 -tests/resources/test_1.pkl.gz +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# Support for Project snippet scope + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### VisualStudio ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +*.code-workspace + +# Local History for Visual Studio Code + +# Windows Installer files from build outputs + +# JetBrains Rider +*.sln.iml + +### VisualStudio Patch ### +# Additional files built by Visual Studio + +# End of https://www.toptal.com/developers/gitignore/api/macos,linux,windows,python,jupyternotebooks,jetbrains,pycharm,vim,emacs,visualstudiocode,visualstudio + +scratch/ diff --git a/.readthedocs.yml b/.readthedocs.yml index fceee2a..a8e09ac 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,12 +1,18 @@ -# See: https://docs.readthedocs.io/en/latest/config-file/v2.html +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details version: 2 +# Set the version of Python and other tools you might need build: - image: latest + os: ubuntu-22.04 + apt_packages: + - graphviz + tools: + python: "3.12" python: - version: "3.8" install: - method: pip path: . diff --git a/LICENSE b/LICENSE index 94a5e80..6ee2b47 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Charles Tapley Hoyt +Copyright (c) 2024 Charles Tapley Hoyt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/MANIFEST.in b/MANIFEST.in index 8aaed91..ba13bbc 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,13 +1,11 @@ graft src graft tests +prune scripts +prune notebooks +prune tests/.pytest_cache +prune docs -recursive-include docs Makefile -recursive-include docs/source *.py -recursive-include docs/source *.rst -recursive-include docs/source *.png +global-exclude *.py[cod] __pycache__ *.so *.dylib .DS_Store *.gpickle .idea/** -global-exclude *.py[cod] __pycache__ *.so *.dylib .DS_Store *.gpickle - -exclude .appveyor.yml .bumpversion.cfg .coveragerc .flake8 .travis.yml .readthedocs.yml tox.ini .pre-commit-config.yaml -exclude .appveyor_on_request.yml -include LICENSE *.md *.rst +include README.md LICENSE +exclude tox.ini .readthedocs.yml .cruft.json CITATION.cff docker-compose.yml Dockerfile noxfile.py diff --git a/README.md b/README.md index b92dd46..8d67b2f 100644 --- a/README.md +++ b/README.md @@ -3,34 +3,31 @@

- - Build status - - - - PyPI - Python Version - - - - License - - - - Documentation Status - - - - DOI - - - - Code style: black - + + Tests + + PyPI + + PyPI - Python Version + + PyPI - License + + Documentation Status + + Codecov status + + Cookiecutter template from @cthoyt + + Ruff + + Contributor Covenant + + DOI

-👜 Easily pick a place to store data for your python code. +👜 Easily pick a place to store data for your Python code -## 🚀 Getting Started +## 💪 Getting Started Get a directory for your application. @@ -187,28 +184,185 @@ overridden by `PYSTOW_HOME`. The most recent release can be installed from [PyPI](https://pypi.org/project/pystow/) with: -```bash -$ pip install pystow +```console +python3 -m pip install pystow ``` -Note, as of v0.3.0, Python 3.6 isn't officially supported (its -end-of-life was in December 2021). For the time being, `pystow` might still -work on py36, but this is only coincidental. - The most recent code and data can be installed directly from GitHub with: -```bash -$ pip install git+https://github.com/cthoyt/pystow.git +```console +python3 -m pip install git+https://github.com/cthoyt/pystow.git ``` +## 👐 Contributing + +Contributions, whether filing an issue, making a pull request, or forking, are appreciated. See +[CONTRIBUTING.md](https://github.com/cthoyt/pystow/blob/master/.github/CONTRIBUTING.md) +for more information on getting involved. + +## 👋 Attribution + +### ⚖️ License + +The code in this package is licensed under the MIT License. + +### 🍪 Cookiecutter + +This package was created with [@audreyfeldroy](https://github.com/audreyfeldroy)'s +[cookiecutter](https://github.com/cookiecutter/cookiecutter) package using [@cthoyt](https://github.com/cthoyt)'s +[cookiecutter-snekpack](https://github.com/cthoyt/cookiecutter-snekpack) template. + +## 🛠️ For Developers + +
+ See developer instructions + +The final section of the README is for if you want to get involved by making a code contribution. + +### Development Installation + To install in development mode, use the following: -```bash -$ git clone git+https://github.com/cthoyt/pystow.git -$ cd pystow -$ pip install -e . +```console +git clone git+https://github.com/cthoyt/pystow.git +cd pystow +python3 -m pip install -e . ``` -## ⚖️ License +### Updating Package Boilerplate -The code in this package is licensed under the MIT License. +This project uses `cruft` to keep boilerplate (i.e., configuration, contribution guidelines, documentation +configuration) +up-to-date with the upstream cookiecutter package. Update with the following: + +```console +python3 -m pip install cruft +cruft update +``` + +More info on Cruft's update command is +available [here](https://github.com/cruft/cruft?tab=readme-ov-file#updating-a-project). + +### 🥼 Testing + +After cloning the repository and installing `tox` with +`python3 -m pip install tox tox-uv`, +the unit tests in the `tests/` folder can be run reproducibly with: + +```console +tox -e py +``` + +Additionally, these tests are automatically re-run with each commit in a +[GitHub Action](https://github.com/cthoyt/pystow/actions?query=workflow%3ATests). + +### 📖 Building the Documentation + +The documentation can be built locally using the following: + +```console +git clone git+https://github.com/cthoyt/pystow.git +cd pystow +tox -e docs +open docs/build/html/index.html +``` + +The documentation automatically installs the package as well as the `docs` +extra specified in the [`pyproject.toml`](pyproject.toml). `sphinx` plugins +like `texext` can be added there. Additionally, they need to be added to the +`extensions` list in [`docs/source/conf.py`](docs/source/conf.py). + +The documentation can be deployed to [ReadTheDocs](https://readthedocs.io) using +[this guide](https://docs.readthedocs.io/en/stable/intro/import-guide.html). +The [`.readthedocs.yml`](.readthedocs.yml) YAML file contains all the configuration you'll need. +You can also set up continuous integration on GitHub to check not only that +Sphinx can build the documentation in an isolated environment (i.e., with `tox -e docs-test`) +but also that [ReadTheDocs can build it too](https://docs.readthedocs.io/en/stable/pull-requests.html). + +#### Configuring ReadTheDocs + +1. Log in to ReadTheDocs with your GitHub account to install the integration + at https://readthedocs.org/accounts/login/?next=/dashboard/ +2. Import your project by navigating to https://readthedocs.org/dashboard/import then clicking the plus icon next to + your repository +3. You can rename the repository on the next screen using a more stylized name (i.e., with spaces and capital letters) +4. Click next, and you're good to go! + +### 📦 Making a Release + +#### Configuring Zenodo + +[Zenodo](https://zenodo.org) is a long-term archival system that assigns a DOI to each release of your package. + +1. Log in to Zenodo via GitHub with this link: https://zenodo.org/oauth/login/github/?next=%2F. This brings you to a + page that lists all of your organizations and asks you to approve installing the Zenodo app on GitHub. Click "grant" + next to any organizations you want to enable the integration for, then click the big green "approve" button. This + step only needs to be done once. +2. Navigate to https://zenodo.org/account/settings/github/, which lists all of your GitHub repositories (both in your + username and any organizations you enabled). Click the on/off toggle for any relevant repositories. When you make + a new repository, you'll have to come back to this + +After these steps, you're ready to go! After you make "release" on GitHub (steps for this are below), you can navigate +to https://zenodo.org/account/settings/github/repository/cthoyt/pystow +to see the DOI for the release and link to the Zenodo record for it. + +#### Registering with the Python Package Index (PyPI) + +You only have to do the following steps once. + +1. Register for an account on the [Python Package Index (PyPI)](https://pypi.org/account/register) +2. Navigate to https://pypi.org/manage/account and make sure you have verified your email address. A verification email + might not have been sent by default, so you might have to click the "options" dropdown next to your address to get to + the "re-send verification email" button +3. 2-Factor authentication is required for PyPI since the end of 2023 (see + this [blog post from PyPI](https://blog.pypi.org/posts/2023-05-25-securing-pypi-with-2fa/)). This means + you have to first issue account recovery codes, then set up 2-factor authentication +4. Issue an API token from https://pypi.org/manage/account/token + +#### Configuring your machine's connection to PyPI + +You have to do the following steps once per machine. + +```console +$ uv tool install keyring +$ keyring set https://upload.pypi.org/legacy/ __token__ +$ keyring set https://test.pypi.org/legacy/ __token__ +``` + +Note that this deprecates previous workflows using `.pypirc`. + +#### Uploading to PyPI + +After installing the package in development mode and installing +`tox` with `python3 -m pip install tox tox-uv`, +run the following from the console: + +```console +tox -e finish +``` + +This script does the following: + +1. Uses [bump-my-version](https://github.com/callowayproject/bump-my-version) to switch the version number in + the `pyproject.toml`, `CITATION.cff`, `src/pystow/version.py`, + and [`docs/source/conf.py`](docs/source/conf.py) to not have the `-dev` suffix +2. Packages the code in both a tar archive and a wheel using + [`uv build`](https://docs.astral.sh/uv/guides/publish/#building-your-package) +3. Uploads to PyPI using [`uv publish`](https://docs.astral.sh/uv/guides/publish/#publishing-your-package). +4. Push to GitHub. You'll need to make a release going with the commit where the version was bumped. +5. Bump the version to the next patch. If you made big changes and want to bump the version by minor, you can + use `tox -e bumpversion -- minor` after. + +#### Releasing on GitHub + +1. Navigate + to https://github.com/cthoyt/pystow/releases/new + to draft a new release +2. Click the "Choose a Tag" dropdown and select the tag corresponding to the release you just made +3. Click the "Generate Release Notes" button to get a quick outline of recent changes. Modify the title and description + as you see fit +4. Click the big green "Publish Release" button + +This will trigger Zenodo to assign a DOI to your release as well. + +