From d3c74f6276dd4716472e64df4d8fd88585620f46 Mon Sep 17 00:00:00 2001 From: richarddushime Date: Mon, 3 Mar 2025 02:07:23 +0100 Subject: [PATCH 01/36] Improve doc content #58 --- .github/workflows/cookiecutter_docs.yml | 31 ++++++++ docs/.nojekyll | 0 docs/Makefile | 20 ++++++ docs/make.bat | 35 +++++++++ docs/requirements.txt | 3 + docs/source/_static/css/custom.css | 59 ++++++++++++++++ docs/source/_static/logo.png | Bin 0 -> 4695 bytes docs/source/_templates/navbar.html | 30 ++++++++ docs/source/_templates/sidebar-nav.html | 7 ++ docs/source/conf.py | 59 ++++++++++++++++ docs/source/contributing.rst | 90 ++++++++++++++++++++++++ docs/source/documentation.rst | 47 +++++++++++++ docs/source/getting_started.rst | 25 +++++++ docs/source/github_actions_setup.rst | 10 +++ docs/source/index.rst | 21 ++++++ docs/source/modules.rst | 53 ++++++++++++++ docs/source/pre_commits.rst | 60 ++++++++++++++++ docs/source/project_setup.rst | 89 +++++++++++++++++++++++ docs/source/versioning.rst | 23 ++++++ 19 files changed, 662 insertions(+) create mode 100644 .github/workflows/cookiecutter_docs.yml create mode 100644 docs/.nojekyll create mode 100644 docs/Makefile create mode 100644 docs/make.bat create mode 100644 docs/requirements.txt create mode 100644 docs/source/_static/css/custom.css create mode 100644 docs/source/_static/logo.png create mode 100644 docs/source/_templates/navbar.html create mode 100644 docs/source/_templates/sidebar-nav.html create mode 100644 docs/source/conf.py create mode 100644 docs/source/contributing.rst create mode 100644 docs/source/documentation.rst create mode 100644 docs/source/getting_started.rst create mode 100644 docs/source/github_actions_setup.rst create mode 100644 docs/source/index.rst create mode 100644 docs/source/modules.rst create mode 100644 docs/source/pre_commits.rst create mode 100644 docs/source/project_setup.rst create mode 100644 docs/source/versioning.rst diff --git a/.github/workflows/cookiecutter_docs.yml b/.github/workflows/cookiecutter_docs.yml new file mode 100644 index 0000000..ac8b7ee --- /dev/null +++ b/.github/workflows/cookiecutter_docs.yml @@ -0,0 +1,31 @@ +name: Documentation +on: + push: + branches: [main] + tags: ['*'] + +jobs: + deploy-docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Install dependencies + run: | + pip install -r docs/requirements.txt + + - name: Build docs + run: | + cd docs + make html + + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs/build/html \ No newline at end of file diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..dc1312a --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..abcb530 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,3 @@ +sphinx +pydata-sphinx-theme +myst-parser \ No newline at end of file diff --git a/docs/source/_static/css/custom.css b/docs/source/_static/css/custom.css new file mode 100644 index 0000000..f355b67 --- /dev/null +++ b/docs/source/_static/css/custom.css @@ -0,0 +1,59 @@ +/* Top navbar */ +.navbar { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.8rem 2rem; + background: #2B3A42; +} + +.navbar-brand { + flex: 0 0 auto; +} + +.navbar-center-group { + flex: 1; + display: flex; + justify-content: center; + gap: 2rem; + margin: 0 2rem; +} + +.navbar-nav { + display: flex; + gap: 1.5rem; + margin: 0; + padding: 0; + align-items: center; +} + +.navbar-icons { + display: flex; + gap: 1.5rem; + align-items: center; +} + +/* Rest of your existing styles remain */ +.navbar-brand-logo img { height: 40px; } +.nav-link { color: white !important; font-weight: 500; } +.icon-link { color: white !important; font-size: 1.2rem; } +.bd-sidebar-secondary { display: none !important; } + +/* Mobile responsiveness */ +@media (max-width: 768px) { + .navbar { + flex-wrap: wrap; + padding: 0.8rem; + } + + .navbar-center-group { + order: 2; + width: 100%; + margin: 1rem 0; + justify-content: center; + } + + .navbar-brand { + order: 1; + } +} \ No newline at end of file diff --git a/docs/source/_static/logo.png b/docs/source/_static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..324b1bcaf28d93b6f39ae57406120f2b42d515b5 GIT binary patch literal 4695 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 + + + + + + + \ No newline at end of file diff --git a/docs/source/_templates/sidebar-nav.html b/docs/source/_templates/sidebar-nav.html new file mode 100644 index 0000000..e9b6173 --- /dev/null +++ b/docs/source/_templates/sidebar-nav.html @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..e7df00b --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,59 @@ +# conf.py + +# -- Project information ----------------------------------------------------- +project = 'cookiecutter-python' +author = 'Name' +release = '0.1.0' + +# -- General configuration --------------------------------------------------- +extensions = [ + "myst_parser", + "sphinx_design", + "sphinx.ext.autodoc", + "sphinx.ext.napoleon" +] + +myst_enable_extensions = [ + "colon_fence", + "deflist", + "linkify", + "substitution", + "tasklist", +] + +source_suffix = { + '.md': 'markdown', + '.rst': 'restructuredtext' +} + +templates_path = ['_templates'] + +# -- HTML output options ----------------------------------------------------- +html_theme = 'pydata_sphinx_theme' +html_logo = "_static/logo.png" +html_static_path = ["_static"] + +html_theme_options = { + # Disable right sidebar TOC + "show_toc_level": 0, + + # Configure navbar + "navbar_start": [], + "navbar_center": ["navbar.html"], + "navbar_end": [], + + # Disable default right sidebar + "secondary_sidebar_items": [], + + # Keep other settings + "show_nav_level": 2, + "navigation_depth": 3, + "collapse_navigation": False, +} + +html_sidebars = { + "**": ["sidebar-nav.html", "search-field.html"] +} + +def setup(app): + app.add_css_file("css/custom.css") \ No newline at end of file diff --git a/docs/source/contributing.rst b/docs/source/contributing.rst new file mode 100644 index 0000000..ddb75f0 --- /dev/null +++ b/docs/source/contributing.rst @@ -0,0 +1,90 @@ +Contributing to cookiecutter-python +===================================== + +Thank you for considering contributing to cookiecutter-python! +We welcome contributions that improve the project, whether it’s code, documentation, or enhancements. +Please follow the guidelines below to ensure a smooth process. + +Workflow +-------- + +1. **Fork and Clone the Repository** + Fork the main repository on GitHub, then clone your fork locally: + + .. code-block:: bash + + git clone https://github.com//python-cookiecutter.git + cd python-cookiecutter + +2. **Create a New Branch** + Create and switch to a new branch for your changes: + + .. code-block:: bash + + git checkout -b my_new_feature + +3. **Make Your Changes** + Edit the website content, code, or documentation as needed. + When you’re ready, add and commit your changes with a descriptive message: + + .. code-block:: bash + + git add . + git commit -m "Describe your changes here" + +4. **Push Your Branch and Create a Pull Request** + Push the new branch to GitHub: + + .. code-block:: bash + + git push origin --set-upstream origin my_new_feature + + Then, open a pull request against the `main` branch of the main repository. + This will automatically trigger a GitHub Action to verify that the website builds correctly. + +5. **Review and Merge** + If the build checks pass, assign someone to review your pull request. + Once approved and merged into the `main` branch, another GitHub Action will build the website and publish it to the `gh-pages` branch. + +6. **Deployment** + After merging, the updated website will be available at: + `python-cookiecutter.github.io` + +Local Testing +------------- + +Before pushing your changes, you can test the website locally: + +- **First-Time Setup:** + Install the required dependencies and build the site: + + .. code-block:: bash + + pip install -r docs/requirements.txt + sphinx-build docs/source docs/build + +Alternatively, you can use the following commands to install the dependencies and build the site: + + .. code-block:: bash + + pip install -r docs/requirements.txt + cd docs + make html + +- **Rebuilding the Site:** + Each time you update the documentation, rebuild the site by running: + + .. code-block:: bash + + rm -rf docs/build && sphinx-build docs/source docs/build + + Then, open ``docs/build/index.html`` in your browser to preview the changes. + +Additional Guidelines +--------------------- + +- **Coding Standards:** Ensure that your contributions follow the project's coding and documentation guidelines. +- **Commit Messages:** Write clear and concise commit messages. +- **Documentation:** If your changes affect the website or project behavior, please update the documentation accordingly. + +Thank you for your contributions! diff --git a/docs/source/documentation.rst b/docs/source/documentation.rst new file mode 100644 index 0000000..ad0d230 --- /dev/null +++ b/docs/source/documentation.rst @@ -0,0 +1,47 @@ +Documentation +============= + +Good documentation is key for both users and developers. If you chose to create docs during cookiecutter setup, +a ``docs`` folder was generated with a basic Sphinx configuration. + +Building the Documentation Locally +---------------------------------- + +To build the docs locally: + +1. Install the build requirements: + + .. code-block:: bash + + pip install -r docs/requirements.txt + +2. Build the documentation: + + .. code-block:: bash + + sphinx-build docs/source docs/build + +Open ``docs/build/index.html`` in your browser to view the docs. + +Refreshing the Build +-------------------- + +After updating your documentation, remove the build folder and rebuild: + +.. code-block:: bash + + rm -rf docs/build + sphinx-build docs/source docs/build + +Publishing the Documentation +---------------------------- + +A separate GitHub Actions workflow (``.github/workflows/docs_build_and_deploy.yml``) builds and deploys +the documentation to GitHub Pages when changes are pushed to ``main`` or when a tag is created. + +Docstrings and API Documentation +-------------------------------- + +Write clear docstrings for all functions in your code (e.g. using the NumPy or Google style). +Sphinx’s ``autodoc`` extension automatically generates API documentation from these docstrings. +For an example setup, see the ``docs/source/api_index.rst`` file. diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst new file mode 100644 index 0000000..36b87f7 --- /dev/null +++ b/docs/source/getting_started.rst @@ -0,0 +1,25 @@ +Getting Started +=============== + +Overview +-------- +A cookiecutter template that creates: + +* Pre-configured Python project structure +* GitHub Actions CI/CD pipeline +* Sphinx documentation setup +* Automated versioning +* Pre-commit hooks + +Features +-------- +.. list-table:: + :widths: 30 70 + :header-rows: 0 + + * - :octicon:`package` Project Setup + - Pre-configured pyproject.toml, LICENSE, tests + * - :octicon:`workflow` CI/CD + - GitHub Actions for testing and deployment + * - :octicon:`book` Documentation + - Sphinx with PyData theme + auto API generation \ No newline at end of file diff --git a/docs/source/github_actions_setup.rst b/docs/source/github_actions_setup.rst new file mode 100644 index 0000000..cce7075 --- /dev/null +++ b/docs/source/github_actions_setup.rst @@ -0,0 +1,10 @@ +GitHub Actions Workflow +======================= + +A GitHub Actions workflow (located at ``.github/workflows/test_and_deploy.yml``) is configured to run: + +- **Linting checks** via pre-commit. +- **Testing** if linting passes. +- **Deployment to PyPI** if a Git tag is present and tests pass (requires the ``TWINE_API_KEY`` in repository secrets). + +This automation ensures that each commit or pull request is validated and that releases are published only when all checks pass. diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..4a8e63b --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,21 @@ +Welcome to cookiecutter-python Documentation +============================================ + +A tool to automatically create a Python project structure ready to release via GitHub and PyPI. +It sets up a blank README, LICENSE, pre-commit hooks, automated versioning, tests with pytest, +GitHub Actions for CI/CD, and Sphinx documentation. + + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + :hidden: + + getting_started + project_setup + modules + pre_commits + versioning + github_actions_setup + documentation + contributing \ No newline at end of file diff --git a/docs/source/modules.rst b/docs/source/modules.rst new file mode 100644 index 0000000..f9df5b0 --- /dev/null +++ b/docs/source/modules.rst @@ -0,0 +1,53 @@ +Modules and Tests +================= + +Your Python code should live in the ``my_awesome_software`` package. +You can organize your code into multiple modules and write tests to ensure everything works as expected. + +Adding Modules +-------------- + +Create your Python modules as separate ``.py`` files. For example: + +.. code-block:: text + + my_awesome_software/ + ├── __init__.py + ├── greetings.py + └── math.py + +To import functions between modules, use relative imports: + +.. code-block:: python + + # Inside greetings.py + from .math import subtract_two_integers + +If you want to import all modules when installing, add the following in ``__init__.py``: + +.. code-block:: python + + from . import * + +Adding Dependencies +------------------- + +To include dependencies (e.g. ``numpy``, ``pandas``), list them in the ``pyproject.toml`` file: + +.. code-block:: toml + + [project] + dependencies = ["numpy", "pandas"] + +Writing Tests +------------- + +Place your tests in the ``tests`` directory. Use pytest to write unit tests and integration tests. +For example, a unit test in ``tests/test_unit/test_math.py`` might look like: + +.. code-block:: python + + from my_awesome_software import math + + def test_add_two_integers(): + assert math.add_two_integers(1, 2) == 3 diff --git a/docs/source/pre_commits.rst b/docs/source/pre_commits.rst new file mode 100644 index 0000000..45747dc --- /dev/null +++ b/docs/source/pre_commits.rst @@ -0,0 +1,60 @@ +Before Committing Your Changes +============================== + +Ensure that your code passes all tests and follows formatting standards before committing. + +Running the Tests +----------------- + +Install pytest if needed and run the tests: + +.. code-block:: bash + + pip install pytest + pytest + +Local Installation +------------------ + +For a local, editable install run: + +.. code-block:: bash + + pip install -e . + +For development (with additional tools): + +.. code-block:: bash + + pip install -e '.[dev]' + +Testing the Installation +------------------------ + +Test that your modules work from another folder: + +.. code-block:: python + + from my_awesome_software.math import add_two_integers + add_two_integers(1, 2) + +Pre-commit Hooks +---------------- + +Setting up pre-commit hooks ensures consistent code quality. Install them by running: + +.. code-block:: bash + + pre-commit install + +The hooks include: +- **ruff**: For linting, formatting, and import sorting. +- **mypy**: For static type checking. +- **check-manifest**: To verify the correct files are packaged. +- **codespell**: To catch common misspellings. + +To run all hooks before committing, use: + +.. code-block:: bash + + pre-commit run diff --git a/docs/source/project_setup.rst b/docs/source/project_setup.rst new file mode 100644 index 0000000..8f768e3 --- /dev/null +++ b/docs/source/project_setup.rst @@ -0,0 +1,89 @@ +Setup +===== + +This section describes how to set up your project using cookiecutter. + +Installing Cookiecutter +----------------------- + +Install Cookiecutter using pip or conda: + +.. code-block:: bash + + pip install cookiecutter + # or with conda: + conda install -c conda-forge cookiecutter + +Creating a Cookiecutter Project +------------------------------- + +Run the following command in your target folder: + +.. code-block:: bash + + cookiecutter https://github.com/neuroinformatics-unit/python-cookiecutter + +You'll be prompted for several configuration options, such as: + +- **full_name**: e.g. ``Adam Tyson`` +- **email**: e.g. ``cookiecutter@adamltyson.com`` +- **github_username_or_organization**: e.g. ``adamltyson`` +- **package_name**: e.g. ``my-awesome-software`` +- **module_name**: (auto-generated from package_name) +- **short_description**: A brief description of your package +- **license**: Choose from BSD-3, MIT, MPL 2.0, Apache 2.0, GNU LGPL, or GNU GPL +- **create_docs**: Choose whether to generate Sphinx documentation (``1 - Yes``) + +Project Structure +----------------- + +After running cookiecutter, your project will have a structure similar to: + +.. code-block:: text + + my-awesome-software/ + ├── LICENSE + ├── MANIFEST.in + ├── README.md + ├── pyproject.toml + ├── tox.ini + ├── my_awesome_software/ + │ └── __init__.py + └── tests/ + ├── __init__.py + ├── test_integration/ + │ └── __init__.py + └── test_unit/ + ├── __init__.py + └── test_placeholder.py + +Initializing a Git Repository +----------------------------- + +Navigate to your project folder and initialize git: + +.. code-block:: bash + + cd my-awesome-software + git init -b main + +If you’re using an older Git version (<2.28), use: + +.. code-block:: bash + + git init + git checkout -b main + +Then, add and commit your changes: + +.. code-block:: bash + + git add . + git commit -m "Initial commit" + +Finally, add the remote origin and push to GitHub: + +.. code-block:: bash + + git remote add origin git@github.com:adamltyson/my-awesome-software.git + git push diff --git a/docs/source/versioning.rst b/docs/source/versioning.rst new file mode 100644 index 0000000..75e26b4 --- /dev/null +++ b/docs/source/versioning.rst @@ -0,0 +1,23 @@ +Versioning +========== + +We recommend following [Semantic Versioning](https://semver.org/) where versions follow a ``MAJOR.MINOR.PATCH`` scheme: + +- **PATCH**: Bug fixes. +- **MINOR**: New features. +- **MAJOR**: Breaking changes. + +Automated Versioning +-------------------- + +The project is configured to use ``setuptools_scm`` to automatically determine the version based on Git tags. +To release a new version, commit your changes and create a new tag. For example, to bump to version ``1.0.0``: + +.. code-block:: bash + + git add . + git commit -m "Add new changes" + git tag -a v1.0.0 -m "Bump to version 1.0.0" + git push --follow-tags + +You can also use the GitHub interface or CLI to create tags. From f882987e1627dcfd9af67d19bc621b61165d051f Mon Sep 17 00:00:00 2001 From: richarddushime Date: Mon, 3 Mar 2025 02:16:15 +0100 Subject: [PATCH 02/36] Github repos creation --- docs/source/project_setup.rst | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/docs/source/project_setup.rst b/docs/source/project_setup.rst index 8f768e3..7692a44 100644 --- a/docs/source/project_setup.rst +++ b/docs/source/project_setup.rst @@ -57,6 +57,30 @@ After running cookiecutter, your project will have a structure similar to: ├── __init__.py └── test_placeholder.py + +Creating a GitHub Repository +---------------------------- + +1. **Sign In to GitHub:** + Visit [GitHub](https://github.com) and sign in with your account. + +2. **Create a New Repository:** + - Click on the **+** icon in the upper-right corner of the page and select **"New repository"**. + - Alternatively, you can navigate directly to: + https://github.com/new + +3. **Fill in Repository Details:** + - **Repository Name:** Enter a name for your project (e.g., `my-awesome-software`). + - **Description:** Optionally, provide a short description of your project. + - **Repository Visibility:** Choose between **Public** or **Private**. + - **Initialize Repository:** + You may leave the repository empty (without a README, .gitignore, or license) if you plan to push your existing local project. If you prefer, you can initialize it with a README file. + *Note: If you initialize with a README, you will need to pull those changes before pushing your local repository.* + +4. **Create the Repository:** + Click the **"Create repository"** button. GitHub will then create your new repository and provide you with the repository URL (e.g., `https://github.com/yourusername/my-awesome-software.git`). + + Initializing a Git Repository ----------------------------- @@ -86,4 +110,4 @@ Finally, add the remote origin and push to GitHub: .. code-block:: bash git remote add origin git@github.com:adamltyson/my-awesome-software.git - git push + git push --set-upstream origin main From c20945b0d96ea401b12b5413e65f8a58285f04d6 Mon Sep 17 00:00:00 2001 From: richarddushime Date: Mon, 3 Mar 2025 22:56:31 +0100 Subject: [PATCH 03/36] Fix pre-commit issues --- .github/workflows/cookiecutter_docs.yml | 6 +-- docs/requirements.txt | 4 +- docs/source/_static/css/custom.css | 42 ++++++++++++++++-- docs/source/_templates/navbar.html | 56 +++++++++++++----------- docs/source/_templates/search-field.html | 11 +++++ docs/source/_templates/sidebar-nav.html | 2 +- docs/source/conf.py | 12 ++--- docs/source/contributing.rst | 40 ++++++++--------- docs/source/documentation.rst | 1 + docs/source/getting_started.rst | 35 +++++++++------ docs/source/index.rst | 14 +++--- docs/source/project_setup.rst | 29 +++++++----- 12 files changed, 158 insertions(+), 94 deletions(-) create mode 100644 docs/source/_templates/search-field.html diff --git a/.github/workflows/cookiecutter_docs.yml b/.github/workflows/cookiecutter_docs.yml index ac8b7ee..5784232 100644 --- a/.github/workflows/cookiecutter_docs.yml +++ b/.github/workflows/cookiecutter_docs.yml @@ -13,7 +13,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.x' + python-version: '3.13' - name: Install dependencies run: | @@ -22,10 +22,10 @@ jobs: - name: Build docs run: | cd docs - make html + make clean && make html - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/build/html \ No newline at end of file + publish_dir: ./docs/build/html diff --git a/docs/requirements.txt b/docs/requirements.txt index abcb530..59cc7cd 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,3 +1,3 @@ -sphinx +myst-parser pydata-sphinx-theme -myst-parser \ No newline at end of file +sphinx diff --git a/docs/source/_static/css/custom.css b/docs/source/_static/css/custom.css index f355b67..f6f3b85 100644 --- a/docs/source/_static/css/custom.css +++ b/docs/source/_static/css/custom.css @@ -4,7 +4,7 @@ justify-content: space-between; align-items: center; padding: 0.8rem 2rem; - background: #2B3A42; + background: transparent; } .navbar-brand { @@ -17,6 +17,7 @@ justify-content: center; gap: 2rem; margin: 0 2rem; + float: right; } .navbar-nav { @@ -45,15 +46,48 @@ flex-wrap: wrap; padding: 0.8rem; } - + .navbar-center-group { order: 2; width: 100%; margin: 1rem 0; justify-content: center; } - + .navbar-brand { order: 1; } -} \ No newline at end of file +} + +/* Search field positioning */ +.navbar-search { + margin-left: auto; + flex: 0 0 250px; +} +.bd-search { + display: flex; + gap: 1rem; + float: right; + position: relative; +} + +/* Search input styling */ +.bd-search .form-control { + background: rgba(255, 255, 255, 0.1) !important; + border: 1px solid rgba(255, 255, 255, 0.3) !important; + color: white !important; + padding: 0.5rem 1rem !important; +} + +.bd-search .btn { + color: rgba(255, 255, 255, 0.7) !important; +} + +/* Mobile responsiveness */ +@media (max-width: 768px) { + .navbar-search { + flex: 1 1 100%; + order: 3; + margin-top: 1rem; + } +} diff --git a/docs/source/_templates/navbar.html b/docs/source/_templates/navbar.html index 2517df1..66a5d46 100644 --- a/docs/source/_templates/navbar.html +++ b/docs/source/_templates/navbar.html @@ -1,30 +1,34 @@ \ No newline at end of file + + + diff --git a/docs/source/_templates/search-field.html b/docs/source/_templates/search-field.html new file mode 100644 index 0000000..aff2cc1 --- /dev/null +++ b/docs/source/_templates/search-field.html @@ -0,0 +1,11 @@ +{%- if pagename != "search" %} + +{%- endif %} diff --git a/docs/source/_templates/sidebar-nav.html b/docs/source/_templates/sidebar-nav.html index e9b6173..cfa575c 100644 --- a/docs/source/_templates/sidebar-nav.html +++ b/docs/source/_templates/sidebar-nav.html @@ -4,4 +4,4 @@ {{ toctree(maxdepth=2, includehidden=True, collapse=False) }} - \ No newline at end of file + diff --git a/docs/source/conf.py b/docs/source/conf.py index e7df00b..bbf3667 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -34,21 +34,23 @@ html_static_path = ["_static"] html_theme_options = { - # Disable right sidebar TOC - "show_toc_level": 0, + # Disable all default search locations + "navbar_end": [], + "navbar_persistent": [], # Configure navbar "navbar_start": [], - "navbar_center": ["navbar.html"], + "navbar_center": ["navbar.html"], "navbar_end": [], - # Disable default right sidebar + # Disable right sidebar and TOC + "show_toc_level": 0, "secondary_sidebar_items": [], # Keep other settings "show_nav_level": 2, "navigation_depth": 3, - "collapse_navigation": False, + "collapse_navigation": True, } html_sidebars = { diff --git a/docs/source/contributing.rst b/docs/source/contributing.rst index ddb75f0..7ad4e0f 100644 --- a/docs/source/contributing.rst +++ b/docs/source/contributing.rst @@ -1,53 +1,53 @@ Contributing to cookiecutter-python ===================================== -Thank you for considering contributing to cookiecutter-python! -We welcome contributions that improve the project, whether it’s code, documentation, or enhancements. +Thank you for considering contributing to cookiecutter-python! +We welcome contributions that improve the project, whether it’s code, documentation, or enhancements. Please follow the guidelines below to ensure a smooth process. Workflow -------- -1. **Fork and Clone the Repository** +1. **Fork and Clone the Repository** Fork the main repository on GitHub, then clone your fork locally: - + .. code-block:: bash git clone https://github.com//python-cookiecutter.git cd python-cookiecutter -2. **Create a New Branch** +2. **Create a New Branch** Create and switch to a new branch for your changes: - + .. code-block:: bash git checkout -b my_new_feature -3. **Make Your Changes** - Edit the website content, code, or documentation as needed. +3. **Make Your Changes** + Edit the website content, code, or documentation as needed. When you’re ready, add and commit your changes with a descriptive message: - + .. code-block:: bash git add . git commit -m "Describe your changes here" -4. **Push Your Branch and Create a Pull Request** +4. **Push Your Branch and Create a Pull Request** Push the new branch to GitHub: - + .. code-block:: bash git push origin --set-upstream origin my_new_feature - Then, open a pull request against the `main` branch of the main repository. + Then, open a pull request against the `main` branch of the main repository. This will automatically trigger a GitHub Action to verify that the website builds correctly. -5. **Review and Merge** - If the build checks pass, assign someone to review your pull request. +5. **Review and Merge** + If the build checks pass, assign someone to review your pull request. Once approved and merged into the `main` branch, another GitHub Action will build the website and publish it to the `gh-pages` branch. -6. **Deployment** - After merging, the updated website will be available at: +6. **Deployment** + After merging, the updated website will be available at: `python-cookiecutter.github.io` Local Testing @@ -55,9 +55,9 @@ Local Testing Before pushing your changes, you can test the website locally: -- **First-Time Setup:** +- **First-Time Setup:** Install the required dependencies and build the site: - + .. code-block:: bash pip install -r docs/requirements.txt @@ -71,9 +71,9 @@ Alternatively, you can use the following commands to install the dependencies an cd docs make html -- **Rebuilding the Site:** +- **Rebuilding the Site:** Each time you update the documentation, rebuild the site by running: - + .. code-block:: bash rm -rf docs/build && sphinx-build docs/source docs/build diff --git a/docs/source/documentation.rst b/docs/source/documentation.rst index ad0d230..8f7ade1 100644 --- a/docs/source/documentation.rst +++ b/docs/source/documentation.rst @@ -31,6 +31,7 @@ After updating your documentation, remove the build folder and rebuild: .. code-block:: bash rm -rf docs/build + sphinx-build docs/source docs/build Publishing the Documentation diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 36b87f7..5e32e84 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -1,25 +1,32 @@ Getting Started =============== -Overview --------- -A cookiecutter template that creates: +**python-cookiecutter** is a tool that helps you quickly set up a Python project with everything needed to publish it on GitHub and `PyPI `_. + +It automatically creates a structured project and sets up essential tools, including: + +- A blank ``README.md`` file for documentation. +- A ``LICENSE`` file to define usage rights. +- `Pre-commit hooks `_ to maintain code quality. +- Automatic versioning with `setuptools_scm `_. +- A test setup using `pytest `_. +- Automated formatting, testing, and publishing via `GitHub Actions `_. +- A documentation setup with `Sphinx `_. -* Pre-configured Python project structure -* GitHub Actions CI/CD pipeline -* Sphinx documentation setup -* Automated versioning -* Pre-commit hooks +This tool is based on `cookiecutter-napari-plugin `_ and provides a solid starting point for your projects. Features -------- + .. list-table:: :widths: 30 70 :header-rows: 0 - * - :octicon:`package` Project Setup - - Pre-configured pyproject.toml, LICENSE, tests - * - :octicon:`workflow` CI/CD - - GitHub Actions for testing and deployment - * - :octicon:`book` Documentation - - Sphinx with PyData theme + auto API generation \ No newline at end of file + * - :octicon:`package` **Project Setup** + - Pre-configured ``pyproject.toml``, ``LICENSE``, and test folder. + * - :octicon:`workflow` **CI/CD** + - Automated testing and deployment using GitHub Actions. + * - :octicon:`book` **Documentation** + - Sphinx setup with PyData theme and auto API generation. + +With this tool, you can start immediately without manually setting up everything! 🚀 diff --git a/docs/source/index.rst b/docs/source/index.rst index 4a8e63b..d254ebf 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,10 +1,10 @@ -Welcome to cookiecutter-python Documentation -============================================ - -A tool to automatically create a Python project structure ready to release via GitHub and PyPI. -It sets up a blank README, LICENSE, pre-commit hooks, automated versioning, tests with pytest, -GitHub Actions for CI/CD, and Sphinx documentation. +Cookiecutter Data Science +========================= +A logical, flexible, and reasonably standardized project structure for doing and sharing data science work. +Humble Opinion +-------------- +The default project structure reflects certain opinions about how to do collaborative data science work. These opinions grew out of our own experiences with what works and what doesn't. Some of these opinions are about workflows, and others are about tools that can make the process easier. .. toctree:: :maxdepth: 2 @@ -18,4 +18,4 @@ GitHub Actions for CI/CD, and Sphinx documentation. versioning github_actions_setup documentation - contributing \ No newline at end of file + contributing diff --git a/docs/source/project_setup.rst b/docs/source/project_setup.rst index 7692a44..5dcfb0e 100644 --- a/docs/source/project_setup.rst +++ b/docs/source/project_setup.rst @@ -1,5 +1,5 @@ -Setup -===== +Installation & Setup +==================== This section describes how to set up your project using cookiecutter. @@ -7,6 +7,7 @@ Installing Cookiecutter ----------------------- Install Cookiecutter using pip or conda: +>Note: you must have Python installed to use Cookiecutter .. code-block:: bash @@ -61,23 +62,22 @@ After running cookiecutter, your project will have a structure similar to: Creating a GitHub Repository ---------------------------- -1. **Sign In to GitHub:** +1. **Sign In to GitHub:** Visit [GitHub](https://github.com) and sign in with your account. -2. **Create a New Repository:** +2. **Create a New Repository:** - Click on the **+** icon in the upper-right corner of the page and select **"New repository"**. - - Alternatively, you can navigate directly to: - https://github.com/new + - Alternatively, you can navigate directly to: https://github.com/new -3. **Fill in Repository Details:** +3. **Fill in Repository Details:** - **Repository Name:** Enter a name for your project (e.g., `my-awesome-software`). - **Description:** Optionally, provide a short description of your project. - **Repository Visibility:** Choose between **Public** or **Private**. - - **Initialize Repository:** - You may leave the repository empty (without a README, .gitignore, or license) if you plan to push your existing local project. If you prefer, you can initialize it with a README file. - *Note: If you initialize with a README, you will need to pull those changes before pushing your local repository.* + - **Initialize Repository:** + You may leave the repository empty (without a README, .gitignore, or license) if you plan to push your existing local project. If you prefer, you can initialize it with a README file. + *Note: If you initialize with a README, you will need to pull those changes before pushing your local repository.* -4. **Create the Repository:** +4. **Create the Repository:** Click the **"Create repository"** button. GitHub will then create your new repository and provide you with the repository URL (e.g., `https://github.com/yourusername/my-awesome-software.git`). @@ -96,6 +96,7 @@ If you’re using an older Git version (<2.28), use: .. code-block:: bash git init + git checkout -b main Then, add and commit your changes: @@ -103,11 +104,15 @@ Then, add and commit your changes: .. code-block:: bash git add . + git commit -m "Initial commit" Finally, add the remote origin and push to GitHub: .. code-block:: bash - git remote add origin git@github.com:adamltyson/my-awesome-software.git + git remote add origin https://github.com//my-awesome-software.git + git push --set-upstream origin main + +That's it! Your project is now set up and ready to go. 🚀 From acecc889a9ee4a1bcda4fbd376775ac4d2276e75 Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Wed, 5 Mar 2025 13:36:53 +0100 Subject: [PATCH 04/36] title update Co-authored-by: Adam Tyson --- docs/source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index d254ebf..72d0e90 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,4 +1,4 @@ -Cookiecutter Data Science +Neuroinformatics Unit Python cookiecutter ========================= A logical, flexible, and reasonably standardized project structure for doing and sharing data science work. From 43f7a9cbfa9066d8262597bc515b3d0e97f13854 Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Wed, 5 Mar 2025 13:37:28 +0100 Subject: [PATCH 05/36] description Co-authored-by: Adam Tyson --- docs/source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index 72d0e90..fa28c9b 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,6 +1,6 @@ Neuroinformatics Unit Python cookiecutter ========================= -A logical, flexible, and reasonably standardized project structure for doing and sharing data science work. +A tool to automatically create a Python project structure ready to release via GitHub and [PyPI](https://pypi.org/). Humble Opinion -------------- From 5279ba8a39044a88675a118515e71202dd20d576 Mon Sep 17 00:00:00 2001 From: richarddushime Date: Wed, 5 Mar 2025 18:54:08 +0100 Subject: [PATCH 06/36] Fix Requested Changes --- .gitattributes | 1 + docs/source/_static/css/custom.css | 34 ----- docs/source/_static/favicon.ico | Bin 0 -> 4695 bytes docs/source/_templates/navbar.html | 22 +--- docs/source/_templates/search-field.html | 11 -- docs/source/conf.py | 72 ++++++++--- docs/source/contributing.md | 81 ++++++++++++ docs/source/contributing.rst | 90 ------------- docs/source/documentation.md | 38 ++++++ docs/source/documentation.rst | 48 ------- docs/source/getting_started.rst | 32 ----- docs/source/github_actions_setup.md | 8 ++ docs/source/github_actions_setup.rst | 10 -- docs/source/index.md | 53 ++++++++ docs/source/index.rst | 21 --- docs/source/modules.md | 74 +++++++++++ docs/source/modules.rst | 53 -------- docs/source/pre_commits.md | 37 ++++++ docs/source/pre_commits.rst | 60 --------- docs/source/project_setup.md | 157 +++++++++++++++++++++++ docs/source/project_setup.rst | 118 ----------------- docs/source/versioning.md | 18 +++ docs/source/versioning.rst | 23 ---- 23 files changed, 519 insertions(+), 542 deletions(-) create mode 100644 .gitattributes create mode 100644 docs/source/_static/favicon.ico delete mode 100644 docs/source/_templates/search-field.html create mode 100644 docs/source/contributing.md delete mode 100644 docs/source/contributing.rst create mode 100644 docs/source/documentation.md delete mode 100644 docs/source/documentation.rst delete mode 100644 docs/source/getting_started.rst create mode 100644 docs/source/github_actions_setup.md delete mode 100644 docs/source/github_actions_setup.rst create mode 100644 docs/source/index.md delete mode 100644 docs/source/index.rst create mode 100644 docs/source/modules.md delete mode 100644 docs/source/modules.rst create mode 100644 docs/source/pre_commits.md delete mode 100644 docs/source/pre_commits.rst create mode 100644 docs/source/project_setup.md delete mode 100644 docs/source/project_setup.rst create mode 100644 docs/source/versioning.md delete mode 100644 docs/source/versioning.rst diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/docs/source/_static/css/custom.css b/docs/source/_static/css/custom.css index f6f3b85..ed4067e 100644 --- a/docs/source/_static/css/custom.css +++ b/docs/source/_static/css/custom.css @@ -34,7 +34,6 @@ align-items: center; } -/* Rest of your existing styles remain */ .navbar-brand-logo img { height: 40px; } .nav-link { color: white !important; font-weight: 500; } .icon-link { color: white !important; font-size: 1.2rem; } @@ -58,36 +57,3 @@ order: 1; } } - -/* Search field positioning */ -.navbar-search { - margin-left: auto; - flex: 0 0 250px; -} -.bd-search { - display: flex; - gap: 1rem; - float: right; - position: relative; -} - -/* Search input styling */ -.bd-search .form-control { - background: rgba(255, 255, 255, 0.1) !important; - border: 1px solid rgba(255, 255, 255, 0.3) !important; - color: white !important; - padding: 0.5rem 1rem !important; -} - -.bd-search .btn { - color: rgba(255, 255, 255, 0.7) !important; -} - -/* Mobile responsiveness */ -@media (max-width: 768px) { - .navbar-search { - flex: 1 1 100%; - order: 3; - margin-top: 1rem; - } -} diff --git a/docs/source/_static/favicon.ico b/docs/source/_static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..324b1bcaf28d93b6f39ae57406120f2b42d515b5 GIT binary patch literal 4695 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 - - - - - diff --git a/docs/source/_templates/search-field.html b/docs/source/_templates/search-field.html deleted file mode 100644 index aff2cc1..0000000 --- a/docs/source/_templates/search-field.html +++ /dev/null @@ -1,11 +0,0 @@ -{%- if pagename != "search" %} - -{%- endif %} diff --git a/docs/source/conf.py b/docs/source/conf.py index bbf3667..4c037ff 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,61 +1,91 @@ # conf.py - -# -- Project information ----------------------------------------------------- +# Configuration file for the Sphinx documentation builder. project = 'cookiecutter-python' -author = 'Name' -release = '0.1.0' +copyright = "2025, Neuroinformatics Unit" +author = 'NIU' +release = "1.0.0" # -- General configuration --------------------------------------------------- extensions = [ "myst_parser", "sphinx_design", "sphinx.ext.autodoc", - "sphinx.ext.napoleon" + "sphinx.ext.napoleon", + "sphinx.ext.githubpages", + "sphinx_autodoc_typehints", + "sphinx.ext.autosummary", + "sphinx.ext.viewcode", + "sphinx.ext.intersphinx", + "sphinx_sitemap", + "nbsphinx", ] +# Configure MyST Parser myst_enable_extensions = [ "colon_fence", "deflist", + "fieldlist", + "html_admonition", + "html_image", "linkify", + "replacements", + "smartquotes", "substitution", "tasklist", + "attrs_inline" ] +myst_heading_anchors = 4 + source_suffix = { '.md': 'markdown', '.rst': 'restructuredtext' } templates_path = ['_templates'] +exclude_patterns = [ + "**.ipynb_checkpoints", + "**/includes/**", +] # -- HTML output options ----------------------------------------------------- html_theme = 'pydata_sphinx_theme' html_logo = "_static/logo.png" html_static_path = ["_static"] +html_title = "Python Cookiecutter" +html_favicon = "_static/favicon.ico" +html_show_sourcelink = False html_theme_options = { - # Disable all default search locations - "navbar_end": [], - "navbar_persistent": [], - - # Configure navbar - "navbar_start": [], - "navbar_center": ["navbar.html"], - "navbar_end": [], - - # Disable right sidebar and TOC - "show_toc_level": 0, - "secondary_sidebar_items": [], - - # Keep other settings + "navbar_start": ["navbar-logo"], + "navbar_center": ["navbar.html"], + "navbar_end": ["theme-switcher", "navbar-icon-links"], + "icon_links": [ + { + "name": "GitHub", + "url": "https://github.com/neuroinformatics-unit/python-cookiecutter", + "icon": "fa-brands fa-github", + "type": "fontawesome", + } + ], + "logo": { + "text": "Python Cookiecutter", + "image_light": "logo.png", + "image_dark": "logo.png", + }, "show_nav_level": 2, "navigation_depth": 3, "collapse_navigation": True, } +# Sitemap configuration +html_baseurl = "https://neuroinformatics-unit.github.io/python-cookiecutter/" +sitemap_url_scheme = "{link}" + + html_sidebars = { - "**": ["sidebar-nav.html", "search-field.html"] + "**": ["sidebar-nav.html"] } def setup(app): - app.add_css_file("css/custom.css") \ No newline at end of file + app.add_css_file("css/custom.css") diff --git a/docs/source/contributing.md b/docs/source/contributing.md new file mode 100644 index 0000000..fea616f --- /dev/null +++ b/docs/source/contributing.md @@ -0,0 +1,81 @@ +# Contributing to cookiecutter-python + +Thank you for considering contributing to cookiecutter-python! We welcome contributions that improve the project, whether it's code, +documentation, or enhancements. + +Please follow the guidelines below to ensure a smooth process. + +1. **Fork and Clone the Repository** Fork the main repository on + GitHub, then clone your fork locally: + + ``` sh + git clone https://github.com//python-cookiecutter.git + cd python-cookiecutter + ``` + +2. **Create a New Branch** Create and switch to a new branch for your + changes: + + ``` sh + git checkout -b my_new_feature + ``` + +3. **Make Your Changes** Edit the content, code, or + documentation as needed. When you're ready, add and commit your + changes with a descriptive message: + + ``` sh + git add . + git commit -m "Describe your changes in short here" + ``` + +4. **Push Your Branch and Create a Pull Request** Push the new branch + to GitHub: + + ``` sh + git push origin --set-upstream origin my_new_feature + ``` + + Then, open a pull request against the ``main`` branch of the main repository. This will automatically trigger a GitHub Action to verify that the builds correctly. + +5. **Review and Merge** If the build checks pass, assign someone to review your pull request. Once approved and merged into the ``main`` branch, another GitHub Action will build and add your changes to the ``main`` branch. + + +## Documentation Local Testing + +If you are contributing to the Documentation, Before pushing your changes, you can test locally: + +- **First-Time Setup:** Install the required dependencies and build + the docs: + + ``` sh + pip install -r docs/requirements.txt + sphinx-build docs/source docs/build + ``` + +Alternatively, you can use the following commands to install the +dependencies and build the docs: + + ``` sh +pip install -r docs/requirements.txt +cd docs +make html +``` + +- **Rebuilding:** Each time you update the documentation, + rebuild the docs by running: + + ``` sh + rm -rf docs/build && sphinx-build docs/source docs/build + ``` + or + + ```sh + cd docs + make clean && make html + ``` + + Then, open `docs/build/index.html` in your browser to preview the changes. + + +Thank you for your contributions! diff --git a/docs/source/contributing.rst b/docs/source/contributing.rst deleted file mode 100644 index 7ad4e0f..0000000 --- a/docs/source/contributing.rst +++ /dev/null @@ -1,90 +0,0 @@ -Contributing to cookiecutter-python -===================================== - -Thank you for considering contributing to cookiecutter-python! -We welcome contributions that improve the project, whether it’s code, documentation, or enhancements. -Please follow the guidelines below to ensure a smooth process. - -Workflow --------- - -1. **Fork and Clone the Repository** - Fork the main repository on GitHub, then clone your fork locally: - - .. code-block:: bash - - git clone https://github.com//python-cookiecutter.git - cd python-cookiecutter - -2. **Create a New Branch** - Create and switch to a new branch for your changes: - - .. code-block:: bash - - git checkout -b my_new_feature - -3. **Make Your Changes** - Edit the website content, code, or documentation as needed. - When you’re ready, add and commit your changes with a descriptive message: - - .. code-block:: bash - - git add . - git commit -m "Describe your changes here" - -4. **Push Your Branch and Create a Pull Request** - Push the new branch to GitHub: - - .. code-block:: bash - - git push origin --set-upstream origin my_new_feature - - Then, open a pull request against the `main` branch of the main repository. - This will automatically trigger a GitHub Action to verify that the website builds correctly. - -5. **Review and Merge** - If the build checks pass, assign someone to review your pull request. - Once approved and merged into the `main` branch, another GitHub Action will build the website and publish it to the `gh-pages` branch. - -6. **Deployment** - After merging, the updated website will be available at: - `python-cookiecutter.github.io` - -Local Testing -------------- - -Before pushing your changes, you can test the website locally: - -- **First-Time Setup:** - Install the required dependencies and build the site: - - .. code-block:: bash - - pip install -r docs/requirements.txt - sphinx-build docs/source docs/build - -Alternatively, you can use the following commands to install the dependencies and build the site: - - .. code-block:: bash - - pip install -r docs/requirements.txt - cd docs - make html - -- **Rebuilding the Site:** - Each time you update the documentation, rebuild the site by running: - - .. code-block:: bash - - rm -rf docs/build && sphinx-build docs/source docs/build - - Then, open ``docs/build/index.html`` in your browser to preview the changes. - -Additional Guidelines ---------------------- - -- **Coding Standards:** Ensure that your contributions follow the project's coding and documentation guidelines. -- **Commit Messages:** Write clear and concise commit messages. -- **Documentation:** If your changes affect the website or project behavior, please update the documentation accordingly. - -Thank you for your contributions! diff --git a/docs/source/documentation.md b/docs/source/documentation.md new file mode 100644 index 0000000..7eef932 --- /dev/null +++ b/docs/source/documentation.md @@ -0,0 +1,38 @@ +# Documentation + +Software documentation is important for effectively communicating how to use the software to others as well as to your future self. + +If you want to include documentation in your package, make sure to respond with `1 - Yes` when prompted during the `cookiecutter` setup. This will instantiate a `docs` folder with a skeleton documentation system, that you can build upon. + +The documentation source files are located in the `docs/source` folder and should be written in either [reStructuredText](https://docutils.sourceforge.io/rst.html) or [markdown](https://myst-parser.readthedocs.io/en/stable/syntax/typography.html). The `index.rst` file corresponds to the main page of the documentation website. Other `.rst` or `.md` files can be included in the main page via the `toctree` directive. + +The documentation is built using [Sphinx](https://www.sphinx-doc.org/en/master/) and the [PyData Sphinx Theme](https://pydata-sphinx-theme.readthedocs.io/en/latest/). The `docs/source/conf.py` file contains the `Sphinx` configuration. + +## Building the documentation locally +You can build and view the documentation website locally, on your machine. To do so, run the following commands from the root of your project: + +```sh +# Install the documentation build dependencies +pip install -r docs/requirements.txt +# Build the documentation +sphinx-build docs/source docs/build +``` +This should create a `docs/build` folder. You can view the local build by opening `docs/build/index.html` in a browser. +To refresh the documentation, after making changes, remove the `docs/build` folder and re-run the above command: + +```sh +rm -rf docs/build +sphinx-build docs/source docs/build +``` + +### Publishing the documentation +We have included an extra GitHub actions workflow in `.github/workflows/docs_build_and_deploy.yml` that will build the documentation and deploy it to [GitHub pages](https://pages.github.com/). +* The build step is triggered every time a pull request is opened or a push is made to the `main` branch. This way you can make sure that the documentation does not break before merging your changes. +* The deployment is triggered only when a tag is present (see [Automated versioning](versioning.md)). This ensures that new documentation versions are published in tandem with the release of a new package version on PyPI (see [GitHub actions workflow](github_actions_setup.md)). +* The published docs are by default hosted at `https://.github.io//`. To enable hosting, you will need to go to the settings of your repository, and under the "Pages" section, select the `gh-pages` branch as the source for your GitHub pages site. +* A popular alternative to GitHub pages for hosting the documentation is [Read the Docs](https://readthedocs.org/). To enable hosting on Read the Docs, you will need to create an account on the website and follow the instructions to link your GitHub repository to your Read the Docs account. + +### Docstrings and API documentation +The journey towards good documentation starts with writing docstrings for all functions in your module code. In the example `math.py` and `greetings.py` modules you will find some docstrings that you can use as a template. We have written the example docstrings following the [numpy style](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_numpy.html) but you may also choose another widely used style, such as the [Google style](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html). + +Once you have written docstrings for all your functions, API documentation can be automatically generated via the [Sphinx autodoc extension](https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html). We have given examples of how to do this in the `docs/source/api_index.rst` file. diff --git a/docs/source/documentation.rst b/docs/source/documentation.rst deleted file mode 100644 index 8f7ade1..0000000 --- a/docs/source/documentation.rst +++ /dev/null @@ -1,48 +0,0 @@ -Documentation -============= - -Good documentation is key for both users and developers. If you chose to create docs during cookiecutter setup, -a ``docs`` folder was generated with a basic Sphinx configuration. - -Building the Documentation Locally ----------------------------------- - -To build the docs locally: - -1. Install the build requirements: - - .. code-block:: bash - - pip install -r docs/requirements.txt - -2. Build the documentation: - - .. code-block:: bash - - sphinx-build docs/source docs/build - -Open ``docs/build/index.html`` in your browser to view the docs. - -Refreshing the Build --------------------- - -After updating your documentation, remove the build folder and rebuild: - -.. code-block:: bash - - rm -rf docs/build - - sphinx-build docs/source docs/build - -Publishing the Documentation ----------------------------- - -A separate GitHub Actions workflow (``.github/workflows/docs_build_and_deploy.yml``) builds and deploys -the documentation to GitHub Pages when changes are pushed to ``main`` or when a tag is created. - -Docstrings and API Documentation --------------------------------- - -Write clear docstrings for all functions in your code (e.g. using the NumPy or Google style). -Sphinx’s ``autodoc`` extension automatically generates API documentation from these docstrings. -For an example setup, see the ``docs/source/api_index.rst`` file. diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst deleted file mode 100644 index 5e32e84..0000000 --- a/docs/source/getting_started.rst +++ /dev/null @@ -1,32 +0,0 @@ -Getting Started -=============== - -**python-cookiecutter** is a tool that helps you quickly set up a Python project with everything needed to publish it on GitHub and `PyPI `_. - -It automatically creates a structured project and sets up essential tools, including: - -- A blank ``README.md`` file for documentation. -- A ``LICENSE`` file to define usage rights. -- `Pre-commit hooks `_ to maintain code quality. -- Automatic versioning with `setuptools_scm `_. -- A test setup using `pytest `_. -- Automated formatting, testing, and publishing via `GitHub Actions `_. -- A documentation setup with `Sphinx `_. - -This tool is based on `cookiecutter-napari-plugin `_ and provides a solid starting point for your projects. - -Features --------- - -.. list-table:: - :widths: 30 70 - :header-rows: 0 - - * - :octicon:`package` **Project Setup** - - Pre-configured ``pyproject.toml``, ``LICENSE``, and test folder. - * - :octicon:`workflow` **CI/CD** - - Automated testing and deployment using GitHub Actions. - * - :octicon:`book` **Documentation** - - Sphinx setup with PyData theme and auto API generation. - -With this tool, you can start immediately without manually setting up everything! 🚀 diff --git a/docs/source/github_actions_setup.md b/docs/source/github_actions_setup.md new file mode 100644 index 0000000..64a3ffb --- /dev/null +++ b/docs/source/github_actions_setup.md @@ -0,0 +1,8 @@ +# GitHub actions workflow + +A GitHub actions workflow (`.github/workflows/test_and_deploy.yml`) has been set up to run (on each commit/PR): +* Linting checks (pre-commit). +* Testing (only if linting checks pass) +* Release to PyPI (only if a git tag is present and if tests pass). Requires `TWINE_API_KEY` from PyPI to be set in repository secrets. + +This automation ensures that each commit or pull request is validated and that releases are published only when all checks pass. diff --git a/docs/source/github_actions_setup.rst b/docs/source/github_actions_setup.rst deleted file mode 100644 index cce7075..0000000 --- a/docs/source/github_actions_setup.rst +++ /dev/null @@ -1,10 +0,0 @@ -GitHub Actions Workflow -======================= - -A GitHub Actions workflow (located at ``.github/workflows/test_and_deploy.yml``) is configured to run: - -- **Linting checks** via pre-commit. -- **Testing** if linting passes. -- **Deployment to PyPI** if a Git tag is present and tests pass (requires the ``TWINE_API_KEY`` in repository secrets). - -This automation ensures that each commit or pull request is validated and that releases are published only when all checks pass. diff --git a/docs/source/index.md b/docs/source/index.md new file mode 100644 index 0000000..6beb41f --- /dev/null +++ b/docs/source/index.md @@ -0,0 +1,53 @@ +# Neuroinformatics Unit Python cookiecutter + +The Neuroinformatics Unit (NIU) is a **Research Software Engineering** team based at the **Sainsbury Wellcome Centre** and the **Gatsby Computational Neuroscience Unit**. + +The NIU is dedicated to the development of high quality, accurate, robust, easy to use and maintainable open-source software for neuroscience and machine learning. We collaborate with researchers and other software engineers to advance research in the two research centres and make new algorithms and tools available to the global community,[Read more](https://neuroinformatics.dev/index.html). + +## Python cookiecutter + +A tool to automatically create a Python project structure ready to +release via GitHub and [PyPI](https://pypi.org/). + +### Getting Started + +**Python-cookiecutter** is a tool that helps you quickly set up a Python +project with everything needed to publish it in a very easy steps on GitHub and +[PyPI](https://pypi.org/). + +It automatically creates a structured project and sets up essential +tools, including: + +- A blank `README.md` file for documentation. +- A `LICENSE` file to define usage rights. +- [Pre-commit hooks](https://pre-commit.com/) to maintain code + quality. +- Automatic versioning with + [setuptools_scm](https://setuptools-scm.readthedocs.io/en/latest/). +- A test setup using [pytest](https://docs.pytest.org/en/7.0.x/). +- Automated formatting, testing, and publishing via [GitHub + Actions](https://github.com/features/actions). +- A documentation setup with + [Sphinx](https://www.sphinx-doc.org/en/master/). + +This tool is based on +[cookiecutter-napari-plugin](https://github.com/napari/napari-plugin-template) +and provides a solid starting point for your projects. + +>With this tool, you can start immediately without manually setting up +everything! + + +```{toctree} +:maxdepth: 2 +:caption: Documentation +:hidden: + +project_setup +modules +github_actions_setup +pre_commits +versioning +documentation +contributing +``` diff --git a/docs/source/index.rst b/docs/source/index.rst deleted file mode 100644 index fa28c9b..0000000 --- a/docs/source/index.rst +++ /dev/null @@ -1,21 +0,0 @@ -Neuroinformatics Unit Python cookiecutter -========================= -A tool to automatically create a Python project structure ready to release via GitHub and [PyPI](https://pypi.org/). - -Humble Opinion --------------- -The default project structure reflects certain opinions about how to do collaborative data science work. These opinions grew out of our own experiences with what works and what doesn't. Some of these opinions are about workflows, and others are about tools that can make the process easier. - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - :hidden: - - getting_started - project_setup - modules - pre_commits - versioning - github_actions_setup - documentation - contributing diff --git a/docs/source/modules.md b/docs/source/modules.md new file mode 100644 index 0000000..8297588 --- /dev/null +++ b/docs/source/modules.md @@ -0,0 +1,74 @@ +# Add your modules and tests + +Your methods and classes would live inside the folder `my_awesome_software`. Split the functionalities into modules, and save them as `.py` files, e.g.: +``` +my_awesome_software + ├── __init__.py + ├── greetings.py + └── math.py +``` + +If you want to import methods and classes from one module to another you can use the dot: +```python +# filename: greetings.py +from .math import subtract_two_integers +``` + +If you want to import all the modules when installing you can add the following to your `__init__.py`: +```python +from . import * +``` + +## Add dependencies +To ensure any dependencies are installed at the same time as installing +your package, add them to your `pyproject.toml` file. E.g. to add `numpy` +and `pandas` as dependencies, add them to the `dependencies = []` list under +the `[project]` heading: + +```toml +dependencies = ["numpy", "pandas"] +``` + +### Write tests + +Write your test methods and classes in the `test` folder. We are using [pytest](https://docs.pytest.org/en/7.2.x/getting-started.html). +In your test module you can call your methods in a simple way: +```python +# filename: test_math.py +from my_awesome_software import math + +# here your test function +``` + +If you're testing a small piece of code, make it a unit test. If you want to test whether two or more software units work well together, create an integration test. + +>**Before committing your changes** + +### Run the tests + +Be sure that you have installed pytest and run it +```bash +pip install pytest +pytest +``` +You should also see coverage information. + +### Install your package locally + +For a local, editable install, in the project directory, run: +```bash +pip install -e . +``` + +For a local, editable install with all the development tools (e.g. testing, formatting etc.) run: +```bash +pip install -e '.[dev]' +``` + +You might want to install your package in an _ad hoc_ environment. + +To test if the installation works, try to call your modules with python in another folder from the same environment. +```python +from my_awesome_sofware.math import add_two_integers +add_two_integers(1, 2) +``` diff --git a/docs/source/modules.rst b/docs/source/modules.rst deleted file mode 100644 index f9df5b0..0000000 --- a/docs/source/modules.rst +++ /dev/null @@ -1,53 +0,0 @@ -Modules and Tests -================= - -Your Python code should live in the ``my_awesome_software`` package. -You can organize your code into multiple modules and write tests to ensure everything works as expected. - -Adding Modules --------------- - -Create your Python modules as separate ``.py`` files. For example: - -.. code-block:: text - - my_awesome_software/ - ├── __init__.py - ├── greetings.py - └── math.py - -To import functions between modules, use relative imports: - -.. code-block:: python - - # Inside greetings.py - from .math import subtract_two_integers - -If you want to import all modules when installing, add the following in ``__init__.py``: - -.. code-block:: python - - from . import * - -Adding Dependencies -------------------- - -To include dependencies (e.g. ``numpy``, ``pandas``), list them in the ``pyproject.toml`` file: - -.. code-block:: toml - - [project] - dependencies = ["numpy", "pandas"] - -Writing Tests -------------- - -Place your tests in the ``tests`` directory. Use pytest to write unit tests and integration tests. -For example, a unit test in ``tests/test_unit/test_math.py`` might look like: - -.. code-block:: python - - from my_awesome_software import math - - def test_add_two_integers(): - assert math.add_two_integers(1, 2) == 3 diff --git a/docs/source/pre_commits.md b/docs/source/pre_commits.md new file mode 100644 index 0000000..84e4caf --- /dev/null +++ b/docs/source/pre_commits.md @@ -0,0 +1,37 @@ +# Pre-commit hooks + +Running `pre-commit install` will set up [pre-commit hooks](https://pre-commit.com/) to ensure the code is +formatted correctly. Currently, these are: +* [ruff](https://github.com/charliermarsh/ruff) does a number of jobs, including linting, auto-formatting code (with `ruff-format`), and sorting import statements. +* [mypy](https://mypy.readthedocs.io/en/stable/index.html) a static type checker +* [check-manifest](https://github.com/mgedmin/check-manifest) to ensure that the right files are included in the pip package. +* [codespell](https://github.com/codespell-project/codespell) to check for common misspellings. + + +These will prevent code from being committed if any of these hooks fail. To run them individually: +```sh +ruff check --fix # Lint all files in the current directory, and fix any fixable errors. +ruff format # Format all files in the current directory. +mypy -p my_awesome_software +check-manifest +codespell +``` + +You can also execute all the hooks using +```sh +pre-commit run +``` +or +```sh +pre-commit run --all-files +``` + + The best time to run this is after you have staged your changes, but before you commit them. + +In the case you see `mypy` failing with an error like `Library stubs not installed for this-package`, you do have to edit the `.pre-commit-config.yaml` file by adding the additional dependency to `mypy`: +``` sh +- id: mypy + additional_dependencies: + - types-setuptools + - types-this-package +``` diff --git a/docs/source/pre_commits.rst b/docs/source/pre_commits.rst deleted file mode 100644 index 45747dc..0000000 --- a/docs/source/pre_commits.rst +++ /dev/null @@ -1,60 +0,0 @@ -Before Committing Your Changes -============================== - -Ensure that your code passes all tests and follows formatting standards before committing. - -Running the Tests ------------------ - -Install pytest if needed and run the tests: - -.. code-block:: bash - - pip install pytest - pytest - -Local Installation ------------------- - -For a local, editable install run: - -.. code-block:: bash - - pip install -e . - -For development (with additional tools): - -.. code-block:: bash - - pip install -e '.[dev]' - -Testing the Installation ------------------------- - -Test that your modules work from another folder: - -.. code-block:: python - - from my_awesome_software.math import add_two_integers - add_two_integers(1, 2) - -Pre-commit Hooks ----------------- - -Setting up pre-commit hooks ensures consistent code quality. Install them by running: - -.. code-block:: bash - - pre-commit install - -The hooks include: -- **ruff**: For linting, formatting, and import sorting. -- **mypy**: For static type checking. -- **check-manifest**: To verify the correct files are packaged. -- **codespell**: To catch common misspellings. - -To run all hooks before committing, use: - -.. code-block:: bash - - pre-commit run diff --git a/docs/source/project_setup.md b/docs/source/project_setup.md new file mode 100644 index 0000000..f6cd3ad --- /dev/null +++ b/docs/source/project_setup.md @@ -0,0 +1,157 @@ +# Installation & Setup + +This section describes how to set up your project using cookiecutter. + +## Installing Cookiecutter + +First, install cookiecutter in your desired environment. Running in the terminal in your environment: +>Note: you must have Python installed to use Cookiecutter + +using pip or conda: + +``` sh +pip install cookiecutter +# or with conda: +conda install -c conda-forge cookiecutter +``` + +### Creating a Cookiecutter Project + +In the folder or directory, you want to create the project: +>You can use ``cd folder_name or directory`` to change directories + +Then Run the following command: + +``` +cookiecutter https://github.com/neuroinformatics-unit/python-cookiecutter +``` + +You will be then asked a series of questions about how you want to set up your project. + +For each one, type your answer, enter a single number (or just hit return) to choose from a default option. + +such as: + + +* `full_name [Python developer]:` - e.g. `Adam Tyson` +* `email [yourname@example.com]:` - e.g. `cookiecutter@adamltyson.com` +* `github_username_or_organization [githubuser]:` - e.g. `adamltyson` +* `package_name [python-package]:` - e.g. `my-awesome-software` +* `Select github_repository_url:` - Default will be e.g. `https://github.com//my-awesome-software`, but you can also provide this later. +* `module_name [my_awesome_software]:` - The default will be the same as `package_name` but with hyphens converted to underscores. +* `short_description [A simple Python package]:` - Enter a simple, one-line description of your Python package. +* `Select license:` - choose from: + - `1 - BSD-3` + - `2 - MIT` + - `3 - Mozilla Public License 2.0` + - `4 - Apache Software License 2.0` + - `5 - GNU LGPL v3.0` + - `6 - GNU GPL v3.0` +* `Select create_docs:` - Whether to generate documentation using [Sphinx](https://www.sphinx-doc.org/en/master/), choose from: + - `1 - Yes` + - `2 - No` + +This is the structure cookiecutter will create: +``` +└── my-awesome-software/ + ├── LICENSE + ├── MANIFEST.in + ├── README.md + ├── pyproject.toml + ├── tox.ini + ├── my_awesome_software/ + │ └── __init__.py + └── tests/ + ├── __init__.py + ├── test_integration/ + │ └── __init__.py + └── test_unit/ + ├── __init__.py + └── test_placeholder.py +``` + +A project with this information will then be written to the current working directory. + +If you respond positively to `Select create_docs:`, an additional `docs` folder will be created and two example Python modules (`math.py` and `greetings.py`) will be added to the above structure. + +``` +└── my-awesome-software/ + └── docs/ + ├── make.bat + ├── Makefile + ├── requirements.txt + └── source/ + ├── api_index.rst + ├── conf.py + ├── getting_started.md + └── index.rst + └── my_awesome_software/ + ├── __init__.py + ├── greetings.py + └── math.py +``` + +### Creating a GitHub Repository + +1. **Sign In to GitHub:** Visit [GitHub](https://github.com) and sign in with your account. +>If you do not have an account create one + +2. **Create a New Repository:** + + - Click on the **+** icon in the upper-right corner of the page and select **New repository**. + - Alternatively, you can navigate directly to: [New Repository](https://github.com/new) + +3. **Fill in Repository Details:** + + - **Repository Name:** Enter a name for your project (e.g: ``my-awesome-software``). + - **Description:** Optionally, provide a short description of your project. + - **Repository Visibility:** Choose between **Public** or **Private**. + + - **Initialize Repository:** You may leave the repository empty (without a README, .gitignore, or license) if you plan to push your existing local project. If you prefer, you can initialize it with a README file. + + >***Note:*** If you initialize with a README, you will need to pull those changes before pushing your local repository. + +4. **Create the Repository:** Click the **Create repository** button. GitHub will then create your new repository and provide you + with the repository URL (e.g.``https://github.com/your-username/my-awesome-software.git``). + +### Initializing a Git Repository + +Although While creating a Cookiecutter Projects, it asks for a GitHub username or organization and package name, it does not initialize a git repository. + +Navigate to your project folder and initialize git: + +```sh +cd my-awesome-software +``` +```sh +git init -b main +``` + +If you're using an older Git version (``<2.28``), use: + +```sh +git init +``` +```sh +git checkout -b main +``` + +Then, add and commit your changes: + +```sh +git add . +``` +```sh +git commit -m "Initial commit" +``` + +Finally, add the remote origin and push to GitHub: + +```sh +git remote add origin https://github.com//my-awesome-software.git +``` +```sh +git push --set-upstream origin main +``` + +That\'s it! Your project is now set up and ready to go. 🚀 diff --git a/docs/source/project_setup.rst b/docs/source/project_setup.rst deleted file mode 100644 index 5dcfb0e..0000000 --- a/docs/source/project_setup.rst +++ /dev/null @@ -1,118 +0,0 @@ -Installation & Setup -==================== - -This section describes how to set up your project using cookiecutter. - -Installing Cookiecutter ------------------------ - -Install Cookiecutter using pip or conda: ->Note: you must have Python installed to use Cookiecutter - -.. code-block:: bash - - pip install cookiecutter - # or with conda: - conda install -c conda-forge cookiecutter - -Creating a Cookiecutter Project -------------------------------- - -Run the following command in your target folder: - -.. code-block:: bash - - cookiecutter https://github.com/neuroinformatics-unit/python-cookiecutter - -You'll be prompted for several configuration options, such as: - -- **full_name**: e.g. ``Adam Tyson`` -- **email**: e.g. ``cookiecutter@adamltyson.com`` -- **github_username_or_organization**: e.g. ``adamltyson`` -- **package_name**: e.g. ``my-awesome-software`` -- **module_name**: (auto-generated from package_name) -- **short_description**: A brief description of your package -- **license**: Choose from BSD-3, MIT, MPL 2.0, Apache 2.0, GNU LGPL, or GNU GPL -- **create_docs**: Choose whether to generate Sphinx documentation (``1 - Yes``) - -Project Structure ------------------ - -After running cookiecutter, your project will have a structure similar to: - -.. code-block:: text - - my-awesome-software/ - ├── LICENSE - ├── MANIFEST.in - ├── README.md - ├── pyproject.toml - ├── tox.ini - ├── my_awesome_software/ - │ └── __init__.py - └── tests/ - ├── __init__.py - ├── test_integration/ - │ └── __init__.py - └── test_unit/ - ├── __init__.py - └── test_placeholder.py - - -Creating a GitHub Repository ----------------------------- - -1. **Sign In to GitHub:** - Visit [GitHub](https://github.com) and sign in with your account. - -2. **Create a New Repository:** - - Click on the **+** icon in the upper-right corner of the page and select **"New repository"**. - - Alternatively, you can navigate directly to: https://github.com/new - -3. **Fill in Repository Details:** - - **Repository Name:** Enter a name for your project (e.g., `my-awesome-software`). - - **Description:** Optionally, provide a short description of your project. - - **Repository Visibility:** Choose between **Public** or **Private**. - - **Initialize Repository:** - You may leave the repository empty (without a README, .gitignore, or license) if you plan to push your existing local project. If you prefer, you can initialize it with a README file. - *Note: If you initialize with a README, you will need to pull those changes before pushing your local repository.* - -4. **Create the Repository:** - Click the **"Create repository"** button. GitHub will then create your new repository and provide you with the repository URL (e.g., `https://github.com/yourusername/my-awesome-software.git`). - - -Initializing a Git Repository ------------------------------ - -Navigate to your project folder and initialize git: - -.. code-block:: bash - - cd my-awesome-software - git init -b main - -If you’re using an older Git version (<2.28), use: - -.. code-block:: bash - - git init - - git checkout -b main - -Then, add and commit your changes: - -.. code-block:: bash - - git add . - - git commit -m "Initial commit" - -Finally, add the remote origin and push to GitHub: - -.. code-block:: bash - - git remote add origin https://github.com//my-awesome-software.git - - git push --set-upstream origin main - -That's it! Your project is now set up and ready to go. 🚀 diff --git a/docs/source/versioning.md b/docs/source/versioning.md new file mode 100644 index 0000000..c77ccf3 --- /dev/null +++ b/docs/source/versioning.md @@ -0,0 +1,18 @@ +# Versioning +We recommend the use of [semantic versioning](https://semver.org/), which uses a `MAJOR`.`MINOR`.`PATCH` versiong number where these mean: + +* PATCH = small bugfix +* MINOR = new feature +* MAJOR = breaking change + +## Automated versioning +[`setuptools_scm`](https://github.com/pypa/setuptools_scm) can be used to automatically version your package. It has been pre-configured in the `pyproject.toml` file. [`setuptools_scm` will automatically infer the version using git](https://github.com/pypa/setuptools_scm#default-versioning-scheme). To manually set a new semantic version, create a tag and make sure the tag is pushed to GitHub. Make sure you commit any changes you wish to be included in this version. E.g. to bump the version to `1.0.0`: + +```sh +git add . +git commit -m "Add new changes" +git tag -a v1.0.0 -m "Bump to version 1.0.0" +git push --follow-tags +``` + +**N.B. It is also possible to perform this step by using the [GitHub web interface or CLI](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository).** diff --git a/docs/source/versioning.rst b/docs/source/versioning.rst deleted file mode 100644 index 75e26b4..0000000 --- a/docs/source/versioning.rst +++ /dev/null @@ -1,23 +0,0 @@ -Versioning -========== - -We recommend following [Semantic Versioning](https://semver.org/) where versions follow a ``MAJOR.MINOR.PATCH`` scheme: - -- **PATCH**: Bug fixes. -- **MINOR**: New features. -- **MAJOR**: Breaking changes. - -Automated Versioning --------------------- - -The project is configured to use ``setuptools_scm`` to automatically determine the version based on Git tags. -To release a new version, commit your changes and create a new tag. For example, to bump to version ``1.0.0``: - -.. code-block:: bash - - git add . - git commit -m "Add new changes" - git tag -a v1.0.0 -m "Bump to version 1.0.0" - git push --follow-tags - -You can also use the GitHub interface or CLI to create tags. From b82c0a070cab5d699eae993721972b7c9dbf0b86 Mon Sep 17 00:00:00 2001 From: richarddushime Date: Thu, 6 Mar 2025 21:59:26 +0100 Subject: [PATCH 07/36] improved layout --- docs/source/_static/css/custom.css | 140 ++++++++++++------ .../_static/{logo.png => dark-logo-niu.png} | Bin docs/source/_static/light-logo-niu.png | Bin 0 -> 4699 bytes docs/source/_templates/footer_end.html | 6 + docs/source/_templates/footer_start.html | 9 ++ docs/source/_templates/navbar.html | 1 - docs/source/conf.py | 53 +++++-- docs/source/contributing.md | 7 +- docs/source/get_started.md | 25 ++++ docs/source/index.md | 85 +++++++---- docs/source/project_setup.md | 44 ++++-- 11 files changed, 271 insertions(+), 99 deletions(-) rename docs/source/_static/{logo.png => dark-logo-niu.png} (100%) create mode 100644 docs/source/_static/light-logo-niu.png create mode 100644 docs/source/_templates/footer_end.html create mode 100644 docs/source/_templates/footer_start.html create mode 100644 docs/source/get_started.md diff --git a/docs/source/_static/css/custom.css b/docs/source/_static/css/custom.css index ed4067e..278ecbc 100644 --- a/docs/source/_static/css/custom.css +++ b/docs/source/_static/css/custom.css @@ -1,59 +1,109 @@ -/* Top navbar */ -.navbar { - display: flex; - justify-content: space-between; - align-items: center; - padding: 0.8rem 2rem; - background: transparent; +html[data-theme=dark] { + --pst-color-primary: #04B46D; + --pst-color-link: var(--pst-color-primary); + } + +html[data-theme=light] { + --pst-color-primary: #03A062; + --pst-color-link: var(--pst-color-primary); +} + +body .bd-article-container { +max-width: 100em !important; +} + +.col { +flex: 0 0 50%; +max-width: 50%; +} + +.img-sponsor { +height: 50px; +padding-top: 5px; +padding-right: 5px; +padding-bottom: 5px; +padding-left: 5px; +} + +.things-in-a-row { +display: flex; +flex-wrap: wrap; +justify-content: space-between; +} + +/* grids to match theme colors */ +.sd-card-icon { + color: var(--sd-color-primary); + font-size: 1.5em; + margin-bottom: 0.5rem; +} + +.sd-card { + padding: 1.5rem; + transition: transform 0.2s; +} + +.sd-card:hover { + transform: translateY(-5px); +} + +/* Ensuring content area uses full width when sidebar is hidden */ +.bd-page-width { + max-width: 90% !important; +} + +/* Hide sidebar on pages with hide-sidebar metadata */ +body[data-hide-sidebar="true"] .bd-sidebar-primary { + display: none !important; +} + +/* Expand content width when sidebar hidden */ +body[data-hide-sidebar="true"] .bd-main { + flex-grow: 1; + max-width: 75%; } -.navbar-brand { - flex: 0 0 auto; +/* Center the navbar content */ +.bd-navbar.navbar { + display: flex; + justify-content: center; } .navbar-center-group { - flex: 1; - display: flex; - justify-content: center; - gap: 2rem; - margin: 0 2rem; - float: right; + display: flex; + margin-left: auto; + margin-right: auto; } -.navbar-nav { - display: flex; - gap: 1.5rem; - margin: 0; - padding: 0; - align-items: center; +.navbar-center-group .navbar-nav { + display: flex; + gap: 2rem; + padding-left: 0; + margin-bottom: 0; + list-style: none; } -.navbar-icons { - display: flex; - gap: 1.5rem; - align-items: center; +.navbar-center-group .nav-link { + padding: 0.5rem 1rem; + color: var(--pst-color-primary); + font-weight: 500; + transition: all 0.2s ease; } -.navbar-brand-logo img { height: 40px; } -.nav-link { color: white !important; font-weight: 500; } -.icon-link { color: white !important; font-size: 1.2rem; } -.bd-sidebar-secondary { display: none !important; } +.navbar-center-group .nav-link:hover { + color: var(--pst-color-active-navigation); + text-decoration: underline; +} + +/* Optional: Remove default navbar padding */ +.bd-header .bd-navbar { + padding: 1rem 0; +} -/* Mobile responsiveness */ @media (max-width: 768px) { - .navbar { - flex-wrap: wrap; - padding: 0.8rem; - } - - .navbar-center-group { - order: 2; - width: 100%; - margin: 1rem 0; - justify-content: center; - } - - .navbar-brand { - order: 1; - } + .navbar-center-group .navbar-nav { + flex-direction: column; + gap: 1rem; + text-align: center; + } } diff --git a/docs/source/_static/logo.png b/docs/source/_static/dark-logo-niu.png similarity index 100% rename from docs/source/_static/logo.png rename to docs/source/_static/dark-logo-niu.png diff --git a/docs/source/_static/light-logo-niu.png b/docs/source/_static/light-logo-niu.png new file mode 100644 index 0000000000000000000000000000000000000000..efba94043d36525417700f77ed519fbf5cc708fd GIT binary patch literal 4699 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 literal 0 HcmV?d00001 diff --git a/docs/source/_templates/footer_end.html b/docs/source/_templates/footer_end.html new file mode 100644 index 0000000..b012a8f --- /dev/null +++ b/docs/source/_templates/footer_end.html @@ -0,0 +1,6 @@ + diff --git a/docs/source/_templates/footer_start.html b/docs/source/_templates/footer_start.html new file mode 100644 index 0000000..e078fd3 --- /dev/null +++ b/docs/source/_templates/footer_start.html @@ -0,0 +1,9 @@ +

