Skip to content

Commit

Permalink
Fix: edits from review
Browse files Browse the repository at this point in the history
  • Loading branch information
lwasser committed Dec 28, 2023
1 parent da9994e commit a51c1c2
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 39 deletions.
6 changes: 6 additions & 0 deletions index.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# pyOpenSci Python Open Source Package Development Guide

```{toctree}
:hidden:
:caption: Tutorials
Tutorials <tutorials/intro>
```

```{toctree}
:hidden:
:caption: Documentation
Expand Down
135 changes: 96 additions & 39 deletions tutorials/1-installable-code.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
# Make your Python code pip installable
# Make your Python code installable

The first step in creating a Python package based on code that you
have is to make that code pip installable. You will learn how to make
your code pip installable in this lesson.
In the previous lesson, you learned about both what a Python package is. You also learned about the [benefits of creating a Python
package](tutorials/intro.html#why-create-a-python-package) including:

<!--
TODO: is it clear where to add commands? bash vs. python console
* Being able to easily reuse in multiple workflows on your computer
* Being able to share your code with others who may find the functionality useful.
* Being able to better organize code that needs to be reused.


The first step in creating a Python package is turning that
code into a Python package that is pip installable.
The package that you create in this lesson will have
the bare minimum elements that you need to install a package.

In upcoming lessons you will learn how to:
* add a **README** file to support community use of your package
* add package metadata in a **pyproject.toml** file to support publication to PyPI

:::{todo}

1. Is it clear where to add commands? bash vs. Python console
Bash vs zsh is different
does this work on windows and mac? i know it works on mac/linux
-->
2. Does this lesson run as expected on windows and mac?
:::

:::{figure-md} code-to-python-package

:::{figure-md} code-to-script
<img src="../images/tutorials/code-to-python-package.png" alt="Diagram showing the basic steps to creating an installable package. There are 4 boxes with arrows pointing towards the right. The boxes read, your code, create package structure, add metadata to pyproject.toml and pip install package." width="700px">

<img src="../images/tutorials/code-to-script-diagram.png" alt="Diagram showing the basic steps to creating an installable package. There are 4 boxes with arrows pointing towards the right. The boxes read, your code, create package structure, add metadata to pyproject.toml and pip install package." width="700px">
A basic installable package needs a few things: code, a [specific package file structure](https://www.pyopensci.org/python-package-guide/package-structure-code/python-package-structure.html) and a `pyproject.toml` containing your package's name and version. Once you have these items in the correct directory structure, you can pip install your package into any environment on your computer.

A basic installable package needs a few things: code, a specific package structure and a `pyproject.toml` containing your package's name and version. Once you have these items in the correct directory structure, you can pip install your package into any environment on your computer.
:::

:::{admonition} Learning Objectives
Expand All @@ -33,41 +47,58 @@ environment. You are welcome to use any environment manager that you choose.

* [If you need guidance creating a Python environment, review this lesson](extras/1-create-environment.md) which walks you through creating an environment using both `venv` and `conda`.
* If you aren't sure which environment manager to use and
you are a scientist, we suggest that you use `conda`.
you are a scientist, we suggest that you use `conda`, particularly if you are working with any sort of spatial data.
:::

## Make your package installable


## Make a basic installable Python package


:::{figure-md} packages-environment

<img src="../images/tutorials/environment-package-install.png" alt="This diagram has two smaller boxes with arrows pointing to the right to a python environment. The small boxes read your-package and pip install package. The environment box on the right reads - your python environment. It them lists your-package along with a few other core packages such as matplotlib, numpy, pandas, xarray and geopandas." width="700px">

Making your source code pip-installable is the first step towards creating a Python package. Once your code is pip-installable, it is a Python package and can be added to any Python environment on your computer and imported in the same way that you might import a package such as `Pandas` or `Geopandas`.
Making your source code pip-installable is the first step towards creating a Python package. Once your code is pip-installable, it is a Python package and can be added to any Python environment on your computer and imported in the same way that you might import a package such as Pandas or GeoPandas.
:::

## Make a basic Python package

It’s time to create the most basic version of a Python package.
While this code can't be yet published to PyPI or conda and
is not documented, it will be installable on your computer or
anyone elses.

What you'll be able to do with this package at the end of this lesson is:

* Install it into any Python environment on your computer
* If you share your code with someone else on GitHub or some other file/sharing or cloud based sharing platform, others will be able to install your package too.

While installable code is the first step towards making a Python package, there are some limitations. What you won't be able to do
by the end of this lesson is publish your package to PyPI and then conda-forge.

The next 3 lessons in this series will teach you how to add the proper
metadata and documentation that you will need to publish to PyPI.

:::{admonition} Installing packages from GitHub

If you wish to share your code without publishing to PyPI you can
always install packages directly from GitHub using the syntax:

`pip install git+https://github.com/user/repo.git@branch_or_tag``

:::

### What does a basic package directory structure look like?
To make your code installable you need:

- A `pyproject.toml` file
- An (optional but recommended) `__init__.py` file in your code directory
- A specific directory structure
- A `pyproject.toml` file.
- A specific directory structure.
- Some code.
- An `__init__.py` file in your code directory.

The directory structure you’ll create in this first section looks like this:

