From 6a7f72ba22c4b028a401e276d6a74b0ca8564bac Mon Sep 17 00:00:00 2001 From: Leah Wasser <leah@pyopensci.org> Date: Tue, 25 Jun 2024 18:59:30 -0600 Subject: [PATCH 1/5] Fix: update hatch install instructions --- tutorials/get-to-know-hatch.md | 92 ++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 15 deletions(-) diff --git a/tutorials/get-to-know-hatch.md b/tutorials/get-to-know-hatch.md index 9f61cbc3..ed20f776 100644 --- a/tutorials/get-to-know-hatch.md +++ b/tutorials/get-to-know-hatch.md @@ -1,35 +1,99 @@ # Get to know Hatch -Our Python packaging tutorials use the tool Hatch. -In this tutorial, you will install and get to know Hatch a bit more before starting to use it. +Our Python packaging tutorials use the tool +[Hatch](https://hatch.pypa.io/latest/). While there are [many great packaging](/package-structure-code/python-package-build-tools) +tool options out there, we have selected to teach Hatch because + +1. It is an end-to-end tool that supports most of the steps required to create a quality Python package. Beginners will have fewer tools to learn if they use Hatch. +1. It supports different build back-ends if you ever need to compile code in other languages. +1. As a community, pyOpenSci has decided that Hatch is a user-friendly tool that supports many different scientific Python use cases. + +In this tutorial, you will install and get to know Hatch a bit more before +starting to use it. + +You need two things to successfully complete this tutorial: + +1. You need Python installed. +2. You need Hatch installed. + +:::{important} +If you don't already have Python installed, Hatch will do it for you when you +install Hatch. + +Hatch uses [UV](https://astral.sh/blog/uv) to install Python. UV is a super +fast Python package installer and resolver written in Rust. +::: ## Install Hatch -To begin, install Hatch from the command line using [pipx](https://pipx.pypa.io/stable/) + +To begin, follow the operating-specific instructions below to install Hatch. + +::::{tab-set} + +:::{tab-item} MAC + +Follow the instructions [here](https://hatch.pypa.io/latest/install/#installers). + +* Download the latest GUI installer for MAC [hatch-universal.pkg](https://github.com/pypa/hatch/releases/latest/download/hatch-universal.pkg). +* Run the installer and follow the setup instructions. +* If your terminal is open, then restart it. + +::: + +:::{tab-item} Windows + +* In your browser, download the correct `.msi` file for your system: +[hatch-x64.msi](https://github.com/pypa/hatch/releases/latest/download/hatch-x64.msi) +* Run your downloaded installer file and follow the on-screen instructions. + +::: + +:::{tab-item} Linux + +We suggest that you install Hatch using pipx on Linux. +however, if you prefer another method, check out the [Hatch installation documentation](https://hatch.pypa.io/latest/install/) for other methods. ```bash -pipx install hatch +# First install pipx +> apt install pipx +# Then install hatch using pipx +> pipx install hatch ``` -:::{tip} -Hatch can also be installed directly using `pip` or `conda`, but we encourage you to use `pipx`. -This is because `pipx` will ensure that your package is available across all of your Python -environments on your computer rather than just in the environment that you install it into. -If you install hatch this way you will have to take care that the environment it is installed into -is activated for the command to work. ::: +:::: + +### Check that hatch installed correctly -You can check that hatch is working properly by issuing a simple command to get the version +Once you have completed the installation instructions above, you can open your terminal, and make sure that Hatch installed correctly using +the command below: ```bash hatch --version # Hatch, version 1.9.4 ``` -Note the version numbers will likely be different +*Note the version number output of `hatch --version` will likely be +different from the output above in this tutorial.* + +:::{tip} +Hatch can also be installed directly using `pip` or `conda`. We +encourage +you to follow the instructions above because we have found that the Hatch installers for Windows and Mac are easiest and most efficient. + +Our Linux users have found success installing Hatch with `pipx` if they +already use `apt install`. + +Both approaches (using a graphical installer on Windows / MAC and `pipx`) ensure that you have Hatch installed +globally. A global install means that Hatch is available +across all of your Python environments on your computer. +::: ## Configure hatch -Once you have installed Hatch, you will want to customize the configuration. +Once you have installed Hatch, you can customize the configuration which +includes the default name and setup that you want to have for every +package that you create using Hatch. While this step is not required, we suggest it. Hatch stores your configuration information in a [`config.toml` file](https://hatch.pypa.io/latest/config/project-templates/). @@ -141,14 +205,12 @@ and maintaining your Python package easier. A few features that Hatch offers - 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 )) 2. It will help you by storing configuration information for publishing to PyPI after you've entered it once. Use `hatch -h` to see all of the available commands. - ## What's next In the next lesson you'll learn how to package and make your code installable using Hatch. From dd8f91f1e46bd6dbb150f045a341510b834fd454 Mon Sep 17 00:00:00 2001 From: Leah Wasser <leah@pyopensci.org> Date: Wed, 26 Jun 2024 10:21:30 -0600 Subject: [PATCH 2/5] Fix: edits from review --- tutorials/get-to-know-hatch.md | 86 +++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/tutorials/get-to-know-hatch.md b/tutorials/get-to-know-hatch.md index ed20f776..2dd90617 100644 --- a/tutorials/get-to-know-hatch.md +++ b/tutorials/get-to-know-hatch.md @@ -1,12 +1,17 @@ -# Get to know Hatch +# Get to Know Hatch Our Python packaging tutorials use the tool -[Hatch](https://hatch.pypa.io/latest/). While there are [many great packaging](/package-structure-code/python-package-build-tools) -tool options out there, we have selected to teach Hatch because - -1. It is an end-to-end tool that supports most of the steps required to create a quality Python package. Beginners will have fewer tools to learn if they use Hatch. -1. It supports different build back-ends if you ever need to compile code in other languages. -1. As a community, pyOpenSci has decided that Hatch is a user-friendly tool that supports many different scientific Python use cases. +[Hatch](https://hatch.pypa.io/latest/). While there are [many great packaging +tools](/package-structure-code/python-package-build-tools) out there, we have +selected Hatch because: + +1. It is an end-to-end tool that supports most of the steps required to create + a quality Python package. Beginners will have fewer tools to learn if they + use Hatch. +2. It supports different build back-ends if you ever need to compile code in + other languages. +3. As a community, pyOpenSci has decided that Hatch is a user-friendly tool that + supports many different scientific Python use cases. In this tutorial, you will install and get to know Hatch a bit more before starting to use it. @@ -17,16 +22,14 @@ You need two things to successfully complete this tutorial: 2. You need Hatch installed. :::{important} -If you don't already have Python installed, Hatch will do it for you when you -install Hatch. - -Hatch uses [UV](https://astral.sh/blog/uv) to install Python. UV is a super -fast Python package installer and resolver written in Rust. +If you don't already have Python installed on your computer, Hatch will do it +for you when you install Hatch. ::: ## Install Hatch -To begin, follow the operating-specific instructions below to install Hatch. +To begin, follow the operating-system-specific instructions below to install +Hatch. ::::{tab-set} @@ -65,8 +68,8 @@ however, if you prefer another method, check out the [Hatch installation documen ### Check that hatch installed correctly -Once you have completed the installation instructions above, you can open your terminal, and make sure that Hatch installed correctly using -the command below: +Once you have completed the installation instructions above, you can open your +terminal, and make sure that Hatch installed correctly using the command below: ```bash hatch --version @@ -77,38 +80,42 @@ hatch --version different from the output above in this tutorial.* :::{tip} -Hatch can also be installed directly using `pip` or `conda`. We -encourage -you to follow the instructions above because we have found that the Hatch installers for Windows and Mac are easiest and most efficient. +Hatch can also be installed directly using pip or conda. We encourage you to +follow the instructions above because we have found that the Hatch installers +for Windows and Mac are the easiest and most efficient. -Our Linux users have found success installing Hatch with `pipx` if they -already use `apt install`. +Our Linux users have found success installing Hatch with pipx if they already +use apt install. -Both approaches (using a graphical installer on Windows / MAC and `pipx`) ensure that you have Hatch installed -globally. A global install means that Hatch is available -across all of your Python environments on your computer. +Both approaches (using a graphical installer on Windows/Mac and pipx) ensure +that you have Hatch installed globally. A global install means that Hatch is +available across all of your Python environments on your computer. ::: -## Configure hatch +## Configure Hatch -Once you have installed Hatch, you can customize the configuration which -includes the default name and setup that you want to have for every -package that you create using Hatch. While this step is not required, we suggest it. +Once you have installed Hatch, you can customize its configuration. This +includes setting the default name and setup for every package you create. While +this step is not required, we suggest that you do it. -Hatch stores your configuration information in a [`config.toml` file](https://hatch.pypa.io/latest/config/project-templates/). +Hatch stores your configuration in a [`config.toml` file](https://hatch.pypa.io/latest/config/project-templates/). -While you can update the `config.toml` file through the command line, -it might be easier to look at it and update it in a text editor if you are using it for the first time. +While you can update the `config.toml` file through the command line, it might +be easier to look at and update it in a text editor if you are using it for the +first time. -### Step 1: Open and edit your `config.toml` file +### Step 1: Open and Edit Your `config.toml` File -To open the config file in your file browser, run the following command in your shell: +To open the config file in your file browser, run the following command in your +shell: `hatch config explore` -This will open up a directory window that will allow you to double click on the file and open it in your favorite text editor. +This will open up a directory window that allows you to double-click on the file +and open it in your favorite text editor. -You can also retrieve the location of the Hatch config file by running the following command in your shell: +You can also retrieve the location of the Hatch config file by running the +following command in your shell: ```bash hatch config find @@ -117,7 +124,9 @@ hatch config find ### Step 2 - update your email and name -Once the file is open, update the [template] table of the `config.toml` file with your name and email. This information will be used in any `pyproject.toml` metadata files that you create using Hatch. +Once the file is open, update the [template] table of the `config.toml` file +with your name and email. This information will be used in any `pyproject.toml` +metadata files that you create using Hatch. ```toml [template] @@ -174,7 +183,8 @@ src-layout = true Also notice that the default license option is MIT. While we will discuss license in more detail in a later lesson, the MIT license is the -recommended permissive license from [choosealicense.com](https://www.choosealicense.com) and as such we will +recommended permissive license from +[choosealicense.com](https://www.choosealicense.com) and as such we will use it for this tutorial series. You are of course welcome to select another license. @@ -189,7 +199,9 @@ Once you have completed the steps above run the following command in your shell. `hatch config show` -`hatch config show` will print out the contents of your `config.toml` file in your shell. look at the values and ensure that your name, email is set. Also make sure that `tests=false`. +`hatch config show` will print out the contents of your `config.toml` file in +your shell. look at the values and ensure that your name, email is set. Also +make sure that `tests=false`. ## Hatch features From 65bdd1be1f3be8606344284bca5875e992944e23 Mon Sep 17 00:00:00 2001 From: Leah Wasser <leah@pyopensci.org> Date: Fri, 28 Jun 2024 11:58:24 -0600 Subject: [PATCH 3/5] Cleanup --- noxfile.py | 13 ++++++------- package-structure-code/code-style-linting-format.md | 1 + 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/noxfile.py b/noxfile.py index 7ba28129..31799979 100644 --- a/noxfile.py +++ b/noxfile.py @@ -9,6 +9,7 @@ docs_dir = os.path.join("_build", "html") build_command = ["-b", "html", ".", docs_dir] + @nox.session def docs(session): session.install("-e", ".") @@ -16,6 +17,7 @@ def docs(session): cmd.extend(build_command + session.posargs) session.run(*cmd) + @nox.session(name="docs-test") def docs_test(session): """ @@ -23,7 +25,7 @@ def docs_test(session): """ session.install("-e", ".") cmd = ["sphinx-build"] - cmd.extend(['-W', '--keep-going', '-E', '-a']) + cmd.extend(["-W", "--keep-going", "-E", "-a"]) cmd.extend(build_command + session.posargs) session.run(*cmd) @@ -43,9 +45,7 @@ def docs_live(session): # well, they're static. # Include these as the final `filenames` argument - AUTOBUILD_INCLUDE = [ - os.path.join("_static", "pyos.css") - ] + AUTOBUILD_INCLUDE = [os.path.join("_static", "pyos.css")] # ---------------- # Assemble command @@ -53,7 +53,7 @@ def docs_live(session): for folder in AUTOBUILD_IGNORE: cmd.extend(["--ignore", f"*/{folder}/*"]) - #cmd.extend(build_command) + # cmd.extend(build_command) cmd.extend(build_command + session.posargs) # Use positional arguments if we have them @@ -66,7 +66,6 @@ def docs_live(session): session.run(*cmd) - @nox.session(name="docs-clean") def clean_dir(dir_path=docs_dir): """ @@ -74,7 +73,7 @@ def clean_dir(dir_path=docs_dir): live build. """ dir_path = pathlib.Path(dir_path) - dir_contents = dir_path.glob('*') + dir_contents = dir_path.glob("*") for content in dir_contents: print(content) diff --git a/package-structure-code/code-style-linting-format.md b/package-structure-code/code-style-linting-format.md index 1616ddc6..7c5975b4 100644 --- a/package-structure-code/code-style-linting-format.md +++ b/package-structure-code/code-style-linting-format.md @@ -174,6 +174,7 @@ Also notice that there are no spaces in the imports listed below. ::: From the project root, run: + ```bash isort src/examplePy/temporal.py ``` From f6d16253aec71de3457f8ff8ff1f14c4880c0071 Mon Sep 17 00:00:00 2001 From: Leah Wasser <leah@pyopensci.org> Date: Wed, 3 Jul 2024 17:24:17 -0600 Subject: [PATCH 4/5] Fix: rebase main --- noxfile.py | 261 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 219 insertions(+), 42 deletions(-) diff --git a/noxfile.py b/noxfile.py index 31799979..34c18b82 100644 --- a/noxfile.py +++ b/noxfile.py @@ -5,79 +5,256 @@ nox.options.reuse_existing_virtualenvs = True -OUTPUT_DIR = "_build" -docs_dir = os.path.join("_build", "html") -build_command = ["-b", "html", ".", docs_dir] +## Sphinx related options + +# Sphinx output and source directories +BUILD_DIR = "_build" +OUTPUT_DIR = pathlib.Path(BUILD_DIR, "html") +SOURCE_DIR = pathlib.Path(".") + +# Location of the translation templates +TRANSLATION_TEMPLATE_DIR = pathlib.Path(BUILD_DIR, "gettext") +TRANSLATION_LOCALES_DIR = pathlib.Path("locales") + +# Sphinx build commands +SPHINX_BUILD = "sphinx-build" +SPHINX_AUTO_BUILD = "sphinx-autobuild" + +# Sphinx parameters used to build the guide +BUILD_PARAMETERS = ["-b", "html"] + +# Sphinx parameters used to test the build of the guide +TEST_PARAMETERS = ["-W", "--keep-going", "-E", "-a"] + +# Sphinx parameters to generate translation templates +TRANSLATION_TEMPLATE_PARAMETERS = ["-b", "gettext"] + +# Sphinx-autobuild ignore and include parameters +AUTOBUILD_IGNORE = [ + "_build", + ".nox", + "build_assets", + "tmp", +] +AUTOBUILD_INCLUDE = [pathlib.Path("_static", "pyos.css")] + +## Localization options (translations) + +# List of languages for which locales will be generated in (/locales/<lang>) +LANGUAGES = ["es"] + +# List of languages that should be built when releasing the guide (docs or docs-test sessions) +RELEASE_LANGUAGES = [] @nox.session def docs(session): + """Build the packaging guide.""" session.install("-e", ".") - cmd = ["sphinx-build"] - cmd.extend(build_command + session.posargs) - session.run(*cmd) + session.run( + SPHINX_BUILD, + *BUILD_PARAMETERS, + SOURCE_DIR, + OUTPUT_DIR, + *session.posargs, + ) + # When building the guide, also build the translations in RELEASE_LANGUAGES + session.notify("build-translations", ["release-build"]) @nox.session(name="docs-test") def docs_test(session): """ - Same as `docs`, but rebuild everything and fail on warnings for testing + Build the packaging guide with more restricted parameters. + + Note: this is the session used in CI/CD to release the guide. """ session.install("-e", ".") - cmd = ["sphinx-build"] - cmd.extend(["-W", "--keep-going", "-E", "-a"]) - cmd.extend(build_command + session.posargs) - session.run(*cmd) + session.run( + SPHINX_BUILD, + *BUILD_PARAMETERS, + *TEST_PARAMETERS, + SOURCE_DIR, + OUTPUT_DIR, + *session.posargs, + ) + # When building the guide with additional parameters, also build the translations in RELEASE_LANGUAGES + # with those same parameters. + session.notify("build-translations", ["release-build", *TEST_PARAMETERS]) @nox.session(name="docs-live") def docs_live(session): - session.install("-e", ".") + """ + Build and launch a local copy of the guide. - AUTOBUILD_IGNORE = [ - "_build", - "build_assets", - "tmp", - ] + This session will use sphinx-autobuild to build the guide and launch a local server so you can + browse it locally. It will automatically rebuild the guide when changes are detected in the source. - # Explicitly include custom CSS in each build since - # sphinx doesn't think _static files should change since, - # well, they're static. - # Include these as the final `filenames` argument + It can be used with the language parameter to build a specific translation, for example: - AUTOBUILD_INCLUDE = [os.path.join("_static", "pyos.css")] + nox -s docs-live -- -D language=es - # ---------------- - # Assemble command - cmd = ["sphinx-autobuild"] + Note: The docs-live-lang session below is provided as a convenience session for beginner contributors + so they don't need to remember the specific sphinx-build parameters to build a different language. + """ + session.install("-e", ".") + cmd = [ + SPHINX_AUTO_BUILD, + *BUILD_PARAMETERS, + SOURCE_DIR, + OUTPUT_DIR, + *session.posargs, + ] for folder in AUTOBUILD_IGNORE: cmd.extend(["--ignore", f"*/{folder}/*"]) + # This part was commented in the previous version of the nox file, keeping the same here + # for folder in AUTOBUILD_INCLUDE: + # cmd.extend(["--watch", folder]) + session.run(*cmd) - # cmd.extend(build_command) - cmd.extend(build_command + session.posargs) - # Use positional arguments if we have them - # if len(session.posargs) > 0: - # cmd.extend(session.posargs) - # # Otherwise use default output and include directory - # else: - # cmd.extend(AUTOBUILD_INCLUDE) +@nox.session(name="docs-live-lang") +def docs_live_lang(session): + """ + A convenience session for beginner contributors to use the docs-live session with + a specific language. - session.run(*cmd) + It expects the language code to be passed as the first positional argument, so it needs + to be called with from the command line with the following syntax: + nox -s docs-live-lang -- LANG -@nox.session(name="docs-clean") -def clean_dir(dir_path=docs_dir): - """ - Clean out the docs directory used in the - live build. + where LANG is one of the available languages defined in LANGUAGES. + For example, for Spanish: nox -s docs-live-lang -- es """ - dir_path = pathlib.Path(dir_path) - dir_contents = dir_path.glob("*") + if not session.posargs: + session.error( + "Please provide a language using:\n\n " + "nox -s docs-live-lang -- LANG\n\n " + f" where LANG is one of: {LANGUAGES}" + ) + lang = session.posargs[0] + if lang in LANGUAGES: + session.posargs.pop(0) + session.notify( + "docs-live", ("-D", f"language={lang}", *session.posargs) + ) + else: + session.error( + f"[{lang}] locale is not available. Try using:\n\n " + "nox -s docs-live-lang -- LANG\n\n " + f"where LANG is one of: {LANGUAGES}" + ) + +@nox.session(name="docs-clean") +def clean_dir(session): + """Clean out the docs directory used in the live build.""" + session.warn(f"Cleaning out {OUTPUT_DIR}") + dir_contents = OUTPUT_DIR.glob("*") for content in dir_contents: - print(content) + session.log(f"removing {content}") if content.is_dir(): shutil.rmtree(content) else: os.remove(content) + + +@nox.session(name="update-translations") +def update_translations(session): + """ + Update the translation files (./locales/*/.po) for all languages translations. + + Note: this step is important because it makes sure that the translation files are + up to date with the latest changes in the guide. + """ + session.install("-e", ".") + session.install("sphinx-intl") + session.log("Updating templates (.pot)") + session.run( + SPHINX_BUILD, + *TRANSLATION_TEMPLATE_PARAMETERS, + SOURCE_DIR, + TRANSLATION_TEMPLATE_DIR, + *session.posargs, + ) + for lang in LANGUAGES: + session.log(f"Updating .po files for [{lang}] translation") + session.run( + "sphinx-intl", "update", "-p", TRANSLATION_TEMPLATE_DIR, "-l", lang + ) + + +@nox.session(name="build-languages") +def build_languages(session): + """ + Build the translations of the guide for the specified language. + + Note: This sessions expects a list of languages to build in the first position of the session arguments. + It does not need to be called directly, it is started by build_translations session. + """ + if not session.posargs: + session.error( + "Please provide the list of languages to build the translation for" + ) + languages_to_build = session.posargs.pop(0) + + session.install("-e", ".") + for lang in languages_to_build: + if lang not in LANGUAGES: + session.warn(f"Language [{lang}] is not available for translation") + continue + session.log(f"Building [{lang}] guide") + session.run( + SPHINX_BUILD, + *BUILD_PARAMETERS, + "-D", + f"language={lang}", + ".", + OUTPUT_DIR / lang, + *session.posargs, + ) + + +@nox.session(name="build-translations") +def build_translations(session): + """ + Build translations of the guide. + + Note: this session can be called directly to build all available translations (defined in LANGUAGES). + It is also called by the docs and docs-test sessions with 'release-build' as the first positional + argument, to build only the translations defined in RELEASE_LANGUAGES. + """ + release_build = False + if session.posargs and session.posargs[0] == "release-build": + session.posargs.pop(0) + release_build = True + # if running from the docs or docs-test sessions, build only release languages + BUILD_LANGUAGES = RELEASE_LANGUAGES if release_build else LANGUAGES + # only build languages that have a locale folder + BUILD_LANGUAGES = [ + lang + for lang in BUILD_LANGUAGES + if (TRANSLATION_LOCALES_DIR / lang).exists() + ] + session.log(f"Declared languages: {LANGUAGES}") + session.log(f"Release languages: {RELEASE_LANGUAGES}") + session.log( + f"Building languages{' for release' if release_build else ''}: {BUILD_LANGUAGES}" + ) + if not BUILD_LANGUAGES: + session.warn("No translations to build") + else: + session.notify("build-languages", [BUILD_LANGUAGES, *session.posargs]) + + +@nox.session(name="build-translations-test") +def build_translations_test(session): + """ + Build all translations of the guide with testing parameters. + + This is a convenience session to test the build of all translations with the testing parameters + in the same way docs-test does for the English version. + """ + session.notify("build-translations", [*TEST_PARAMETERS]) From ff8e19046b2309133ec073538f2123153407e9f7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 23:26:35 +0000 Subject: [PATCH 5/5] =?UTF-8?q?'[pre-commit.ci=20=F0=9F=A4=96]=20Apply=20c?= =?UTF-8?q?ode=20format=20tools=20to=20PR'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- noxfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noxfile.py b/noxfile.py index 0e5b2bb6..4a0ea835 100644 --- a/noxfile.py +++ b/noxfile.py @@ -214,4 +214,4 @@ def build_translations_test(session): This is a convenience session to test the build of all translations with the testing parameters in the same way docs-test does for the English version. """ - session.notify("build-translations", [*TEST_PARAMETERS]) \ No newline at end of file + session.notify("build-translations", [*TEST_PARAMETERS])