+ {% trans sphinx_version=sphinx_version|e %}Created using Sphinx {{ sphinx_version }}.{% endtrans %} +
+

+

+ {{ _("Built with the") }} + PyData Sphinx Theme + {{ theme_version }}. +

diff --git a/docs/source/_templates/navbar.html b/docs/source/_templates/navbar.html index e282767..02f5aff 100644 --- a/docs/source/_templates/navbar.html +++ b/docs/source/_templates/navbar.html @@ -10,5 +10,4 @@ - diff --git a/docs/source/conf.py b/docs/source/conf.py index 4c037ff..ecb1873 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,7 +1,6 @@ # conf.py # Configuration file for the Sphinx documentation builder. -project = 'cookiecutter-python' -copyright = "2025, Neuroinformatics Unit" +project = 'python cookiecutter' author = 'NIU' release = "1.0.0" @@ -50,42 +49,70 @@ # -- HTML output options ----------------------------------------------------- html_theme = 'pydata_sphinx_theme' -html_logo = "_static/logo.png" +html_logo = "_static/dark-logo-niu.png" html_static_path = ["_static"] html_title = "Python Cookiecutter" html_favicon = "_static/favicon.ico" -html_show_sourcelink = False + html_theme_options = { "navbar_start": ["navbar-logo"], "navbar_center": ["navbar.html"], - "navbar_end": ["theme-switcher", "navbar-icon-links"], "icon_links": [ { "name": "GitHub", "url": "https://github.com/neuroinformatics-unit/python-cookiecutter", "icon": "fa-brands fa-github", "type": "fontawesome", - } + }, + { + "name": "Zulip (chat)", + "url": "https://neuroinformatics.zulipchat.com/#narrow/channel/406003-Python-cookiecutter", + "icon": "fa-solid fa-comments", + "type": "fontawesome", + }, ], "logo": { - "text": "Python Cookiecutter", - "image_light": "logo.png", - "image_dark": "logo.png", + "text": f"{project}", }, - "show_nav_level": 2, - "navigation_depth": 3, - "collapse_navigation": True, + "footer_start": ["footer_start"], + "footer_end": ["footer_end"], + "external_links": [], } # Sitemap configuration +github_user = "neuroinformatics-unit" html_baseurl = "https://neuroinformatics-unit.github.io/python-cookiecutter/" sitemap_url_scheme = "{link}" +# -- HTML sidebar configuration --------------------------------------------- html_sidebars = { - "**": ["sidebar-nav.html"] + # Apply sidebar to ALL pages except index + "**": ["sidebar-nav.html"], + "index": [] } +html_show_sourcelink = False + def setup(app): app.add_css_file("css/custom.css") + + +# What to show on the 404 page +notfound_context = { + "title": "Page Not Found", + "body": """ +

