2 | pyOpensci is dedicated to creating a welcoming, supportive and diverse
3 | community around the open source Python tools that drive open science. Our
4 | Code of Conduct
9 | defines expected behavior and guidelines that help create such a community.
10 |
11 |
--------------------------------------------------------------------------------
/_templates/language-selector.html:
--------------------------------------------------------------------------------
1 | {%- macro langlink(lang, selected=False) -%} {%- if lang == "en" %}
2 |
13 | {%- else %}
14 |
25 | {%- endif -%} {%- endmacro -%}
26 |
31 |
--------------------------------------------------------------------------------
/bibliography.bib:
--------------------------------------------------------------------------------
1 | @article{hunterReclaimingComputingCommons2016,
2 | title = {Reclaiming the {{Computing Commons}}},
3 | author = {Hunter, Rob},
4 | year = {2016},
5 | month = may,
6 | journal = {Jacobin},
7 | url = {https://jacobin.com/2016/02/free-software-movement-richard-stallman-linux-open-source-enclosure/},
8 | urldate = {2023-03-09},
9 | abstract = {Resisting the commodification of information is a political struggle, not a technical one.},
10 | archive = {https://web.archive.org/web/20230309005744/https://jacobin.com/2016/02/free-software-movement-richard-stallman-linux-open-source-enclosure/},
11 | langid = {american},
12 | keywords = {foss culture,copyleft}
13 | }
14 |
15 | @misc{gnuprojectWhatFreeSoftware2019,
16 | title = {What Is {{Free Software}}?},
17 | author = {{GNU Project}},
18 | year = {2019},
19 | month = jul,
20 | journal = {Free Software Foundation},
21 | url = {https://www.gnu.org/philosophy/free-sw.html},
22 | urldate = {2024-03-01}
23 | }
24 |
25 | @misc{gnuprojectWhatCopyleft2022,
26 | title = {What Is {{Copyleft}}?},
27 | author = {{GNU Project}},
28 | year = {2022},
29 | month = jan,
30 | journal = {Free Software Foundation},
31 | url = {https://www.gnu.org/copyleft/},
32 | urldate = {2024-03-01}
33 | }
34 |
35 | @misc{creativecommonsShareAlikeCompatibilityGPLv32015,
36 | title = {{{ShareAlike}} Compatibility: {{GPLv3}}},
37 | author = {{Creative Commons}},
38 | year = {2015},
39 | month = sep,
40 | journal = {Creative Commons Wiki},
41 | url = {https://wiki.creativecommons.org/wiki/ShareAlike_compatibility:_GPLv3},
42 | urldate = {2024-03-02}
43 | }
44 |
--------------------------------------------------------------------------------
/codespell-ignore.txt:
--------------------------------------------------------------------------------
1 | aways
2 | Soler
3 |
--------------------------------------------------------------------------------
/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | #
13 | import os
14 | import sys
15 | sys.path.insert(0, os.path.abspath('.'))
16 | from datetime import datetime
17 | import subprocess
18 | import os
19 | from typing import TYPE_CHECKING
20 | from _ext import rss
21 |
22 | if TYPE_CHECKING:
23 | from sphinx.application import Sphinx
24 |
25 | current_year = datetime.now().year
26 | organization_name = "pyOpenSci"
27 |
28 | # env vars
29 | sphinx_env = os.environ.get("SPHINX_ENV", "development")
30 | language_env = os.environ.get("SPHINX_LANG", "en")
31 |
32 |
33 | # -- Project information -----------------------------------------------------
34 |
35 | project = "pyOpenSci Python Package Guide"
36 | copyright = f"{current_year}, {organization_name}"
37 | author = "pyOpenSci Community"
38 |
39 | # Language of the current build
40 | # language can later be overridden (eg with the -D flag)
41 | # but we need it set here so it can make it into the html_context
42 | language = language_env
43 | # all languages that have .po files generated for them
44 | # (excluding english)
45 | languages = ["es", "ja"]
46 | # the languages that will be included in a production build
47 | # (also excluding english)
48 | release_languages = ["ja"]
49 |
50 | # languages that will be included in the language dropdown
51 | # (ie. all that are being built in this nox build session)
52 | if sphinx_env == "production":
53 | build_languages = ["en"] + release_languages
54 | else:
55 | build_languages = ["en"] + languages
56 |
57 | # Get the latest Git tag - there might be a prettier way to do this but...
58 | try:
59 | release_value = (
60 | subprocess.check_output(["git", "describe", "--tags"])
61 | .decode("utf-8")
62 | .strip()
63 | )
64 | release_value = release_value[:4]
65 | except subprocess.CalledProcessError:
66 | release_value = "0.1" # Default value in case there's no tag
67 |
68 | # Update the release value
69 | release = release_value
70 |
71 | # -- General configuration ---------------------------------------------------
72 |
73 | # Add any Sphinx extension module names here, as strings. They can be
74 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
75 | # ones.
76 | extensions = [
77 | "myst_nb",
78 | "sphinx_design",
79 | "sphinx_copybutton",
80 | "sphinx.ext.intersphinx",
81 | "sphinx.ext.todo",
82 | "sphinx_sitemap",
83 | "sphinxext.opengraph",
84 | "sphinx_favicon",
85 | "sphinxcontrib.bibtex",
86 | ]
87 |
88 | # colon fence for card support in md
89 | myst_enable_extensions = [
90 | "colon_fence",
91 | "deflist",
92 | "attrs_block",
93 | ]
94 | myst_heading_anchors = 3
95 | myst_footnote_transition = False
96 |
97 | # Sphinx_favicon is used now in favor of built in support
98 | # https://pypi.org/project/sphinx-favicon/
99 | favicons = [
100 | {"href": "https://www.pyopensci.org/images/favicon.ico"},
101 | ]
102 |
103 | html_baseurl = "https://www.pyopensci.org/python-package-guide/"
104 | lang_selector_baseurl = "/python-package-guide/"
105 | if not sphinx_env == "production":
106 | # for links in language selector when developing locally
107 | lang_selector_baseurl = "/"
108 |
109 | html_theme_options = {
110 | "announcement": "
",
111 | # "navbar_center": ["nav"], this can be a way to override the default navigation structure
112 | "external_links": [
113 | {
114 | "url": "https://www.pyopensci.org",
115 | "name": "pyOpenSci Website",
116 | },
117 | {
118 | "url": "https://www.pyopensci.org/software-peer-review",
119 | "name": "Peer Review Guide",
120 | },
121 | {
122 | "url": "https://pyopensci.org/handbook",
123 | "name": "Handbook",
124 | },
125 | ],
126 | "icon_links": [
127 | {
128 | "name": "Mastodon",
129 | "url": "https://fosstodon.org/@pyOpenSci",
130 | "icon": "fa-brands fa-mastodon",
131 | },
132 | ],
133 | "logo": {
134 | # "text": "Python Packaging",
135 | "image_dark": "logo-dark-mode.png",
136 | "image_light": "logo-light-mode.png",
137 | "alt_text": "pyOpenSci Python Package Guide. The pyOpenSci logo is a purple flower with pyOpenSci under it. The o in open sci is the center of the flower",
138 | },
139 | "header_links_before_dropdown": 5,
140 | "use_edit_page_button": True,
141 | "show_nav_level": 2,
142 | "navigation_depth": 3,
143 | "show_toc_level": 1,
144 | # "navbar_align": "left", # [left, content, right] For testing that the navbar items align properly
145 | "github_url": "https://github.com/pyopensci/python-package-guide",
146 | "footer_start": ["code_of_conduct", "copyright"],
147 | "footer_end": [],
148 | "navbar_persistent": ["language-selector", "search-button"]
149 | }
150 |
151 | html_context = {
152 | "github_user": "pyopensci",
153 | "github_repo": "python-package-guide",
154 | "github_version": "main",
155 | "language": language,
156 | "languages": build_languages,
157 | "baseurl": lang_selector_baseurl,
158 | }
159 |
160 | # Add any paths that contain templates here, relative to this directory.
161 | templates_path = ["_templates"]
162 |
163 | # List of patterns, relative to source directory, that match files and
164 | # directories to ignore when looking for source files.
165 | # This pattern also affects html_static_path and html_extra_path.
166 | exclude_patterns = [
167 | "_build",
168 | "Thumbs.db",
169 | ".DS_Store",
170 | ".github",
171 | ".nox",
172 | "README.md",
173 | "styles/write-good/README.md",
174 | "styles/*",
175 | ".pytest_cache/README.md",
176 | "vale-styles/*",
177 | "CODE_OF_CONDUCT.md",
178 | ]
179 |
180 | # For sitemap generation
181 |
182 | sitemap_url_scheme = "{link}"
183 |
184 | # -- Options for HTML output -------------------------------------------------
185 |
186 | # The theme to use for HTML and HTML Help pages. See the documentation for
187 | # a list of builtin themes.
188 | #
189 | html_theme = "pydata_sphinx_theme"
190 | html_static_path = ["_static"]
191 | html_css_files = ["pyos.css"]
192 | html_title = "Python Packaging Guide"
193 | html_js_files = ["matomo.js", "language_select.js"]
194 |
195 |
196 | # Social cards
197 | ogp_site_url = "https://www.pyopensci.org/python-package-guide/"
198 | ogp_social_cards = {
199 | "line_color": "#6D597A",
200 | "image": "_static/pyopensci-logo-package-guide.png",
201 | }
202 |
203 | # Bibliographies
204 | bibtex_bibfiles = ["bibliography.bib"]
205 | # myst complains about bibtex footnotes because of render order
206 | suppress_warnings = ["myst.footnote"]
207 |
208 |
209 | def _post_build(app: "Sphinx", exception: Exception | None) -> None:
210 | rss.generate_tutorials_feed(app)
211 |
212 |
213 | def setup(app: "Sphinx"):
214 | app.connect("build-finished", _post_build)
215 |
216 | # Parallel safety: https://www.sphinx-doc.org/en/master/extdev/index.html#extension-metadata
217 | return {"parallel_read_safe": True, "parallel_write_safe": True}
218 |
--------------------------------------------------------------------------------
/continuous-integration/ci.md:
--------------------------------------------------------------------------------
1 | (ci-cd)=
2 | # Continuous Integration and Continuous Deployment (CI/CD) For Python Packages
3 |
4 | When you develop, work on, and contribute to software, there is more to consider than
5 | just writing code. Having tests and checks ensures that your code
6 | runs reliably and follows a consistent format is also important. You can use
7 | **Continuous Integration (CI)** and **Continuous
8 | Deployment (CD)** to run tests and checks on your code every time someone suggests a change online
9 | in a platform like GitHub or GitLab.
10 |
11 | - **Continuous Integration (CI):** Automates the process of running tests,
12 | code checks, and other workflows each time code is updated.
13 | - **Continuous Deployment (CD):** Extends CI by allowing you to automate publishing your package to PyPI, publishing your documentation, and more.
14 |
15 | CI and CD streamline software development by automating repetitive
16 | tasks and ensuring code quality and consistency. Having CI setup also makes it easier for new contributors
17 | to contribute to your code base without setting up all your test suites and
18 | other local checks.
19 |
20 | ## What is continuous integration?
21 |
22 | When you’re ready to publish your code online, you can set up Continuous Integration (CI). CI is a platform that allows you to specify and run jobs or workflows you define.
23 | These workflows include:
24 |
25 | - Running your test suite
26 | - Running code checkers / linters / spellcheck
27 | - Building your documentation
28 |
29 | CI allows you to automate running workflows across a suite of environments, including:
30 |
31 | - environments containing different Python versions and
32 | - different operating systems (Mac, Linux, Windows).
33 |
34 | ## What is Continuous Deployment (CD)?
35 |
36 | Continuous deployment (CD) extends the CI process by automating the deployment of code changes to production or staging environments. In the case of your open source tool, CD can be used to:
37 |
38 | - Automate publishing to PyPI
39 | - Automate publishing your documentation to GitHub Pages or Read the Docs.
40 |
41 | It is also used once your conda-forge recipe is set up to keep your package up to date on conda-forge.
42 |
43 | ### Why use CI
44 |
45 | CI can be configured to run a workflow on every commit pushed to GitHub and every pull request opened. This ensures that any changes made to your package are tested across environments before merging into the main branch of your code.
46 |
47 | These checks are particularly useful if someone new is contributing to your code. Every contributor's change will be tested when pushed to your code repository.
48 |
49 | Together, CI and CD streamline the process of building, testing, and deploying code. They aim to improve software development and publication efficiency, quality, and reliability.
50 |
51 | ```{note}
52 | All pyOpenSci packages must use some form of continuous integration. Even if you are not planning to go through peer review, we strongly recommend that you use continuous integration, too!
53 | ```
54 |
55 | In the case of GitHub actions (which we will focus on here), CI workflows are running on online servers that support GitHub.
56 |
57 | ## CI / CD platforms
58 |
59 | There are numerous platforms available for CI/CD. Here, we will focus on GitHub Actions (GHA), built into GitHub. GitHub is the most commonly used platform to store scientific open-source software.
60 |
61 | :::{note}
62 | If you use [GitLab](https://about.gitlab.com/) CI/CD, many of the principles described here will apply. However, the workflow files may look different.
63 | :::
64 |
65 | ### If you aren't sure, use GitHub Actions
66 |
67 | While you are welcome to use the continuous integration platform of your choice,
68 | we recommend GitHub Actions because it is free-to-use and integrated tightly
69 | into the GitHub user interface. There is also an entire store of GitHub action
70 | templates that you can easily use and adapt to your own needs.
71 |
72 | :::{admonition} Other platforms that you may run into
73 | :class: info
74 |
75 | - [Appveyor:](https://www.appveyor.com/): Supports running tests on Windows operating systems and predated the release of GitHub Actions. Today, AppVeyor supports operating systems beyond Windows.
76 | - [Travis CI:](https://www.travis-ci.com/) had been a common CI platform choice in our ecosystem. Usage dropped after Travis CI ended free support for open-source projects.
77 | - [CircleCI:](https://circleci.com/) CircleCI can be useful for automated builds of websites and documentation since it offers a preview of the PR changes.
78 | :::
79 |
80 | ## Embrace automation
81 |
82 | By embracing CI/CD, you can ensure that your code runs as you expect it to across the diverse landscapes of user environments. Further, you can
83 | automate certain checks (and, in some cases, code fixes), including linting and code style. You can even automate spell-checking your documentation
84 | and docstrings!
85 |
--------------------------------------------------------------------------------
/continuous-integration/index.md:
--------------------------------------------------------------------------------
1 | (ci-cd-intro)=
2 | # Continuous Integration (CI) and Continuous Deployment (CD) for your Python package
3 |
4 |
5 | :::{toctree}
6 | :caption: Continuous Integration
7 |
8 |
9 | What is CI?
10 | :::
11 |
--------------------------------------------------------------------------------
/crowdin.yml:
--------------------------------------------------------------------------------
1 | project_id: 785976
2 | api_token: "${{ secrets.CROWDIN_PERSONAL_TOKEN }}"
3 | files:
4 | - source: /locales/en/LC_MESSAGES/messages.po
5 | translation: /locales/%two_letters_code%/LC_MESSAGES/messages.po
6 | type: gettext
7 |
--------------------------------------------------------------------------------
/documentation/hosting-tools/intro.md:
--------------------------------------------------------------------------------
1 | # Tools to Build and Host your Documentation
2 |
3 | The most common tool for building documentation in the Python
4 | ecosystem currently is Sphinx. However, some maintainers
5 | are using tools like [mkdocs](https://www.mkdocs.org/) for documentation. It is
6 | up to you to use the platform that you prefer for your documentation!
7 |
8 | In this section, we introduce Sphinx as a common tool to
9 | build documentation. We talk about various syntax options that you can use
10 | when writing Sphinx documentation including mySt and rST.
11 |
12 | We also talk about ways to publish your
13 | documentation online and Sphinx tools that might help you optimize
14 | your documentation website.
15 |
--------------------------------------------------------------------------------
/documentation/hosting-tools/myst-markdown-rst-doc-syntax.md:
--------------------------------------------------------------------------------
1 | # Documentation syntax: markdown vs. myST vs. rst syntax to create your docs
2 |
3 | There are three commonly used syntaxes for creating Python documentation:
4 | 1. [markdown](https://www.markdownguide.org/): Markdown is an easy-to-learn text
5 | syntax. It is the default syntax used in Jupyter Notebooks. There are tools that you can add to a Sphinx website that allow it to render markdown as html. However, using markdown to write documentation has limitations. For instance if you want to add references,
6 | colored call out blocks and other custom elements to your documentation, you will
7 | need to use either **myST** or **rST**.
8 | 1. [rST (ReStructured Text):](https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html). **rST** is the native syntax that sphinx supports. rST was the default syntax used for documentation for many years. However, in recent years myST has risen to the top as a favorite for documentation given the flexibility that it allows.
9 | 1. [myST:](https://myst-parser.readthedocs.io/en/latest/intro.html) myST is a combination of `markdown` and `rST` syntax. It is a nice option if you are comfortable writing markdown. `myst` is preferred by many because it offers both the rich functionality
10 | of rST combined with a simple-to-write markdown syntax.
11 |
12 | While you can chose to use any of the syntaxes listed above, we suggest using
13 | `myST` because:
14 |
15 | * It is a simpler syntax and thus easier to learn;
16 | * The above simplicity will make it easier for more people to contribute to your documentation.
17 | * Most of your core Python package text files, such as your README.md file, are already in `.md` format
18 | * `GitHub` and `Jupyter Notebooks` support markdown thus it's more widely used in the scientific ecosystem.
19 |
20 |
21 | ```{tip}
22 | If you are on the fence about myST vs rst, you might find that **myST** is easier
23 | for more people to contribute to.
24 | ```
25 |
26 |
30 |
--------------------------------------------------------------------------------
/documentation/hosting-tools/publish-documentation-online.md:
--------------------------------------------------------------------------------
1 | # How to publish your Python package documentation online
2 |
3 | We suggest that you setup a hosting service for your Python package
4 | documentation. Two free and commonly used ways to
5 | quickly create a documentation website hosting environment are below.
6 |
7 | 1. You can host your documentation yourself using [GitHub Pages](https://pages.github.com/) or another online hosting service.
8 | 1. You can host your documentation using [Read the Docs](https://readthedocs.org/).
9 |
10 | ## What is Read the Docs ?
11 | [Read the Docs](https://readthedocs.org/) is a documentation hosting service that supports publishing your project's documentation.
12 |
13 | Read the Docs is a fully featured, free, documentation hosting
14 | service. Some of its many features include:
15 |
16 | * Is free to host your documentation (but there are also paid tiers if you wish to customize hosting)
17 | * Automates building your documentation
18 | * Allows you to turn on integration with pull requests where you can view documentation build progress (success vs failure).
19 | * Supports versioning of your documentation which allows users to refer to older tagged versions of the docs if they are using older versions of your package.
20 | * Supports downloading of documentation in PDF and other formats.
21 | * You can customize the documentation build using a **.readthedocs.yaml** file in your GitHub repository.
22 |
23 |
24 | ## What is GitHub Pages?
25 | [GitHub Pages](https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages) is a free web
26 | hosting service offered by GitHub. Using GitHub pages, you can build your
27 | documentation locally or using a Continuous Integration setup, and then push
28 | to a branch in your GitHub repository that is setup to run the GitHub Pages
29 | web build.
30 |
31 |
32 |
33 | ## Read the Docs vs GitHub Pages
34 |
35 | GitHub pages is a great option for your documentation deployment.
36 | However, you will need to do a bit more work to build and deploy your
37 | documentation if you use GitHub pages.
38 |
39 | Read the Docs can be setup in your Read the Docs user account. The service
40 | automates the entire process of building and deploying your documentation.
41 |
42 | If you don't want to maintain a documentation website for your Python package,
43 | we suggest using the Read the Docs website.
44 |
--------------------------------------------------------------------------------
/documentation/hosting-tools/sphinx-python-package-documentation-tools.md:
--------------------------------------------------------------------------------
1 | # Using Sphinx to Build Python Package Documentation
2 |
3 |
5 |
16 |
17 | On this page we discuss using [Sphinx](https://www.sphinx-doc.org/) to build your user-facing
18 | package documentation. While Sphinx is currently the most
19 | commonly-used tool in the scientific Python ecosystem, you
20 | are welcome to explore other tools to build documentation
21 | such as [mkdocs](https://www.mkdocs.org/) which is gaining
22 | popularity in the Python packaging ecosystem.
23 |
24 | ```{tip}
25 | Examples of documentation websites that we love:
26 |
27 | * [GeoPandas](https://geopandas.org/en/stable/)
28 | * [View rst to create landing page](https://raw.githubusercontent.com/geopandas/geopandas/main/doc/source/index.rst)
29 | * [verde](https://www.fatiando.org/verde/latest/)
30 | * [View verde landing page code - rst file.](https://github.com/fatiando/verde/blob/main/doc/index.rst)
31 | * [Here is our documentation if you want to see a myST example of a landing page.](https://github.com/pyOpenSci/python-package-guide/blob/main/index.md)
32 | ```
33 |
34 | ## Sphinx - a static site generator
35 |
36 | Sphinx is a [static-site generator](https://www.cloudflare.com/learning/performance/static-site-generator/). A static site generator is a tool that creates
37 | html for a website based upon a set of templates. The html files are then served "Statically" which means that there is no generation or modification of the files on the fly.
38 |
39 | Sphinx is written using Python.
40 |
41 | ### Sphinx sites can be customized using extensions and themes
42 |
43 | The functionality of Sphinx can be extended using extensions
44 | and themes. A few examples include:
45 |
46 | * You can apply documentation themes for quick generation of beautiful documentation.
47 | * You can [automatically create documentation for your package's functions and classes (the package's API) from docstrings in your code using the autodoc extension](https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html)
48 | * You can [run and test code examples in your docstrings using the doctest extension](https://www.sphinx-doc.org/en/master/usage/extensions/doctest.html)
49 | * While Sphinx natively supports the `rST` syntax, you can add custom syntax parsers to support easier-to-write syntax using tools such as [the MyST parser](https://myst-parser.readthedocs.io/).
50 |
51 | ### Commonly used Sphinx themes
52 |
53 | You are free to use whatever Sphinx theme that you prefer.
54 | However, the most common Sphinx themes used in the Python
55 | scientific community include:
56 |
57 | * [pydata-sphinx-theme](https://pydata-sphinx-theme.readthedocs.io/)
58 | * [sphinx-book-theme](https://sphinx-book-theme.readthedocs.io/)
59 | * [furo](https://pradyunsg.me/furo/quickstart/)
60 |
61 |
62 | ```{tip}
63 | This book is created using Sphinx and the `furo` theme.
64 | ```
65 |
66 |
--------------------------------------------------------------------------------
/documentation/hosting-tools/website-hosting-optimizing-your-docs.md:
--------------------------------------------------------------------------------
1 | # Optimizing your documentation so search engines (and other users) find it
2 |
3 | If you are interested in more people finding your package, you may want to
4 | add some core Sphinx extensions (and theme settings) that will help search
5 | engines such as Google find your documentation.
6 |
7 | ## Google Analytics
8 |
9 | ```{important}
10 |
11 | Google analytics [is not compliant with the European General Data Protection Regulation (GDPR)](https://matomo.org/blog/2022/05/google-analytics-4-gdpr/). While there are many components to this regulation, one of the core elements is that you have to let users know on your site that you are collecting data and they have to consent. While it is possible to add infrastructure around Google Analytics to make it close to following GDPR regulations, the community is slowly shifting away from Google using open tools such as [Plausible](https://plausible.io/), [Cloudflare Web Analytics](https://www.cloudflare.com/web-analytics/) and [Matomo](https://matomo.org) for web analytics.
12 |
13 | pyOpenSci is currently looking into free options for open source
14 | developers.
15 | ```
16 | Some of the [sphinx themes such as the `pydata-sphinx-theme` and
17 | sphinx-book-theme have built in support for Google Analytics](https://pydata-sphinx-theme.readthedocs.io/en/latest/user_guide/analytics.html#google-analytics). However, if the theme that you chose does not offer
18 | Google Analytics support, you can use the [`sphinxcontrib-gtagjs` extension](https://github.com/attakei/sphinxcontrib-gtagjs).
19 | This extension will add a Google Analytics site tag to each page of your
20 | documentation.
21 |
22 | ### [sphinx-sitemap](https://sphinx-sitemap.readthedocs.io/en/latest/index.html) for search engine optimization
23 |
24 | While we are trying to move away from Google Analytics do
25 | to compliance and privacy issues, search engine optimization
26 | is still important. Google is the most popular search engine.
27 | And if your documentation is search optimized, users are more
28 | likely to find your package!
29 |
30 | If you are interested in optimizing your documentation for
31 | search engines such as Google, you want a **sitemap.xml** file.
32 | You can submit this sitemap to Google and it will index your
33 | entire site. This over time can make the content on your site
34 | more visible to others when they search.
35 |
36 | This extension is lightweight.
37 |
38 | It [requires that you to add it to your Sphinx `conf.py` extension list and site your documentation base url](https://sphinx-sitemap.readthedocs.io/en/latest/getting-started.html).
39 |
40 | ### [sphinxext.opengraph](https://github.com/wpilibsuite/sphinxext-opengraph)
41 |
42 | OpenGraph is an extension that allows you to add metadata to your documentation
43 | content pages. [The OpenGraph protocol allows other websites to provide a
44 | useful preview of the content on your page when shared](https://www.freecodecamp.org/news/what-is-open-graph-and-how-can-i-use-it-for-my-website/#heading-what-is-open-graph). This is important
45 | for when the pages in your documentation are shared on social
46 | media sites like Twitter and Mastodon and even for shares on
47 | tools like Slack and Discourse.
48 |
--------------------------------------------------------------------------------
/documentation/index.md:
--------------------------------------------------------------------------------
1 | # Documentation for your Open Source Python Package
2 |
3 | :::{toctree}
4 | :hidden:
5 | :caption: Intro
6 |
7 | Documentation Overview
8 | :::
9 |
10 | ```{toctree}
11 | :hidden:
12 | :maxdepth: 2
13 | :caption: Write User Documentation
14 |
15 | Intro
16 | Create Your Docs
17 | Document Your Code (API)
18 | Create Package Tutorials
19 | ```
20 |
21 | ```{toctree}
22 | :hidden:
23 | :caption: Docs for Contributors & Maintainers
24 | :maxdepth: 2
25 |
26 | Intro
27 | Contributing File
28 | Development Guide
29 | Changelog File
30 | ```
31 |
32 | ```{toctree}
33 | :hidden:
34 | :caption: Community Docs
35 | :maxdepth: 2
36 |
37 | README file
38 | Code of Conduct File
39 | LICENSE files
40 | ```
41 |
42 | ```{toctree}
43 | :maxdepth: 2
44 | :hidden:
45 | :caption: Publication tools for your docs
46 |
47 | Intro
48 | Sphinx for Docs
49 | myST vs Markdown vs rst
50 | Publish Your Docs
51 | Website Hosting and Optimization
52 | ```
53 |
54 | ```{important}
55 | Please note that the tools discussed here are those that
56 | we see commonly used in the community. As tools evolve we
57 | will update this guide. If you are submitting a package for
58 | pyOpenSci peer review and use other tools that are not listed
59 | in our guide to build your package you can still submit for
60 | review! The tools listed here are suggestions, not
61 | requirements. Our requirements are focused on the
62 | documentation content of your package.
63 | ```
64 |
65 | ## Documentation is critical for your Python package's success
66 |
67 | Documentation is as important to the success of your Python open source package
68 | as the code itself.
69 |
70 | Quality code is of course valuable as its how your package gets the tasks done. However, if users don't understand
71 | how to use your package in their workflows, then they won't use it.
72 |
73 | Further, explicitly documenting how to contribute is important if you wish
74 | to build a base of contributors to your package.
75 |
76 | ## Two types of Python package users
77 |
78 | The documentation that you write for your
79 | package should target two types of users:
80 |
81 | ### 1. Basic Tool Users
82 |
83 | Basic tool users are the people who will use your package code in their
84 | Python workflows. They might be new(er) to Python and/or data science. Or
85 | expert programmers. But they might not have a background in software
86 | development. These users need to know:
87 |
88 | - How to install your package
89 | - How to install dependencies that your package requires
90 | - How to get started using the code base
91 | - Information on how to cite your code / give you credit if they are using it
92 | in a research application.
93 | - Information on the license that your code uses so they know how they can
94 | or can't use the code in an operational setting.
95 |
96 | ### 2. Potential tool contributors
97 |
98 | The other subset of users are more experienced and/or more engaged
99 | with your package. As such they are
100 | potential contributors. These users:
101 |
102 | - might have a software development background,
103 | - might also be able to contribute bug fixes to your package or updates to your documentation
104 | - might also just be users who will find spelling errors in your documentation, or bugs in your tutorials.
105 |
106 | These users need all of the things that a basic user needs. But, they
107 | also need to understand how you'd like for them to contribute to your
108 | package. These potential contributors need:
109 |
110 | - A development guide to help them understand the infrastructure used in your package repository.
111 | - Contributing guidelines that clarify the types of contributions that you welcome and how you'd prefer those contributions to be submitted.
112 |
113 | ```{important}
114 | It's important to remember that the definition of what a contribution is can be
115 | broad. A contribution could be something as simple as a bug report. Or fixing a
116 | spelling issue in your documentation. Or it could be a code fix that includes a
117 | new test that covers an edge-case that they discovered.
118 | ```
119 |
120 | ## Documentation elements that pyOpenSci looks for reviewing a Python package
121 |
122 | In the pyOpenSci open peer review, we look for
123 | a documentation structure that supports both your tool users and potential
124 | contributors. The files and elements that we look for specifically can be
125 | found in our peer review check list (see link below).
126 |
127 | In this guide, we discuss each required element, and also discuss other elements
128 | that you should consider in your package's documentation in more detail.
129 |
130 |
131 | ```{button-link} https://www.pyopensci.org/software-peer-review/how-to/editor-in-chief-guide.html#editor-checklist-template
132 | :color: primary
133 | :class: sd-rounded-pill float-left
134 | View pyOpenSci peer review check list
135 | ```
136 |
137 |
138 | ```{figure} ../images/moving-pandas-python-package-github-main-repo.png
139 | ---
140 | name: moving-pandas-github-repo-image
141 | width: 80%
142 | alt: Image showing the files in the the MovingPandas GitHub repository. Files in the image include code of conduct.md contributing.md license.txt and readme.md.
143 | ---
144 | An example from the MovingPandas GitHub repository with all of the major files in it including CONTRIBUTING.md, README.md, CODE_OF_CONDUCT.md and a LICENSE.txt file. *(screen shot taken Nov 23 2022)*
145 | ```
146 |
147 | ## What's next in this Python package documentation section?
148 |
149 | In this section of the pyOpenSci package guide, we will walk
150 | you through best practices for setting up
151 | documentation for your Python package. We will also suggest
152 | tools that you can use to build your user-facing documentation website.
153 |
154 | :::{todo}
155 |
156 | Python version support
157 | You should always be explicit about which versions of Python your package supports.
158 | Keeping compatibility with old Python versions can be difficult as functionality changes.
159 | A good rule of thumb is that the package should support, at least,
160 | the latest three Python versions (e.g., 3.8, 3.7, 3.6).
161 | :::
162 |
--------------------------------------------------------------------------------
/documentation/repository-files/changelog-file.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG.md Guide
2 |
3 | ## Introduction
4 |
5 | The `CHANGELOG.md` document serves as a valuable resource for developers and users alike to track the evolution of a project over time. Understanding the structure and purpose of a changelog helps users and contributors stay informed about new features, bug fixes, and other changes introduced in each release.
6 |
7 | ## What is CHANGELOG.md?
8 |
9 | The primary purpose of `CHANGELOG.md` is to provide a record of notable changes made to the project with each new release. This document helps users understand what has been added, fixed, modified, or removed with each version of the software.
10 |
11 | [Keep a CHAGELOG.md](https://keepachangelog.com/en/1.1.0/) is a great, simple resource for understanding what a changelog is and how to create a good changelog. It also includes examples of things to avoid.
12 |
13 | ```{admonition} Versioning your Python package and semantic versioning
14 | :class: tip
15 |
16 | An important component of a package that serves as the backbone behind the changelog file is a good versioning scheme. Semantic Versioning is widely used across Python packages.
17 | * [Creating New Versions of Your Python Package](../../package-structure-code/python-package-versions.md)
18 | * [Semantic Versioning](https://semver.org)
19 | ```
20 |
21 | ## Why is it important?
22 |
23 | A well-maintained changelog is essential for transparent communication with users and developers. It serves as a centralized hub for documenting changes and highlights the progress made in each release. By keeping the changelog up-to-date, project maintainers can build trust with their user base and demonstrate their commitment to improving the software.
24 |
25 | ## What does it include?
26 |
27 | The contents of a changelog.md file typically follow a structured format, detailing the changes introduced in each release. While the exact format may vary depending on the project's conventions, some common elements found in changelogs for Python packages include:
28 |
29 | - **Versioning**: Clear identification of each release version using semantic versioning or another versioning scheme adopted by the project.
30 |
31 | - **Release Date**: The date when each version was released to the public, providing context for the timeline of changes.
32 |
33 | - **Change Categories**: Organizing changes into categories such as "Added," "Changed," "Fixed," and "Removed" to facilitate navigation and understanding.
34 |
35 | - **Description of Changes**: A concise description of the changes made in each category, including new features, enhancements, bug fixes, and deprecated functionality.
36 |
37 | - **Links to Issues or Pull Requests**: References to relevant issue tracker items or pull requests associated with each change, enabling users to access more detailed information if needed.
38 |
39 | - **Upgrade Instructions**: Guidance for users on how to upgrade to the latest version, including any breaking changes or migration steps they need to be aware of.
40 |
41 | - **Contributor Recognition**: Acknowledgment of contributors who made significant contributions to the release, fostering a sense of community and appreciation for their efforts.
42 |
43 | ## How do maintainers use it?
44 |
45 | Often you will see a changelog that documents a few things:
46 |
47 | ### Unreleased Section
48 |
49 | Unreleased commits are at the top of the changelog, commonly in an `Unreleased` section. This is where you can add new fixes, updates and features that have been added to the package since the last release.
50 |
51 | This section might look something like this:
52 |
53 | ```markdown
54 | ## Unreleased
55 | * Fix: Fixed a bug.... more here. (@github_username, #issuenumber)
56 | * Add: new feature to... more here. (@github_username, #issuenumber)
57 | ```
58 |
59 | ### Release Sections
60 |
61 | When you are ready to make a new release, you can move the elements into a section that is specific to that new release number.
62 |
63 | This specific release section will sit below the unreleased section and can include any updates, additions, deprecations and contributors.
64 |
65 | The unreleased section then always lives at the top of the file and new features continue to be added there. At the same time, after releasing a version like v1.0 all of its features remain in that specific section.
66 |
67 | ```markdown
68 | ## Unreleased
69 |
70 | ## v1.0
71 |
72 | ### Updates
73 | * Fix: Fixed a bug.... more here. (@github_username, #issuenumber)
74 |
75 | ### Additions
76 | * Add: new feature to ...more here (@github_username, #issuenumber)
77 |
78 | ### Deprecations
79 |
80 | ### Contributors to this release
81 | ```
82 |
83 | ## What does it look like?
84 |
85 | This example comes from [Devicely](https://github.com/hpi-dhc/devicely/blob/main/CHANGELOG.md), a pyOpenSci accepted package.
86 |
87 | ```markdown
88 | # Changelog
89 | All notable changes to this project will be documented in this file.
90 |
91 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
92 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
93 |
94 | ## [Unreleased]
95 |
96 | ## [1.1.0] - 2021-08-24
97 | - removed acceleration magnitude from devicely.EmpaticaReader and devicely.FarosReader since it was out of the scope of the package
98 | - added more flexibility to missing files (e.g. ACC.csv, EDA.csv) to devicely.EmpaticaReader
99 | - changed TagsReader to TimeStampReader to be more consistent with the class naming structure in devicely
100 | - deprecated methods in devicely.SpacelabsReader: set_window and drop_EB
101 | - fixed issue with the timestamp index and fixed column names in devicely.SpacelabsReader
102 |
103 | ## [1.0.0] - 2021-07-19
104 | ### Added
105 | - devicely.FarosReader can both read from and write to EDF files and directories
106 | - devicely.FarosReader has as attributes the individual dataframes (ACC, ECG, ...) and not only the joined dataframe
107 |
108 | ### Changed
109 | - in devicely.SpacelabsReader, use xml.etree from the standard library instead of third-party "xmltodict"
110 | - switch from setuptools to Poetry
111 |
112 | ### Removed
113 | - removed setup.py because static project files such as pyproject.toml are preferred
114 | ```
115 |
--------------------------------------------------------------------------------
/documentation/repository-files/code-of-conduct-file.md:
--------------------------------------------------------------------------------
1 | (coc-file)=
2 |
3 | # The CODE_OF_CONDUCT file - Python Packaging
4 |
5 | ```{admonition} Example CODE_OF_CONDUCT files
6 | :class: tip
7 |
8 | * [SciPy Code of Conduct file - notice they included theirs in their documentation](https://docs.scipy.org/doc/scipy/dev/conduct/code_of_conduct.html)
9 | * [fatiando CODE_OF_CONDUCT.md file](https://github.com/fatiando/community/blob/main/CODE_OF_CONDUCT.md)
10 | ```
11 |
12 | Your package should have a `CODE_OF_CONDUCT.md` file located
13 | the root of the repository. Once you have people using your
14 | package, you can consider the package itself as having a community
15 | around it. Some of this community uses your tool. These users
16 | may have questions or encounter challenges using your package.
17 |
18 | Others in the community might want to contribute to your tool.
19 | They might fix bugs, update documentation and engage with the
20 | maintainer team.
21 |
22 | ## Why you need a CODE_OF_CONDUCT
23 |
24 | In order to keep this community healthy and to protect yourself,
25 | your maintainer team and your users from unhealthy behavior,
26 | it is important to have a [`CODE_OF_CONDUCT`](https://opensource.guide/code-of-conduct/).
27 |
28 | The `CODE_OF_CONDUCT` is important
29 | as it establishes what you expect in terms of how users and
30 | contributors interact with maintainers and each other. It also
31 | establishes rules and expectations which can then be enforced
32 | if need be to protect others from harmful and/or negative behaviors.
33 |
34 | If you are not comfortable
35 | with creating your own `CODE_OF_CONDUCT` text, we encourage you to adopt the
36 | `CODE_OF_CONDUCT` language used in the [Contributor Covenant](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).
37 | [Many other communities](https://www.contributor-covenant.org/adopters/) have adopted this `CODE_OF_CONDUCT` as
38 | their own. See the [Fatiando a Terra Geoscience Python community's example here.](https://github.com/fatiando/community/blob/main/CODE_OF_CONDUCT.md)
39 |
--------------------------------------------------------------------------------
/documentation/repository-files/contributing-file.md:
--------------------------------------------------------------------------------
1 | (contributing-file)=
2 | # Your Python Package CONTRIBUTING File
3 |
4 | The **CONTRIBUTING.md** is the landing page guide for your project's contributors. It outlines how contributors can get involved, the contribution types that you welcome, and how contributors should interact or engage with you and your maintainer team. The contributor guide should also link to get-started resources that overview how to set up development environments, what type of workflow you expect on GitHub/GitLab, and anything else that contributors might need to get started.
5 |
6 | This file benefits maintainers and contributors. For contributors, it provides a roadmap that helps them get started and makes their first contribution easier. For maintainers, it answers commonly asked questions and reduces the burden of explaining your process to every person who wants to contribute. This document creates a more collaborative and efficient development process for everyone.
7 |
8 | ## CONTRIBUTING files lower barriers to entry
9 |
10 | The contributing file lowers barriers to entry for new and seasoned contributors as it provides a roadmap.
11 |
12 | - **For Contributors**: It provides clear instructions on contributing, from reporting issues to submitting pull requests.
13 | - **For Maintainers**: It streamlines contributions by setting expectations and standardizing processes, reducing the time spent clarifying common questions or handling incomplete issues or pull requests.
14 |
15 | Including a well-written CONTRIBUTING.md file in your project is one way of making it more welcoming and open to new and seasoned contributors. It also helps create a smoother workflow for everyone involved.
16 |
17 | ## Make it welcoming
18 |
19 | Make the guide welcoming. Use accessible language to encourage participation from contributors of all experience levels. For example:
20 |
21 | - Avoid technical jargon or explain terms when necessary (for example, "fork the repository").
22 | - Include a friendly introduction, such as "Thank you for your interest in contributing! We're excited to collaborate with you."
23 | - Highlight that all contributions, no matter how small, are valued.
24 |
25 | ## What a CONTRIBUTING.md file should contain
26 |
27 | :::{admonition} Example contributing files
28 | :class: tip
29 |
30 | - [PyGMT contributing file](https://github.com/GenericMappingTools/pygmt/blob/main/CONTRIBUTING.md)
31 | - [Verde's contributing file](https://github.com/fatiando/verde/blob/main/CONTRIBUTING.md)
32 | :::
33 |
34 | Your Python package should include a file called **CONTRIBUTING.md** located in the
35 | root of your repository next to [your **README.md** file](readme-file).
36 |
37 | The CONTRIBUTING.md file should include information about:
38 |
39 | - The types of contributions that you welcome
40 |
41 | > Example: We welcome contributions of all kinds. If you want to address an existing issue, check out our issues in this repository and comment on the one that you'd like to help with. Otherwise, you can open a new issue...
42 |
43 | - How you'd like contributions to happen. Clearly outline your contribution process. For example:
44 | - Should contributors address open issues
45 | - Are new issues welcome?
46 | - Should contributors open a pull request (PR) directly or discuss changes first?
47 |
48 | - Include instructions for the fork and pull request workflow and link to resources or guides explaining these steps (if available).
49 | - Guidelines that you have in place for users submitting issues, pull requests, or asking questions.
50 |
51 | If you have a [development guide](development-guide), link to it. This guide should provide clear instructions on how to set up your development environment locally. It also should overview CI tools that you have that could simplify the contribution process (for example, pre-[commit.ci bot](https://www.pyopensci.org/python-package-guide/package-structure-code/code-style-linting-format.html#pre-commit-ci), and so on), [linters, code formatters](https://www.pyopensci.org/python-package-guide/package-structure-code/code-style-linting-format.html#code-linting-formatting-and-styling-tools), and so on.
52 |
53 | This guide should also include information for someone
54 | interested in asking questions. Some projects accept questions as GitHub or GitLab issues. Others use GitHub discussions, Discourse, or even a Discord server.
55 |
56 | The contributing file should also include:
57 |
58 | - A link to your [code of conduct](coc-file)
59 | - A link to your project's [LICENSE](license-file)
60 | - A link to a [development guide](development-guide) if you have one
61 |
62 | ## Summary
63 |
64 | A well-crafted CONTRIBUTING.md file is welcome mat for your project! By providing clear instructions, helpful resources, and a welcoming tone, you make it easier for contributors to get involved and build a stronger, more collaborative community around your project.
65 |
--------------------------------------------------------------------------------
/documentation/repository-files/development-guide.md:
--------------------------------------------------------------------------------
1 | (pyos-development-guide)=
2 | # What the development guide for your Python package should contain
3 |
4 | Ideally, your package should also have a development guide. This file may live in your package documentation and should be linked to from your CONTRIBUTING.md file (discussed above).
5 | A development guide should clearly show
6 | technically proficient users how to:
7 |
8 | * Set up a development environment locally to work on your package
9 | * Run the test suite
10 | * Build documentation locally
11 |
12 | The development guide should also have guidelines for:
13 |
14 | * code standards including docstring style, code format and any specific code approaches that the package follows.
15 |
16 | It's also helpful to specify the types of tests you request if a contributor submits a new feature or a change to an existing feature that will not be covered by your existing test suite.
17 |
18 | If you have time to document it, it's also helpful to document your maintainer workflow and release processes.
19 |
20 | ## Why a development guide is important
21 |
22 | It's valuable to have a development guide, in the
23 | case that you wish to:
24 |
25 | * Onboard new maintainers.
26 | * Allow technically inclined contributors to make thoughtful and useful code based pull requests to your repository.
27 |
28 | It also is important to pyOpenSci that the maintenance workflow is
29 | documented in the case that we need to help you onboard new
30 | maintainers in the future.
31 |
32 | ```{note}
33 | A well thought out continuous integration setup in your repository
34 | can allow users to skip building the package locally (especially if they are just updating text).
35 | ```
36 |
37 | ```{tip}
38 | A development guide, while strongly recommended, is not a file that
39 | pyOpenSci requires a package to have in order to be eligible for
40 | review. Some maintainers may also opt to include the development information in their contributing guide.
41 | ```
42 |
43 | ```{tip}
44 | [The Mozilla Science Lab website has a nice outline of things to consider when
45 | creating a contributing guide](https://mozillascience.github.io/working-open-workshop/contributing/)
46 | ```
47 |
48 |
59 |
--------------------------------------------------------------------------------
/documentation/repository-files/intro.md:
--------------------------------------------------------------------------------
1 | # Documentation Files That Should be in your Python Package Repository
2 |
3 | In this section of the Python packaging guide, we review all of the files that
4 | you should have in your Python package repository. Your Python package should,
5 | at a minimum have the following files:
6 |
7 | The files mentions above (README, Code of Conduct, license
8 | file, etc) are used as a measure of package community health
9 | on many online platforms. Below, you can see an example how GitHub
10 | evaluates community health. This community health link is available for
11 | all GitHub repositories.
12 |
13 | ```{figure} /images/moving-pandas-python-package-github-community-standards.png
14 | ---
15 | name: moving-pandas-github-community
16 | width: 80%
17 | alt: Image showing that the MovingPandas GitHub repository community health page with green checks next to each file including a description, README, code of conduct, contributing, license and issue templates. Note that Security policy has a yellow circle next to it as that is missing from the repo.
18 | ---
19 | GitHub community health looks for a readme file among other elements when it evaluates the community level health of your repository. This example is from the [MovingPandas GitHub repo](https://github.com/movingpandas/movingpandas/community) *(screen shot taken Nov 23 2022)*
20 | ```
21 |
22 | [Snyk](https://snyk.io/advisor/python) is another well-known company that
23 | keeps tabs on package health. Below you can see a similar evaluation of files
24 | in the GitHub repo as a measure of community health.
25 |
26 | ```{figure} /images/moving-pandas-python-package-snyk-health.png
27 | ---
28 | name: moving-pandas-snyk
29 | width: 80%
30 | alt: Screenshot of the Snyk page for movingpandas. It shows that the repository has a README file, contributing file, code of conduct. It also shows that it has 30 contributors and no funding. The package health score is 78/100.
31 | ---
32 | Screenshot showing [SNYK](https://snyk.io/advisor/python/movingpandas) package health for moving pandas. Notice both platforms look for a README file. *(screen shot taken Nov 23 2022)*
33 | ```
34 |
--------------------------------------------------------------------------------
/documentation/repository-files/license-files.md:
--------------------------------------------------------------------------------
1 | ---
2 | bibliography:
3 | - ../../bibliography.bib
4 | ---
5 |
6 | (license-file)=
7 |
8 | # License files for Python open source software
9 |
10 | :::{button-link}
11 | :color: primary
12 | :class: sd-rounded-pill float-left
13 |
14 | Want to learn how to add a license file to your GitHub repository? Check out this lesson.
15 | :::
16 |
17 | ## What is a Open Source License file?
18 |
19 | When we talk about LICENSE files, we are referring to a file in your
20 | GitHub or GitLab repository that contains legally binding language
21 | that describes to your users how they can legally use (and not use) your package.
22 |
23 | ## Why licenses are important
24 |
25 | A license file is important for all open source projects because it protects both you as a maintainer and your users. The license file helps your users and the community understand:
26 |
27 | 1. How they can use your software
28 | 2. Whether the software can be reused or adapted for other purposes
29 | 3. How people can contribute to your project
30 |
31 | and more.
32 |
33 | [Read more about why license files are critical in protecting both you as a maintainer and your users of your scientific Python open source package.](https://opensource.guide/legal/#just-give-me-the-tldr-on-what-i-need-to-protect-my-project)
34 |
35 | ## Where to store your license
36 |
37 | Your `LICENSE` file should be stored at root of your GitHub / GitLab repository.
38 |
39 | Some maintainers customize the language in their license files for specific reasons. However, if you are just getting started, we suggest that you select a
40 | permissive license and then use the legal language templates provided both by GitHub and/or the [choosealicense.com](https://choosealicense.com/) website.
41 |
42 | Licenses are legally binding, as such you should avoid trying to create your own license unless you have the guidance of legal council.
43 |
44 | ### Use open permissive licenses when possible
45 |
46 | We generally suggest that you use a permissive, license that is [Open Software Initiative (OSI) approved](https://opensource.org/licenses/). If you are
47 | [submitting your package to pyOpenSci for peer review](https://www.pyopensci.org/about-peer-review/index.html), then we require an OSI approved
48 | license.
49 |
50 | :::{admonition} Copyleft licenses
51 | The other major category of licenses are ["copyleft" licenses](https://en.wikipedia.org/wiki/Copyleft).
52 | Copyleft licenses require people that use your work to redistribute it with the same (or greater) rights to modify, copy, share, and redistribute it.
53 | In other words, copyleft licenses prohibit someone taking your work, making a proprietary version of it, and redistributing it without providing the source code so others can do the same.
54 | Copyleft licenses are "sticky" in that they are designed to ensure that more free software is created.
55 |
56 | The difference between copyleft and permissive licenses is an important cultural divide in free and open source software (e.g., see {footcite}`hunterReclaimingComputingCommons2016`, {footcite}`gnuprojectWhatFreeSoftware2019`, {footcite}`gnuprojectWhatCopyleft2022`).
57 | It is important to understand this difference when choosing your license. Copyleft licenses represents the "free" part of "free and open source software".
58 | Free and open source software is intrinsically political, and it is important to be aware of power dynamics in computing as well as the practical problems of license compatibility (discussed below).
59 | :::
60 |
61 | ### How to choose a license
62 |
63 | To select your license, we suggest that you use GitHub's
64 | [Choose a License tool](https://choosealicense.com/).
65 |
66 | If you choose your license when creating a new GitHub repository, you can also
67 | automatically get a text copy of the license file to add to your repository. However
68 | in some cases the license that you want is not available through that online
69 | process.
70 |
71 | :::{admonition} License recommendations from the SciPy package
72 | [The SciPy documentation has an excellent overview of licenses.](https://docs.scipy.org/doc/scipy/dev/core-dev/index.html#licensing) One of the key elements
73 | that these docs recommend is ensuring that the license that you select is
74 | compatible with licenses used in many parts of the scientific Python ecosystem.
75 | Below is a highlight of this text which outlines license that are compatible
76 | with the modified BSD license that SciPy uses.
77 |
78 | > Other licenses that are compatible with the modified BSD license that SciPy uses are 2-clause BSD, MIT and PSF. Incompatible licenses are GPL, Apache and custom licenses that require attribution/citation or prohibit use for commercial purposes.
79 |
80 | If your primary goal is for your code to be used by other, major packages in the scientific ecosystem, we also recommend
81 | that you consider using either BSD or MIT as your
82 | license. If you are unsure, the MIT license tends to be a simpler easier-to-understand option.
83 | :::
84 |
85 | ## Important: make sure that you closely follow the guidelines outlines by the License that you chose
86 |
87 | Every license has different guidelines in terms of what code
88 | you can use in your package and also how others can (or can not) use the code in your package.
89 |
90 | If you borrow code from other tools or online sources, make
91 | sure that the license for the code that you are using also complies
92 | with the license that you selected for your package.
93 |
94 | A useful way to think about license compatibility is the distinction between **"inbound"** and **"outbound"** compatibility.
95 | "Inbound" licenses are those that cover the software you plan to include in your package.
96 | Your package is protected by an "outbound" license.
97 |
98 | **Permissive licenses** like BSD and MIT have few **outbound** restrictions - they can be used in any way by downstream consumers, including making them proprietary.
99 | This is why they are favored by many businesses and large packages that want to be adopted by businesses.
100 | Permissive licenses have more **inbound** restrictions - they can't use software that requires more freedoms to be preserved than they do, like copyleft licenses.
101 | A package licensed under MIT needs to take special care when including or modifying a package licensed under the GPL-3.
102 |
103 | **Copyleft licenses** like GPL-3 have more **outbound** restrictions - they require more of packages that include, use, modify, and reproduce them.
104 | This is the purpose of copyleft licenses, to ensure that derivative works remain free and open source.
105 | They have fewer **inbound** restrictions - a GPL-3 licensed package can include any other permissively licensed and most copyleft licensed packages.
106 |
107 | | Compatible | Dependency ("Inbound") | Your Package | Downstream Package ("Outbound") |
108 | |----------------------------------------------------------------:|-----------------------------|--------------|--------------------------------------|
109 | | | Permissive | Permissive | |
110 | | | Copyleft | Permissive | |
111 | | | | Permissive | Permissive |
112 | | | | Permissive | Copyleft |
113 | | | Permissive | Copyleft | |
114 | | | Copyleft | Copyleft | |
115 | | | | Copyleft | Permissive |
116 | | | | Copyleft | Copyleft |
117 |
118 | :::{admonition} An example of how a license determine how code can be reused
119 | :class: note
120 |
121 | Let's use StackOverflow as an example that highlights how a license determines how code can or can not be used.
122 |
123 | [Stack Overflow uses a Creative Commons Share Alike license.](https://stackoverflow.com/help/licensing). The sharealike license requires you to use the same sharealike license when you reuse any code from Stack Overflow.
124 |
125 | This means that from a legal perspective, if you copy code from the Stack Overflow website and use it in your package that is licensed differently, say with a MIT license, you are violating Stack Overflow's license requirements!
126 | This would not be true with a GPL licensed package. `GPL-3` packages can include code licensed by `CC-BY-SA` {footcite}`creativecommonsShareAlikeCompatibilityGPLv32015`.
127 |
128 | 🚨 Proceed with caution! 🚨
129 | :::
130 |
131 | ## What about software citation?
132 |
133 | While many permissive licenses do not require citation we STRONG encourage that you cite all software that you use in papers, blogs and other publications. You tell your users how to cite your package by using a [citation.cff file](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-citation-files). We will cover this topic when we talk about creating DOI's for your package using Zenodo.
134 |
135 |
140 |
141 | # References
142 |
143 | ```{footbibliography}
144 | ```
145 |
--------------------------------------------------------------------------------
/documentation/repository-files/readme-file-best-practices.md:
--------------------------------------------------------------------------------
1 | (readme-file)=
2 |
3 | # README File Guidelines and Resources
4 |
5 | Your **README.md** file should be located in the root of your GitHub repository.
6 | The **README.md** file is important as it is often the first thing that someone
7 | sees before they install your package.
8 |
9 | The README.md file is the landing page of:
10 |
11 | * Your package as it appears on a repository site such as PyPI or Anaconda.org
12 | * Your package's GitHub repository
13 |
14 | Your README.md file is also used as a measure of package and community
15 | health on sites such as:
16 |
17 | * [GitHub community health for MovingPandas (available for all repositories)](https://github.com/movingpandas/movingpandas/community) and [Snyk - MovingPandas example](https://snyk.io/advisor/python/movingpandas)
18 |
19 | ```{figure} /images/pandera-python-package-readme-github.png
20 | ---
21 | name: pandera-readme
22 | width: 80%
23 | alt: README landing page screenshot for the Pandera package. It has the Pandera logo at the top - which has two arrows in a chevron pattern pointing downward within a circle. Subtitle is statistical data testing toolkit. A data validation library for scientists, engineering, and analytics seeking correctness. Below that are a series of badges including CI tests passing, docs passing, version of Pandera on pypi (0.13.4), MIT license and that it has been pyOpenSci peer reviewed. There are numerous badges below that. Finally below the badges the text says, Pandera provides a flexible and expressive API for performing data validation on dataframe-like objects to make data processing pipelines more readable and robust.
24 | ---
25 | Your GitHub repository landing page highlights the README.md file. Here you can see the README.md file for the pyOpenSci package [Pandera](https://github.com/unionai-oss/pandera). *(screen shot taken Nov 23 2022)*
26 | ```
27 |
28 | Thus, it is important that you spend some time up front creating a high quality
29 | **README.md** file for your Python package.
30 |
31 | ````{note}
32 | An editor or the editor in chief will ask you to revise your README file
33 | before a review begins if it does not meet the criteria specified below.
34 |
35 | Please go through this list before submitting your package to pyOpenSci
36 |
37 | ```
38 | ### pyOpenSci README checklist
39 |
40 | Your README file should have the following information:
41 | - [ ] The name of the package
42 | - [ ] Badges for the packages current published version, documentation and test suite build. (OPTIONAL: test coverage)
43 | - [ ] Easy-to-understand explanation (2-4 sentences) of what your tool does
44 | - [ ] Context for how the tool fits into the broader ecosystem
45 | - [ ] If your library/package "wraps" around another package, link to the package that it is wrapping and any associated documentation. *(HINT: If you don't know what a wrapper is, this probably doesn't apply to you!)*
46 | - [ ] A simple quick-start code example that a user can follow to provide a demonstration of what the package can do for them
47 | - [ ] Links to your package's documentation / website.
48 | - [ ] A few descriptive links to any tutorials you've created for your package.
49 | ```
50 | ````
51 |
52 | ## What your README.md file should contain
53 |
54 | Your **README.md** file should contain the following things (listed from top to bottom):
55 |
56 | ### ✔️ Your package's name
57 |
58 | Ideally your GitHub repository's name is also the name of your package. The more
59 | self explanatory that name is, the better.
60 |
61 | ### ✔️ Badges for current package version, continuous integration and test coverage
62 |
63 | Badges are a useful way to draw attention to the quality of your project. Badges
64 | assure users that your package is well-designed, tested, and maintained. They
65 | are also a useful maintenance tool to evaluate if things are building properly.
66 | A great example of this is adding a [Read the Docs status badge](https://docs.readthedocs.io/en/stable/badges.html) to your README.md file to quickly
67 | see when the build on that site fails.
68 |
69 | It is common to provide a collection of badges towards the top of your
70 | README file for others to quickly browse.
71 |
72 | Some badges that you might consider adding to your README file include:
73 |
74 | * Current version of the package on PyPI / Anaconda.org
75 |
76 | Example: [](https://pypi.org/project/pandera/)
77 |
78 | * Status of tests (pass or fail) - Example: [](https://github.com/pandera-dev/pandera/actions?query=workflow%3A%22CI+Tests%22+branch%3Amain)
79 |
80 | * Documentation build - Example: 
81 |
82 | * DOI (for citation) Example: [](https://zenodo.org/badge/latestdoi/556814582)
83 |
84 | ```{tip}
85 | Once you package is accepted to pyOpenSci, we will provide you with
86 | a badge to add to your repository that shows that it has been reviewed.
87 | [](https://github.com/pyOpenSci/software-review/issues/12)
88 |
89 | ```
90 |
91 | ```{caution}
92 | Beware of the overuse of badges! There is such a thing as too much of a good thing (which can overload a potential user!).
93 | ```
94 |
95 | ### ✔️ A short, easy-to-understand description of what your package does
96 |
97 | At the top of your README file you should have a short, easy-to-understand, 1-3
98 | sentence description of what your package does. This section should clearly
99 | state your goals for the package. The language in this description should use
100 | less technical terms so that a variety of users with varying scientific (and
101 | development) backgrounds can understand it.
102 |
103 | In this description, it's useful to let users know how your package fits within
104 | the broader scientific Python package ecosystem. If there are other similar packages
105 | or complementary package mentions them here in 1-2 sentences.
106 |
107 | ```{tip}
108 | Consider writing for a high school level (or equivalent) level. This
109 | level of writing is often considered an appropriate level for scientific content that
110 | serves a variety of users with varying backgrounds.
111 |
112 | The goal of this description is to maximize accessibility of your **README**
113 | file.
114 | ```
115 |
116 | ### ✔️ Installation instructions
117 |
118 | Include instructions for installing your package. If you have published
119 | the package on both PyPI and Anaconda.org, be sure to include instructions for both.
120 |
121 | ### ✔️ Document any additional setup required
122 |
123 | Add any additional setup required such as authentication tokens, to
124 | get started using your package. If setup is complex, consider linking to an
125 | installation page in your online documentation here rather than over complicating
126 | your README file.
127 |
128 | ### ✔️ Brief demonstration of how to use the package
129 |
130 | This description ideally includes a brief, quick start code
131 | example that shows a user how to get started using your package.
132 |
133 | ### ✔️ Descriptive links to package documentation, short tutorials
134 |
135 | Include descriptive links to:
136 |
137 | * The package's documentation page.
138 | * Short tutorials that demonstrate application of your package.
139 |
140 | ```{admonition} Too Much Of A Good Thing
141 | :class: tip
142 |
143 | Try to avoid including several tutorials in the README.md file itself. This too will overwhelm the user with information.
144 |
145 | A short quick-start code example that shows someone how to use your package
146 | is plenty of content for the README file. All other tutorials and
147 | documentation
148 | should be presented as descriptive links.
149 | ```
150 |
151 | ### ✔️ A Community Section with Links to Contributing Guide, Code of Conduct
152 |
153 | Use your README.md file to direct users to more information on:
154 |
155 | * Contributing to your package
156 | * Development setup for more advanced technical contributors
157 | * Your code of conduct
158 | * Licensing information
159 |
160 | All of the above files are important for building community around your
161 | project.
162 |
163 | ### ✔️ Citation information
164 |
165 | Finally be sure to include instructions on how to cite your package.
166 | Citation should include the DOI that you want used when citing your package,
167 | and any language that you'd like to see associated with the citation.
168 |
169 | :::{admonition} README Resources
170 | :class: tip
171 |
172 | Below are some resources on creating great README.md files that you
173 | might find helpful.
174 |
175 | * [How to Write a Great README - Bane Sullivan](https://github.com/banesullivan/README)
176 | * [Art of README - Kira (@hackergrrl)](https://github.com/hackergrrl/art-of-readme)
177 |
178 | :::
179 |
--------------------------------------------------------------------------------
/documentation/write-user-documentation/create-package-tutorials.md:
--------------------------------------------------------------------------------
1 | # Create tutorials in your Python package documentation
2 |
3 |
6 | Your package should have tutorials that make it easy for a user
7 | to get started using your package. Ideally, those tutorials
8 | also can be run from start to finish providing a second set of
9 | checks (on top of your test suite) to your package's code base.
10 |
11 | On this page, we review two Sphinx extensions (`sphinx-gallery` and `nbsphinx`)
12 | that allow you to create reproducible tutorials that are run
13 | when your Sphinx documentation builds.
14 |
15 | ## Create Python package tutorials that run when you build your docs
16 |
17 | Adding well constructed tutorials to your package will make it easier for someone
18 | new to begin using your package.
19 |
20 | There are two Sphinx tools that make it easy to add tutorials to your package:
21 |
22 | * [Sphinx Gallery](https://sphinx-gallery.github.io/stable/index.html) and
23 | * [NbSphinx](https://nbsphinx.readthedocs.io/en/latest/)
24 |
25 | Both of these tools act as Sphinx extensions and:
26 |
27 | * Support creating a gallery type page in your Sphinx documentation where users can explore tutorials via thumbnails.
28 | * Run the code in your tutorials adding another level of "testing" for your package as used.
29 | * Render your tutorials with Python code and plot outputs
30 |
31 | ### [sphinx gallery:](https://sphinx-gallery.github.io/stable/index.html)
32 |
33 | If you prefer to write your tutorials using Python **.py** scripts, you
34 | may enjoy using Sphinx gallery. Sphinx gallery uses **.py** files with
35 | text and code sections that mimic the Jupyter Notebook format. When you build
36 | your documentation, the gallery extension:
37 |
38 | 1. Runs the code in each tutorial. Running your tutorial like this acts as a check to ensure your package's functions, classes, methods, and attributes (ie the API) are working as they should.
39 | 1. Creates a downloadable Jupyter Notebook **.ipynb** file and a **.py** script for your tutorial that a user can quickly download and run.
40 | 1. Creates a rendered **.html** page with the code elements and code outputs in a user-friendly tutorial gallery.
41 | 1. Creates a gallery landing page with visual thumbnails for each tutorial that you create.
42 |
43 |
44 | ```{figure} /images/sphinx-gallery-overview.png
45 | ---
46 | name: sphinx-gallery
47 | width: 80%
48 | alt: Image showing the gallery output provided by sphinx-gallery where each tutorial is in a grid and the tutorial thumbnails are created from a graphic in the tutorial.
49 | ---
50 | `sphinx-gallery` makes it easy to create a user-friendly tutorial gallery.
51 | Each tutorial has a download link where the user can download a **.py** file or a Jupyter Notebook. And it renders the tutorials in a user-friendly grid.
52 | ```
53 |
54 | Below you can see what a tutorial looks like created with sphinx-gallery.
55 |
56 | ```{figure} /images/sphinx-gallery-tutorial.png
57 | ---
58 | name: spinx-gallery-tutorial
59 | width: 80%
60 | alt: Image showing ta single tutorial from Sphinx gallery. The tutorial shows a simple matplotlib created plot and associated code.
61 | ---
62 | `sphinx-gallery` tutorials by default include download links for both the
63 | python script (**.py** file) and a Jupyter notebook (**.ipynb** file) at the bottom.
64 | ```
65 |
66 | ### Sphinx Gallery benefits
67 | * easy-to-download notebook and .py outputs for each tutorials.
68 | * .py files are easy to work with in the GitHub pull request environment.
69 | * Nice gridded gallery output.
70 | * Build execution time data per tutorial. [Example](https://sphinx-gallery.github.io/stable/auto_examples/sg_execution_times.html)
71 |
72 | #### Sphinx gallery challenges
73 |
74 | The downsides of using Sphinx gallery include:
75 |
76 | * the **.py** files can be finicky to configure, particularly if you have matplotlib plot outputs.
77 |
78 | For example: To allow for plots to render, you need to name each file with `plot_`
79 | at the beginning.
80 |
81 | * Many users these days are used to working in Jupyter Notebooks. .py may be slightly less user friendly to work with
82 |
83 | These nuances can make it challenging for potential contributors to add
84 | tutorials to your package. This can also present maintenance challenge.
85 |
86 | Add about the gallery setup:
87 |
88 | ```bash
89 | $ docs % make html
90 |
91 | Sphinx-Gallery successfully executed 2 out of 2 files
92 | ```
93 | File directory structure:
94 |
95 | ```bash
96 | tutorials/
97 | index.rst # landing page for your gallery
98 | plot_tutorial.py # a tutorial
99 | plot_tutorial-2.py # a tutorial that produces a plot output
100 | _build/
101 | build_examples/ # This is where the downloadable tutorial files live
102 | plot_sample-1.ipynb
103 | plot_sample-1.py
104 | ...
105 | html/
106 | built_examples/ # You can specify this dir name in gallery settings
107 | index.html
108 | plot_sample-1.html
109 | plot_sample.html
110 | sg_execution_times.html # in case you want to see build times for each tutorial
111 |
112 | ```
113 |
114 | ### [nbsphinx - tutorials using Jupyter Notebooks](https://nbsphinx.readthedocs.io/en/latest/)
115 |
116 | If you prefer to use Jupyter Notebooks to create tutorials you can use nbsphinx.
117 | nbsphinx operates similarly to Sphinx gallery in that:
118 |
119 | * It runs your notebooks and produces outputs in the rendered tutorials
120 |
121 | * Pro/con By default it does not support downloading of **.py** and **.ipynb** files. However you can add a [link to the notebook at the top of the page with
122 | some additional conf.py settings (see: epilog settings)](https://nbsphinx.readthedocs.io/en/0.8.10/prolog-and-epilog.html)
123 |
124 |
125 | ```{figure} /images/python-package-documentation-nb_sphinx-gallery-output.png
126 | ---
127 | name: directive-fig
128 | width: 80%
129 | alt: Image showing the gallery output provided by nbsphinx using the sphinx-gallery front end interface.
130 | ---
131 | `nbsphinx` can be combined with Sphinx gallery to create a gallery of tutorials.
132 | However, rather than rendering the gallery as a grid, it lists all of the gallery
133 | elements in a single column.
134 | ```
135 |
136 | ```bash
137 | tutorials/
138 | index.md # Landing page for your gallery
139 | tutorial.ipynb # A tutorial in a jupyter notebook
140 | another_tutorial.ipynb
141 | # This shows you what the build directory looks like when you build with sphinx-build
142 | _build/
143 | html/
144 | # Notice that nbsphinx runs each notebook and produces an
145 | # html file with all of the outputs of your code
146 | # you can link to the notebook in your docs by modifying
147 | # the nbsphinx build - we will cover this in a separate tutorial series focused onPythonpackaging!
148 | tutorials/
149 | index.html
150 | index.md
151 | plot_sample-2.html
152 | plot_sample-2.ipynb
153 | ...
154 | ```
155 |
--------------------------------------------------------------------------------
/documentation/write-user-documentation/get-started.md:
--------------------------------------------------------------------------------
1 | # Create User Facing Documentation for your Python Package
2 |
3 |
13 |
14 | ## Core components of user-facing Python package documentation
15 | Below we break documentation into two broad types.
16 |
17 | **User-facing documentation** refers to documentation that describes the way the
18 | tools within a package are broadly used in workflows. **API documentation** refers
19 | to documentation of functions, classes, methods, and attributes in your code and
20 | is written at a more granular level. This documentation is what a user sees when
21 | they type `help(function-name)`.
22 |
23 | Your user-facing documentation for your Python package should include several
24 | core components.
25 |
26 | * **Documentation Website:** This refers to easy-to-read documentation that helps someone use your package. This documentation should help users both install and use your package.
27 | * **Short Tutorials:** Your user-facing documentation should also include [**short tutorials** that showcase core features of your package](create-package-tutorials).
28 | * **Package Code / API documentation:** You package's functions, classes, methods, and attributes (the API) should also be documented. API documentation can be generated from [docstrings](https://pandas.pydata.org/docs/development/contributing_docstring.html) found in your
29 | code. Ideally, you have docstrings for all user-facing functions, classes, and methods in
30 | your Python package. [We discuss code documentation and docstrings in greater detail here.](document-your-code-api-docstrings)
31 |
32 | ### Write usable documentation
33 |
34 | User-facing documentation should be published on a
35 | easy-to-navigate website. The documentation should be written keeping in mind that users may not be developers or expert-level programmers. Rather, the language
36 | that you use in your documentation should not be
37 | highly technical.
38 |
39 | To make the language of your documentation more accessible
40 | to a broader audience:
41 |
42 | * Whenever possible, define technical terms and jargon.
43 | * Consider writing instructions for a high-school level reader.
44 | * Include step-by-step code examples, tutorials or vignettes that support getting started using your package.
45 |
46 | ## Four elements of a good open source documentation landing page
47 |
48 | To make it easy for users to find what they need quickly,
49 | consider adding quick links on your package's landing
50 | page to the following elements:
51 |
52 | * **Getting started:** This section should provide the user with a quick start for installing your package. A small example of how to use the package is good to have here as well. Or you can link to useful tutorials in the get started section.
53 | * **About:** Describe your project, stating its goals and its functionality.
54 | * **Community:** Instructions for how to help and/or get involved. This might include links to your issues (if that is where you let users ask questions) or the discussion part of your GitHub repo. This section might include a development guide for those who might contribute to your package.
55 | * **API Documentation:** This is the detailed project documentation. Here you store documentation for your package's API including all user-facing functions, classes, methods, and attributes as well as any additional high level discussion that will help people use your package.
56 |
57 |
58 | ```{figure} /images/geopandas-documentation-landing-page.png
59 | ---
60 | name: geopandas-landing
61 | width: 80%
62 | alt: Image showing the landing page for GeoPandas documentation which has 4 sections including Getting started, Documentation, About GeoPandas, Community.
63 | ---
64 | The documentation landing page of GeoPandas, a spatial Python library, has the 4 element specified above. Notice that the landing page is simple and directs users to each element using a Sphinx card.
65 | ```
66 |
67 | NOTE: in many cases you can include your **README** file and your **CONTRIBUTING** files
68 | in your documentation given those files may have some of the components listed above.
69 |
70 | `````{tip}
71 | You can include files in Sphinx using the include directive.
72 | Below is an example of doing this using `myst` syntax.
73 | ````
74 | ```{include} ../README.md
75 | ```
76 | ````
77 | `````
78 |
--------------------------------------------------------------------------------
/documentation/write-user-documentation/intro.md:
--------------------------------------------------------------------------------
1 | # Writing user-facing documentation for your Python package
2 |
3 | This section walks you through best practices for with writing
4 | documentation for your Python package.
5 |
6 | We talk about the elements that you should consider adding to your documentation,
7 | the different types of users who might read your documentation and how to
8 | create tutorials for your package.
9 |
10 | Here we also cover sphinx extensions that you can user to make documentation
11 | easier such as:
12 |
13 | * autodoc to automagically populate documentation for your code's functions,
14 | classes, methods and attributes (API documentation) and
15 | * sphinx gallery for tutorials.
16 |
--------------------------------------------------------------------------------
/examples/extension-hatch/README:
--------------------------------------------------------------------------------
1 | An example Python package used to support Python packaging tutorials
2 |
3 | This project demonstrates mixing C and Python code by using the frontend hatch with the backend mesonpy
4 |
--------------------------------------------------------------------------------
/examples/extension-hatch/examplePy/__init__.py:
--------------------------------------------------------------------------------
1 | from .temperature import celsius_to_fahrenheit, fahrenheit_to_celsius
2 |
3 | __all__ = ["celsius_to_fahrenheit", "fahrenheit_to_celsius"]
4 | __version__ = "0.1.0dev0"
5 |
--------------------------------------------------------------------------------
/examples/extension-hatch/examplePy/meson.build:
--------------------------------------------------------------------------------
1 | py.extension_module(
2 | 'temperature',
3 | 'temperature.c',
4 | install: true,
5 | subdir: 'examplePy'
6 | )
7 |
8 | python_sources = [
9 | '__init__.py'
10 | ]
11 |
12 | py.install_sources(
13 | python_sources,
14 | subdir: 'examplePy'
15 | )
16 |
--------------------------------------------------------------------------------
/examples/extension-hatch/examplePy/temperature.c:
--------------------------------------------------------------------------------
1 | #define PY_SSIZE_T_CLEAN
2 | #include
3 |
4 | static PyObject *
5 | temperature_celsius_to_fahrenheit(PyObject *self, PyObject *args)
6 | {
7 | long celsius;
8 | long fahrenheit;
9 | PyObject *ret;
10 |
11 | if (!PyArg_ParseTuple(args, "l", &celsius))
12 | return NULL;
13 |
14 | fahrenheit = (celsius * 9/5) + 32;
15 |
16 | ret = PyLong_FromLong(fahrenheit);
17 | Py_INCREF(ret);
18 | return ret;
19 | }
20 |
21 | static PyObject *
22 | temperature_fahrenheit_to_celsius(PyObject *self, PyObject *args)
23 | {
24 | long fahrenheit;
25 | long celsius;
26 | PyObject *ret;
27 |
28 | if (!PyArg_ParseTuple(args, "l", &fahrenheit))
29 | return NULL;
30 |
31 | celsius = (fahrenheit - 32) * 9/5;
32 |
33 | ret = PyLong_FromLong(celsius);
34 | Py_INCREF(ret);
35 | return ret;
36 | }
37 |
38 | static PyMethodDef CoreMethods[] = {
39 | {"celsius_to_fahrenheit", temperature_celsius_to_fahrenheit, METH_VARARGS, "Convert temperature from Celsius to Fahrenheit"},
40 | {"fahrenheit_to_celsius", temperature_fahrenheit_to_celsius, METH_VARARGS, "Convert temperature from Fahrenheit to Celsius"},
41 | {NULL, NULL, 0, NULL} /* Sentinel */
42 | };
43 |
44 | static struct PyModuleDef temperaturemodule = {
45 | PyModuleDef_HEAD_INIT,
46 | "temperature", /* name of module */
47 | NULL, /* module documentation, may be NULL */
48 | -1, /* size of per-interpreter state of the module,
49 | or -1 if the module keeps state in global variables. */
50 | CoreMethods
51 | };
52 |
53 | PyMODINIT_FUNC
54 | PyInit_temperature(void)
55 | {
56 | PyObject *m;
57 |
58 | m = PyModule_Create(&temperaturemodule);
59 | if (m == NULL)
60 | return NULL;
61 |
62 | return m;
63 | }
64 |
--------------------------------------------------------------------------------
/examples/extension-hatch/meson.build:
--------------------------------------------------------------------------------
1 | project(
2 | 'examplePy',
3 | 'c',
4 | version: '0.1.dev0',
5 | license: 'MIT',
6 | meson_version: '>= 0.64.0',
7 | default_options: [
8 | 'buildtype=debugoptimized',
9 | 'c_std=c99',
10 | 'cpp_std=c++14',
11 | ],
12 | )
13 |
14 | cc = meson.get_compiler('c')
15 |
16 | py_mod = import('python')
17 | py = py_mod.find_installation(pure: false)
18 | py_dep = py.dependency()
19 |
20 | subdir('examplePy')
21 |
--------------------------------------------------------------------------------
/examples/extension-hatch/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | build-backend = "mesonpy"
3 | requires = [
4 | "meson-python>=0.13.0rc0",
5 | ]
6 |
7 | [project]
8 | name = "examplePy"
9 | version = "0.1"
10 | authors = [
11 | {name = "Some Maintainer", email = "some-email@pyopensci.org"},
12 | ]
13 | maintainers = [
14 | {name = "All the contributors"},
15 | ]
16 | description = "An example Python package used to support Python packaging tutorials"
17 | keywords = ["pyOpenSci", "python packaging"]
18 | readme = "README"
19 | classifiers = [
20 | "Programming Language :: Python :: 3",
21 | "License :: OSI Approved :: BSD License",
22 | "Operating System :: OS Independent",
23 | ]
24 |
--------------------------------------------------------------------------------
/examples/pure-hatch/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/PyCQA/isort
3 | rev: 5.11.4
4 | hooks:
5 | - id: isort
6 | files: \.py$
7 | # Misc commit checks using built in pre-commit checks
8 | - repo: https://github.com/pre-commit/pre-commit-hooks
9 | rev: v4.4.0
10 | # ref: https://github.com/pre-commit/pre-commit-hooks#hooks-available
11 | hooks:
12 | # Autoformat: Makes sure files end in a newline and only a newline.
13 | - id: end-of-file-fixer
14 | # Lint: Check for files with names that would conflict on a
15 | # case-insensitive filesystem like MacOS HFS+ or Windows FAT.
16 | - id: check-case-conflict
17 | - id: trailing-whitespace
18 | # Linting: Python code (see the file .flake8)
19 | - repo: https://github.com/PyCQA/flake8
20 | rev: "6.0.0"
21 | hooks:
22 | - id: flake8
23 | # Black for auto code formatting
24 | - repo: https://github.com/psf/black
25 | rev: 22.12.0
26 | hooks:
27 | - id: black
28 | language_version: python3.8
29 | # Tell precommit.ci bot to update codoe format tools listed in the file
30 | # versions every quarter
31 | # The default it so update weekly which is too many new pr's for many
32 | # maintainers (remove these lines if you aren't using the bot!)
33 | ci:
34 | autoupdate_schedule: quarterly
35 |
--------------------------------------------------------------------------------
/examples/pure-hatch/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["hatchling"]
3 | build-backend = "hatchling.build"
4 |
5 | [project]
6 | name = "examplePy"
7 | authors = [
8 | {name = "Some Maintainer", email = "some-email@pyopensci.org"},
9 | ]
10 | maintainers = [
11 | {name = "All the contributors"},
12 | ]
13 | description = "An example Python package used to support Python packaging tutorials"
14 | keywords = ["pyOpenSci", "python packaging"]
15 | readme = "README.md"
16 | classifiers = [
17 | "Programming Language :: Python :: 3",
18 | "License :: OSI Approved :: BSD License",
19 | "Operating System :: OS Independent",
20 | ]
21 | dependencies = [
22 | "dependency-package-name-1",
23 | "dependency-package-name-2",
24 | ]
25 |
26 | [project.optional-dependencies]
27 | tests = [
28 | "pytest",
29 | "pytest-cov"
30 | ]
31 | lint = [
32 | "black",
33 | "flake8"
34 | ]
35 | docs = [
36 | "sphinx",
37 | "pydata-sphinx-theme"
38 | ]
39 |
40 | [tool.ruff]
41 | select = [
42 | "E", # pycodestyle errors
43 | "W", # pycodestyle warnings
44 | "F", # pyflakes. "E" + "W" + "F" + "C90" (mccabe complexity) is equivalent to flake8
45 | "I", # isort
46 | ]
47 |
48 | [tool.ruff.isort]
49 | known-first-party = ["examplePy"]
50 |
--------------------------------------------------------------------------------
/examples/pure-hatch/src/examplePy/temperature.py:
--------------------------------------------------------------------------------
1 | def celsius_to_fahrenheit(celsius):
2 | """
3 | Convert temperature from Celsius to Fahrenheit.
4 |
5 | Parameters:
6 | celsius (float): Temperature in Celsius.
7 |
8 | Returns:
9 | float: Temperature in Fahrenheit.
10 | """
11 | fahrenheit = (celsius * 9/5) + 32
12 | return fahrenheit
13 |
14 |
15 | def fahrenheit_to_celsius(fahrenheit):
16 | """
17 | Convert temperature from Fahrenheit to Celsius.
18 |
19 | Parameters:
20 | fahrenheit (float): Temperature in Fahrenheit.
21 |
22 | Returns:
23 | float: Temperature in Celsius.
24 | """
25 | celsius = (fahrenheit - 32) * 5/9
26 | return celsius
27 |
--------------------------------------------------------------------------------
/examples/pure-hatch/src/examplePy/temporal-raw.py:
--------------------------------------------------------------------------------
1 | from examplePy.temperature import fahrenheit_to_celsius
2 | import pandas
3 | from typing import Sequence
4 |
5 | def calc_annual_mean(df: pandas.DataFrame):
6 | """Function to calculate the mean temperature for each year and the final mean"""
7 | # TODO: make this a bit more robust so we can write integration test examples??
8 | # Calculate the mean temperature for each year
9 | yearly_means = df.groupby('Year').mean()
10 |
11 | # Calculate the final mean temperature across all years
12 | final_mean = yearly_means.mean()
13 |
14 | # Return a converted value
15 | return fahrenheit_to_celsius(yearly_means), fahrenheit_to_celsius(final_mean)
16 |
--------------------------------------------------------------------------------
/examples/pure-hatch/src/examplePy/temporal.py:
--------------------------------------------------------------------------------
1 | from typing import Sequence
2 |
3 | import pandas
4 |
5 | from examplePy.temperature import fahrenheit_to_celsius
6 |
7 | def calc_annual_mean(df: pandas.DataFrame):
8 | """Function to calculate the mean temperature for each year and the final mean"""
9 | # TODO: make this a bit more robust so we can write integration test examples??
10 | # Calculate the mean temperature for each year
11 | yearly_means = df.groupby('Year').mean()
12 |
13 | # Calculate the final mean temperature across all years
14 | final_mean = yearly_means.mean()
15 |
16 | # Return a converted value
17 | return fahrenheit_to_celsius(yearly_means), fahrenheit_to_celsius(final_mean)
18 |
--------------------------------------------------------------------------------
/examples/pure-setuptools/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["setuptools>=61"]
3 | build-backend = "setuptools.build_meta"
4 |
5 | [project]
6 | name = "examplePy"
7 | authors = [
8 | {name = "Some Maintainer", email = "some-email@pyopensci.org"},
9 | ]
10 | maintainers = [
11 | {name = "All the contributors"},
12 | ]
13 | description = "An example Python package used to support Python packaging tutorials"
14 | keywords = ["pyOpenSci", "python packaging"]
15 | readme = "README.md"
16 | classifiers = [
17 | "Programming Language :: Python :: 3",
18 | "License :: OSI Approved :: BSD License",
19 | "Operating System :: OS Independent",
20 | ]
21 | dependencies = [
22 | "dependency-package-name-1",
23 | "dependency-package-name-2",
24 | ]
25 |
--------------------------------------------------------------------------------
/images/code-cov-stravalib.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/code-cov-stravalib.png
--------------------------------------------------------------------------------
/images/conda-channels-geohackweek.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/conda-channels-geohackweek.jpeg
--------------------------------------------------------------------------------
/images/conda-forge-staged-recipes-ci.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/conda-forge-staged-recipes-ci.png
--------------------------------------------------------------------------------
/images/contributing/clone-repository.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/contributing/clone-repository.png
--------------------------------------------------------------------------------
/images/contributing/commit-changes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/contributing/commit-changes.png
--------------------------------------------------------------------------------
/images/contributing/edit-button-pencil.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/contributing/edit-button-pencil.png
--------------------------------------------------------------------------------
/images/contributing/edit-file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/contributing/edit-file.png
--------------------------------------------------------------------------------
/images/contributing/new-pull-request.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/contributing/new-pull-request.png
--------------------------------------------------------------------------------
/images/contributing/preview-changes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/contributing/preview-changes.png
--------------------------------------------------------------------------------
/images/contributing/pull-requests-checks-fails.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/contributing/pull-requests-checks-fails.png
--------------------------------------------------------------------------------
/images/contributing/pull-requests-checks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/contributing/pull-requests-checks.png
--------------------------------------------------------------------------------
/images/contributing/pull-requests-tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/contributing/pull-requests-tab.png
--------------------------------------------------------------------------------
/images/flower-puzzle-pyopensci.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/flower-puzzle-pyopensci.jpg
--------------------------------------------------------------------------------
/images/geopandas-documentation-landing-page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/geopandas-documentation-landing-page.png
--------------------------------------------------------------------------------
/images/license-github-root-dir.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/license-github-root-dir.png
--------------------------------------------------------------------------------
/images/moving-pandas-python-package-github-community-standards.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/moving-pandas-python-package-github-community-standards.png
--------------------------------------------------------------------------------
/images/moving-pandas-python-package-github-main-repo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/moving-pandas-python-package-github-main-repo.png
--------------------------------------------------------------------------------
/images/moving-pandas-python-package-snyk-health.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/moving-pandas-python-package-snyk-health.png
--------------------------------------------------------------------------------
/images/packaging-lifecycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/packaging-lifecycle.png
--------------------------------------------------------------------------------
/images/pandera-python-package-readme-github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/pandera-python-package-readme-github.png
--------------------------------------------------------------------------------
/images/precommit-hook-python-code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/precommit-hook-python-code.png
--------------------------------------------------------------------------------
/images/publish-python-package-pypi-conda.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/publish-python-package-pypi-conda.png
--------------------------------------------------------------------------------
/images/pyopensci-puzzle-pieces-tests.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/pyopensci-puzzle-pieces-tests.png
--------------------------------------------------------------------------------
/images/pyopensci-python-package-pypi-to-conda-forge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/pyopensci-python-package-pypi-to-conda-forge.png
--------------------------------------------------------------------------------
/images/pypi-project-landing-page-no-meta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/pypi-project-landing-page-no-meta.png
--------------------------------------------------------------------------------
/images/python-build-package/pypi-metadata-classifiers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-build-package/pypi-metadata-classifiers.png
--------------------------------------------------------------------------------
/images/python-build-package/pypi-metadata-keywords-license.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-build-package/pypi-metadata-keywords-license.png
--------------------------------------------------------------------------------
/images/python-build-package/pypi-metadata-maintainers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-build-package/pypi-metadata-maintainers.png
--------------------------------------------------------------------------------
/images/python-dependency-conflicts-xkcd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-dependency-conflicts-xkcd.png
--------------------------------------------------------------------------------
/images/python-flying-xkcd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-flying-xkcd.png
--------------------------------------------------------------------------------
/images/python-package-dependencies.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-package-dependencies.png
--------------------------------------------------------------------------------
/images/python-package-dependency-types.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-package-dependency-types.png
--------------------------------------------------------------------------------
/images/python-package-development-process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-package-development-process.png
--------------------------------------------------------------------------------
/images/python-package-documentation-nb_sphinx-gallery-output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-package-documentation-nb_sphinx-gallery-output.png
--------------------------------------------------------------------------------
/images/python-package-tools-2022-survey-pypa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-package-tools-2022-survey-pypa.png
--------------------------------------------------------------------------------
/images/python-package-tools-decision-tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-package-tools-decision-tree.png
--------------------------------------------------------------------------------
/images/python-pypi-conda-channels.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-pypi-conda-channels.png
--------------------------------------------------------------------------------
/images/python-tests-puzzle-fit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-tests-puzzle-fit.png
--------------------------------------------------------------------------------
/images/python-tests-puzzle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/python-tests-puzzle.png
--------------------------------------------------------------------------------
/images/sphinx-gallery-overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/sphinx-gallery-overview.png
--------------------------------------------------------------------------------
/images/sphinx-gallery-tutorial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/sphinx-gallery-tutorial.png
--------------------------------------------------------------------------------
/images/sphinx-rendering-extent-to-json-earthpy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/sphinx-rendering-extent-to-json-earthpy.png
--------------------------------------------------------------------------------
/images/tutorials/code-to-python-package.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/tutorials/code-to-python-package.png
--------------------------------------------------------------------------------
/images/tutorials/environment-package-install.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/tutorials/environment-package-install.png
--------------------------------------------------------------------------------
/images/tutorials/github-new-repo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/tutorials/github-new-repo.png
--------------------------------------------------------------------------------
/images/tutorials/package-components.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/tutorials/package-components.png
--------------------------------------------------------------------------------
/images/tutorials/packaging-101-outline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/tutorials/packaging-101-outline.png
--------------------------------------------------------------------------------
/images/tutorials/packaging-elements.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/tutorials/packaging-elements.png
--------------------------------------------------------------------------------
/images/tutorials/packaging-lifecycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/tutorials/packaging-lifecycle.png
--------------------------------------------------------------------------------
/images/tutorials/publish-package-pypi-conda.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/tutorials/publish-package-pypi-conda.png
--------------------------------------------------------------------------------
/images/tutorials/test-pypi-package.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/tutorials/test-pypi-package.png
--------------------------------------------------------------------------------
/images/tutorials/testpypi-search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/tutorials/testpypi-search.png
--------------------------------------------------------------------------------
/images/tutorials/toolbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/tutorials/toolbox.png
--------------------------------------------------------------------------------
/images/tutorials/view-license-github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/images/tutorials/view-license-github.png
--------------------------------------------------------------------------------
/locales/es/LC_MESSAGES/continuous-integration.po:
--------------------------------------------------------------------------------
1 | # SOME DESCRIPTIVE TITLE.
2 | # Copyright (C) 2025, pyOpenSci
3 | # This file is distributed under the same license as the pyOpenSci Python
4 | # Package Guide package.
5 | # FIRST AUTHOR , 2025.
6 | #
7 | #, fuzzy
8 | msgid ""
9 | msgstr ""
10 | "Project-Id-Version: pyOpenSci Python Package Guide \n"
11 | "Report-Msgid-Bugs-To: \n"
12 | "POT-Creation-Date: 2025-01-18 13:00-0500\n"
13 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
14 | "Last-Translator: FULL NAME \n"
15 | "Language: es\n"
16 | "Language-Team: es \n"
17 | "Plural-Forms: nplurals=2; plural=(n != 1);\n"
18 | "MIME-Version: 1.0\n"
19 | "Content-Type: text/plain; charset=utf-8\n"
20 | "Content-Transfer-Encoding: 8bit\n"
21 | "Generated-By: Babel 2.16.0\n"
22 |
23 | #: ../../continuous-integration/ci.md:2
24 | msgid ""
25 | "Continuous Integration and Continuous Deployment (CI/CD) For Python "
26 | "Packages"
27 | msgstr ""
28 |
29 | #: ../../continuous-integration/ci.md:4
30 | msgid ""
31 | "When you develop, work on, and contribute to software, there is more to "
32 | "consider than just writing code. Having tests and checks ensures that "
33 | "your code runs reliably and follows a consistent format is also "
34 | "important. You can use **Continuous Integration (CI)** and **Continuous "
35 | "Deployment (CD)** to run tests and checks on your code every time someone"
36 | " suggests a change online in a platform like GitHub or GitLab."
37 | msgstr ""
38 |
39 | #: ../../continuous-integration/ci.md:11
40 | msgid ""
41 | "**Continuous Integration (CI):** Automates the process of running tests, "
42 | "code checks, and other workflows each time code is updated."
43 | msgstr ""
44 |
45 | #: ../../continuous-integration/ci.md:13
46 | msgid ""
47 | "**Continuous Deployment (CD):** Extends CI by allowing you to automate "
48 | "publishing your package to PyPI, publishing your documentation, and more."
49 | msgstr ""
50 |
51 | #: ../../continuous-integration/ci.md:15
52 | msgid ""
53 | "CI and CD streamline software development by automating repetitive tasks "
54 | "and ensuring code quality and consistency. Having CI setup also makes it "
55 | "easier for new contributors to contribute to your code base without "
56 | "setting up all your test suites and other local checks."
57 | msgstr ""
58 |
59 | #: ../../continuous-integration/ci.md:20
60 | msgid "What is continuous integration?"
61 | msgstr ""
62 |
63 | #: ../../continuous-integration/ci.md:22
64 | msgid ""
65 | "When you’re ready to publish your code online, you can set up Continuous "
66 | "Integration (CI). CI is a platform that allows you to specify and run "
67 | "jobs or workflows you define. These workflows include:"
68 | msgstr ""
69 |
70 | #: ../../continuous-integration/ci.md:25
71 | msgid "Running your test suite"
72 | msgstr ""
73 |
74 | #: ../../continuous-integration/ci.md:26
75 | msgid "Running code checkers / linters / spellcheck"
76 | msgstr ""
77 |
78 | #: ../../continuous-integration/ci.md:27
79 | msgid "Building your documentation"
80 | msgstr ""
81 |
82 | #: ../../continuous-integration/ci.md:29
83 | msgid ""
84 | "CI allows you to automate running workflows across a suite of "
85 | "environments, including:"
86 | msgstr ""
87 |
88 | #: ../../continuous-integration/ci.md:31
89 | msgid "environments containing different Python versions and"
90 | msgstr ""
91 |
92 | #: ../../continuous-integration/ci.md:32
93 | msgid "different operating systems (Mac, Linux, Windows)."
94 | msgstr ""
95 |
96 | #: ../../continuous-integration/ci.md:34
97 | msgid "What is Continuous Deployment (CD)?"
98 | msgstr ""
99 |
100 | #: ../../continuous-integration/ci.md:36
101 | msgid ""
102 | "Continuous deployment (CD) extends the CI process by automating the "
103 | "deployment of code changes to production or staging environments. In the "
104 | "case of your open source tool, CD can be used to:"
105 | msgstr ""
106 |
107 | #: ../../continuous-integration/ci.md:38
108 | msgid "Automate publishing to PyPI"
109 | msgstr ""
110 |
111 | #: ../../continuous-integration/ci.md:39
112 | msgid "Automate publishing your documentation to GitHub Pages or Read the Docs."
113 | msgstr ""
114 |
115 | #: ../../continuous-integration/ci.md:41
116 | msgid ""
117 | "It is also used once your conda-forge recipe is set up to keep your "
118 | "package up to date on conda-forge."
119 | msgstr ""
120 |
121 | #: ../../continuous-integration/ci.md:43
122 | msgid "Why use CI"
123 | msgstr ""
124 |
125 | #: ../../continuous-integration/ci.md:45
126 | msgid ""
127 | "CI can be configured to run a workflow on every commit pushed to GitHub "
128 | "and every pull request opened. This ensures that any changes made to your"
129 | " package are tested across environments before merging into the main "
130 | "branch of your code."
131 | msgstr ""
132 |
133 | #: ../../continuous-integration/ci.md:47
134 | msgid ""
135 | "These checks are particularly useful if someone new is contributing to "
136 | "your code. Every contributor's change will be tested when pushed to your "
137 | "code repository."
138 | msgstr ""
139 |
140 | #: ../../continuous-integration/ci.md:49
141 | msgid ""
142 | "Together, CI and CD streamline the process of building, testing, and "
143 | "deploying code. They aim to improve software development and publication "
144 | "efficiency, quality, and reliability."
145 | msgstr ""
146 |
147 | #: ../../continuous-integration/ci.md:52
148 | msgid ""
149 | "All pyOpenSci packages must use some form of continuous integration. Even"
150 | " if you are not planning to go through peer review, we strongly recommend"
151 | " that you use continuous integration, too!"
152 | msgstr ""
153 |
154 | #: ../../continuous-integration/ci.md:55
155 | msgid ""
156 | "In the case of GitHub actions (which we will focus on here), CI workflows"
157 | " are running on online servers that support GitHub."
158 | msgstr ""
159 |
160 | #: ../../continuous-integration/ci.md:57
161 | msgid "CI / CD platforms"
162 | msgstr ""
163 |
164 | #: ../../continuous-integration/ci.md:59
165 | msgid ""
166 | "There are numerous platforms available for CI/CD. Here, we will focus on "
167 | "GitHub Actions (GHA), built into GitHub. GitHub is the most commonly used"
168 | " platform to store scientific open-source software."
169 | msgstr ""
170 |
171 | #: ../../continuous-integration/ci.md:62
172 | msgid ""
173 | "If you use [GitLab](https://about.gitlab.com/) CI/CD, many of the "
174 | "principles described here will apply. However, the workflow files may "
175 | "look different."
176 | msgstr ""
177 |
178 | #: ../../continuous-integration/ci.md:65
179 | msgid "If you aren't sure, use GitHub Actions"
180 | msgstr ""
181 |
182 | #: ../../continuous-integration/ci.md:67
183 | msgid ""
184 | "While you are welcome to use the continuous integration platform of your "
185 | "choice, we recommend GitHub Actions because it is free-to-use and "
186 | "integrated tightly into the GitHub user interface. There is also an "
187 | "entire store of GitHub action templates that you can easily use and adapt"
188 | " to your own needs."
189 | msgstr ""
190 |
191 | #: ../../continuous-integration/ci.md:72
192 | msgid "Other platforms that you may run into"
193 | msgstr ""
194 |
195 | #: ../../continuous-integration/ci.md:75
196 | msgid ""
197 | "[Appveyor:](https://www.appveyor.com/): Supports running tests on Windows"
198 | " operating systems and predated the release of GitHub Actions. Today, "
199 | "AppVeyor supports operating systems beyond Windows."
200 | msgstr ""
201 |
202 | #: ../../continuous-integration/ci.md:76
203 | msgid ""
204 | "[Travis CI:](https://www.travis-ci.com/) had been a common CI platform "
205 | "choice in our ecosystem. Usage dropped after Travis CI ended free support"
206 | " for open-source projects."
207 | msgstr ""
208 |
209 | #: ../../continuous-integration/ci.md:77
210 | msgid ""
211 | "[CircleCI:](https://circleci.com/) CircleCI can be useful for automated "
212 | "builds of websites and documentation since it offers a preview of the PR "
213 | "changes."
214 | msgstr ""
215 |
216 | #: ../../continuous-integration/ci.md:80
217 | msgid "Embrace automation"
218 | msgstr ""
219 |
220 | #: ../../continuous-integration/ci.md:82
221 | msgid ""
222 | "By embracing CI/CD, you can ensure that your code runs as you expect it "
223 | "to across the diverse landscapes of user environments. Further, you can "
224 | "automate certain checks (and, in some cases, code fixes), including "
225 | "linting and code style. You can even automate spell-checking your "
226 | "documentation and docstrings!"
227 | msgstr ""
228 |
229 | #: ../../continuous-integration/index.md:5
230 | msgid "What is CI?"
231 | msgstr ""
232 |
233 | #: ../../continuous-integration/index.md:5
234 | msgid "Continuous Integration"
235 | msgstr ""
236 |
237 | #: ../../continuous-integration/index.md:2
238 | msgid ""
239 | "Continuous Integration (CI) and Continuous Deployment (CD) for your "
240 | "Python package"
241 | msgstr ""
242 |
--------------------------------------------------------------------------------
/package-structure-code/complex-python-package-builds.md:
--------------------------------------------------------------------------------
1 | # Complex Python package builds
2 |
3 | This guide is focused on packages that are either pure-python or that
4 | have a few simple extensions in another language such as C or C++.
5 |
6 | In the future, we want to provide resources for packaging workflows that require more complex builds. If you have questions about these types of package, please [add a question to our discourse](https://pyopensci.discourse.group/) or open an [issue about this guide specifically in the GitHub repo for this guide](https://github.com/pyOpenSci/python-package-guide/issues). There are many nuances to building and distributing Python packages that have compiled extensions requiring non-Python dependencies at build time. For an overview and thorough discussion of these nuances, please see [this site.](https://pypackaging-native.github.io/)
7 |
8 | ## Pure Python Packages vs. packages with extensions in other languages
9 |
10 | You can classify Python package complexity into three general categories. These
11 | categories can in turn help you select the correct package frontend and
12 | backend tools.
13 |
14 | 1. **Pure-python packages:** these are packages that only rely on Python to function. Building a pure Python package is simpler. As such, you can chose a tool below that has the features that you want and be done with your decision!
15 |
16 | 2. **Python packages with non-Python extensions:** These packages have additional components called extensions written in other languages (such as C or C++). If you have a package with non-Python extensions, then you need to select a build backend tool that allows additional build steps needed to compile your extension code. Further, if you wish to use a frontend tool to support your workflow, you will need to select a tool that supports additional build setups. We suggest that you chose build tool that supports custom build steps like Hatch.
17 |
18 | 3. **Python packages that have extensions written in different languages (e.g. Fortran and C++) or that have non Python dependencies that are difficult to install (e.g. GDAL):** These packages often have complex build steps (more complex than a package with just a few C extensions for instance). As such, these packages require tools such as [scikit-build](https://scikit-build.readthedocs.io/en/latest/)
19 | or [meson-python](https://mesonbuild.com/Python-module.html) to build. NOTE: you can use meson-python with PDM.
20 |
21 | ## Mixing frontend and backend projects
22 |
23 | It is sometimes necessary or desirable to use a build frontend with an alternative build-backend.
24 | This is because some frontends do not have a default backend (`build`), and this choice is placed on the maintainer.
25 | Other backends (`hatch`) have a preferred backend (`hatchling`) but allow the maintainer to migrate to another, while
26 | some backends (`poetry`) only work with a single backend (`poetry-core`). Refer to (#python-package-build-tools) for
27 | more information about frontend and backend compatibility.
28 |
29 | In this packaging guide we recommend using `hatch` along with its preferred backend `hatchling`. While this will be
30 | suitable for most packages, an alternate backend may be used with Hatch if needed when creating an extension module.
31 | A Python extension module is one that is made up, either in part or entirely, of compiled code. In this case the
32 | backend chosen (such as `meson-python`) must know how to compile the extension language and bind it to Python.
33 | `hatchling` does not know how to do this all on its own and must either make use of
34 | [plugins](https://hatch.pypa.io/1.9/plugins/about/) or be replaced by a backend that is already capable of building
35 | extension modules.
36 |
37 | In order to use a different backend you will need to edit your project's `pyproject.toml`. If you have a
38 | `pyproject.toml` generated by the `hatch` command, or from following the packaging tutorial, you may have
39 | to make a change like this
40 |
41 | ```diff
42 | [build-system]
43 | -requires = ["hatchling"]
44 | +requires = ["meson-python"]
45 | -build-backend = "hatchling.build"
46 | +build-backend = "mesonpy"
47 | ```
48 |
--------------------------------------------------------------------------------
/package-structure-code/intro.md:
--------------------------------------------------------------------------------
1 | # Python Package Structure
2 |
3 | This section provides guidance on your Python package's structure, code format,
4 | and style. It also reviews the various [packaging tools](python-package-build-tools) you can use to
5 | [build](python-package-distribution-files-sdist-wheel) and [publish](publish-python-package-pypi-conda) your Python package.
6 |
7 | If you want end-to-end tutorials, check out our tutorial series that starts by introducing [what a Python package is](what-is-a-package).
8 |
9 | If you are confused by Python packaging, you are not alone! The good news is
10 | that some great modern packaging tools ensure you follow
11 | best practices. Here, we review tool features and suggest tools you can use
12 | for your Python packaging workflow.
13 |
14 | :::{button-link} /tutorials/intro
15 | :color: success
16 | :class: sd-rounded-pill float-left
17 |
18 | Checkout our beginning-to-end create a Python package tutorials
19 |
20 | :::
21 |
22 |
23 | :::{admonition} How this content is developed
24 | All of the content in this guide has been vetted by community members, including maintainers and developers of the core packaging tools.
25 | :::
26 |
27 |
28 | :::::{grid} 1 1 2 2
29 | :class-container: text-center
30 | :gutter: 3
31 |
32 | ::::{grid-item}
33 | :::{card} ✨ 1. Package file structure ✨
34 | :link: python-package-structure
35 | :link-type: doc
36 |
37 | src layout, flat layout and where should tests folders live? No matter what your level of packaging knowledge is, this page will help you decide upon a package structure that follows modern python best practices.
38 | :::
39 | ::::
40 |
41 | ::::{grid-item}
42 | :::{card} ✨ 2. Learn about building your package ✨
43 | :link: python-package-structure
44 | :link-type: doc
45 |
46 | To publish your Python package on PyPI, you will need to first build it. The act
47 | of "building" refers to the process of placing your package code and
48 | metadata into a format that can be published on PyPI. Learn more about building
49 | your Python package.
50 | :::
51 | ::::
52 |
53 |
54 | ::::{grid-item}
55 | :::{card} ✨ 4. Add metadata ✨
56 | :link: pyproject-toml-python-package-metadata
57 | :link-type: doc
58 |
59 | Learn how to add project metadata to your Python package to support both
60 | filtering on PyPI and also the metadata that a package installer needs to
61 | build and install your package.
62 | :::
63 | ::::
64 |
65 | ::::{grid-item}
66 | :::{card} ✨ 3. What Python package tool should you use? ✨
67 | :link: python-package-build-tools
68 | :link-type: doc
69 |
70 | Learn more about the suite of packaging tools out there.
71 | And learn which tool might be best for you.
72 | :::
73 | ::::
74 |
75 | ::::{grid-item}
76 | :::{card} ✨ 4. Publish to PyPI and Conda ✨
77 | :link: python-package-build-tools
78 | :link-type: doc
79 |
80 | If you have a pure Python package, it's a straight forward
81 | process to publish to both PyPI and then a Conda channel such as
82 | conda-forge. Learn more here.
83 | :::
84 | ::::
85 |
86 | ::::{grid-item}
87 | :::{card} ✨ 5. Setup package versioning ✨
88 | :link: python-package-versions
89 | :link-type: doc
90 |
91 | Semver (numeric versioning) and Calver (versioning using the date) are 2
92 | common ways to version a package. Which one should you pick? Learn more here.
93 | :::
94 | ::::
95 |
96 | ::::{grid-item}
97 | :::{card} ✨ 6. Code style & linters ✨
98 | :link: code-style-linting-format
99 | :link-type: doc
100 |
101 | Black, blue, flake8, Ruff - which tools can help you ensure your
102 | package follows best practices for code format? Learn more about the options
103 | and why this is important here.
104 | :::
105 | ::::
106 |
107 | :::::
108 |
109 | :::{figure-md} packaging-tools-decision-tree
110 |
111 |
112 |
113 | Diagram showing the various front-end build tools that you can select from.
114 | See the packaging tools page to learn more about each tool.
115 | :::
116 |
117 | :::{note}
118 | If you are considering submitting a package for peer review, have a look
119 | at the bare-minimum [editor checks](https://www.pyopensci.org/software-peer-review/how-to/editor-in-chief-guide.html#editor-checklist-template)
120 | that pyOpenSci performs before a review begins. These checks are useful
121 | to explore for both authors planning to submit a package to us for review
122 | and for anyone who is just getting started with creating a Python package.
123 | :::
124 |
125 | ## What you will learn here
126 |
127 | In this section of our Python packaging guide, we:
128 |
129 | - Provide an overview of the options available to you when packaging your
130 | code.
131 | - Suggest tools and approaches that both meet your needs and also support
132 | existing standards.
133 | - Suggest tools and approaches that will allow you to expand upon a workflow
134 | that may begin as a pure Python code and evolve into code that requires
135 | addition layers of complexity in the packaging build.
136 | - Align our suggestions with the most current, accepted
137 | [PEPs (Python Enhancement Protocols)](https://peps.python.org/pep-0000/)
138 | and the [Scientific Python community SPECs](https://scientific-python.org/specs/).
139 | - In an effort to maintain consistency within our community, we also align
140 | with existing best practices being implemented by developers of core
141 | Scientific Python packages such as Numpy, SciPy and others.
142 |
143 | ## Guidelines for pyOpenSci's packaging recommendations
144 |
145 | The flexibility of the Python programming language lends itself to a diverse
146 | range of tool options for creating a Python package. Python is so flexible that
147 | it is one of the few languages that can be used to wrap around other languages.
148 | The ability of Python to wrap other languages is one the reasons you will often
149 | hear Python described as a ["glue" language](https://numpy.org/doc/stable/user/c-info.python-as-glue.html)"
150 |
151 | If you are building a pure Python package, then your packaging setup can be
152 | simple. However, some scientific packages have complex requirements as they may
153 | need to support extensions or tools written in other languages such as C or C++.
154 |
155 | To support the many different uses of Python, there are many ways to create a
156 | Python package. In this guide, we suggest packaging approaches and tools based on:
157 |
158 | 1. What we think will be best and easiest to adopt for those who are newer to
159 | packaging.
160 | 2. Tools that we think are well maintained and documented.
161 | 3. A shared goal of standardizing packaging approaches across this (scientific)
162 | Python ecosystem.
163 |
164 | Here, we also try to align our suggestions with the most current, accepted
165 | [Python community](https://packaging.python.org/en/latest/) and [scientific community](https://scientific-python.org/specs/).
166 |
167 | :::{admonition} Suggestions in this guide are not pyOpenSci review requirements
168 | :class: important
169 |
170 | The suggestions for package layout in this section are made with the
171 | intent of being helpful; they are not specific requirements for your
172 | package to be reviewed and accepted into our pyOpenSci open source ecosystem.
173 |
174 | Please check out our [package scope page](https://www.pyopensci.org/software-peer-review/about/package-scope.html)
175 | and [review requirements in our author guide](https://www.pyopensci.org/software-peer-review/how-to/author-guide.html#)
176 | if you are looking for pyOpenSci's Python package review requirements!
177 | :::
178 |
179 | :::{toctree}
180 | :hidden:
181 | :caption: Create & Build Your Package
182 |
183 | Intro
184 |
185 | Python package structure
186 | pyproject.toml Package Metadata
187 | Build Your Package
188 | Declare dependencies
189 | Package Build Tools
190 | Complex Builds
191 | :::
192 |
193 | :::{toctree}
194 | :hidden:
195 | :caption: Publish your package
196 |
197 | Publish with Conda / PyPI
198 | Package versions
199 | Code style
200 |
201 | :::
202 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["hatchling", "hatch-vcs"]
3 | build-backend = "hatchling.build"
4 |
5 | [project]
6 | name = "python-package-guide"
7 | dynamic = [
8 | "version"
9 | ]
10 | dependencies = [
11 | "pydata-sphinx-theme==0.16.1",
12 | "myst-nb",
13 | "sphinx",
14 | "sphinx-autobuild",
15 | "sphinx-copybutton",
16 | "sphinx-design",
17 | "sphinx-favicon",
18 | # XML feed for analytics
19 | "sphinx-sitemap",
20 | # Support for social / adds meta tags
21 | "sphinxext-opengraph",
22 | "sphinx-inline-tabs",
23 | # for project cards
24 | "matplotlib",
25 | # for license page bibliography
26 | "sphinxcontrib-bibtex",
27 | ]
28 |
29 | [project.optional-dependencies]
30 | dev = [
31 | # for general build workflows
32 | "nox",
33 | # for prose linting
34 | "vale",
35 | # for managing translation files
36 | "sphinx-intl",
37 | ]
38 |
39 | [tool.hatch.build.targets.wheel]
40 | bypass-selection = true
41 |
42 | [tool.hatch]
43 | version.source = "vcs"
44 |
45 |
46 | # https://github.com/codespell-project/codespell#usage
47 | [tool.codespell]
48 | ignore-words = "codespell-ignore.txt"
49 | skip = "./.git,./.nox,./_static,./_build,codespell-ignore.txt,*.svg"
50 |
--------------------------------------------------------------------------------
/scripts/translation_stats.py:
--------------------------------------------------------------------------------
1 | from babel.messages import pofile
2 |
3 | from pathlib import Path
4 | from babel.messages import pofile
5 |
6 | # Paths needed for this script
7 | BASE_DIR = Path(__file__).resolve().parent.parent # Repository base directory
8 | LOCALES_DIR = BASE_DIR / "locales" # Locales directory
9 | STATIC_DIR = BASE_DIR / "_static" # Static directory
10 |
11 | def calculate_translation_percentage(po_path : Path, locale : str) -> dict:
12 | """
13 | Calculate the translation percentage for a given .po file.
14 |
15 | Parameters
16 | ----------
17 | po_path : Path
18 | Path to the .po file.
19 | locale : str
20 | Locale code (e.g., 'es', 'fr').
21 |
22 | Returns
23 | -------
24 | dict
25 | A dictionary containing the total number of strings, translated strings,
26 | fuzzy strings, untranslated strings, and the translation percentage.
27 | """
28 | with open(po_path, "r", encoding="utf-8") as f:
29 | catalog = pofile.read_po(f, locale=locale)
30 |
31 | total = 0
32 | translated = 0
33 | fuzzy = 0
34 |
35 | for message in catalog:
36 | if message.id:
37 | total += 1
38 | # Check if the message is fuzzy
39 | # Fuzzy messages are not considered translated
40 | if message.fuzzy:
41 | fuzzy += 1
42 | break
43 | # Check if the message is translated
44 | if message.string:
45 | translated += 1
46 |
47 | percentage = (translated / total * 100) if total > 0 else 0
48 |
49 | return {
50 | "total": total,
51 | "translated": translated,
52 | "fuzzy": fuzzy,
53 | "untranslated": total - translated - fuzzy,
54 | "percentage": round(percentage, 2)
55 | }
56 |
57 | def main():
58 | # Get all .po files in the locales directory
59 | po_files = list(LOCALES_DIR.rglob("*.po"))
60 |
61 | # Let's use a dictionary to store the results
62 | #
63 | # We will store the info as
64 | # {
65 | # "es": {
66 | # "file1": {
67 | # "total": 100,
68 | # "translated": 50,
69 | # "fuzzy": 0,
70 | # "untranslated": 50,
71 | # "percentage": 50.0
72 | # },
73 | # ...
74 | # },
75 | # "fr": {
76 | # "file1": {
77 | # "total": 100,
78 | # "translated": 50,
79 | # "fuzzy": 0,
80 | # "untranslated": 50,
81 | # "percentage": 50.0
82 | # },
83 | # ...
84 | # }
85 | results = {}
86 |
87 | # Calculate translation percentages for each file
88 | for po_file in po_files:
89 | # Get the locale from the file path
90 | locale = po_file.parent.parent.name
91 | stats = calculate_translation_percentage(po_file, locale)
92 | print(f"({po_file.stem}): {stats['percentage']}% translated ({stats['translated']} of {stats['total']})")
93 |
94 | # Store the results in the dictionary
95 | if locale not in results:
96 | results[locale] = {}
97 |
98 | results[locale][po_file.stem] = stats
99 |
100 | # Dump the results to a JSON file
101 | with open(STATIC_DIR / "translation_stats.json", "w") as f:
102 | import json
103 | json.dump(results, f, indent=4)
104 |
105 | if __name__ == "__main__":
106 | main()
107 |
--------------------------------------------------------------------------------
/tests/code-cov.md:
--------------------------------------------------------------------------------
1 | # Code coverage for your Python package test suite
2 |
3 | Code coverage measures how much of your package's code runs during testing.
4 | Achieving high coverage can help ensure the reliability of your codebase, but
5 | it’s not a guarantee of quality. Below, we outline key considerations for
6 | using code coverage effectively.
7 |
8 | ## Why aim for high code coverage?
9 |
10 | A good practice is to ensure that every line of your code runs at least once
11 | during your test suite. This helps you:
12 |
13 | - Identify untested parts of your codebase.
14 | - Catch bugs that might otherwise go unnoticed.
15 | - Build confidence in your software's stability.
16 |
17 | ## Limitations of code coverage
18 |
19 | While high code coverage is valuable, it has its limits:
20 |
21 | - **Difficult-to-test code:** Some parts of your code might be challenging to
22 | test, either due to complexity or limited resources.
23 | - **Missed edge cases:** Running all lines of code doesn’t guarantee that edge
24 | cases are handled correctly.
25 |
26 | Ultimately, you should focus on how your package will be used and ensure your
27 | tests cover those scenarios adequately.
28 |
29 | ## Tools for analyzing Python package code coverage
30 |
31 | Some common services for analyzing code coverage are [codecov.io](https://codecov.io/) and [coveralls.io](https://coveralls.io/). These projects are free for open source tools and will provide dashboards that tell you how much of your codebase is covered during your tests. We recommend setting up an account (on either CodeCov or Coveralls) and using it to keep track of your code coverage.
32 |
33 | :::{figure} ../images/code-cov-stravalib.png
34 | :height: 450px
35 | :alt: Screenshot of the code cov service - showing test coverage for the stravalib package. This image shows a list of package modules and the associated number of lines and % lines covered by tests. At the top of the image, you can see what branch is being evaluated and the path to the repository.
36 |
37 | The CodeCov platform is a useful tool if you wish to track code coverage visually. Using it, you can not only get the same summary information that you can get with the **pytest-cov** extension. You can also see what lines are covered by your tests and which are not. Code coverage is useful for evaluating unit tests and/or how much of your package code is "covered". It, however, will not evaluate things like integration tests and end-to-end workflows.
38 |
39 | :::
40 |
41 |
42 |
43 | :::{admonition} Typing & MyPy coverage
44 | You can also create and upload typing reports to CodeCov.
45 | :::
46 |
47 | ## Exporting Local Coverage Reports
48 |
49 | In addition to using services like CodeCov or Coveralls, you can generate local coverage reports directly using the **coverage.py** tool. This can be especially useful if you want to create reports in Markdown or HTML format for offline use or documentation.
50 |
51 | To generate a coverage report in **Markdown** format, run:
52 |
53 | ```bash
54 | $ python -m coverage report --format=markdown
55 | ```
56 | This command will produce a Markdown-formatted coverage summary that you can easily include in project documentation or share with your team.
57 |
58 | To generate an HTML report that provides a detailed, interactive view of which lines are covered, use:
59 |
60 | ```bash
61 | python -m coverage html
62 | ```
63 |
64 | The generated HTML report will be saved in a directory named htmlcov by default. Open the index.html file in your browser to explore your coverage results.
65 |
66 | These local reports are an excellent way to quickly review coverage without setting up an external service.
67 |
--------------------------------------------------------------------------------
/tests/index.md:
--------------------------------------------------------------------------------
1 | (tests-intro)=
2 | # Tests and data for your Python package
3 |
4 | Tests are an important part of your Python package because they
5 | provide a set of checks that ensure that your package is
6 | functioning how you expect it to.
7 |
8 | In this section, you will learn more about the importance of writing
9 | tests for your Python package and how you can set up infrastructure
10 | to run your tests both locally and on GitHub.
11 |
12 |
13 | :::::{grid} 1 1 3 2
14 | :class-container: text-center
15 | :gutter: 3
16 |
17 | ::::{grid-item}
18 | :::{card} ✨ Why write tests ✨
19 | :link: write-tests
20 | :link-type: doc
21 | :class-card: left-aligned
22 |
23 | Learn more about the art of writing tests for your Python package.
24 | Learn about why you should write tests and how they can help you and
25 | potential contributors to your project.
26 | :::
27 | ::::
28 |
29 | ::::{grid-item}
30 | :::{card} ✨ Types of tests ✨
31 | :link: test-types
32 | :link-type: doc
33 | :class-card: left-aligned
34 |
35 | There are three general types of tests that you can write for your Python
36 | package: unit tests, integration tests and end-to-end (or functional) tests. Learn about all three.
37 | :::
38 | ::::
39 |
40 | ::::{grid-item}
41 | :::{card} ✨ Run tests locally ✨
42 | :link: run-tests
43 | :link-type: doc
44 | :class-card: left-aligned
45 |
46 | If you expect your users to use your package across different versions
47 | of Python, then using an automation tool such as nox to run your tests is useful. Learn about the various tools that you can use to run your tests across python versions here.
48 | :::
49 | ::::
50 |
51 | ::::{grid-item}
52 | :::{card} ✨ Run tests online (using CI) ✨
53 | :link: tests-ci
54 | :link-type: doc
55 | :class-card: left-aligned
56 |
57 | Continuous integration platforms such as GitHub Actions can be
58 | useful for running your tests across both different Python versions
59 | and different operating systems. Learn about setting up tests to run in Continuous Integration here.
60 | :::
61 | ::::
62 |
63 | :::::
64 |
65 |
66 | :::{figure-md} fig-target
67 |
68 |
69 |
70 | Graphic showing the elements of the packaging process.
71 | :::
72 |
73 | ```{toctree}
74 | :hidden:
75 | :maxdepth: 2
76 | :caption: Create & Run Tests
77 |
78 | Intro
79 | Write tests
80 | Test types
81 | Run tests locally
82 | Run tests online (using CI)
83 | Code coverage
84 | ```
85 |
--------------------------------------------------------------------------------
/tests/test-types.md:
--------------------------------------------------------------------------------
1 | # Test Types for Python packages
2 |
3 | ## Three types of tests: Unit, Integration & Functional Tests
4 |
5 | There are different types of tests that you want to consider when creating your
6 | test suite:
7 |
8 | 1. Unit tests
9 | 2. Integration
10 | 3. End-to-end (also known as Functional) tests
11 |
12 | Each type of test has a different purpose. Here, you will learn about all three types of tests.
13 |
14 | ```{todo}
15 | I think this page would be stronger if we did have some
16 | examples from our package here: https://github.com/pyOpenSci/pyosPackage
17 |
18 | ```
19 |
20 | ## Unit Tests
21 |
22 | A unit test involves testing individual components or units of code in isolation to ensure that they work correctly. The goal of unit testing is to verify that each part of the software, typically at the function or method level, performs its intended task correctly.
23 |
24 | Unit tests can be compared to examining each piece of your puzzle to ensure parts of it are not broken. If all of the pieces of your puzzle don’t fit together, you will never complete it. Similarly, when working with code, tests ensure that each function, attribute, class, method works properly when isolated.
25 |
26 | **Unit test example:** Pretend that you have a function that converts a temperature value from Celsius to Fahrenheit. A test for that function might ensure that when provided with a value in Celsius, the function returns the correct value in degrees Fahrenheit. That function is a unit test. It checks a single unit (function) in your code.
27 |
28 | ```python
29 | # Example package function
30 | def celsius_to_fahrenheit(celsius):
31 | """
32 | Convert temperature from Celsius to Fahrenheit.
33 |
34 | Parameters:
35 | celsius (float): Temperature in Celsius.
36 |
37 | Returns:
38 | float: Temperature in Fahrenheit.
39 | """
40 | fahrenheit = (celsius * 9/5) + 32
41 | return fahrenheit
42 | ```
43 |
44 | Example unit test for the above function. You'd run this test using the `pytest` command in your **tests/** directory.
45 |
46 | ```python
47 | import pytest
48 | from temperature_converter import celsius_to_fahrenheit
49 |
50 | def test_celsius_to_fahrenheit():
51 | """
52 | Test the celsius_to_fahrenheit function.
53 | """
54 | # Test with freezing point of water
55 | assert pytest.approx(celsius_to_fahrenheit(0), abs=0.01) == 32.0
56 |
57 | # Test with boiling point of water
58 | assert pytest.approx(celsius_to_fahrenheit(100), abs=0.01) == 212.0
59 |
60 | # Test with a negative temperature
61 | assert pytest.approx(celsius_to_fahrenheit(-40), abs=0.01) == -40.0
62 |
63 | ```
64 |
65 | ```{figure} ../images/pyopensci-puzzle-pieces-tests.png
66 | :height: 300px
67 | :alt: image of puzzle pieces that all fit together nicely. The puzzle pieces are colorful - purple, green and teal.
68 |
69 | Your unit tests should ensure each part of your code works as expected on its own.
70 | ```
71 |
72 | ## Integration tests
73 |
74 | Integration tests involve testing how parts of your package work together or integrate. Integration tests can be compared to connecting a bunch of puzzle pieces together to form a whole picture. Integration tests focus on how different pieces of your code fit and work together.
75 |
76 | For example, if you had a series of steps that collected temperature data in a spreadsheet, converted it from degrees celsius to Fahrenheit and then provided an average temperature for a particular time period. An integration test would ensure that all parts of that workflow behaved as expected.
77 |
78 | ```python
79 |
80 | def fahr_to_celsius(fahrenheit):
81 | """
82 | Convert temperature from Fahrenheit to Celsius.
83 |
84 | Parameters:
85 | fahrenheit (float): Temperature in Fahrenheit.
86 |
87 | Returns:
88 | float: Temperature in Celsius.
89 | """
90 | celsius = (fahrenheit - 32) * 5/9
91 | return celsius
92 |
93 | # Function to calculate the mean temperature for each year and the final mean
94 | def calc_annual_mean(df):
95 | # TODO: make this a bit more robust so we can write integration test examples??
96 | # Calculate the mean temperature for each year
97 | yearly_means = df.groupby('Year').mean()
98 |
99 | # Calculate the final mean temperature across all years
100 | final_mean = yearly_means.mean()
101 |
102 | # Return a converted value
103 | return fahr_to_celsius(yearly_means), fahr_to_celsius(final_mean)
104 |
105 | ```
106 |
107 | ```{figure} ../images/python-tests-puzzle.png
108 | :height: 350px
109 | :alt: image of two puzzle pieces with some missing parts. The puzzle pieces are purple teal yellow and blue. The shapes of each piece don’t fit together.
110 |
111 | If puzzle pieces have missing ends, they can’t work together with other elements in the puzzle. The same is true with individual functions, methods and classes in your software. The code needs to work both individually and together to perform certain sets of tasks.
112 |
113 | ```
114 |
115 | ```{figure} ../images/python-tests-puzzle-fit.png
116 | :height: 450px
117 | :alt: image of puzzle pieces that all fit together nicely. The puzzle pieces are colorful - purple, green and teal.
118 |
119 | Your integration tests should ensure that parts of your code that are expected to work
120 | together, do so as expected.
121 |
122 | ```
123 |
124 | ## End-to-end (functional) tests
125 |
126 | End-to-end tests (also referred to as functional tests) in Python are like comprehensive checklists for your software. They simulate real user end-to-end workflows to make sure the code base supports real life applications and use-cases from start to finish. These tests help catch issues that might not show up in smaller tests and ensure your entire application or program behaves correctly. Think of them as a way to give your software a final check before it's put into action, making sure it's ready to deliver a smooth experience to its users.
127 |
128 | ```{figure} ../images/flower-puzzle-pyopensci.jpg
129 | :height: 450px
130 | :alt: Image of a completed puzzle showing a daisy
131 |
132 | End-to-end or functional tests represent an entire workflow that you
133 | expect your package to support.
134 |
135 | ```
136 |
137 | End-to-end test also test how a program runs from start to finish. A tutorial that you add to your documentation that runs in CI in an isolated environment is another example of an end-to-end test.
138 |
139 | ```{note}
140 | For scientific packages, creating short tutorials that highlight core workflows that your package supports, that are run when your documentation is built could also serve as end-to-end tests.
141 | ```
142 |
143 | ## Comparing unit, integration and end-to-end tests
144 |
145 | Unit tests, integration tests, and end-to-end tests have complementary advantages and disadvantages. The fine-grained nature of unit tests make them well-suited for isolating where errors are occurring. However, unit tests are not useful for verifying that different sections of code work together.
146 |
147 | Integration and end-to-end tests verify that the different portions of the program work together, but are less well-suited for isolating where errors are occurring. For example, when you refactor your code, it is possible that that your end-to-end tests will
148 | break. But if the refactor didn't introduce new behavior to your existing
149 | code, then you can rely on your unit tests to continue to pass, testing the
150 | original functionality of your code.
151 |
152 | It is important to note that you don't need to spend energy worrying about
153 | the specifics surrounding the different types of tests. When you begin to
154 | work on your test suite, consider what your package does and how you
155 | may need to test parts of your package. Bring familiar with the different types of tests can provides a framework to
156 | help you think about writing tests and how different types of tests can complement each other.
157 |
--------------------------------------------------------------------------------
/tests/tests-ci.md:
--------------------------------------------------------------------------------
1 | # Run tests with Continuous Integration
2 |
3 | Running your [test suite locally](run-tests) is useful as you develop code and also test new features or changes to the code base. However, you also will want to setup Continuous Integration (CI) to run your tests online. CI allows you to run all of your tests in the cloud. While you may only be able to run tests locally on a specific operating system, using CI you can specify tests to run both on various versions of Python and across different operating systems.
4 |
5 | CI can also be triggered for pull requests and pushes to your repository. This means that every pull request that you, your maintainer team or a contributor submit, can be tested. In the end CI testing ensures your code continues to run as expected even as changes are made to the code base.
6 |
7 | ::::{todo}
8 | ```{note}
9 | Learn more about Continuous Integration and how it can be used, here. (add link)
10 | ```
11 | ::::
12 |
13 | ## CI & pull requests
14 |
15 | CI is invaluable if you have outside people contributing to your software.
16 | You can setup CI to run on all pull requests submitted to your repository.
17 | CI can make your repository more friendly to new potential contributors.
18 | It allows users to contribute code, documentation fixes and more without
19 | having to create development environments, run tests and build documentation
20 | locally.
21 |
22 | ## Example GitHub Actions that runs tests
23 |
24 | Below is an example GitHub Actions that runs tests using nox
25 | across both Windows, Mac and Linux and on Python versions
26 | 3.9-3.11.
27 |
28 | To work properly, this file should be located in a root directory of your
29 | GitHub repository:
30 |
31 | ```bash
32 | pyospackage/
33 | ├──.github/
34 | └── workflows/
35 | └── run-tests.yml # The name of this file can be whatever you wish
36 | ```
37 |
38 |
39 | ```yaml
40 | name: Pytest unit/integration
41 |
42 | on:
43 | pull_request:
44 | push:
45 | branches:
46 | - main
47 |
48 | # Use bash by default in all jobs
49 | defaults:
50 | run:
51 | shell: bash
52 |
53 | jobs:
54 | build-test:
55 | name: Test Run (${{ matrix.python-version }}, ${{ matrix.os }})
56 | runs-on: ${{ matrix.os }}
57 | strategy:
58 | fail-fast: false
59 | matrix:
60 | os: ["ubuntu-latest", "macos-latest", "windows-latest"]
61 | python-version: ["3.9", "3.10", "3.11"]
62 |
63 | steps:
64 | - uses: actions/checkout@v4
65 | - name: Set up Python ${{ matrix.python-version }}
66 | uses: actions/setup-python@v4
67 | with:
68 | python-version: ${{ matrix.python-version }}
69 | - name: Install dependencies
70 | run: |
71 | python -m pip install --upgrade pip
72 | python -m pip install nox
73 | - name: List installed packages
74 | run: pip list
75 | - name: Run tests with pytest & nox
76 | run: |
77 | nox -s tests-${{ matrix.python-version }}
78 | # You only need to upload code coverage once to codecov unless you have a
79 | # more complex build that you need coverage for.
80 | - name: Upload coverage to Codecov
81 | if: ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.10'}}
82 | uses: codecov/codecov-action@v3
83 | ```
84 |
--------------------------------------------------------------------------------
/tests/write-tests.md:
--------------------------------------------------------------------------------
1 | # Write tests for your Python package
2 |
3 | Writing code that tests your package code, also known as test suites, is important for you as a maintainer, your users, and package contributors. Test suites consist of sets of functions, methods, and classes
4 | that are written with the intention of making sure a specific part of your code
5 | works as you expected it to.
6 |
7 | ## Why write tests for your package?
8 |
9 | Tests act as a safety net for code changes. They help you spot and rectify bugs
10 | before they affect users. Tests also instill confidence that code alterations from
11 | contributors won't breaking existing functionality.
12 |
13 | Writing tests for your Python package is important because:
14 |
15 | - **Catch Mistakes:** Tests are a safety net. When you make changes or add new features to your package, tests can quickly tell you if you accidentally broke something that was working fine before.
16 | - **Save Time:** Imagine you have a magic button that can automatically check if your package is still working properly. Tests are like that magic button! They can run all those checks for you saving you time.
17 | - **Easier Collaboration:** If you're working with others, or have outside contributors, tests help everyone stay on the same page. Your tests explain how your package is supposed to work, making it easier for others to understand and contribute to your project.
18 | - **Fearless Refactoring:** Refactoring means making improvements to your code structure without changing its behavior. Tests empower you to make these changes as if you break something, test failures will let you know.
19 | - **Documentation:** Tests serve as technical examples of how to use your package. This can be helpful for a new technical contributor that wants to contribute code to your package. They can look at your tests to understand how parts of your code functionality fits together.
20 | - **Long-Term ease of maintenance:** As your package evolves, tests ensure that your code continues to behave as expected, even as you make changes over time. Thus you are helping your future self when writing tests.
21 | - **Easier pull request reviews:** By running your tests in a CI framework such as GitHub Actions, each time you or a contributor makes a change to your code-base, you can catch issues and things that may have changed in your code base. This ensures that your software behaves the way you expect it to.
22 |
23 | ### Tests for user edge cases
24 |
25 | Edge cases refer to unexpected or "outlier" ways that some users may use your package. Tests enable you to address various edge cases that could impair
26 | your package's functionality. For example, what occurs if a function expects a
27 | pandas `dataframe` but a user supplies a numpy `array`? Does your code gracefully
28 | handle this situation, providing clear feedback, or does it leave users
29 | frustrated by an unexplained failure?
30 |
31 | :::{note}
32 |
33 | For a good introduction to testing, see [this Software Carpentry lesson](https://swcarpentry.github.io/python-novice-inflammation/10-defensive.html)
34 |
35 | :::
36 |
37 | ```{figure} ../images/python-tests-puzzle.png
38 | :height: 350px
39 |
40 | Imagine you're working on a puzzle where each puzzle piece represents a function, method, class or attribute in your Python package that you want other people to be able to use. Would you want to give someone a puzzle that has missing pieces or pieces that don't fit together? Providing people with the right puzzle pieces that work together can be compared to writing tests for your Python package.
41 |
42 | ```
43 |
44 | ````{admonition} Test examples
45 | :class: note
46 |
47 | Let’s say you have a Python function that adds two numbers a and b together.
48 |
49 | ```python
50 | def add_numbers(a, b):
51 | return a + b
52 | ```
53 |
54 | A test to ensure that function runs as you might expect when provided with different numbers might look like this:
55 |
56 | ```python
57 | def test_add_numbers():
58 | result = add_numbers(2, 3)
59 | assert result == 5, f"Expected 5, but got {result}"
60 |
61 | result2 = add_numbers(-1, 4)
62 | assert result2 == 3, f"Expected 3, but got {result2}"
63 |
64 | result3 = add_numbers(0, 0)
65 | assert result3 == 0, f"Expected 0, but got {result3}"
66 |
67 | test_add_numbers()
68 |
69 | ```
70 | ````
71 |
72 | 🧩🐍
73 |
74 | ### How do I know what type of tests to write?
75 |
76 | :::{note}
77 | This section has been adapted from [a presentation by Nick Murphy](https://zenodo.org/record/8185113).
78 | :::
79 |
80 | At this point, you may be wondering - what should you be testing in your package? Below are a few examples:
81 |
82 | - **Test some typical cases:** Test that the package functions as you expect it to when users use it. For instance, if your package is supposed to add two numbers, test that the outcome value of adding those two numbers is correct.
83 |
84 | - **Test special cases:** Sometimes there are special or outlier cases. For instance, if a function performs a specific calculation that may become problematic closer to the value = 0, test it with the input of both 0 and
85 |
86 | * **Test at and near the expected boundaries:** If a function requires a value that is greater than or equal to 1, make sure that the function still works with both the values 1 and less than one and 1.001 as well (something close to the constraint value)..
87 |
88 | * **Test that code fails correctly:** If a function requires a value greater than or equal to 1, then test at 0.999. Make sure that the function fails gracefully when given unexpected values and help and that the user can easily understand why if failed (provides a useful error message).
89 |
--------------------------------------------------------------------------------
/tutorials/command-line-reference.md:
--------------------------------------------------------------------------------
1 | ---
2 | :og:description: Learn how to add a command-line interface (CLI) to your Python package using the argparse library. This lesson walks you through creating a CLI entry point so users can run your package directly from the terminal.
3 | :og:title: Command Line Reference Guide
4 | date: 1970-01-04
5 | ---
6 |
7 | # Command Line Reference Guide
8 |
9 | ```{important}
10 | **What these tables are:** These tables summarize the command line inputs (e.g., `pipx install hatch`, `hatch build`) necessary to complete all steps in the package creation process, from installing Hatch to publishing the package on PyPI and conda-forge.
11 |
12 | **What these tables are not:** These tables do not cover the manual/non-automated steps (e.g., create PyPI account, create PyPI API token) you have to complete throughout the package creation process.
13 |
14 | **Operating system note:** The current iteration of this guide has been tested on the Windows OS only. Many commands are Windows-specific. OS-specific commands are indicated with parentheses after the description of the command, e.g., [COMMAND_DESCRIPTION] (Windows). Corresponding commands for macOS and Linux will be added in the future.
15 | ```
16 |
17 | ## Environment Setup
18 |
19 | :::{table}
20 | :widths: auto
21 | :align: center
22 |
23 | | Description | Syntax |
24 | |---|---|
25 | | Set PowerShell execution policy (Windows) | `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser` |
26 | | Install Scoop (Windows) | `Invoke-RestMethod -Uri https://get.scoop.sh \| Invoke-Expression` |
27 | | Add "main" bucket as download source (Windows) | `scoop bucket add main` |
28 | | Add "versions" bucket as download source (Windows) | `scoop bucket add versions` |
29 | | Install pipx (Windows) | `scoop install pipx` or `scoop install main/pipx` |
30 | | Update PATH variable with pipx directory | `pipx ensurepath` |
31 | | Install hatch | `pipx install hatch` or `pip install hatch` |
32 | | List hatch commands | `hatch -h` |
33 | | Open location of hatch config file | `hatch config explore` |
34 | | Print contents of hatch config file | `hatch config show` |
35 | | Install grayskull | `pipx install grayskull` or `pip install grayskull` |
36 |
37 | :::
38 |
39 | ## Package Development
40 |
41 | :::{table}
42 | :widths: auto
43 | :align: center
44 |
45 | | Description | Syntax |
46 | |---|---|
47 | | Create package structure and baseline contents | `hatch new [PACKAGE_NAME]` |
48 | | Install package locally in editable mode | `python -m pip install -e .` |
49 | | Install development dependencies | `python -m pip install ".[DEPENDENCY_GROUP]"` |
50 | | List packages installed in current environment | `pip list` |
51 | | Install package from GitHub | `pip install git+https://github.com/user/repo.git@branch_or_tag` |
52 | | Create development environment | `hatch env create` |
53 | | Activate development environment | `hatch shell` |
54 | | Exit development environment | `exit` |
55 |
56 | :::
57 |
58 | ## Package Publishing
59 |
60 | :::{table}
61 | :widths: auto
62 | :align: center
63 |
64 | | Description | Syntax |
65 | |---|---|
66 | | Build package sdist and wheel distributions | `hatch build` |
67 | | Publish package to Test PyPI | `hatch publish -r test` |
68 | | Install package from Test PyPI | `pip install -i https://test.pypi.org/simple/ [PACKAGE_NAME]` |
69 | | Publish package to PyPI | `hatch publish` |
70 | | Install package from PyPI | `pip install -i https://pypi.org/simple/ [PACKAGE_NAME]` |
71 | | Create conda-forge recipe | `grayskull pypi [PACKAGE_NAME]` |
72 | | Check that package installs properly | `pip check` |
73 | | Install package from conda-forge | `conda install -c conda-forge [PACKAGE_NAME]` |
74 |
75 | :::
76 |
77 | ## Versions and Environments
78 |
79 | :::{table}
80 | :widths: auto
81 | :align: center
82 |
83 | | Description | Syntax |
84 | |---|---|
85 | | View environments | `hatch env show` |
86 | | Print path to active hatch environment | `hatch env find` |
87 | | Bump package version - major | `hatch version major` |
88 | | Bump package version - minor | `hatch version minor` |
89 | | Bump package version - patch | `hatch version patch` |
90 | | Run test scripts on multiple Python versions | `hatch run all:[SCRIPT_NAME]` |
91 |
92 | :::
93 |
--------------------------------------------------------------------------------
/tutorials/get-to-know-hatch.md:
--------------------------------------------------------------------------------
1 | ---
2 | :og:description: Get started with Hatch, a modern Python packaging tool. This lesson introduces Hatch’s features and shows how it simplifies environment management, project scaffolding, and building your package.
3 | :og:title: Get to Know Hatch
4 | date: 1970-01-05
5 | ---
6 |
7 | # Get to Know Hatch
8 |
9 | Our Python packaging tutorials use the tool
10 | [Hatch](https://hatch.pypa.io/latest/). While there are [many great packaging
11 | tools](/package-structure-code/python-package-build-tools) out there, we have
12 | selected Hatch because:
13 |
14 | 1. It is an end-to-end tool that supports most of the steps required to create
15 | a quality Python package. Beginners will have fewer tools to learn if they
16 | use Hatch.
17 | 2. It supports different build back-ends if you ever need to compile code in
18 | other languages.
19 | 3. As a community, pyOpenSci has decided that Hatch is a user-friendly tool that
20 | supports many different scientific Python use cases.
21 |
22 | In this tutorial, you will install and get to know Hatch a bit more before
23 | starting to use it.
24 |
25 | You need two things to successfully complete this tutorial:
26 |
27 | 1. You need Python installed.
28 | 2. You need Hatch installed.
29 |
30 | :::{important}
31 | If you don't already have Python installed on your computer, Hatch will do it
32 | for you when you install Hatch.
33 | :::
34 |
35 | ## Install Hatch
36 |
37 | To begin, follow the operating-system-specific instructions below to install
38 | Hatch.
39 |
40 | ::::{tab-set}
41 |
42 | :::{tab-item} MAC
43 |
44 | Follow the instructions [here](https://hatch.pypa.io/latest/install/#installers).
45 |
46 | * Download the latest GUI installer for MAC [hatch-universal.pkg](https://github.com/pypa/hatch/releases/latest/download/hatch-universal.pkg).
47 | * Run the installer and follow the setup instructions.
48 | * If your terminal is open, then restart it.
49 |
50 | :::
51 |
52 | :::{tab-item} Windows
53 |
54 | * In your browser, download the correct `.msi` file for your system:
55 | [hatch-x64.msi](https://github.com/pypa/hatch/releases/latest/download/hatch-x64.msi)
56 | * Run your downloaded installer file and follow the on-screen instructions.
57 |
58 | :::
59 |
60 | :::{tab-item} Linux
61 |
62 | We suggest that you install Hatch using pipx on Linux.
63 | however, if you prefer another method, check out the [Hatch installation documentation](https://hatch.pypa.io/latest/install/) for other methods.
64 |
65 | ```bash
66 | # First install pipx
67 | > apt install pipx
68 | # Then install hatch using pipx
69 | > pipx install hatch
70 | ```
71 |
72 | :::
73 | ::::
74 |
75 | :::{tip}
76 | Hatch can also be installed directly using [pip](https://hatch.pypa.io/latest/install/#pip) or [conda](https://hatch.pypa.io/latest/install/#conda). We encourage you to
77 | follow the instructions above because we have found that the Hatch installers
78 | for Windows and Mac are the easiest and most efficient.
79 |
80 | Our Linux users have found success installing Hatch with pipx if they already
81 | use apt install.
82 |
83 | Both approaches (using a graphical installer on Windows/Mac and pipx) ensure
84 | that you have Hatch installed globally. A global install means that Hatch is
85 | available across all of your Python environments on your computer.
86 | :::
87 |
88 | ### Check that hatch installed correctly
89 |
90 | Once you have completed the installation instructions above, you can open your
91 | terminal, and make sure that Hatch installed correctly using the command below:
92 |
93 | ```bash
94 | hatch --version
95 | # Hatch, version 1.9.4
96 | ```
97 |
98 | *Note the version number output of `hatch --version` will likely be
99 | different from the output above in this tutorial.*
100 |
101 | ## Configure Hatch
102 |
103 | Once you have installed Hatch, you can customize its configuration. This
104 | includes setting the default name and setup for every package you create. While
105 | this step is not required, we suggest that you do it.
106 |
107 | Hatch stores your configuration in a [`config.toml` file](https://hatch.pypa.io/latest/config/project-templates/).
108 |
109 | While you can update the `config.toml` file through the command line, it might
110 | be easier to look at and update it in a text editor if you are using it for the
111 | first time.
112 |
113 | ### Step 1: Open and Edit Your `config.toml` File
114 |
115 | To open the config file in your file browser, run the following command in your
116 | shell:
117 |
118 | `hatch config explore`
119 |
120 | This will open up a directory window that allows you to double-click on the file
121 | and open it in your favorite text editor.
122 |
123 | You can also retrieve the location of the Hatch config file by running the
124 | following command in your shell:
125 |
126 | ```bash
127 | hatch config find
128 | # hatch config --help will show you all the options for config.
129 | ```
130 |
131 | ### Step 2 - update your email and name
132 |
133 | Once the file is open, update the [template] table of the `config.toml` file
134 | with your name and email. This information will be used in any `pyproject.toml`
135 | metadata files that you create using Hatch.
136 |
137 | ```toml
138 | [template]
139 | name = "firstName LastName"
140 | email = "your-email@your-domain.org"
141 | ```
142 |
143 | ### Step 3
144 |
145 | Next, set tests to false in the `[template.plugins.default]` table.
146 |
147 | While tests are important, setting the tests configuration in Hatch
148 | to `true` will create a more complex `pyproject.toml` file. You won't
149 | need to use this feature in this beginner friendly tutorial series
150 | but we will introduce it in later tutorials.
151 |
152 | Your `config.toml` file should look something like the one below.
153 |
154 | ```toml
155 | mode = "local"
156 | project = ""
157 | shell = ""
158 |
159 | [dirs]
160 | project = []
161 | python = "isolated"
162 | data = "/Users/your/path/Application Support/hatch"
163 | cache = "/Users/your/path/Library/Caches/hatch"
164 |
165 | [dirs.env]
166 |
167 | [projects]
168 |
169 | [publish.index]
170 | repo = "main"
171 |
172 | [template]
173 | name = "Leah Wasser"
174 | email = "leah@pyopensci.org"
175 |
176 | [template.licenses]
177 | headers = true
178 | default = [
179 | "MIT",
180 | ]
181 |
182 | [template.plugins.default]
183 | tests = false
184 | ci = false
185 | src-layout = true
186 |
187 | [terminal.styles]
188 | ```
189 |
190 | Also notice that the default license option is MIT. While we will discuss
191 | license in more detail in a later lesson, the MIT license is the
192 | recommended permissive license from
193 | [choosealicense.com](https://www.choosealicense.com) and as such we will
194 | use it for this tutorial series.
195 |
196 | You are of course welcome to select another license.
197 |
198 | :::{todo}
199 | I think we'd need the SPDX license options here if they want to chose bsd-3 for instance
200 | :::
201 |
202 | ### Step 4: Close the config file and run `hatch config show`
203 |
204 | Once you have completed the steps above run the following command in your shell.
205 |
206 | `hatch config show`
207 |
208 | `hatch config show` will print out the contents of your `config.toml` file in
209 | your shell. Look at the values and ensure that your name, email is set. Also
210 | make sure that `tests=false`.
211 |
212 | ## Hatch features
213 |
214 | Hatch offers a suite of features that will make creating, publishing
215 | and maintaining your Python package easier.
216 |
217 | :::{admonition} Comparison to other tools
218 | :class: tip
219 | [We compared Hatch to several of the other popular packaging tools in the ecosystem including flit, pdm and poetry. Learn more here](package-features)
220 | :::
221 |
222 | [More on Hatch here](hatch)
223 |
224 | A few features that Hatch offers
225 |
226 | 1. It will convert metadata stored in a `setup.py` or `setup.cfg` file to a pyproject.toml file for you (see [Migrating setup.py to pyproject.toml using Hatch](setup-py-to-pyproject-toml.md
227 | ))
228 | 2. It will help you by storing configuration information for publishing to PyPI after you've entered it once.
229 |
230 | Use `hatch -h` to see all of the available commands.
231 |
232 | ## What's next
233 |
234 | In the next lesson you'll learn how to package and make your code installable using Hatch.
235 |
--------------------------------------------------------------------------------
/tutorials/setup-py-to-pyproject-toml.md:
--------------------------------------------------------------------------------
1 | ---
2 | :og:description: If you’re creating a pure Python project, pyproject.toml is preferred over setup.py for packaging and configuration. Learn how to migrate from the older setup.py format to the modern pyproject.toml file. This lesson walks you through updating your package metadata and build settings to align with current Python packaging standards.
3 | :og:title: Using Hatch to Migrate setup.py to a pyproject.toml
4 | date: 1970-01-09
5 | ---
6 |
7 | # Using Hatch to Migrate setup.py to a pyproject.toml
8 |
9 | Hatch can be particularly useful to generate your project's `pyproject.toml` if your project already has a `setup.py`.
10 |
11 | :::{admonition} Note
12 | :class: tip
13 |
14 | This step is not necessary and is only useful if your project already has a `setup.py` file defined.
15 | * If your project does not already define a `setup.py` see [Make your Python code installable](installable-code.md)
16 | :::
17 |
18 | :::{admonition} Learning Objectives
19 | :class: tip
20 |
21 | In this lesson you will learn:
22 |
23 | 1. The process of using Hatch to transition to using `pyproject.toml` for projects that already have a `setup.py` defined.
24 | :::
25 |
26 | ## What is Hatch?
27 |
28 | Hatch is a Python package manager designed to streamline the process of creating, managing, and distributing Python packages. It provides a convenient CLI (Command-Line Interface) for tasks such as creating new projects, managing dependencies, building distributions, and publishing packages to repositories like PyPI.
29 |
30 | :::{admonition} Get to know Hatch
31 | :class: tip
32 |
33 | See [Get to know Hatch](get-to-know-hatch.md) for more information.
34 |
35 | :::
36 |
37 | ## Prerequisites
38 |
39 | Before we begin, ensure that you have Hatch installed on your system. You can install it via pip:
40 |
41 | ```bash
42 | pipx install hatch
43 | ```
44 |
45 | ## Sample Directory Tree
46 |
47 | Let's take a look at a sample directory tree structure before and after using `hatch init`:
48 |
49 | ### Before `hatch init`
50 |
51 | ```
52 | project/
53 | │
54 | ├── src/
55 | │ └── my_package/
56 | │ ├── __init__.py
57 | │ └── module.py
58 | │
59 | ├── tests/
60 | │ └── test_module.py
61 | │
62 | └── setup.py
63 | ```
64 |
65 | ### After `hatch init`
66 |
67 | ```
68 | project/
69 | │
70 | ├── pyproject.toml
71 | │
72 | ├── src/
73 | │ └── my_package/
74 | │ ├── __init__.py
75 | │ └── module.py
76 | │
77 | ├── tests/
78 | │ └── test_module.py
79 | │
80 | └── setup.py
81 | ```
82 |
83 | As you can see, the main change after running `hatch init` is the addition of the `pyproject.toml` file in the project directory.
84 |
85 | ## Step-by-Step Guide
86 |
87 | Now, let's walk through the steps to use Hatch to create a `pyproject.toml` file for your project.
88 |
89 | 1. **Navigate to Your Project Directory**: Open your terminal or command prompt and navigate to the directory where your Python project is located.
90 |
91 | 2. **Initialize Hatch**: Run the following command to initialize Hatch in your project directory:
92 |
93 | ```bash
94 | hatch new --init
95 | ```
96 |
97 | 3. **Review and Customize**: After running the previous command, Hatch will automatically generate a `pyproject.toml` file based on your existing project configuration. Take some time to review the contents of the generated `pyproject.toml` file. You may want to customize certain settings or dependencies based on your project's requirements (see [pyproject.toml tutorial](pyproject-toml.md) for more information about the `pyproject.toml`).
98 |
99 | 4. **Verify**: Verify that the `pyproject.toml` file accurately reflects your project configuration and dependencies. You can manually edit the file if needed, but be cautious and ensure that the syntax is correct.
100 |
101 | 5. **Delete setup.py**: Since we're migrating to using `pyproject.toml` exclusively, the `setup.py` file becomes unnecessary. You can safely delete it from your project directory.
102 |
103 | 6. **Test Build**: Before proceeding further, it's essential to ensure that your project builds successfully using only the `pyproject.toml` file. Run the following command to build your project:
104 |
105 | ```bash
106 | hatch build
107 | ```
108 |
109 | This command will build your project based on the specifications in the `pyproject.toml` file. Make sure to check for any errors or warnings during the build process.
110 |
111 | 7. **Test Existing Functionality**: After successfully building your project with `pyproject.toml`, it's crucial to ensure that your project's existing functionality remains intact. Run any pre-existing tests to verify that everything still works as expected.
112 |
--------------------------------------------------------------------------------
/vale-styles/config/vocabularies/sample/accept.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/vale-styles/config/vocabularies/sample/accept.txt
--------------------------------------------------------------------------------
/vale-styles/config/vocabularies/sample/reject.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyOpenSci/python-package-guide/4a1a5869e6aaeaea534be4cc30b9e610670b9197/vale-styles/config/vocabularies/sample/reject.txt
--------------------------------------------------------------------------------
/vale-styles/package-guide-test/PyPI.yml:
--------------------------------------------------------------------------------
1 | extends: substitution
2 | message: Consider using '%s' instead of '%s'
3 | level: warning
4 | ignorecase: false
5 | action:
6 | name: replace
7 | # swap maps tokens in form of bad: good
8 | swap:
9 | # lower case defined as regex to prevent false positives in URLs or other identifiers
10 | - (?:\spypi[\.,]?\s): PyPI
11 | - (?:\stestpypi[\.,;:]?\s): TestPyPI
12 | - (?:\stest-pypi[\.,;:]?\s): TestPyPI
13 | # other tests are defined with strings
14 | - pyPi: PyPI
15 | - pyPI: PyPI
16 | - PYPI: PyPI
17 | - PyPi: PyPI
18 | - Pypi: PyPI
19 | - testPyPI: TestPyPI
20 | - testPYPI: TestPyPI
21 | - TestPypi: TestPyPI
22 | - TestPYPI: TestPyPI
23 |
--------------------------------------------------------------------------------
/vale-styles/write-good/E-Prime.yml:
--------------------------------------------------------------------------------
1 | extends: existence
2 | message: "Try to avoid using '%s'."
3 | ignorecase: true
4 | level: suggestion
5 | tokens:
6 | - am
7 | - are
8 | - aren't
9 | - be
10 | - been
11 | - being
12 | - he's
13 | - here's
14 | - here's
15 | - how's
16 | - i'm
17 | - is
18 | - isn't
19 | - she's
20 | - that's
21 | - there's
22 | - they're
23 | - was
24 | - wasn't
25 | - we're
26 | - were
27 | - weren't
28 | - what's
29 | - where's
30 | - who's
31 | - you're
32 |
--------------------------------------------------------------------------------
/vale-styles/write-good/Illusions.yml:
--------------------------------------------------------------------------------
1 | extends: repetition
2 | message: "'%s' is repeated!"
3 | level: warning
4 | alpha: true
5 | action:
6 | name: edit
7 | params:
8 | - truncate
9 | - " "
10 | tokens:
11 | - '[^\s]+'
12 |
--------------------------------------------------------------------------------
/vale-styles/write-good/Passive.yml:
--------------------------------------------------------------------------------
1 | extends: existence
2 | message: "'%s' may be passive voice. Use active voice if you can."
3 | ignorecase: true
4 | level: warning
5 | raw:
6 | - \b(am|are|were|being|is|been|was|be)\b\s*
7 | tokens:
8 | - '[\w]+ed'
9 | - awoken
10 | - beat
11 | - become
12 | - been
13 | - begun
14 | - bent
15 | - beset
16 | - bet
17 | - bid
18 | - bidden
19 | - bitten
20 | - bled
21 | - blown
22 | - born
23 | - bought
24 | - bound
25 | - bred
26 | - broadcast
27 | - broken
28 | - brought
29 | - built
30 | - burnt
31 | - burst
32 | - cast
33 | - caught
34 | - chosen
35 | - clung
36 | - come
37 | - cost
38 | - crept
39 | - cut
40 | - dealt
41 | - dived
42 | - done
43 | - drawn
44 | - dreamt
45 | - driven
46 | - drunk
47 | - dug
48 | - eaten
49 | - fallen
50 | - fed
51 | - felt
52 | - fit
53 | - fled
54 | - flown
55 | - flung
56 | - forbidden
57 | - foregone
58 | - forgiven
59 | - forgotten
60 | - forsaken
61 | - fought
62 | - found
63 | - frozen
64 | - given
65 | - gone
66 | - gotten
67 | - ground
68 | - grown
69 | - heard
70 | - held
71 | - hidden
72 | - hit
73 | - hung
74 | - hurt
75 | - kept
76 | - knelt
77 | - knit
78 | - known
79 | - laid
80 | - lain
81 | - leapt
82 | - learnt
83 | - led
84 | - left
85 | - lent
86 | - let
87 | - lighted
88 | - lost
89 | - made
90 | - meant
91 | - met
92 | - misspelt
93 | - mistaken
94 | - mown
95 | - overcome
96 | - overdone
97 | - overtaken
98 | - overthrown
99 | - paid
100 | - pled
101 | - proven
102 | - put
103 | - quit
104 | - read
105 | - rid
106 | - ridden
107 | - risen
108 | - run
109 | - rung
110 | - said
111 | - sat
112 | - sawn
113 | - seen
114 | - sent
115 | - set
116 | - sewn
117 | - shaken
118 | - shaven
119 | - shed
120 | - shod
121 | - shone
122 | - shorn
123 | - shot
124 | - shown
125 | - shrunk
126 | - shut
127 | - slain
128 | - slept
129 | - slid
130 | - slit
131 | - slung
132 | - smitten
133 | - sold
134 | - sought
135 | - sown
136 | - sped
137 | - spent
138 | - spilt
139 | - spit
140 | - split
141 | - spoken
142 | - spread
143 | - sprung
144 | - spun
145 | - stolen
146 | - stood
147 | - stridden
148 | - striven
149 | - struck
150 | - strung
151 | - stuck
152 | - stung
153 | - stunk
154 | - sung
155 | - sunk
156 | - swept
157 | - swollen
158 | - sworn
159 | - swum
160 | - swung
161 | - taken
162 | - taught
163 | - thought
164 | - thrived
165 | - thrown
166 | - thrust
167 | - told
168 | - torn
169 | - trodden
170 | - understood
171 | - upheld
172 | - upset
173 | - wed
174 | - wept
175 | - withheld
176 | - withstood
177 | - woken
178 | - won
179 | - worn
180 | - wound
181 | - woven
182 | - written
183 | - wrung
184 |
--------------------------------------------------------------------------------
/vale-styles/write-good/README.md:
--------------------------------------------------------------------------------
1 | Based on [write-good](https://github.com/btford/write-good).
2 |
3 | > Naive linter for English prose for developers who can't write good and wanna learn to do other stuff good too.
4 |
5 | ```
6 | The MIT License (MIT)
7 |
8 | Copyright (c) 2014 Brian Ford
9 |
10 | Permission is hereby granted, free of charge, to any person obtaining a copy
11 | of this software and associated documentation files (the "Software"), to deal
12 | in the Software without restriction, including without limitation the rights
13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | copies of the Software, and to permit persons to whom the Software is
15 | furnished to do so, subject to the following conditions:
16 |
17 | The above copyright notice and this permission notice shall be included in all
18 | copies or substantial portions of the Software.
19 |
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | SOFTWARE.
27 | ```
28 |
--------------------------------------------------------------------------------
/vale-styles/write-good/So.yml:
--------------------------------------------------------------------------------
1 | extends: existence
2 | message: "Don't start a sentence with '%s'."
3 | level: error
4 | raw:
5 | - '(?:[;-]\s)so[\s,]|\bSo[\s,]'
6 |
--------------------------------------------------------------------------------
/vale-styles/write-good/ThereIs.yml:
--------------------------------------------------------------------------------
1 | extends: existence
2 | message: "Don't start a sentence with '%s'."
3 | ignorecase: false
4 | level: error
5 | raw:
6 | - '(?:[;-]\s)There\s(is|are)|\bThere\s(is|are)\b'
7 |
--------------------------------------------------------------------------------
/vale-styles/write-good/TooWordy.yml:
--------------------------------------------------------------------------------
1 | extends: existence
2 | message: "'%s' is too wordy."
3 | ignorecase: true
4 | level: warning
5 | tokens:
6 | - a number of
7 | - abundance
8 | - accede to
9 | - accelerate
10 | - accentuate
11 | - accompany
12 | - accomplish
13 | - accorded
14 | - accrue
15 | - acquiesce
16 | - acquire
17 | - additional
18 | - adjacent to
19 | - adjustment
20 | - admissible
21 | - advantageous
22 | - adversely impact
23 | - advise
24 | - aforementioned
25 | - aggregate
26 | - aircraft
27 | - all of
28 | - all things considered
29 | - alleviate
30 | - allocate
31 | - along the lines of
32 | - already existing
33 | - alternatively
34 | - amazing
35 | - ameliorate
36 | - anticipate
37 | - apparent
38 | - appreciable
39 | - as a matter of fact
40 | - as a means of
41 | - as far as I'm concerned
42 | - as of yet
43 | - as to
44 | - as yet
45 | - ascertain
46 | - assistance
47 | - at the present time
48 | - at this time
49 | - attain
50 | - attributable to
51 | - authorize
52 | - because of the fact that
53 | - belated
54 | - benefit from
55 | - bestow
56 | - by means of
57 | - by virtue of
58 | - by virtue of the fact that
59 | - cease
60 | - close proximity
61 | - commence
62 | - comply with
63 | - concerning
64 | - consequently
65 | - consolidate
66 | - constitutes
67 | - demonstrate
68 | - depart
69 | - designate
70 | - discontinue
71 | - due to the fact that
72 | - each and every
73 | - economical
74 | - eliminate
75 | - elucidate
76 | - employ
77 | - endeavor
78 | - enumerate
79 | - equitable
80 | - equivalent
81 | - evaluate
82 | - evidenced
83 | - exclusively
84 | - expedite
85 | - expend
86 | - expiration
87 | - facilitate
88 | - factual evidence
89 | - feasible
90 | - finalize
91 | - first and foremost
92 | - for all intents and purposes
93 | - for the most part
94 | - for the purpose of
95 | - forfeit
96 | - formulate
97 | - have a tendency to
98 | - honest truth
99 | - however
100 | - if and when
101 | - impacted
102 | - implement
103 | - in a manner of speaking
104 | - in a timely manner
105 | - in a very real sense
106 | - in accordance with
107 | - in addition
108 | - in all likelihood
109 | - in an effort to
110 | - in between
111 | - in excess of
112 | - in lieu of
113 | - in light of the fact that
114 | - in many cases
115 | - in my opinion
116 | - in order to
117 | - in regard to
118 | - in some instances
119 | - in terms of
120 | - in the case of
121 | - in the event that
122 | - in the final analysis
123 | - in the nature of
124 | - in the near future
125 | - in the process of
126 | - inception
127 | - incumbent upon
128 | - indicate
129 | - indication
130 | - initiate
131 | - irregardless
132 | - is applicable to
133 | - is authorized to
134 | - is responsible for
135 | - it is
136 | - it is essential
137 | - it seems that
138 | - it was
139 | - magnitude
140 | - maximum
141 | - methodology
142 | - minimize
143 | - minimum
144 | - modify
145 | - monitor
146 | - multiple
147 | - necessitate
148 | - nevertheless
149 | - not certain
150 | - not many
151 | - not often
152 | - not unless
153 | - not unlike
154 | - notwithstanding
155 | - null and void
156 | - numerous
157 | - objective
158 | - obligate
159 | - obtain
160 | - on the contrary
161 | - on the other hand
162 | - one particular
163 | - optimum
164 | - overall
165 | - owing to the fact that
166 | - participate
167 | - particulars
168 | - pass away
169 | - pertaining to
170 | - point in time
171 | - portion
172 | - possess
173 | - preclude
174 | - previously
175 | - prior to
176 | - prioritize
177 | - procure
178 | - proficiency
179 | - provided that
180 | - purchase
181 | - put simply
182 | - readily apparent
183 | - refer back
184 | - regarding
185 | - relocate
186 | - remainder
187 | - remuneration
188 | - requirement
189 | - reside
190 | - residence
191 | - retain
192 | - satisfy
193 | - shall
194 | - should you wish
195 | - similar to
196 | - solicit
197 | - span across
198 | - strategize
199 | - subsequent
200 | - substantial
201 | - successfully complete
202 | - sufficient
203 | - terminate
204 | - the month of
205 | - the point I am trying to make
206 | - therefore
207 | - time period
208 | - took advantage of
209 | - transmit
210 | - transpire
211 | - type of
212 | - until such time as
213 | - utilization
214 | - utilize
215 | - validate
216 | - various different
217 | - what I mean to say is
218 | - whether or not
219 | - with respect to
220 | - with the exception of
221 | - witnessed
222 |
--------------------------------------------------------------------------------
/vale-styles/write-good/Weasel.yml:
--------------------------------------------------------------------------------
1 | extends: existence
2 | message: "'%s' is a weasel word!"
3 | ignorecase: true
4 | level: warning
5 | tokens:
6 | - absolutely
7 | - accidentally
8 | - additionally
9 | - allegedly
10 | - alternatively
11 | - angrily
12 | - anxiously
13 | - approximately
14 | - awkwardly
15 | - badly
16 | - barely
17 | - beautifully
18 | - blindly
19 | - boldly
20 | - bravely
21 | - brightly
22 | - briskly
23 | - bristly
24 | - bubbly
25 | - busily
26 | - calmly
27 | - carefully
28 | - carelessly
29 | - cautiously
30 | - cheerfully
31 | - clearly
32 | - closely
33 | - coldly
34 | - completely
35 | - consequently
36 | - correctly
37 | - courageously
38 | - crinkly
39 | - cruelly
40 | - crumbly
41 | - cuddly
42 | - currently
43 | - daily
44 | - daringly
45 | - deadly
46 | - definitely
47 | - deliberately
48 | - doubtfully
49 | - dumbly
50 | - eagerly
51 | - early
52 | - easily
53 | - elegantly
54 | - enormously
55 | - enthusiastically
56 | - equally
57 | - especially
58 | - eventually
59 | - exactly
60 | - exceedingly
61 | - exclusively
62 | - extremely
63 | - fairly
64 | - faithfully
65 | - fatally
66 | - fiercely
67 | - finally
68 | - fondly
69 | - few
70 | - foolishly
71 | - fortunately
72 | - frankly
73 | - frantically
74 | - generously
75 | - gently
76 | - giggly
77 | - gladly
78 | - gracefully
79 | - greedily
80 | - happily
81 | - hardly
82 | - hastily
83 | - healthily
84 | - heartily
85 | - helpfully
86 | - honestly
87 | - hourly
88 | - hungrily
89 | - hurriedly
90 | - immediately
91 | - impatiently
92 | - inadequately
93 | - ingeniously
94 | - innocently
95 | - inquisitively
96 | - interestingly
97 | - irritably
98 | - jiggly
99 | - joyously
100 | - justly
101 | - kindly
102 | - largely
103 | - lately
104 | - lazily
105 | - likely
106 | - literally
107 | - lonely
108 | - loosely
109 | - loudly
110 | - loudly
111 | - luckily
112 | - madly
113 | - many
114 | - mentally
115 | - mildly
116 | - monthly
117 | - mortally
118 | - mostly
119 | - mysteriously
120 | - neatly
121 | - nervously
122 | - nightly
123 | - noisily
124 | - normally
125 | - obediently
126 | - occasionally
127 | - only
128 | - openly
129 | - painfully
130 | - particularly
131 | - patiently
132 | - perfectly
133 | - politely
134 | - poorly
135 | - powerfully
136 | - presumably
137 | - previously
138 | - promptly
139 | - punctually
140 | - quarterly
141 | - quickly
142 | - quietly
143 | - rapidly
144 | - rarely
145 | - really
146 | - recently
147 | - recklessly
148 | - regularly
149 | - remarkably
150 | - relatively
151 | - reluctantly
152 | - repeatedly
153 | - rightfully
154 | - roughly
155 | - rudely
156 | - sadly
157 | - safely
158 | - selfishly
159 | - sensibly
160 | - seriously
161 | - sharply
162 | - shortly
163 | - shyly
164 | - significantly
165 | - silently
166 | - simply
167 | - sleepily
168 | - slowly
169 | - smartly
170 | - smelly
171 | - smoothly
172 | - softly
173 | - solemnly
174 | - sparkly
175 | - speedily
176 | - stealthily
177 | - sternly
178 | - stupidly
179 | - substantially
180 | - successfully
181 | - suddenly
182 | - surprisingly
183 | - suspiciously
184 | - swiftly
185 | - tenderly
186 | - tensely
187 | - thoughtfully
188 | - tightly
189 | - timely
190 | - truthfully
191 | - unexpectedly
192 | - unfortunately
193 | - usually
194 | - very
195 | - victoriously
196 | - violently
197 | - vivaciously
198 | - warmly
199 | - waverly
200 | - weakly
201 | - wearily
202 | - weekly
203 | - wildly
204 | - wisely
205 | - worldly
206 | - wrinkly
207 | - yearly
208 |
--------------------------------------------------------------------------------
/vale-styles/write-good/meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "feed": "https://github.com/errata-ai/write-good/releases.atom",
3 | "vale_version": ">=1.0.0"
4 | }
5 |
--------------------------------------------------------------------------------