```bash
pyospackage/
└─ pyproject.toml
└─ src/ # The src directory ensures your tests always run on the installed
└── pyospackage/ # Package directory where code lives, use the package name
└─ src/ # The source (src/) directory ensures your tests always run on the installed version of your code
└── pyospackage/ # Package directory where code lives, use the package name
├── __init__.py
├── add_numbers.py
└── # Add any other .py modules that you want here
Expand All @@ -79,40 +110,66 @@ Below, you will learn about each element of the above package structure.

Notice a few things about the above layout:

1. Your package code lives within a `src/packagename` directory. We suggest that you use `src/` directory as it ensure you are running tests on the installed version of your code. However, you are welcome to instead use a [flat layout](https://www.pyopensci.org/python-package-guide/package-structure-code/python-package-structure.html#about-the-flat-python-package-layout) which does not have a src/ directory at the root. [Learn more here.](https://www.pyopensci.org/python-package-guide/package-structure-code/python-package-structure.html#the-src-layout-and-testing)
2. Within the `src/` directory you have a package directory called `pyospackage/`. Use the name of your package for that directory name.
3. In your package directory, you have an `__init__.py` file and all of your Python modules.
4. The `pyproject.toml` file lives at the root directory of your package.

## Init.py and pyproject.toml files
1. Your package code lives within a `src/packagename` directory. We suggest that you use `src/` directory as it ensures that you are running tests on the installed version of your code. However, you are welcome to instead use a [flat layout](https://www.pyopensci.org/python-package-guide/package-structure-code/python-package-structure.html#about-the-flat-python-package-layout) which does not have a src/ directory at the root. [Learn more here.](https://www.pyopensci.org/python-package-guide/package-structure-code/python-package-structure.html#the-src-layout-and-testing)
1. Within the `src/` directory you have a package directory called `pyospackage/`. Use the name of your package for that directory name.
1. In your package directory, you have an `__init__.py` file and all of your Python modules.
1. The `pyproject.toml` file lives at the root directory of your package.
1. The name of the root directory for the package is **pyospackage** which is the name of the package. This is not a requirement but you will often see that the GitHub / GitLab repo and the root directory name are the same as the package name.

## __init__.py and pyproject.toml files

The `__init__.py` and `pyproject.toml` files in the above layout
are important to understand. More on that below.

### What is an init.py file?
### What is an __init__.py file?

When a directory contains an `__init__.py` file, it can be imported directly into Python.

For example, following the file structure example above which has an __init__.py file within it, you can run:

```
import pyospackage
```

The `__init__.py` file tells Python that a directory should be treated
as a Python package.


JEREMIAH - potentially remove init.py shortcutsl.... I'm not sure if these three points add anything for a beginner. I see a package already as organized modules, and that you get for free with an empty file. Also IIRC in slack we said that creating shortcuts in __init__.py can actually be harmful - probably not a tactic to start with. A version can go in __init__.py but also version strings as python data is a whole can of worms in python packaging.

The `__init__.py` file tells Python that the directory it’s in should be treated as a Python package.
The `__init__.py` file also:

- Allows you to organize multiple modules within the package.
- Allows you to create shortcuts for importing specific functions, and classes into your code (more on that later!)
- Allows you to create shortcuts for importing specific functions and classes into your code (more on that later!)
- Allows you to create a version object for people to call **version**

:::{admonition} The **init**.py file
:::{admonition} The **__init__**.py file
:class: tip

Since Python 3.3 came out, you can install a package without an `__init__.py` file. However, we suggest that you include it in your package structure as it allows you to customize your package’s user experience.
The __init__.py file does not need to contain any code, it can be
empty. Since Python 3.3 came out, you can install a package without an
`__init__.py` file. However, we suggest that you include empty __init__.py files in your
package structure as it allows you to customize your package’s user
experience.
:::


> Perhaps the resolution is to be really clear that this is an overview and they'll learn more about all 3 things in later lessons? question about publication, etc
### What is a pyproject.toml file?

The **pyproject.toml** file is:

- Where you store your project’s metadata (including its name, authors, license, etc)
- Where you store dependencies (the packages that it depends on)
- Used to specify and configure what build back end you want to use to build your package distributions that are used for PyPI publication.
- Where you define your project’s metadata (including its name, authors, license, etc)
- Where you define dependencies (the packages that it depends on)
- Used to specify and configure what build back end you want to use to [build your package](../package-structure-code/python-package-distribution-files-sdist-wheel).

After the `__init__.py` and `pyproject.toml` files have been added, your package can be built and distributed as an installable Python package using tools such as pip. Note that the `pyproject.toml` file needs to have the a few basic items defined for it to be installable including:
After the `__init__.py` and `pyproject.toml` files have been added,
your package can be built and distributed as an installable Python
package using tools such as pip. Note that the `pyproject.toml` file
needs to have a few basic items defined for the package to be
installable including:

- The `build-backend` that you want to use,
- The project `name` and `version`.
Expand All @@ -136,7 +193,7 @@ Neither 'setup.py' nor 'pyproject.toml' found.

Now that you understand the basics, it's time to create a Python package! Below you will create a directory structure similar to the structure described above.

If you don’t wish to create each of the files and directories below, you can always [fork and clone and customize the pyOpenSci example package, here.](https://github.com/pyOpenSci/pyosPackage)
If you don’t wish to create each of the files and directories below, you can always [fork and clone and customize the pyOpenSci example package.](https://github.com/pyOpenSci/pyosPackage)

### Step 1: Set Up the Package Directory Structure

Expand Down
12 changes: 12 additions & 0 deletions tutorials/intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Python packaging 101

When we merge PR 1 this file will be updated with
full content. please ignore for now it's a placeholder for the toctree

:::{toctree}
:hidden:
:caption: Python Packaging 101

What is a Python package? <self>
Make your code pip installable <1-installable-code>
:::

0 comments on commit a51c1c2

Please sign in to comment.