Page Not Found

+ +

Sorry, we couldn't find that page.

+ +

We occasionally restructure the cookiercutter website, and some links may have broken.

+ +

Try using the search box or go to the homepage.

+""", +} + +# needed for GH pages (vs readthedocs), +# because we have no '///' in the URL +notfound_urls_prefix = None diff --git a/docs/source/contributing.md b/docs/source/contributing.md index fea616f..1025183 100644 --- a/docs/source/contributing.md +++ b/docs/source/contributing.md @@ -3,6 +3,10 @@ Thank you for considering contributing to cookiecutter-python! We welcome contributions that improve the project, whether it's code, documentation, or enhancements. +:::{note} +You can Join the [Zulip Channel](https://neuroinformatics.zulipchat.com/#narrow/channel/406003-Python-cookiecutter) here. +::: + Please follow the guidelines below to ensure a smooth process. 1. **Fork and Clone the Repository** Fork the main repository on @@ -77,5 +81,6 @@ make html Then, open `docs/build/index.html` in your browser to preview the changes. - +:::{important} Thank you for your contributions! +::: diff --git a/docs/source/get_started.md b/docs/source/get_started.md new file mode 100644 index 0000000..1a584bc --- /dev/null +++ b/docs/source/get_started.md @@ -0,0 +1,25 @@ + +# Getting Started + +**Python-cookiecutter** is a tool that helps you quickly set up a Python +project with everything needed to publish it in a very easy steps on GitHub and +[PyPI](https://pypi.org/). + +It automatically creates a structured project and sets up essential +tools, including: + +- A blank `README.md` file for documentation. +- A `LICENSE` file to define usage rights. +- [Pre-commit hooks](https://pre-commit.com/) to maintain code + quality. +- Automatic versioning with + [setuptools_scm](https://setuptools-scm.readthedocs.io/en/latest/). +- A test setup using [pytest](https://docs.pytest.org/en/7.0.x/). +- Automated formatting, testing, and publishing via [GitHub + Actions](https://github.com/features/actions). +- A documentation setup with + [Sphinx](https://www.sphinx-doc.org/en/master/). + +:::{tip} +With this tool, you can start immediately without manually setting up everything! +::: diff --git a/docs/source/index.md b/docs/source/index.md index 6beb41f..48d36cf 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -1,48 +1,77 @@ -# Neuroinformatics Unit Python cookiecutter +--- +hide-sidebar: true +--- -The Neuroinformatics Unit (NIU) is a **Research Software Engineering** team based at the **Sainsbury Wellcome Centre** and the **Gatsby Computational Neuroscience Unit**. - -The NIU is dedicated to the development of high quality, accurate, robust, easy to use and maintainable open-source software for neuroscience and machine learning. We collaborate with researchers and other software engineers to advance research in the two research centres and make new algorithms and tools available to the global community,[Read more](https://neuroinformatics.dev/index.html). - -## Python cookiecutter +# Python cookiecutter A tool to automatically create a Python project structure ready to release via GitHub and [PyPI](https://pypi.org/). -### Getting Started +::::{grid} 1 2 2 3 +:gutter: 3 +:class-container: sd-p-3 + +:::{grid-item-card} {fas}`rocket;sd-text-primary` Get Started +:link: get_started +:link-type: doc +:text-align: center + +Learn how to begin using python cookiecutter. +::: + +:::{grid-item-card} {fas}`tools;sd-text-primary` Project Setup +:link: project_setup +:link-type: doc +:text-align: center + +Installation && Setup. +::: + +:::{grid-item-card} {fas}`book-open;sd-text-primary` Documentation +:link: documentation +:link-type: doc +:text-align: center -**Python-cookiecutter** is a tool that helps you quickly set up a Python -project with everything needed to publish it in a very easy steps on GitHub and -[PyPI](https://pypi.org/). +Build and publish project documentation +::: -It automatically creates a structured project and sets up essential -tools, including: +:::{grid-item-card} {fas}`handshake-angle;sd-text-primary` Contributing +:link: contributing +:link-type: doc +:text-align: center -- A blank `README.md` file for documentation. -- A `LICENSE` file to define usage rights. -- [Pre-commit hooks](https://pre-commit.com/) to maintain code - quality. -- Automatic versioning with - [setuptools_scm](https://setuptools-scm.readthedocs.io/en/latest/). -- A test setup using [pytest](https://docs.pytest.org/en/7.0.x/). -- Automated formatting, testing, and publishing via [GitHub - Actions](https://github.com/features/actions). -- A documentation setup with - [Sphinx](https://www.sphinx-doc.org/en/master/). +Guidelines on How to Contribute. +::: +:::{grid-item-card} {fas}`code-branch;sd-text-primary` Versioning +:link: versioning +:link-type: doc +:text-align: center + +Semantic and Automated versioning. +::: + +:::{grid-item-card} {fas}`circle-check;sd-text-primary` Pre Commits +:link: pre_commits +:link-type: doc +:text-align: center + +Set up pre-commit hooks. +::: +:::: + +:::{note} This tool is based on [cookiecutter-napari-plugin](https://github.com/napari/napari-plugin-template) and provides a solid starting point for your projects. - ->With this tool, you can start immediately without manually setting up -everything! - +::: ```{toctree} :maxdepth: 2 -:caption: Documentation +:caption: Get Started :hidden: +get_started project_setup modules github_actions_setup diff --git a/docs/source/project_setup.md b/docs/source/project_setup.md index f6cd3ad..c89788e 100644 --- a/docs/source/project_setup.md +++ b/docs/source/project_setup.md @@ -2,27 +2,41 @@ This section describes how to set up your project using cookiecutter. -## Installing Cookiecutter - First, install cookiecutter in your desired environment. Running in the terminal in your environment: ->Note: you must have Python installed to use Cookiecutter + +:::{note} +You must have Python installed to use Cookiecutter +::: using pip or conda: -``` sh +::::{tab-set} +:::{tab-item} pip +Install using pip +```sh pip install cookiecutter -# or with conda: +``` +::: +:::{tab-item} conda +Install using conda +```sh conda install -c conda-forge cookiecutter ``` +::: +:::: + -### Creating a Cookiecutter Project +## Creating a Cookiecutter Project In the folder or directory, you want to create the project: ->You can use ``cd folder_name or directory`` to change directories + +:::{tip} +You can use ``cd folder_name or directory`` to change directories +::: Then Run the following command: -``` +```sh cookiecutter https://github.com/neuroinformatics-unit/python-cookiecutter ``` @@ -72,7 +86,9 @@ This is the structure cookiecutter will create: A project with this information will then be written to the current working directory. +:::{important} If you respond positively to `Select create_docs:`, an additional `docs` folder will be created and two example Python modules (`math.py` and `greetings.py`) will be added to the above structure. +::: ``` └── my-awesome-software/ @@ -94,7 +110,10 @@ If you respond positively to `Select create_docs:`, an additional `docs` folder ### Creating a GitHub Repository 1. **Sign In to GitHub:** Visit [GitHub](https://github.com) and sign in with your account. ->If you do not have an account create one + +:::{note} +If you do not have an account create one +::: 2. **Create a New Repository:** @@ -109,14 +128,18 @@ If you respond positively to `Select create_docs:`, an additional `docs` folder - **Initialize Repository:** You may leave the repository empty (without a README, .gitignore, or license) if you plan to push your existing local project. If you prefer, you can initialize it with a README file. - >***Note:*** If you initialize with a README, you will need to pull those changes before pushing your local repository. +:::{warning} +If you initialize with a README, you will need to pull those changes before pushing your local repository. +::: 4. **Create the Repository:** Click the **Create repository** button. GitHub will then create your new repository and provide you with the repository URL (e.g.``https://github.com/your-username/my-awesome-software.git``). ### Initializing a Git Repository +:::{note} Although While creating a Cookiecutter Projects, it asks for a GitHub username or organization and package name, it does not initialize a git repository. +::: Navigate to your project folder and initialize git: @@ -153,5 +176,4 @@ git remote add origin https://github.com//my-awesome-software.git ```sh git push --set-upstream origin main ``` - That\'s it! Your project is now set up and ready to go. 🚀 From dc847e8b4917758c94b6379992d3be1aabf30d9b Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:09:15 +0100 Subject: [PATCH 08/36] Update .github/workflows/cookiecutter_docs.yml Co-authored-by: Adam Tyson --- .github/workflows/cookiecutter_docs.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cookiecutter_docs.yml b/.github/workflows/cookiecutter_docs.yml index 5784232..3c6c630 100644 --- a/.github/workflows/cookiecutter_docs.yml +++ b/.github/workflows/cookiecutter_docs.yml @@ -1,8 +1,12 @@ name: Documentation on: push: - branches: [main] - tags: ['*'] + branches: + - main + tags: + - '*' + pull_request: + workflow_dispatch: jobs: deploy-docs: From 2fac1216278c933a54e22dd525986d3d97eac1fe Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:10:57 +0100 Subject: [PATCH 09/36] Update docs/source/conf.py Co-authored-by: Adam Tyson --- docs/source/conf.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index ecb1873..8f3e70a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,8 +1,8 @@ # conf.py # Configuration file for the Sphinx documentation builder. -project = 'python cookiecutter' -author = 'NIU' -release = "1.0.0" +project = "python-cookiecutter" +copyright = "2025, University College London" +author = "Neuroinformatics Unit" # -- General configuration --------------------------------------------------- extensions = [ From 77080166723dd12abd71d3354aa919cd5d7230b0 Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:12:07 +0100 Subject: [PATCH 10/36] Update docs/source/conf.py Co-authored-by: Adam Tyson --- docs/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 8f3e70a..417912f 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -107,7 +107,7 @@ def setup(app):

Sorry, we couldn't find that page.

-

We occasionally restructure the cookiercutter website, and some links may have broken.

+

We occasionally restructure the cookiecutter website, and some links may have broken.

Try using the search box or go to the homepage.

""", From bbad1eefa0dc7c0e6751098143e9a6e499cf4a44 Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:12:43 +0100 Subject: [PATCH 11/36] Update docs/source/index.md Co-authored-by: Adam Tyson --- docs/source/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/index.md b/docs/source/index.md index 48d36cf..05a34be 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -2,7 +2,7 @@ hide-sidebar: true --- -# Python cookiecutter +# python-cookiecutter A tool to automatically create a Python project structure ready to release via GitHub and [PyPI](https://pypi.org/). From bbfa393cf7d6b92da62458ce368ffff6b0e2f966 Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:13:04 +0100 Subject: [PATCH 12/36] Update docs/source/project_setup.md Co-authored-by: Adam Tyson --- docs/source/project_setup.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/source/project_setup.md b/docs/source/project_setup.md index c89788e..8f36cfc 100644 --- a/docs/source/project_setup.md +++ b/docs/source/project_setup.md @@ -111,9 +111,6 @@ If you respond positively to `Select create_docs:`, an additional `docs` folder 1. **Sign In to GitHub:** Visit [GitHub](https://github.com) and sign in with your account. -:::{note} -If you do not have an account create one -::: 2. **Create a New Repository:** From ccb30f46ddaec715be1ea9eb70307ea4113ea584 Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:13:40 +0100 Subject: [PATCH 13/36] Update docs/source/project_setup.md Co-authored-by: Adam Tyson --- docs/source/project_setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/project_setup.md b/docs/source/project_setup.md index 8f36cfc..db5f79b 100644 --- a/docs/source/project_setup.md +++ b/docs/source/project_setup.md @@ -135,7 +135,7 @@ If you initialize with a README, you will need to pull those changes before push ### Initializing a Git Repository :::{note} -Although While creating a Cookiecutter Projects, it asks for a GitHub username or organization and package name, it does not initialize a git repository. +When creating a cookiecutter project, it asks for a GitHub username or organization and package name. However this does not initialize a git repository. ::: Navigate to your project folder and initialize git: From 13cdc820c64ca94a180a8292ec6505b6dc325256 Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:14:06 +0100 Subject: [PATCH 14/36] Update docs/source/contributing.md Co-authored-by: Adam Tyson --- docs/source/contributing.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/source/contributing.md b/docs/source/contributing.md index 1025183..602a318 100644 --- a/docs/source/contributing.md +++ b/docs/source/contributing.md @@ -81,6 +81,3 @@ make html Then, open `docs/build/index.html` in your browser to preview the changes. -:::{important} -Thank you for your contributions! -::: From 3d7ec7ab84545c7e44124ec61027478f5947ba66 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 7 Mar 2025 15:14:12 +0000 Subject: [PATCH 15/36] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/source/contributing.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/source/contributing.md b/docs/source/contributing.md index 602a318..6d22b4b 100644 --- a/docs/source/contributing.md +++ b/docs/source/contributing.md @@ -80,4 +80,3 @@ make html ``` Then, open `docs/build/index.html` in your browser to preview the changes. - From 067a818f07bfe9d0d02775d697a0977d93eef727 Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:15:46 +0100 Subject: [PATCH 16/36] Update docs/source/contributing.md Co-authored-by: Adam Tyson --- docs/source/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/contributing.md b/docs/source/contributing.md index 6d22b4b..009ee12 100644 --- a/docs/source/contributing.md +++ b/docs/source/contributing.md @@ -1,4 +1,4 @@ -# Contributing to cookiecutter-python +# Contributing to python-cookiecutter Thank you for considering contributing to cookiecutter-python! We welcome contributions that improve the project, whether it's code, documentation, or enhancements. From d9d5efb966fb380761c7678bbfe7b96384acdafd Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:17:22 +0100 Subject: [PATCH 17/36] Update docs/source/contributing.md Co-authored-by: Adam Tyson --- docs/source/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/contributing.md b/docs/source/contributing.md index 009ee12..56ac380 100644 --- a/docs/source/contributing.md +++ b/docs/source/contributing.md @@ -1,6 +1,6 @@ # Contributing to python-cookiecutter -Thank you for considering contributing to cookiecutter-python! We welcome contributions that improve the project, whether it's code, +Thank you for considering contributing to python-cookiecuttter! We welcome contributions that improve the project, whether it's code, documentation, or enhancements. :::{note} From a860e1a064f20e92c391cce867e1ab05270b9d79 Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:18:08 +0100 Subject: [PATCH 18/36] Update docs/source/contributing.md Co-authored-by: Adam Tyson --- docs/source/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/contributing.md b/docs/source/contributing.md index 56ac380..9ddc36b 100644 --- a/docs/source/contributing.md +++ b/docs/source/contributing.md @@ -4,7 +4,7 @@ Thank you for considering contributing to python-cookiecuttter! We welcome contr documentation, or enhancements. :::{note} -You can Join the [Zulip Channel](https://neuroinformatics.zulipchat.com/#narrow/channel/406003-Python-cookiecutter) here. +To discuss contributing, you can join the [Zulip Channel](https://neuroinformatics.zulipchat.com/#narrow/channel/406003-Python-cookiecutter) here. ::: Please follow the guidelines below to ensure a smooth process. From 1db8ebd99404b64c679bb14b461016bdb912a64b Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:18:38 +0100 Subject: [PATCH 19/36] Update docs/source/get_started.md Co-authored-by: Adam Tyson --- docs/source/get_started.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/source/get_started.md b/docs/source/get_started.md index 1a584bc..c00444f 100644 --- a/docs/source/get_started.md +++ b/docs/source/get_started.md @@ -20,6 +20,3 @@ tools, including: - A documentation setup with [Sphinx](https://www.sphinx-doc.org/en/master/). -:::{tip} -With this tool, you can start immediately without manually setting up everything! -::: From 353e9aa589675b56fc26af82fcbaaa68ae11c0e5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 7 Mar 2025 15:19:04 +0000 Subject: [PATCH 20/36] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/source/get_started.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/source/get_started.md b/docs/source/get_started.md index c00444f..a89d11a 100644 --- a/docs/source/get_started.md +++ b/docs/source/get_started.md @@ -19,4 +19,3 @@ tools, including: Actions](https://github.com/features/actions). - A documentation setup with [Sphinx](https://www.sphinx-doc.org/en/master/). - From 1c7341bb17efa56e60efd704181a2365ec84400c Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:20:32 +0100 Subject: [PATCH 21/36] Update docs/source/index.md Co-authored-by: Adam Tyson --- docs/source/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/index.md b/docs/source/index.md index 05a34be..39ef6dc 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -24,7 +24,7 @@ Learn how to begin using python cookiecutter. :link-type: doc :text-align: center -Installation && Setup. +Installation and Setup. ::: :::{grid-item-card} {fas}`book-open;sd-text-primary` Documentation From 0ffa2a8dacbddf011089877a9a4c42838893477f Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:21:20 +0100 Subject: [PATCH 22/36] Update docs/source/project_setup.md Co-authored-by: Adam Tyson --- docs/source/project_setup.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/source/project_setup.md b/docs/source/project_setup.md index db5f79b..e1efd17 100644 --- a/docs/source/project_setup.md +++ b/docs/source/project_setup.md @@ -30,9 +30,6 @@ conda install -c conda-forge cookiecutter In the folder or directory, you want to create the project: -:::{tip} -You can use ``cd folder_name or directory`` to change directories -::: Then Run the following command: From 78558234c2b6673b52bd40afdfcb3b994cfeaaf2 Mon Sep 17 00:00:00 2001 From: richarddushime Date: Fri, 7 Mar 2025 18:47:04 +0100 Subject: [PATCH 23/36] Minor Requested changes --- README.md | 315 ++------------------ docs/requirements.txt | 10 + docs/source/_static/cookiecutter-python.png | Bin 0 -> 19804 bytes docs/source/_static/css/custom.css | 45 --- docs/source/_templates/footer_end.html | 1 + docs/source/_templates/navbar.html | 13 - docs/source/conf.py | 2 +- docs/source/contributing.md | 2 +- docs/source/index.md | 6 +- docs/source/modules.md | 7 +- docs/source/project_setup.md | 4 +- docs/source/versioning.md | 6 +- 12 files changed, 50 insertions(+), 361 deletions(-) create mode 100644 docs/source/_static/cookiecutter-python.png delete mode 100644 docs/source/_templates/navbar.html diff --git a/README.md b/README.md index db84e76..652a3b1 100644 --- a/README.md +++ b/README.md @@ -1,313 +1,48 @@ -# cookiecutter-python -A tool to automatically create a Python project structure ready to release via GitHub and [PyPI](https://pypi.org/). -It will also set up: -* A blank `README.md` file -* A `LICENSE` file -* [Pre-commit hooks](https://pre-commit.com/) to automate linting checks and formatting -* Automatic versioning using [setuptools_scm](https://github.com/pypa/setuptools_scm) -* A structure for automated tests using [pytest](https://docs.pytest.org/en/7.0.x/) -* Automated formatting checks, testing and release using [GitHub actions](https://github.com/features/actions) -* Documentation using [Sphinx](https://www.sphinx-doc.org/en/master/) +[![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://neuroinformatics.zulipchat.com/#narrow/channel/406003-Python-cookiecutter) +[![License](https://img.shields.io/badge/License-BSD_3--Clause-orange.svg)](https://opensource.org/licenses/BSD-3-Clause) +[![Code style: Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/format.json)](https://github.com/astral-sh/ruff) +[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) -**Based on [cookiecutter-napari-plugin](https://github.com/napari/cookiecutter-napari-plugin)** +# cookiecutter-python -## Table of contents -- [Table of contents](#table-of-contents) -- [Set up](#set-up) - - [Installing Cookiecutter](#installing-cookiecutter) - - [Creating a Cookiecutter project](#creating-a-cookiecutter-project) - - [Make it a git repo](#make-it-a-git-repo) -- [Add your modules and tests](#add-your-modules-and-tests) - - [Add dependencies](#add-dependencies) - - [Write tests](#write-tests) -- [Before committing your changes](#before-committing-your-changes) - - [Run the tests](#run-the-tests) - - [Install your package locally](#install-your-package-locally) - - [Pre-commit hooks](#pre-commit-hooks) -- [Versioning](#versioning) - - [Automated versioning](#automated-versioning) -- [GitHub actions workflow](#github-actions-workflow) -- [Documentation](#documentation) - - [Building the documentation locally](#building-the-documentation-locally) - - [Publishing the documentation](#publishing-the-documentation) - - [Docstrings and API documentation](#docstrings-and-api-documentation) +A tool to automatically create a Python project structure ready to release via GitHub and [PyPI](https://pypi.org/). -## Set up +[![cookiecutter-python](docs/source/_static/cookiecutter-python.png)](https://github.com/neuroinformatics-unit/python-cookiecutter) -### Installing Cookiecutter +## Quick Install First, install cookiecutter in your desired environment. Running in the terminal in your environment, with Pip: -`pip install cookiecutter` - -or conda: +```sh +pip install cookiecutter -`conda install -c conda-forge cookiecutter` +# or conda: +conda install -c conda-forge cookiecutter +``` ### Creating a Cookiecutter project In the folder, you want to create the repo run: -```bash + +```sh cookiecutter https://github.com/neuroinformatics-unit/python-cookiecutter ``` - You will be then asked a series of questions about how you want to set up your project. -For each one, type your answer, enter a single number (or just hit return) to choose from a default option. - -* `full_name [Python developer]:` - e.g. `Adam Tyson` -* `email [yourname@example.com]:` - e.g. `cookiecutter@adamltyson.com` -* `github_username_or_organization [githubuser]:` - e.g. `adamltyson` -* `package_name [python-package]:` - e.g. `my-awesome-software` -* `Select github_repository_url:` - Default will be e.g. `https://github.com/adamltyson/my-awesome-software`, but you can also provide this later. -* `module_name [my_awesome_software]:` - The default will be the same as `package_name` but with hyphens converted to underscores. -* `short_description [A simple Python package]:` - Enter a simple, one-line description of your Python package. -* `Select license:` - choose from: - - `1 - BSD-3` - - `2 - MIT` - - `3 - Mozilla Public License 2.0` - - `4 - Apache Software License 2.0` - - `5 - GNU LGPL v3.0` - - `6 - GNU GPL v3.0` -* `Select create_docs:` - Whether to generate documentation using [Sphinx](https://www.sphinx-doc.org/en/master/), choose from: - - `1 - Yes` - - `2 - No` - -This is the structure cookiecutter will create: -``` -└── my-awesome-software/ - ├── LICENSE - ├── MANIFEST.in - ├── README.md - ├── pyproject.toml - ├── tox.ini - ├── my_awesome_software/ - │ └── __init__.py - └── tests/ - ├── __init__.py - ├── test_integration/ - │ └── __init__.py - └── test_unit/ - ├── __init__.py - └── test_placeholder.py -``` -A project with this information will then be written to the current working directory. - -If you respond positively to `Select create_docs:`, an additional `docs` folder will be created and two example Python modules (`math.py` and `greetings.py`) will be added to the above structure. -``` -└── my-awesome-software/ - └── docs/ - ├── make.bat - ├── Makefile - ├── requirements.txt - └── source/ - ├── api_index.rst - ├── conf.py - ├── getting_started.md - └── index.rst - └── my_awesome_software/ - ├── __init__.py - ├── greetings.py - └── math.py -``` - -### Make it a git repo - -Although it asks for a GitHub username or organization and package name, it does not initialize a git repository. - -To do so navigate to your project folder: -```bash -cd my-awesome-software -``` -and run: -```shell -git init -b main -``` - -**N.B. If you have an older version of Git (.github.io//`. To enable hosting, you will need to go to the settings of your repository, and under the "Pages" section, select the `gh-pages` branch as the source for your GitHub pages site. -* A popular alternative to GitHub pages for hosting the documentation is [Read the Docs](https://readthedocs.org/). To enable hosting on Read the Docs, you will need to create an account on the website and follow the instructions to link your GitHub repository to your Read the Docs account. +## Contributing -### Docstrings and API documentation -The journey towards good documentation starts with writing docstrings for all functions in your module code. In the example `math.py` and `greetings.py` modules you will find some docstrings that you can use as a template. We have written the example docstrings following the [numpy style](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_numpy.html) but you may also choose another widely used style, such as the [Google style](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html). +We welcome contributions! See our Contribution Guidelines for workflow details. -Once you have written docstrings for all your functions, API documentation can be automatically generated via the [Sphinx autodoc extension](https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html). We have given examples of how to do this in the `docs/source/api_index.rst` file. +## License +⚖️ [BSD 3-Clause](./LICENSE) diff --git a/docs/requirements.txt b/docs/requirements.txt index 59cc7cd..1577543 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,3 +1,13 @@ +linkify-it-py myst-parser +nbsphinx pydata-sphinx-theme +setuptools-scm sphinx +sphinx-autodoc-typehints +sphinx-copybutton +sphinx-design +sphinx-gallery +sphinx-notfound-page +sphinx-sitemap +sphinx-togglebutton diff --git a/docs/source/_static/cookiecutter-python.png b/docs/source/_static/cookiecutter-python.png new file mode 100644 index 0000000000000000000000000000000000000000..64b681976247f0bbd01c862661a00138d1baf5cd GIT binary patch literal 19804 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 Sponsors +

python-cookiecutter is based on cookiecutter-napari-plugin.

diff --git a/docs/source/_templates/navbar.html b/docs/source/_templates/navbar.html deleted file mode 100644 index 02f5aff..0000000 --- a/docs/source/_templates/navbar.html +++ /dev/null @@ -1,13 +0,0 @@ - diff --git a/docs/source/conf.py b/docs/source/conf.py index 417912f..66e0b0d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -57,7 +57,7 @@ html_theme_options = { "navbar_start": ["navbar-logo"], - "navbar_center": ["navbar.html"], + "navbar_center": ["navbar-nav"], "icon_links": [ { "name": "GitHub", diff --git a/docs/source/contributing.md b/docs/source/contributing.md index 9ddc36b..18041da 100644 --- a/docs/source/contributing.md +++ b/docs/source/contributing.md @@ -1,4 +1,4 @@ -# Contributing to python-cookiecutter +# Contributing Thank you for considering contributing to python-cookiecuttter! We welcome contributions that improve the project, whether it's code, documentation, or enhancements. diff --git a/docs/source/index.md b/docs/source/index.md index 39ef6dc..4347378 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -60,11 +60,7 @@ Set up pre-commit hooks. ::: :::: -:::{note} -This tool is based on -[cookiecutter-napari-plugin](https://github.com/napari/napari-plugin-template) -and provides a solid starting point for your projects. -::: + ```{toctree} :maxdepth: 2 diff --git a/docs/source/modules.md b/docs/source/modules.md index 8297588..6e04e1d 100644 --- a/docs/source/modules.md +++ b/docs/source/modules.md @@ -1,4 +1,4 @@ -# Add your modules and tests +# modules and tests Your methods and classes would live inside the folder `my_awesome_software`. Split the functionalities into modules, and save them as `.py` files, e.g.: ``` @@ -42,8 +42,9 @@ from my_awesome_software import math If you're testing a small piece of code, make it a unit test. If you want to test whether two or more software units work well together, create an integration test. ->**Before committing your changes** - +:::{important} +Before committing your changes +::: ### Run the tests Be sure that you have installed pytest and run it diff --git a/docs/source/project_setup.md b/docs/source/project_setup.md index e1efd17..027fc6c 100644 --- a/docs/source/project_setup.md +++ b/docs/source/project_setup.md @@ -1,7 +1,9 @@ -# Installation & Setup +# Project Setup This section describes how to set up your project using cookiecutter. +## Installation & Setup + First, install cookiecutter in your desired environment. Running in the terminal in your environment: :::{note} diff --git a/docs/source/versioning.md b/docs/source/versioning.md index c77ccf3..4e72563 100644 --- a/docs/source/versioning.md +++ b/docs/source/versioning.md @@ -1,4 +1,5 @@ # Versioning + We recommend the use of [semantic versioning](https://semver.org/), which uses a `MAJOR`.`MINOR`.`PATCH` versiong number where these mean: * PATCH = small bugfix @@ -14,5 +15,6 @@ git commit -m "Add new changes" git tag -a v1.0.0 -m "Bump to version 1.0.0" git push --follow-tags ``` - -**N.B. It is also possible to perform this step by using the [GitHub web interface or CLI](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository).** +:::{tip} +It is also possible to perform this step by using the [GitHub web interface or CLI](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository). +::: From 9b679986750cf24f03f30ee4f1c6862d72bb9980 Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Mon, 10 Mar 2025 16:21:30 +0100 Subject: [PATCH 24/36] Update README.md Co-authored-by: Adam Tyson --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 652a3b1..b56d552 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Code style: Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/format.json)](https://github.com/astral-sh/ruff) [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) -# cookiecutter-python +# python-cookiecutter A tool to automatically create a Python project structure ready to release via GitHub and [PyPI](https://pypi.org/). From be81e07b664866483735592ff6da0eb299be5da9 Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Mon, 10 Mar 2025 16:24:53 +0100 Subject: [PATCH 25/36] Update README.md Co-authored-by: Adam Tyson --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index b56d552..80042e6 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ A tool to automatically create a Python project structure ready to release via GitHub and [PyPI](https://pypi.org/). -[![cookiecutter-python](docs/source/_static/cookiecutter-python.png)](https://github.com/neuroinformatics-unit/python-cookiecutter) ## Quick Install From 31618c5140c8a8a7fd4359e252ef1759877ba0a8 Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Mon, 10 Mar 2025 16:26:21 +0100 Subject: [PATCH 26/36] Update docs/source/modules.md Co-authored-by: Adam Tyson --- docs/source/modules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/modules.md b/docs/source/modules.md index 6e04e1d..d1c5a27 100644 --- a/docs/source/modules.md +++ b/docs/source/modules.md @@ -1,4 +1,4 @@ -# modules and tests +# Modules and tests Your methods and classes would live inside the folder `my_awesome_software`. Split the functionalities into modules, and save them as `.py` files, e.g.: ``` From 921f001b82141410d2c0c4d360b17e263fe6bc84 Mon Sep 17 00:00:00 2001 From: richarddushime Date: Mon, 10 Mar 2025 17:53:07 +0100 Subject: [PATCH 27/36] Restructuring the Navbar and Contents --- README.md | 28 +++--- docs/source/_static/cookiecutter-python.png | Bin 19804 -> 0 bytes docs/source/get_started.md | 21 ----- docs/source/github_actions_setup.md | 8 -- docs/source/index.md | 58 +++++-------- .../{documentation.md => infrastructure.md} | 76 ++++++++++++++++- docs/source/modules.md | 75 ---------------- docs/source/pre_commits.md | 37 -------- docs/source/project_setup.md | 80 +++++++++++++++++- docs/source/versioning.md | 20 ----- 10 files changed, 191 insertions(+), 212 deletions(-) delete mode 100644 docs/source/_static/cookiecutter-python.png delete mode 100644 docs/source/get_started.md delete mode 100644 docs/source/github_actions_setup.md rename docs/source/{documentation.md => infrastructure.md} (51%) delete mode 100644 docs/source/modules.md delete mode 100644 docs/source/pre_commits.md delete mode 100644 docs/source/versioning.md diff --git a/README.md b/README.md index 80042e6..3bcc060 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -[![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://neuroinformatics.zulipchat.com/#narrow/channel/406003-Python-cookiecutter) +[![Project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://neuroinformatics.zulipchat.com/#narrow/channel/406003-Python-cookiecutter) [![License](https://img.shields.io/badge/License-BSD_3--Clause-orange.svg)](https://opensource.org/licenses/BSD-3-Clause) [![Code style: Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/format.json)](https://github.com/astral-sh/ruff) [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) @@ -8,6 +8,20 @@ A tool to automatically create a Python project structure ready to release via GitHub and [PyPI](https://pypi.org/). +**python-cookiecutter** automatically creates a structured project and sets up essential +tools, including: + +- A blank `README.md` file for documentation. +- A `LICENSE` file to define usage rights. +- [Pre-commit hooks](https://pre-commit.com/) to maintain code + quality. +- Automatic versioning with + [setuptools_scm](https://setuptools-scm.readthedocs.io/en/latest/). +- A test setup using [pytest](https://docs.pytest.org/en/7.0.x/). +- Automated formatting, testing, and publishing via [GitHub + Actions](https://github.com/features/actions). +- A documentation setup with + [Sphinx](https://www.sphinx-doc.org/en/master/). ## Quick Install @@ -29,19 +43,11 @@ cookiecutter https://github.com/neuroinformatics-unit/python-cookiecutter ``` You will be then asked a series of questions about how you want to set up your project. -## Getting Help - -Here's how to learn more: - -- **Getting Started Guide**: Learn setup steps and basics -- **Project Setup**: Instructions for initial configuration -- **Adding Features**: How to integrate new modules - -[View Full Documentation →](docs/source/get_started.md) +[View Full Documentation →](python-cookiecutter.neuroinformatics.dev) ## Contributing -We welcome contributions! See our Contribution Guidelines for workflow details. +We welcome contributions! See our [Contribution Guidelines](python-cookiecutter.neuroinformatics.dev/contributing) for workflow details. ## License ⚖️ [BSD 3-Clause](./LICENSE) diff --git a/docs/source/_static/cookiecutter-python.png b/docs/source/_static/cookiecutter-python.png deleted file mode 100644 index 64b681976247f0bbd01c862661a00138d1baf5cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19804 zcmc$`by!>P+UJ|P&_eM71zOxGrMR}mDNrZ`mqKv}5`tTWws>)OmjrjM0L6<2O(+f_ zNwH9TR(^ZGGv}Q5-7|a7*>lYwTx-P^Ydv<$_j5m?FEo{J-=x0@0)cL;swn7yK$pIP zKo_*HUj^Rj_&{Y394l*3 zC>v&P5a{`~s=^apZ!_$?sS}k~=J|2-m#GgN99Jto-ngau?anYRIUVY|Sv^$L zix6{%%Zt%?(Q>U6_WkW^M3e^`-TT1@J0SsLyr21MQmzfxpK*G7_PAxo z-Fi(&wy==@Mf8I#?fy@_4n&}P1G8(JIlb-giqf*OK2!8r0OsHY41P>zO}t5vyo!@B z3GoCp)u;0Q0`Vm0Da$S5@j5ldE8bUjZ8$cvn6P#HCXqJO1tc2%p*!O!@K@E@F=n{zliQ&~@^#z&ckh&SizH?@au+6V2zJQ$3ZyDYtCvDzMp}N~tixQ}flQ zpefg5GA3=X;psjqL+^W|g$M&{`kX|h!!c3*<_c)?xd5`9t(zL0rqC#Qd=Z2xifz>EZ3b12@PryBl#_tc zoj4{Nv|zT=om60l2d{1tK6U9*}B+i!~(t` zFYyn1?cdPx|L_tej`KlWjx=DNv_ZALO}ie!y{@b?3ju`MY1CEcGFJ0zU)Q_BsoT7( zENS#t)~m8GyTgIJC7Li8Y;{q7+6gR0PY+vwXRVh_4-a(d+1uGY3J1OazC#>V31ZRh zdB^5whQmooJYg<6V3&?v^+D8GTT>&?Yy;BqnBZG;SN?kIK>K*#u60c#kKEbD@MEdd zmat9Nu2zcB-w2f&!&~<+KSBpEgef%IBOx_+J82sJ>>a;g`x=8Z6AQoazH@BgYoXSA zdxyWK(LXT*{$WG>^ONXbxx@oiqv_dVPG+Xjyyz$goIYdfvEIi_fA1eAw?U!r*<4E+NV=5P2Xxlo$HRVr+)ppG?07$|Ake|FwfJjtqf1Tn$Y1r& zFP~Y(8QwDrS0=3Ye*Cz1dVcr;cx)Bmaz__-I#|BK#p!WPELC52i`B_i-=rx{-Z`3--=JOYmeC4{LX$kQYBT?q-;c};6 zOiU7v7;n!|+lz*4v!W&wj(XG`T6e!695c|K*|mOkGgr)CTwpx>Lvmaj-+2EhObtJgytL3qaL-TU&&Nqlua52dcpaEyoF1$B$|EpoHGlrPA z5xVFPJu`)G4bI<Lg$yG0@spK+fMzUZhG}D z75d9{$ic;*M@Kq$b*{d25q2I?6!YowhDakJHt9+k6(jhxXY*;1KT@k zJr05qQLCI^5<)Sf>msJiZN-gEKgi=RAIDcky6>Bh?~gb(2R3c;Uoc>GKKGqHXrb%? zhM`-3tLpE?7?}iETol2n^zKiQhvk?&qz7yP_%%)ZW&Op*Au{u^{gGE0c+sQ_1}=iq zVn?ME*c)G9ZK;wA4rcG*5eni8z&towJ!!$+mE1*Gt0F=g9TN?+TpU`&F(8qc=xHKkf9 zM-yEzNKGP9o>&U8yEsJ!4D05pMoJJ%*glwYP_$`c{K7jkVWHw^t@KeRf(9qS=3)S7Baj$BX8b$tBxwd8E==xF{x z3pl|B&sk$6S*@%kdlJ)BT9Kq4#YrQMY@WT;#gpbgys?0%7$}wg^XmoJERja zqPX;ls>6Sf_TA``>Y!Iz8|0!T!nS2q6ngXfuWTkUV4&WU`i#{0Da~OUH25clwn&@G zH1AuHF4C^(35&`IVnj)Qy|dZKtgXcRc@>xr*}D7^Gz}E zqsw($N`3>lC*)m{r(YhbAUj>nenxn3Yy~`QVN-&$-R(>b2d3n(OFMYB0|h=k$z=-i z(2exUv;$`8%x+poF$!`85!6cc`SLZWU$&j*0f#h6u8`JKdSpTHs|PVd3SV&jT}z)P zM5cpS5f`6Xsqq_}1J~ba(MH}UrKQ~1Ln{nK*MUU8E*A+`A2rr)Sa`YKi_P8K_aG-V zD|&R6d`A!eyHeASVqV3z;y7@-AGy;lw$}5x*tbn=E7fX~A53=3VLOsQ6*2te?eM#E z6Nw#5i-X|iR$hxSR&vtNr(Sp8J)WlSb7)LZYiJp2Oc+;^qGFaTitCMM%!dmEeBq~K zm2~vj4JS-3d6PJO!zQkK{4;VSy1OXGvSQ7SOJircaV9DqhrZP^lY;O}q2c zSSe}IuF=aC#ROwep(LoAW|}49qmG;tO#(BVz!aFyF>d~u6dnL>y}9|u3ceO86EpN4 zL1vs#mFwnh`GQ%hLke$h?*;K{X)>5SGdrZ#1YsV~eoSxH!lg!TzI(G2ySTYuJJY;h ztk->6j6-C2qx**Adb*fU(xN0yf*`@LLdfb<&D^wkiSzmPTUe)wm~BuS->7fnZ%6+= z34JEbTOQ4MVhy@NwwFXNhPtY>y8VjAX;sn0W+TMRHa>QXOLDF^e(5sXs=cS|x0Sd! zp|$?Vy<6pR9-h_-=E{*&6}V#z;iDV$cepC|60(&(MvrZKwq7qS#lIBG!AvDv0dnY} zJ8uCdc(j~kX&WK3g_HSAC1psoA*4}fV>>u3W{sY#83*%1(H@`lMY4*)anohXD3AxQ z6}U{5f64Xpz_%7c2V^5t*y~d8?KS+b#qSSX=6f1#<`c(jA<06O7d4-|VxE!gP7cIP#@}r@Ij|`XQ@fSEpddl7^h_h`n3pUAh z*|78N&n=jEr4{>P!5?#5DaF&p^|JL?4UnCc6}%p}Hj*m5U2~kH1e|fg&Di}d?z1n) zWT@A8b=ZyjpCl-2g(VUXs?>P>7(@<+d;G1x3?v#ro3f0Xb~TG(jRijj2og`+*j)YQ zFG-r0W3u$m6@!vGayAx{8%o8ubl2Va*$PcU#_i{0R+-A%DQ;(9JrbmsF~K>=R`hhc zG0v^|M5Yxh!3HAbdSHQ_W5Zp}*a1`g#BR?*+#7i9O89}~uC&1{Ptc;gGTquuQ87>m4^`dt#y`T}kkr)uC)om50tNqC2 zg4oD_=|NL(>43mQtgdv_Wr!g8%kUsp!XNa>wtbWJkS8?mV4kUzjdT|NC}}D4X4RNZ z+zY=P4Qx@4a~rVg&!Y)njAJ48?%g<+t!|Q{p7gPc(z&yqqsifVH@b}4 z;2E0fzUI!JVk>%ScgG`Z{rSHll`ERQN%B}tvO;J1Oaz6^m$=qUUhzI4C(R-HFUR{H z3xApxqv@-jlM+^7A@#50)n@o_Q@%SAcV$dtxJ*K_<*=0zBjLgj2Pt?N3)m+i_5yFt z)xLy%YNi7zz%tD%Q%xPOoHEJ}%ABnir{bi0WiTh(v4p@!nB$;|gtkcE9j%Z4))RCi zhQkIT$`(lu#v|esjcpODSd=G(#aP9n!D)D_uwb#0Q~Mw>W52t4uMsieowWA4uv_LB z7kUm7)wSU%iOVd~2X4`asqD3}3irka<6@d%SE7$M5)ESE7KSN`-SnVFeE*R$Q9I?k zJaHj1IfZFhDl;3I49wdpNpF9hA3jAp(a#63CN0bD-!5^E*x%YMk(d}Z7Q-b*J#N`{`t^<39`I~B zSN3Q=!1sv9mC3$gBAOCZ zSr_yFKaBrZB9MQWOz`_IXg)UaX31vzYB=ERRStQjtyBb`g*VGeXA9J{Dm7pIfb=+i zBDyG}?;JTSS1Ae1-9M=U`)MnVWq>n_6zsvGOGC@tOzBNArwv0R``VbI@dKR`cgXyl zP-4!xB@UL*PII08yv`?J&qxtnb0(>JL>esBa=|zUBeT zJGh|tfL!SbhAvp&%DqyH6Y$LK1q_}sY-g^_Yy}Bs*H4yEi~}A)9&JKdY~=b@=u1hd zW#h8K#Ux6HEY;0r;I)sX2{faKgvl0I_IyPk6=}K-=2|0Rb$P@aZdpr^cIykoa!1NY zzc34t#ixUQ#WHyz((-k}Hat?$ZD~!URVfka5(RO#N&}07wt(TvS|1C!0exaUN#M8~ zMhp=x;!^xv`_GW3gM#7(K#PdW9S%#kI-X+^aWZ`gJ%Y3l=dgOE_>`1Ay&uX~OR_H| zG!^uwM6kd=0+|J~3xB122EVFV*BGiAGGhOPwEr1n1_I|2^hma8j7^QV2C-MJk;NT( z|11gqlejr*7oAIRN#P#$J*9=U^%yRidJ@AKhZNNkxNzZ*r)s_Js<7Lf-oBDJi8!@E`3T1r}-F4!=8@h%a7lizs>J%mT`)yjWXJBi!9+h5Oc3b zixu})553epb4yz*?F`gA$wXma$J1wN`)P$kF5{Bg+Lkry*mmR?o@8lZ@F{>d%6E>3 zP0b*yQaty4hjQ?Ey*<3)&^8=C;Dz1myBvEO1@@|1v_q!37Be#XQ{fF2wCQEqW)C)tQnC+ zIksbD@JEelwE6*VeGyjd(Sq{lil+FOZq4*Kf1zU_9?44lAdRL4yv4M+dGB5n8&lPf{uclwVY*_F`qfOn}L=c|DCyjGvWM22dpH1I!a zOH862Tr6$%*<+kP-x>C8Z`IZIkE`}Q&MqJ{R2pR~AU>q{>Ywn9tcq2_-k%>YBvw)xAQd#}YM)h%*fnA5m zk;SBn66Ca=d22;>l+Nbebgaf8_aq%Z`EG=7EGOZxgDm27gXwpGmvv!m^GNCs##x&1 za4lgHBcFCBAbry#cbZ~T6r``sh`4L?zTZ+0vFsVL?WGs)rDCOdP`zEtlF`;KU^U{o z(HHu%9rth~lXTv*Ij?{r(F@V)#oY~Fb;;-Hp0Vb9~n4Dw~G6a@M_ zG-|^H*`h4O9uXkuVKyI@3WXF&`F~+CuiDj3`D2Zj(Aez01ih_Xb?`VEA2yCHX}uQ4 zmG~n-R5NOrJF&9)e$?|KYJ2>Szb4=(4swZz-aR>pg`LU$q;@p!jen%A)zDjgmf00W zRvg2UHP-3qMx4@j^^NE-yO{5jXQbxRs$xCk#@UMFWfr%XC2g_Mqmw(qH*@tiQu^D@ zzBjH)Ql2GFvGmZc<60kum3r-^`W_U-d!P?0jZ)V9@-bL@Ejg&l~=?-SGY_%xJ%D- zsjp#??3_418nA&fx6du|E+gy;gu2Vjd!o)KJCZ4Qaprpc|gg%&{++D14VGc(A8%#(1#jjT2$D;;DBnsL1s$eu@8@*C}fDK!N{90bnC`g-~nBdn4l+25$fgD_@D|o5KFMdpm ztg z&X4|h@pImQI%v3csilDA8Mn1`#ZZzq&&H{ABzN7NiK@V3^p5VL(bal>{RqwN2v9ol%~&O6Ln9k*nM^8 zEG=Li(5hYkQ1mF>wfm_T^NZQ9t#c2jh=v94h$=B)U)z5p6{9ad>U3AaN^i?%hO!yQ z=rTWFKv=DXG@^MY>+n*AdMeR=kWr0Wn@W<4fzcN$V(0GudI?Oq;xB)O^u~QSuEHjv zk*lx~0Sd2j{CSnhTnD+BgFSboUmv0G&;x5SF({rHFHU_aaam6=;_t2K;e?y zSRrwo)isQHRri<{GHBq)YO87gT!wo1`Udq$LrJ{XKvqYH9E$vQYp+fw{i)0w5%6@K z-Jta5_qatF6=^Wzw|7h9%kP>N6RO@uVf?+uvkb^GYK%0Gu6eYJ6-o??Wa(D{58cxn zKjSN~dD408unYDesrCgO8rhOIa9K8}vhV|eyPf* z!bfbQe$jPN|2eCOFOqGLJd*%aARzc%s$SBL^oyaA`EYTq#6o5Rn1^j`SJLruqKsPt zmHbZP6u%xlmraJY@cjuKitz4M1O^sW%Nu>i5MC2adBzc}hXNMgH8CMuH2Vz9TQ$={ zg+{NYye^>PwYXAm>21uVwjrA>dYq*=T*lU`xoQf&Zzu?M?B!;+ok`#_ydcU^T7`ynOfR@V^s(k=Fyg6 z*j>UyZVSs7`h_!8nDpJ+^~5i;6oFo5DIq5M3I|0C-is5V^9r@HZnC@aJI_J*Cktf3^>AWz<9oOXLw0ZpZz~?YZNhng4V@AL#wckC;D} zwm|NPYMMrrD%4ftLt%oz<3fyUI17p-w}W*-V1%AN72G^62Ma=W+IPic9yvzx2bg1{ zw)jc!jUGgV%4sLmt%ydA5Yt9 zTc+xRQsG03Au({X<3g?NY!B?r9T&jKOx12~FaTsl`jUIlrki8r+T~(i=F>;UzC0b2 z@0w$xHsAenH}<<}JOMPCeu7E3O?a3L=TmOIF4vYMrD(5oW0NG`+zU{__;098G2Hah zkZ+!iGz{_TJe_K@!>-{L-O`oY+x^{Bt!Jc))?Njf$>YzjM89|A*=~XiO-ejGTslH26sF#XUqCFyMWfk3GrOJq-Elz`44C89h#~YMWOQc~2iMMKjJ{ zI=X)zyDy9pMje?L_L$}dzLZCHcA3Z&*pWc!!Wf?g_id^+JeJ6N3q4zQ;YI9zZ@sO| z;`GUbL)w%+U2v5=L!)qf6@#-t$5i(?H_!V?QMo4B@kg$g%SeRJ%5FoyYm3qb?Co%Pf((B1Q6izdTY1C$hd8Nag-p-36A70lOt$ zdqxZ5oxNXV9iLK(eK4e4hI@Xc#Iu1R_W&=k;luJ`fv{V`d0T}~=I!)jv+HUP$H*d) z(>1!rXo?1poZ<7f#rC4NL!lz)Z>WRHp+SDq=gUR5`D3`_y2BolixqcV4)o98d$LMm zPEq(INc^;plzVq(Yj2ZM*rd;v+i~WRVt?KaO8JRfS^6oTUKX#fUk>^u@Ywm*e0(}~Yg60T_6d2Sz zGn&oT12ia$Q;GdCg|+l<9`8g+QRZf)OH;M$^tUa_fb?xJJOVL76lg(CkN$P(_P>bv z42*%8Ai!JR)TSx_&kB&3mw?a!5^?q?#G6-}FD?`t=TfkJoq7l?>>JA|oJBey4uAffQL{~<8{ucDQ^b(4VE3{7Ss zQ~>E~S*BL@4ZyMHq=KGbrYndIXnq*uXAeYT6d6OjZ54GbN?yaf(_+P{$C~CYkKt96 zYw=8X!MXc|YeS|cNlJcHw`Zb`jn*2T&Q=l{tQX^lQ2WerG&*XUwOk`h5Cyg9*$R=U zG5&_=3Ybz!fKXTJZZxwaC!p5&Zd-N%3fYL29C9t|6s(i6xw$#e^`?5d-1G6{%}!&v z5&fF1l<>0ApFi^pOq_i5g`FZp6HU?=u3PA z0Q`N43*P2xy`3PdD?E{Y4bT}Zjsob{wmz(~y8~)YzCH9wfWM`Qy>+}==4fyG6AjXg zvEJ8ebOrDL0^1j?u&Up&Y5`&YPxONsf!i6Qy_9TUfWgd2RD76LHjR3H>ip>Mr%US2 z#=ne~C|K4_^Ob?tmX|WEd?Kt*)$TV}dFZwQf{&5@mhUU0m?6}ht1#5OXN?MTFhotM zU2fdGINm^$yV-Ux$wQs?NYkFrnSBxxP}ZW(k2;!us>^)q9vNb(3IB^L!0aZT>}#;X z-LQl1{1V>G%PtDES6x)+O&we`9S5W)E$yC{gcL{ZtB<XhS|4mj#r>C^hSW`2>e zjJ$cpdxP|rZtM}@BdXXt{ouYkG8I35hH@+MlV?^qJrzx(-lMQlL2*j!6WgU2ft ztlWn^4GIeos1iqXRtvk`_cKGEn5OhCgDWvF^rhj|aqq+uAP{~1hKU7jJsBPuM2+XE z(`!lo-j}w3Ej4nMTz_nmd@T96Fn;Uwb9o}_L6LynL_;lJej&d!7FKR6vtRSK_&+k? zCKt>szwh80F~Paci2M>TI(JDciKgcljUvrz0)ZMe+NP{Cd$tryT2>&Dci7TS{TMK> z%nE>7fK4AW$YC?kL7s`0NEChtq`8J5iVSkzsVg|;+l&xxg-J%uwYG`_g&XgIetSn< zQZ(I6Xi$yDF~G|I<`=r=9L@2}XXqC$)RzZDdT_Y!myEo(93%vm>zq_~KnxJEYgclV zS?>9wzE8RWZpkXmaAVj#-utvSI8dE6pGT*FJ`W!lmj>>LJ_+Md;0E|tRP)iPjZzf@ zfc&=G7S4tPmNrMh#!MRLLH74Px9++nPO)Z*=LqCT$h^1DfN73(7!lj zrfehox#Dk;Y49?NbgxKWBml`Bc{k16iCTUfx?E%5^KGccHr$Iac&49vyD`s+ z_jMmI^2{G+WwOay4Y5CKM+eV*pA(&+$9cV>uwrGOi04I-zOO_ECS4s>%%;^cXx}r1 zKFrU764(qhk#S6Q(v8+yCKej^5-^YW&`!Q_khf`m@a}i`6Ae;AQykwiXDh2@+Vc{4 z&zQ`#hUo4A>xe*^@z75RuQVXjyHN|_sartfrsB)3pd8A{cgJt9iQq2Zo@6s`Iv|}< z1}L8W1byUY66BAOlCsBSX8B`%t<>#-ejN>&(x=bXB7Ad-&h$RSRK<^{RAPb&>HLuS z-?c_ehtX0MQEM+ZTkmgq`%?sKgah_$s+4#Nj{r`A=LS{w{uh>m_`$!z4gDK0QGkG* z=ad^7lsJjXcKoCbI(i2nA^TGFwa_(y@sPhRJ;+C-PX5`H5Ph0wN*AcUv7oES z$jl4?A9hwpygbhP?|N4l!DNYk)ezhCNQ}0zF-ruEE#s_)i0- zBRc3vcu?~kkt=B;lqO4lHP~pz34p1_`)t(TU&u~$$hbZxLQib8{~hS+-`IHn9sLr~ zc#qi}pa4yoY}Pi*1GvX{y|c*e6wr&8vjBS`dOXS}(C=Wy3Mx-BT1ypyPgtAVOf(8x z(p>5+tZZpgR1eo0T&ymaHU|eh%d1Bs)51X(-<&Hd^nsT|ZXmp`y7rH5OPcY3C1{F@ z-b*PyAVnm+>@WOc-*~_#Az{20+JKVweGU*|35U4QCK`}aGLo=0(S9m7I)8pb1}~Rx zn33&ktF!BAB)(5Z)&}oDwdC1qb%-G^2H&oNA|a;>3*@H<$Sh0?XS6;wdK2Td{#))O zk4ffFc)Q=ulnDt)^!aj~jDsI*X@!l8-VGN;L#g|nNO3BtFA@!Igj zSD>_>8hpptyJN3%To4TAdBP|5Y1MKrs+;3 z)lgnN6SVNj6BjsWas!}o7RMr1&yLmGObiVbBY4Y|LM!9za*L^-CnU_lCtvRZd4JFB z+INMN(iooBIF*P?m4|oGASdg(P`8kAK624Z#dRa}&h(&CORY;*mq+{VEPJ>q4L>4T1qR8( zm{l4PQ7q8+M`U7^U)^(__h`C*wG6bjyqY4H)}69+%)P}5HAypK66PupA~bAt-2&%M>v~j za0qKHbZI}?<%#`O9(XdAwUH)hyBE(801{0BvgmEw;1*(D9ZZczd1E+@2K|AOY71eVr}`njj7!1`7B8xS;J09QpeYiv)DN^SMlMGcQ3ElBhoeHR>H1c%xbK;9y{lLYPmKn%x!fm)4t%Dz#*i~}6?`gWrbQ;>oB zcODSewf`jm`hQ|A`kzG!A3ksp7j!;;*@g}nCJ8Lk8=PfxRJJtr!cwT#2qawS?V&>QKrnyC_)P;pGxR%n8-9tf>+`!2GCpuwn>VKh=sSYTspJMZxaA- z>`^joUy_vb2Qmq5aMXP1;ba5wR6S7;06!%1W5>39 z&IsekZw}nTBboQMY6!muJ~b8dj7)wq%#RVCtO}I&?k6^0X;5pv%sHWs&3?Ee02}TW zI}U)FX(#ok7-#e&)zlLYB|23Hh}>y9SVnn_iFY^z#R{t|Ok?rp?Y&9mE+nSm$HST^w;)(M=c; zluzyt=C!>)d3mK-=DM>LMFF!h^J=N<5mOg%={E~Af&9h1YBIakDG)IexJn~*deabOgfC_|pY)MVlAB{5S7EY+8 zoC1cRQ=MH=kJiT4=YVU%UgbVgJA@Zgpe!1N-2d`OuXG0JoI8${dl&54(R7=@{S3AfVyj=pBs@(+lb(V z1W0pvwUF|1Ty~nB|Imck$BzmPPZdgU3rJLurF*x0)~R;+sj-#u$EFS4IBtcbb+F#v zIQXaBSw%Cyc|N5Z1sp=KO$TVlrfWapWL0oxmjQD%yFXMr6Ehdd=xI0(AIpD?qh$Z!W_pE`Y*_7*`E?Z*Xa!D`pp^ zT=~!I>Mj1S#_mVZ_c~bsC?BuAZ?nanb^5!au@L0Lx;~TA5mWD`db|} zZvELmKVim2$6clk^FiT8Vh93dejY&|sT;N+BTs|`n~j$-s1DVOTZV%2s$NyNmOKMy+Q<6hhm!nTnt#=cpixq0kaln@pjI8P1OwfrEmG7 zqYaO}SEySvdYQ9%!!4*`Qw8(N{x5AZNiSZTCk2h2p7tCO=*vXR4iWk>XHXz%;$BgO zD*Ha)vDXMIUm}F38dKetr0tEL7^LWIhBn_4opwWP3{hea2hGO`n2lUFL8MHxqPFTb zX<4E*EPTjxO;Z}W7) zcHvS*Xd36re$uB2{Y_J22UsIauN zh0qJ{x>>YjxgJgqh5Aq)Si{L*sP3hVwcR+h^vK_@91oD6Y*7@%GIH+4lr+6ntz?@Rrd53(FiKC7EY->2GM5=V!sJI-JDD{3$dDExLEQ?b9-C`U zpsc|;w9A|Jl|(nqnj|+^CNa?R3grq(Nkn;YlrJ%h#=@NF0FyGX6djeSh}&I#YjfYk zzPDr7&fQpvO0RCz~b;jhvB>QG}OC+)?Be7|M_ z2+M8hOzI$qp>&~U|0dkX2<`yRCX|iIn)Tg0p-Ss?Ar8Uc_1#KTnBfWw39;=t$TUVW zM_sok9TBGK70ocHhv8g_zsWvg=o^c7 z=NTBsc-Az3Y}Rs#^>{Rwzw-B<_a%p%F!krC<-l~D4S-PpmV zlXRzoFb;t4BU9~iQ}&P(L+)M{gJELS{*FwIaTIbjey?1S5JA^u>*U*glVNFZ*$-{f z3hN#y;JnCDR&qsaIAIY!2b!Eg1veYMNU~Rc?SSwQOuE_FrawpX3d89lUGaMG`xa^5 zr&451;8$Eo;{zeM&InUWQq*qwtDsY7+>-*BVe3tm_YHS!KdifZGYjfO^?qqzs6u!i z!~rKK+phsT{|?7Q6JKV6F!G%{P$}B;MjQ|SptJQ4Ek`_gCfr2r4EbI0^+(FwlvHo3 zPXaEa^T>@!W~Vzu4k*6JO9ZD}KmI84r$s^wU;(=m;gbONlTGs)oqmJV(aGg!^5RTm z0Z9PrV1P@+EI|75izZ-&TM^OKZG=p7T-|qjkx}tE2bw9=YUbIndOOs9CFNc#T_rj& zrDXX7o^$eQwAReq*66D-`GA+Q3QO6JlKV2#H^^eTIdbvg_8+$L54-F6KgQDmJpWDf zi>LNYhWS1oKa3W(Rk^H*&3?9S_hoXSP)aLoAdt+dT>sa$Dll5($8L^#uia3^`}X@~ zRuArONyUFuxLZbqe#Csb`a|X&Wt{>`guD2DQ`a}YJxiB7 zU;&^yTr#k-iq2nHn-nn;g>Z{Le-Y-?6ladv#$qyO~&!5a>JfJVLhM59I zU7}Ghv!F~_dqB%2itWk-$J&ttg?S_KCWcN=f5lKJMzZQmn{FH#`+~3QElUv(x1XQ`d{yb%9?8X>g2s<9A9UVC+ zYp=SN{n(PB5;pO-I!E4wK^t~!SnU$+(V|w+Lt6cUK;?Iyim8K(^iqi3Z#U|m$J@cM zOg|?S!Xe%iIe=`&ZsalpzX7y*fcb8(iKFRX>J>RA>2HiyQ1W=sJ0NWYK$0lRx`ssU zz5uwFarYUqFL6GRgSBPIX;0rdbgs5*3%JatqQ>q)!Rs6abi?gknXOX>A{_U8(kx%Z zh9fj87;4)qXB&bRJI4cM8APQf=^XzG1KiB}n&>kt!f61Tb)j?+L)OUwsSTVKDp!35 z#c!dLedjvf9B01i2|)UyQ{rbNt-=6AZ>y!kY*+$XpW^=~5N9AARCWSgl%ToNW{Wdv z>3J2{KB>Ce;E>_8}iddHGKNPr&bb`pN z(K96Z`o4z$ioUWc^twS)8m7!3)U(t`_w6*4CuXSFhf5{gPEGU<(zY=I%_mnix#{Y7TLAAT=5TG;Mn|c4)#NKX9z_8%9St^+La##NY=%}`tqsqwG4xv6^x_gw5J81?ZDCY2W>wQ-_~Q2;NSk9zyS&WW z#;P=;X-MIX+r1Tkr7gh_<)uu>7&MGM0-`;_#F*xpSVX-c?OeA7FeGP*YR1RQH>yWG zkELmEejZ`U@RTKc6I6EbB6>_Rijb1;;`e3kN+rOu*>7nBzFxLay0w3yG_uQJCX5njacv30>oZsK&py^Kk;0~P{?pKe#l^Zni+&Zrifxx0@MbWld))^7~9kpb~k*o~jg zeuoBzlMTCQM06&AZT3v0No_t|%bz-Sl=ecbrF$C;d2v;ef*EHoc9`q4<{Gfj zs$axV%N8IHklbPSo;_K0)U+QUjklhFOAAR#uy;`)%hUWh)03U|yh}U+j9uq$yjYid zR8%V@ zZB?0&Z2U~tanRTA>`J$NP{2DhUl;mhUPayc7#?1|?3rdfcN4k%QzcOG=X^KyFk_E# z^TSu*)<F{8a`B^&C@Rg+;p#mBf2Z=31rp^P2 zo3Ts>wVyAa!g(y1dv06#mB|WTkBkupv%e~o$-$u98dv`6%^w~{v9_lG{kLMW1|E>Y zOiwO9SBe1-E9$bzCQ{%dRom}A&Lz2G#H>8zz4);yI##efBBCJP&C&&R_*rS_kJYP8 z+=YOJNS9}0YGO%;0op16V2FaU+q?g^L3u)ZgmP!?RX5Ubhjb}~o>QH*?>&L%LSi=2 zc1~&zL3nRNbWW#l2~WKqKTwwEXL@Cv*I%sy-+}-`Z=JS<^)gG9;})$a;nHrlJ7aX# z@!Adpfn9*UH{h#XfYC4g;iXjKYv1Ii8-|I^xO_~p^JsI~K#J{aEWksF3FhWNo1~s) zF76~aJdsAcJI+_J{Tk=WN#%&xu@tDA&w)xx2((z&|6JCd6kTPyo6ym++Y~mJ%C!{0 ziE|tx75E<%T~|rRvynXySLBxTm!PcPYtSpPhrz?2HUPAWWLL?W0MOq&9TaB5UTgY? zO?A=VoZ9fAG~$B68;JsYbnrU~frYps-Z(G*!!E(K`W5V3{fvu3#drL!u63gLyDoQ! zEjFVZ#fDx*=k7FggG(KQ()QNdwYPbgFr#F`ebRh?y1*k68#8DQ5o3O5R7U~qC9Am7 zC5ED_Rd9}SU&TYUa`VNztyPmHVpn@esaqi=Ncfg-#;S*4Wtms78nQy|4gRuL+v7hb z%RM7@(Gw0^>Tml?%*FH}YNi_`Hubjk_sqE-M?7FaH2F*-0N%n7&;#|{bh?Ef=j(*<79CPgSL=Ffaxf1xnbHKv*(%-qZifeE{FBLt z^$A6znC$OI>``AFZhHlmS9OP2DgT5yl9U@edn&e5Zu#2(g8qum+i)uj_cl8?iiNqC zvs1j9U0$FDmRqWz#HsHAgS}&I`F`?6B=rggv|6>ZHEm~R!^;BTq-wiihh|e+eWw=F zOSDkhY2d4L{fw+*nN?-6B24*m9CX5*lSUGF$H+*(|3uNHxz2>b@zPze5>BzJ!;dAr z$LN`D1C@>hXO_q~MXaLYa6k=Wb&I3^7ctpxS<)8F*z!9GwD>0C%~<>Jt4x5$<0>4p zsjPR7vPD?dgqn+5Y625$$n=;ZtE4a4YaPy31>UiGVY2p)FzYmd#b0l|LG$BGU^~h& z>cE#{`_Z&1?e5|yMrb*nt?Z%$j5m?tTG(Io-?`TYy*NDC=5bT%WTM(|FCd1as=Q?j zI-b4RuPm&Bm-`lUtbK$<`hKKJ<}nEp>A7=9YVp#gO(Vs5hnoI#&4-%>7uHzBqoM$^ z&1^>X1Ic9Xu^__TfP+VoWvjZmRh*KgabBK6XwauyIfGG)cg9K(lLVo%4+VHyrwXeX zxpw>YbdhY-aiC3X9lc_`)M01lYm2>9L^MHV>52{0JxN=ybGOMl4n>3A6v=)cG_W?M zv8F=bZT^MLu?enw8(Ixp-WYDWyCpmnCt|Pui^d1zGvt#MgY!8iSp}w?VH{Uuzpt)0 z2lhUI9KO<`($%g`$&5LI_WZ&G3VRG?_^%(Wi)2h{6wpXl4EhZN)r+=Q91p~meC|qz zsmndKjKbHL_YcR*1P+FN%PX4LDR#X#l*CNpzhn6#+UTvX$E`?ib{BvBkx8u%laL=0 zv^|9+4Vm43R$-S(k1KgI=D}C?zP?a%ZFjp!+aj zM_xIcE*D@QjI|I3|;W{_vp**XYl6<{v?Qu;UVH!`ULR8p9B+!G7eCnj^1Kf>B)O@P|~M#(Ku zCq116RE={uBDt&VuQKYrjj!*UfKPS9{sTS(Vx{1}T#1qJ9hi}5A5g0T3)o9NT{3I{ z3JJ)_)=#V*rwamAft9}nCt}Jdo;mxW!m&0;2JHz0N@OZFbUM5kUG&!*1$+X%>KPjj zz8$xdqJ^d~sTe@VSNiMnDaqplPj!2apo-h5}EdGUF5izH>8_v+@ z{9}{VHP3+3rs$c%SjoRWRoU!*H&-eFL<;)|TNf_?!pp47m0@gl7Gzde2Cyf=gHXbH zavL*e&sdm8CV{;VWhE{#pMxrH0;r6yp}<4lc?!U!aoV-tR3U&*H)yvyW*keb(aqia zp3Q+RAaX}hp36oqv^w+*?txVbMr5<+%>^+z#%Ce10rfNi#iXn#2o0Z^r(KwzNO-2t+1SD4;?7_#TXwo?G$2P+^rzmFAc!s1^% z4j9Y)v8JF|D}=0(~Mrh#6~hMt!q#k5sOjmK3(qOQhqoHjv-s_6!Oeo{|P?B5~4V2nG2^ z06U~P<8{Bn#Hj53#PdpGq6&`(_N}1>V)6U6N`+%#o+jhO(t&xz5D~Opw1NgiVNO=& zn&Ze;BUb8(>wuLcHl@52;EgR)M_$KV_Jb*TNbxJS$n^X~ml;4Ik*TsvcR|7W#PI%p zE5JWTDNWdD#jYgZ+Zvn7OQt~4Ws-12Hh5@d!u;~9WQV6rkbpo!#OS`x+vEl)^>)I_ z#N0Um{Jlf6kdE~hC>Z`f<5hSUn?i2ie+=wUQbsEX9#|~B_xD{R*#EZW#yzgIK?mh$ zd8DoTlmQ~gDFEhj`?iL|Ox-Ns)yYn`3}($@>#wOB^bC&wQh;;y&c%OJ)pG%K{S9D2 z!bJR9f-eDGL(DihJpp3>Ov8!_?h%QiD#|8h;R~QUHh=ph?p;84Ig&{GiT@jrga7?Y zsQphQreYv!CvF6jDaik?REpJ4AOXy$zA=fH_n*>Huy#(5h+E14MCN~1I|hJVW&jdM z)EHR2>Z+%KJ(-FNj5xn~MEKL-YE>I=+$vhc){Obvt z2eC7u3g8a~X6@cN0KX$ld#Uq-pYyP6oB#Gx0EH+Q2g(kOlF!r5a35V#!!KC8w6j0W z$&@)oECLAC--&=e>jYp^Asg5q{JA!utgRc`d?A810Mmoq-{~SDP6%CnPE4U?Q_gsp z8vrhi#RRR7F9KB79-kEg*q$oa%~pX3jSK~88ixMnSxl=oYy;}-oM+ojQ}FE~`T$2% zBRpCTY-9sF=s2^YhBbb5h`+9G$Q#C!mf)#m_R{L*cSFna8z4;Y&G>LF+S)%`B@EKM zShJ-_H(-k$?Pp7xwxLxVpmJK?D1Jeiu`ztsI9t02cCMh%ba05mN&{q|1?Dq08dx`6 zZPDv#eCm*Ry~T?v0d}Sgx>Bh+HE%Zu+C0;_K-@p;(_i~%5s{K_3I>_-smF{UQ8NJx zFs*#38|c5yO!|>@!`d}rhI;Y6!inwQ`;-`Rbl%TBa!cVD;|-aPe1>hCZXMq-$J7gQ v_ScO$S)YCY7iR-OoG5xE6F%h&BdPtjU;N~&w`_<@9mq&eS3j3^P6.github.io//`. To enable hosting, you will need to go to the settings of your repository, and under the "Pages" section, select the `gh-pages` branch as the source for your GitHub pages site. * A popular alternative to GitHub pages for hosting the documentation is [Read the Docs](https://readthedocs.org/). To enable hosting on Read the Docs, you will need to create an account on the website and follow the instructions to link your GitHub repository to your Read the Docs account. -### Docstrings and API documentation +## Docstrings and API documentation The journey towards good documentation starts with writing docstrings for all functions in your module code. In the example `math.py` and `greetings.py` modules you will find some docstrings that you can use as a template. We have written the example docstrings following the [numpy style](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_numpy.html) but you may also choose another widely used style, such as the [Google style](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html). Once you have written docstrings for all your functions, API documentation can be automatically generated via the [Sphinx autodoc extension](https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html). We have given examples of how to do this in the `docs/source/api_index.rst` file. diff --git a/docs/source/modules.md b/docs/source/modules.md deleted file mode 100644 index d1c5a27..0000000 --- a/docs/source/modules.md +++ /dev/null @@ -1,75 +0,0 @@ -# Modules and tests - -Your methods and classes would live inside the folder `my_awesome_software`. Split the functionalities into modules, and save them as `.py` files, e.g.: -``` -my_awesome_software - ├── __init__.py - ├── greetings.py - └── math.py -``` - -If you want to import methods and classes from one module to another you can use the dot: -```python -# filename: greetings.py -from .math import subtract_two_integers -``` - -If you want to import all the modules when installing you can add the following to your `__init__.py`: -```python -from . import * -``` - -## Add dependencies -To ensure any dependencies are installed at the same time as installing -your package, add them to your `pyproject.toml` file. E.g. to add `numpy` -and `pandas` as dependencies, add them to the `dependencies = []` list under -the `[project]` heading: - -```toml -dependencies = ["numpy", "pandas"] -``` - -### Write tests - -Write your test methods and classes in the `test` folder. We are using [pytest](https://docs.pytest.org/en/7.2.x/getting-started.html). -In your test module you can call your methods in a simple way: -```python -# filename: test_math.py -from my_awesome_software import math - -# here your test function -``` - -If you're testing a small piece of code, make it a unit test. If you want to test whether two or more software units work well together, create an integration test. - -:::{important} -Before committing your changes -::: -### Run the tests - -Be sure that you have installed pytest and run it -```bash -pip install pytest -pytest -``` -You should also see coverage information. - -### Install your package locally - -For a local, editable install, in the project directory, run: -```bash -pip install -e . -``` - -For a local, editable install with all the development tools (e.g. testing, formatting etc.) run: -```bash -pip install -e '.[dev]' -``` - -You might want to install your package in an _ad hoc_ environment. - -To test if the installation works, try to call your modules with python in another folder from the same environment. -```python -from my_awesome_sofware.math import add_two_integers -add_two_integers(1, 2) -``` diff --git a/docs/source/pre_commits.md b/docs/source/pre_commits.md deleted file mode 100644 index 84e4caf..0000000 --- a/docs/source/pre_commits.md +++ /dev/null @@ -1,37 +0,0 @@ -# Pre-commit hooks - -Running `pre-commit install` will set up [pre-commit hooks](https://pre-commit.com/) to ensure the code is -formatted correctly. Currently, these are: -* [ruff](https://github.com/charliermarsh/ruff) does a number of jobs, including linting, auto-formatting code (with `ruff-format`), and sorting import statements. -* [mypy](https://mypy.readthedocs.io/en/stable/index.html) a static type checker -* [check-manifest](https://github.com/mgedmin/check-manifest) to ensure that the right files are included in the pip package. -* [codespell](https://github.com/codespell-project/codespell) to check for common misspellings. - - -These will prevent code from being committed if any of these hooks fail. To run them individually: -```sh -ruff check --fix # Lint all files in the current directory, and fix any fixable errors. -ruff format # Format all files in the current directory. -mypy -p my_awesome_software -check-manifest -codespell -``` - -You can also execute all the hooks using -```sh -pre-commit run -``` -or -```sh -pre-commit run --all-files -``` - - The best time to run this is after you have staged your changes, but before you commit them. - -In the case you see `mypy` failing with an error like `Library stubs not installed for this-package`, you do have to edit the `.pre-commit-config.yaml` file by adding the additional dependency to `mypy`: -``` sh -- id: mypy - additional_dependencies: - - types-setuptools - - types-this-package -``` diff --git a/docs/source/project_setup.md b/docs/source/project_setup.md index 027fc6c..e51bd03 100644 --- a/docs/source/project_setup.md +++ b/docs/source/project_setup.md @@ -106,7 +106,7 @@ If you respond positively to `Select create_docs:`, an additional `docs` folder └── math.py ``` -### Creating a GitHub Repository +## Creating a GitHub Repository 1. **Sign In to GitHub:** Visit [GitHub](https://github.com) and sign in with your account. @@ -131,7 +131,7 @@ If you initialize with a README, you will need to pull those changes before push 4. **Create the Repository:** Click the **Create repository** button. GitHub will then create your new repository and provide you with the repository URL (e.g.``https://github.com/your-username/my-awesome-software.git``). -### Initializing a Git Repository +## Initializing a Git Repository :::{note} When creating a cookiecutter project, it asks for a GitHub username or organization and package name. However this does not initialize a git repository. @@ -173,3 +173,79 @@ git remote add origin https://github.com//my-awesome-software.git git push --set-upstream origin main ``` That\'s it! Your project is now set up and ready to go. 🚀 + +# Modules and Tests + +Your methods and classes would live inside the folder `my_awesome_software`. Split the functionalities into modules, and save them as `.py` files, e.g.: +``` +my_awesome_software + ├── __init__.py + ├── greetings.py + └── math.py +``` + +If you want to import methods and classes from one module to another you can use the dot: +```python +# filename: greetings.py +from .math import subtract_two_integers +``` + +If you want to import all the modules when installing you can add the following to your `__init__.py`: +```python +from . import * +``` + +## Add dependencies +To ensure any dependencies are installed at the same time as installing +your package, add them to your `pyproject.toml` file. E.g. to add `numpy` +and `pandas` as dependencies, add them to the `dependencies = []` list under +the `[project]` heading: + +```toml +dependencies = ["numpy", "pandas"] +``` + +## Write tests + +Write your test methods and classes in the `test` folder. We are using [pytest](https://docs.pytest.org/en/7.2.x/getting-started.html). +In your test module you can call your methods in a simple way: +```python +# filename: test_math.py +from my_awesome_software import math + +# here your test function +``` + +If you're testing a small piece of code, make it a unit test. If you want to test whether two or more software units work well together, create an integration test. + +:::{important} +Before committing your changes +::: +### Run the tests + +Be sure that you have installed pytest and run it +```bash +pip install pytest +pytest +``` +You should also see coverage information. + +### Install your package locally + +For a local, editable install, in the project directory, run: +```bash +pip install -e . +``` + +For a local, editable install with all the development tools (e.g. testing, formatting etc.) run: +```bash +pip install -e '.[dev]' +``` + +You might want to install your package in an _ad hoc_ environment. + +To test if the installation works, try to call your modules with python in another folder from the same environment. +```python +from my_awesome_sofware.math import add_two_integers +add_two_integers(1, 2) +``` diff --git a/docs/source/versioning.md b/docs/source/versioning.md deleted file mode 100644 index 4e72563..0000000 --- a/docs/source/versioning.md +++ /dev/null @@ -1,20 +0,0 @@ -# Versioning - -We recommend the use of [semantic versioning](https://semver.org/), which uses a `MAJOR`.`MINOR`.`PATCH` versiong number where these mean: - -* PATCH = small bugfix -* MINOR = new feature -* MAJOR = breaking change - -## Automated versioning -[`setuptools_scm`](https://github.com/pypa/setuptools_scm) can be used to automatically version your package. It has been pre-configured in the `pyproject.toml` file. [`setuptools_scm` will automatically infer the version using git](https://github.com/pypa/setuptools_scm#default-versioning-scheme). To manually set a new semantic version, create a tag and make sure the tag is pushed to GitHub. Make sure you commit any changes you wish to be included in this version. E.g. to bump the version to `1.0.0`: - -```sh -git add . -git commit -m "Add new changes" -git tag -a v1.0.0 -m "Bump to version 1.0.0" -git push --follow-tags -``` -:::{tip} -It is also possible to perform this step by using the [GitHub web interface or CLI](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository). -::: From eded3540510922bca42de4cc4b501cd92b3aebee Mon Sep 17 00:00:00 2001 From: richarddushime Date: Mon, 10 Mar 2025 23:37:08 +0100 Subject: [PATCH 28/36] Minor Fixes --- ...utter_docs.yml => deployment_workflow.yml} | 2 +- docs/source/conf.py | 15 +++++- docs/source/infrastructure.md | 49 ++++++++++++++++++- docs/source/project_setup.md | 47 +----------------- 4 files changed, 63 insertions(+), 50 deletions(-) rename .github/workflows/{cookiecutter_docs.yml => deployment_workflow.yml} (96%) diff --git a/.github/workflows/cookiecutter_docs.yml b/.github/workflows/deployment_workflow.yml similarity index 96% rename from .github/workflows/cookiecutter_docs.yml rename to .github/workflows/deployment_workflow.yml index 3c6c630..ab1c415 100644 --- a/.github/workflows/cookiecutter_docs.yml +++ b/.github/workflows/deployment_workflow.yml @@ -1,4 +1,4 @@ -name: Documentation +name: Deployment Workflow on: push: branches: diff --git a/docs/source/conf.py b/docs/source/conf.py index 66e0b0d..4a58562 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,8 +1,19 @@ # conf.py # Configuration file for the Sphinx documentation builder. +import setuptools_scm + + project = "python-cookiecutter" copyright = "2025, University College London" author = "Neuroinformatics Unit" +try: + full_version = setuptools_scm.get_version(root="../..", relative_to=__file__) + # Splitting the release on '+' to remove the commit hash + release = full_version.split('+', 1)[0] +except LookupError: + # if git is not initialised, still allow local build + # with a dummy version + release = "0.0.0" # -- General configuration --------------------------------------------------- extensions = [ @@ -73,7 +84,7 @@ }, ], "logo": { - "text": f"{project}", + "text": f"{project} v{release}", }, "footer_start": ["footer_start"], "footer_end": ["footer_end"], @@ -107,7 +118,7 @@ def setup(app):

Sorry, we couldn't find that page.

-

We occasionally restructure the cookiecutter website, and some links may have broken.

+

We occasionally restructure the python-cookiecutter website, and some links may have broken.

Try using the search box or go to the homepage.

""", diff --git a/docs/source/infrastructure.md b/docs/source/infrastructure.md index e106ddc..6e3b8f6 100644 --- a/docs/source/infrastructure.md +++ b/docs/source/infrastructure.md @@ -1,6 +1,53 @@ # Infrastructure -## Pre-commit hooks +## Tests + +Write your test methods and classes in the `test` folder. We are using [pytest](https://docs.pytest.org/en/7.2.x/getting-started.html). +In your test module you can call your methods in a simple way: + +```python +# filename: test_math.py +from my_awesome_software import math + +# here your test function +``` + +If you're testing a small piece of code, make it a unit test. If you want to test whether two or more software units work well together, create an integration test. + +:::{important} +Before committing your changes +::: + +### Run the tests + +Be sure that you have installed pytest and run it +```bash +pip install pytest +pytest +``` +You should also see coverage information. + +### Install your package locally + +For a local, editable install, in the project directory, run: +```bash +pip install -e . +``` + +For a local, editable install with all the development tools (e.g. testing, formatting etc.) run: +```bash +pip install -e '.[dev]' +``` + +You might want to install your package in an _ad hoc_ environment. + +To test if the installation works, try to call your modules with python in another folder from the same environment. +```python +from my_awesome_sofware.math import add_two_integers +add_two_integers(1, 2) +``` + +# Pre-commit hooks Running `pre-commit install` will set up [pre-commit hooks](https://pre-commit.com/) to ensure the code is formatted correctly. Currently, these are: diff --git a/docs/source/project_setup.md b/docs/source/project_setup.md index e51bd03..09f16c5 100644 --- a/docs/source/project_setup.md +++ b/docs/source/project_setup.md @@ -174,7 +174,7 @@ git push --set-upstream origin main ``` That\'s it! Your project is now set up and ready to go. 🚀 -# Modules and Tests +# Modules Your methods and classes would live inside the folder `my_awesome_software`. Split the functionalities into modules, and save them as `.py` files, e.g.: ``` @@ -204,48 +204,3 @@ the `[project]` heading: ```toml dependencies = ["numpy", "pandas"] ``` - -## Write tests - -Write your test methods and classes in the `test` folder. We are using [pytest](https://docs.pytest.org/en/7.2.x/getting-started.html). -In your test module you can call your methods in a simple way: -```python -# filename: test_math.py -from my_awesome_software import math - -# here your test function -``` - -If you're testing a small piece of code, make it a unit test. If you want to test whether two or more software units work well together, create an integration test. - -:::{important} -Before committing your changes -::: -### Run the tests - -Be sure that you have installed pytest and run it -```bash -pip install pytest -pytest -``` -You should also see coverage information. - -### Install your package locally - -For a local, editable install, in the project directory, run: -```bash -pip install -e . -``` - -For a local, editable install with all the development tools (e.g. testing, formatting etc.) run: -```bash -pip install -e '.[dev]' -``` - -You might want to install your package in an _ad hoc_ environment. - -To test if the installation works, try to call your modules with python in another folder from the same environment. -```python -from my_awesome_sofware.math import add_two_integers -add_two_integers(1, 2) -``` From 4a2d4753025a36d94fc0fbba940f5ded4b2ed87f Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Tue, 11 Mar 2025 18:19:42 +0100 Subject: [PATCH 29/36] Update docs/source/index.md Co-authored-by: Adam Tyson --- docs/source/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/index.md b/docs/source/index.md index 05e4682..f3ee57e 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -42,7 +42,7 @@ Installation and Setup. :link-type: doc :text-align: center -Pre-commit hooks, Versioning ,Github Actions & Documentation +Pre-commit hooks, Versioning, GitHub Actions & Documentation ::: :::{grid-item-card} {fas}`handshake-angle;sd-text-primary` Contributing From e82601c2be3e8526cf8dddd07f91bbe99bc73220 Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Tue, 11 Mar 2025 18:20:07 +0100 Subject: [PATCH 30/36] Update docs/source/index.md Co-authored-by: Adam Tyson --- docs/source/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/index.md b/docs/source/index.md index f3ee57e..719da1a 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -34,7 +34,7 @@ tools, including: :link-type: doc :text-align: center -Installation and Setup. +Installation and Setup ::: :::{grid-item-card} {fas}`book-open;sd-text-primary` Infrastructure From 01b656aa04d5b9c158eaea615cb249fb22f3182f Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Tue, 11 Mar 2025 18:20:35 +0100 Subject: [PATCH 31/36] Update docs/source/index.md Co-authored-by: Adam Tyson --- docs/source/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/index.md b/docs/source/index.md index 719da1a..2b50b5c 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -50,7 +50,7 @@ Pre-commit hooks, Versioning, GitHub Actions & Documentation :link-type: doc :text-align: center -Guidelines on How to Contribute. +How to improve the cookiecutter ::: :::: From 56a7686a5be005f9f48c9101b78859ff10f6b2fa Mon Sep 17 00:00:00 2001 From: Richard Dushime <45734838+richarddushime@users.noreply.github.com> Date: Tue, 11 Mar 2025 18:21:02 +0100 Subject: [PATCH 32/36] Update docs/source/contributing.md Co-authored-by: Adam Tyson --- docs/source/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/contributing.md b/docs/source/contributing.md index 18041da..b131a6a 100644 --- a/docs/source/contributing.md +++ b/docs/source/contributing.md @@ -1,7 +1,7 @@ # Contributing Thank you for considering contributing to python-cookiecuttter! We welcome contributions that improve the project, whether it's code, -documentation, or enhancements. +documentation, or anything else. :::{note} To discuss contributing, you can join the [Zulip Channel](https://neuroinformatics.zulipchat.com/#narrow/channel/406003-Python-cookiecutter) here. From 8575e62daf9b146dda30c8e578d1112e7de89b20 Mon Sep 17 00:00:00 2001 From: richarddushime Date: Tue, 11 Mar 2025 18:45:20 +0100 Subject: [PATCH 33/36] Final --- .github/workflows/deployment_workflow.yml | 35 --------------- .github/workflows/docs_build_and _deploy.yml | 46 ++++++++++++++++++++ docs/source/_templates/footer_end.html | 4 +- docs/source/_templates/footer_start.html | 4 +- docs/source/conf.py | 2 +- 5 files changed, 51 insertions(+), 40 deletions(-) delete mode 100644 .github/workflows/deployment_workflow.yml create mode 100644 .github/workflows/docs_build_and _deploy.yml diff --git a/.github/workflows/deployment_workflow.yml b/.github/workflows/deployment_workflow.yml deleted file mode 100644 index ab1c415..0000000 --- a/.github/workflows/deployment_workflow.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Deployment Workflow -on: - push: - branches: - - main - tags: - - '*' - pull_request: - workflow_dispatch: - -jobs: - deploy-docs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.13' - - - name: Install dependencies - run: | - pip install -r docs/requirements.txt - - - name: Build docs - run: | - cd docs - make clean && make html - - - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/build/html diff --git a/.github/workflows/docs_build_and _deploy.yml b/.github/workflows/docs_build_and _deploy.yml new file mode 100644 index 0000000..528408c --- /dev/null +++ b/.github/workflows/docs_build_and _deploy.yml @@ -0,0 +1,46 @@ +name: Build and Deploy Sphinx Docs + +# Generate the documentation on all merges to main, all pull requests, or by +# manual workflow dispatch. The build job can be used as a CI check that the +# docs still build successfully. The deploy job only runs when a tag is +# pushed and actually moves the generated html to the gh-pages branch +# (which triggers a GitHub pages deployment). +on: + push: + branches: + - main + tags: + - '*' + pull_request: + merge_group: + workflow_dispatch: + +jobs: + linting: + # scheduled workflows should not run on forks + if: (${{ github.event_name == 'schedule' }} && ${{ github.repository_owner == 'neuroinformatics-unit' }} && ${{ github.ref == 'refs/heads/main' }}) || (${{ github.event_name != 'schedule' }}) + runs-on: ubuntu-latest + steps: + - uses: neuroinformatics-unit/actions/lint@v2 + + build_sphinx_docs: + name: Build Sphinx Docs + runs-on: ubuntu-latest + steps: + - uses: neuroinformatics-unit/actions/build_sphinx_docs@main + with: + python-version: 3.12 + use-make: true + + deploy_sphinx_docs: + name: Deploy Sphinx Docs + needs: build_sphinx_docs + permissions: + contents: write + if: (github.event_name == 'push' && github.ref_type == 'tag') || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + steps: + - uses: neuroinformatics-unit/actions/deploy_sphinx_docs@main + with: + secret_input: ${{ secrets.GITHUB_TOKEN }} + use-make: true diff --git a/docs/source/_templates/footer_end.html b/docs/source/_templates/footer_end.html index 09104d7..bc74856 100644 --- a/docs/source/_templates/footer_end.html +++ b/docs/source/_templates/footer_end.html @@ -1,7 +1,7 @@
- + Sponsors Sponsors -

python-cookiecutter is based on cookiecutter-napari-plugin.

+

python-cookiecutter is based on cookiecutter-napari-plugin.

diff --git a/docs/source/_templates/footer_start.html b/docs/source/_templates/footer_start.html index e078fd3..f1592be 100644 --- a/docs/source/_templates/footer_start.html +++ b/docs/source/_templates/footer_start.html @@ -1,9 +1,9 @@

- {% trans sphinx_version=sphinx_version|e %}Created using Sphinx {{ sphinx_version }}.{% endtrans %} + {% trans sphinx_version=sphinx_version|e %}Created using Sphinx {{ sphinx_version }}.{% endtrans %}

{{ _("Built with the") }} - PyData Sphinx Theme + PyData Sphinx Theme {{ theme_version }}.

diff --git a/docs/source/conf.py b/docs/source/conf.py index 4a58562..4a4ed62 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -84,7 +84,7 @@ }, ], "logo": { - "text": f"{project} v{release}", + "text": f"{project}", }, "footer_start": ["footer_start"], "footer_end": ["footer_end"], From 0717d5dbc529045be92debde4c1e1d46cb3f68c0 Mon Sep 17 00:00:00 2001 From: richarddushime Date: Wed, 12 Mar 2025 16:09:13 +0100 Subject: [PATCH 34/36] lints errors fix --- docs/source/conf.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 4a4ed62..24fe6a6 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -93,7 +93,7 @@ # Sitemap configuration github_user = "neuroinformatics-unit" -html_baseurl = "https://neuroinformatics-unit.github.io/python-cookiecutter/" +html_baseurl = "https://python-cookiecutter.neuroinformatics.dev" sitemap_url_scheme = "{link}" @@ -127,3 +127,16 @@ def setup(app): # needed for GH pages (vs readthedocs), # because we have no '///' in the URL notfound_urls_prefix = None + +# The linkcheck builder will skip verifying that anchors exist when checking +# these URLs +linkcheck_anchors_ignore_for_url = [ + "https://neuroinformatics.zulipchat.com/", + "https://neuroinformatics.zulipchat.com/#narrow/channel/406003-Python-cookiecutter", + "https://github.com/pypa/setuptools_scm#default-versioning-scheme", +] +# A list of regular expressions that match URIs that should not be checked +linkcheck_ignore = [ + "https://github.com/", + "https://opensource.org/license/bsd-3-clause/", # to avoid odd 403 error +] From 92ccf06f397db84b1a5b0c23239e90860da75248 Mon Sep 17 00:00:00 2001 From: richarddushime Date: Wed, 12 Mar 2025 16:29:58 +0100 Subject: [PATCH 35/36] lints fix --- .gitattributes | 1 - docs/.nojekyll | 0 2 files changed, 1 deletion(-) delete mode 100644 docs/.nojekyll diff --git a/.gitattributes b/.gitattributes index 6313b56..e69de29 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +0,0 @@ -* text=auto eol=lf diff --git a/docs/.nojekyll b/docs/.nojekyll deleted file mode 100644 index e69de29..0000000 From 865fff719222199d85518b70edbf7f70d515577a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 12 Mar 2025 15:40:30 +0000 Subject: [PATCH 36/36] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/CNAME | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/CNAME b/docs/CNAME index db786b8..03c5e00 100644 --- a/docs/CNAME +++ b/docs/CNAME @@ -1 +1 @@ -python-cookiecutter.neuroinformatics.dev \ No newline at end of file +python-cookiecutter.neuroinformatics.dev