Part 4. Python Package Development

Overview

Across this course, you have written analysis scripts, dashboards, and small reusable functions. These pieces are valuable on their own. They become much more useful when you wrap them as a Python package that you can install in any project with one command and that other people can install too.

The answer is Python packaging, which means turning your analysis scripts into reusable, installable, shareable software. This final part of the course teaches you how to create a small Python package that you and others can install with pip install your-package.

From scripts to packages

The problem of copy-paste reuse

Consider this scenario.

# project1/analysis.py
def calculate_walkability(streets_gdf, amenities_gdf, buffer_m=800):
    """Calculate walkability scores."""
    # 50 lines of well-crafted code

# Months later in project2/analysis.py
def calculate_walkability(streets_gdf, amenities_gdf, buffer_m=800):
    """Calculate walkability scores."""
    # The same 50 lines, copied and pasted.
    # You fixed a bug in project1 and forgot to update project2.

The packaged alternative

# Done once, in your package
pip install my-urban-toolkit

# Reused forever, in any project
from my_urban_toolkit import calculate_walkability

walkability = calculate_walkability(streets, amenities)

What you will learn

This part covers the package development cycle in four short weeks.

Week 9. Structure and building

  • Why packaging matters for urban analytics
  • Package architecture, the src/ layout
  • Reading and editing pyproject.toml
  • Building distributions with uv
  • Testing the package on your own machine

Week 10. Testing, real-world examples, and TestPyPI

  • Writing simple tests with pytest
  • Walking through real-world package examples (including akl-ped-counts)
  • Publishing to TestPyPI as a safe rehearsal
  • Troubleshooting publication issues on GitHub

Week 11. Poster showcase week

  • Polishing the study design and the package skeleton
  • Preparing the A1 poster that explains your package
  • Poster showcase on Tuesday 25 May (B301-G10)

Week 12. Deploy to PyPI

  • Confirming the TestPyPI install works in a clean environment
  • Deploying to production PyPI once TestPyPI is fully confirmed
  • Versioning, release notes, and basic maintenance

A real package as the running example

Throughout this part we will refer to akl-ped-counts, a small package the instructor maintains that ships hourly Heart of the City pedestrian counts for 21 Auckland CBD sensors from 2019 to 2025. It is published on PyPI, has a typed API, optional extras, and a README with worked examples.

You can install it now and try the API.

pip install akl-ped-counts

from akl_ped_counts import load_hourly, load_locations, list_sensors

counts = load_hourly()
print(list_sensors())

We will use this repository as a worked example because it is realistic in size, has been through actual TestPyPI and PyPI releases, and shows the kind of practical decisions you will face. The package source is at https://github.com/dataandcrowd/akl-ped-counts.

The journey, scripts to package to publication

Phase 1. From notebook to module (Week 9)

Starting point, scattered code across notebooks and scripts.

my_analysis/
├── load_data.py
├── process_pedestrians.py
├── calculate_metrics.py
└── make_maps.py

Week 9 deliverable, a tidy package folder.

your-package/
├── src/
│   └── your_package/
│       ├── __init__.py
│       ├── data.py
│       ├── metrics.py
│       └── viz.py
├── tests/
│   └── test_data.py
├── pyproject.toml
└── README.md

Phase 2. Add quality assurance (Week 10)

A simple test gives you confidence the function does what you expect.

def test_load_sa2():
    gdf = load_sa2('data/auckland_sa2.gpkg')
    assert gdf.crs == 'EPSG:2193'
    assert len(gdf) > 0

A clear docstring helps users.

def calculate_density(gdf, pop_column='population'):
    """
    Calculate population density per square kilometre.

    Parameters
    ----------
    gdf : GeoDataFrame
        Must contain geometry and a population column.
    pop_column : str, default 'population'
        Name of the population column.

    Returns
    -------
    GeoDataFrame
        The input with a new 'density' column.
    """

Phase 3. Share with the world (Weeks 10 to 12)

TestPyPI in Week 10, a safe rehearsal.

uv publish --index testpypi
# Your package is now at test.pypi.org/project/your-package/

PyPI in Week 12, the real release after TestPyPI is fully confirmed.

uv publish
# Anyone can now run: pip install your-package

Learning objectives

By the end of this part, you will be able to do the following.

Technical skills. Structure a Python package using the src/ layout. Write a working pyproject.toml. Build wheel and source distributions. Write a small set of pytest tests. Generate readable docstrings. Publish a package to TestPyPI and then to PyPI.

Geospatial skills. Test spatial operations correctly. Handle CRS validation inside a package. Package small reference data appropriately. Manage geospatial dependencies. Create reusable GIS workflows that you and others can install.

Professional skills. Write code that other people can read. Document for varied audiences. Troubleshoot publication issues. Maintain a small open source project.

Why this matters for urban analytics

Reproducibility

A pinned package version locks the exact tool used in an analysis.

# Requirements file for a research paper
akl-ped-counts==0.2.0
geopandas==0.14.0

Anyone can recreate your analysis with the same tools.

Collaboration

A team works more efficiently with shared, validated functions.

from akl_ped_counts import load_hourly, list_sensors

counts = load_hourly(years=[2024], dropna=True)

This removes the “it works on my machine” problem.

Teaching

A package keeps teaching materials clean.

pip install akl-ped-counts

# Students focus on analysis, not data wrangling
from akl_ped_counts import load_hourly
data = load_hourly(years=[2023])

Career development

Employers value developers who can create reusable tools. A published package is a tangible portfolio piece. Contributing to open source builds professional networks. Your tools can influence research and practice beyond your direct work.

The urban analytics package ecosystem

You will be joining a rich ecosystem of geospatial packages.

Foundation libraries (what you will depend on).

  • geopandas for spatial dataframes
  • shapely for geometric operations
  • osmnx for street networks
  • r5py for routing and accessibility
  • folium for interactive maps

Your package (what you will create). A small, focused tool that addresses one of your assignments or a research question you care about. Think of akl-ped-counts as a model for the size and scope you should aim for.

Assessment overview

Package development spans the final four weeks.

Week Activity Weight
9 Build first package locally Completion credit
10 Publish to TestPyPI In your group
11 Poster showcase, Tuesday 25 May (B301-G10) 10%
12 Assignment 3, PyPI publication 30%

Total, 40% of the final grade.

Chapter structure

Package structure and building

Learn the fundamentals.

  • Why packaging matters for GIS workflows
  • Package architecture, src/ layout best practices
  • pyproject.toml configuration
  • Building distributions with uv
  • Local testing before publication

Week 9 focus, get everyone building packages successfully.

Testing and real-world examples

Add robustness and look at a real package.

  • A first pytest example
  • Common pitfalls in geospatial tests
  • Walkthrough of akl-ped-counts as a real-world example
  • TestPyPI publication
  • Troubleshooting publication issues on GitHub

Week 10 focus, practise publication in a safe environment.

Poster showcase week

Polish your study design and skeleton.

  • Tighten the package scope and module layout
  • Prepare the A1 poster (594 mm by 841 mm)
  • Present at the Tuesday 25 May showcase (B301-G10)

Week 11 focus, communicate your design clearly to a non-expert audience.

Publishing to production PyPI

Final release.

  • Real PyPI publication, once TestPyPI is fully confirmed
  • Semantic versioning
  • Release notes and basic maintenance

Week 12 focus, complete Assignment 3 and confirm a clean install.

Getting started

Before you begin, you will need the following.

Prerequisites. Python 3.10 or later. uv installed via pip install uv. Git and a GitHub account. A TestPyPI account (created in Week 10) and a PyPI account (created in Week 12).

Development tools. A code editor (Positron or VS Code), a terminal, and Git for version control.

Conceptual knowledge. Python modules and imports, functions and classes, basic command line, and Git fundamentals.

Mindset for package development

Think like a library author. Will this make sense to someone else? What might go wrong with this input? How do I explain this clearly?

Embrace iteration. Version 1.0 does not need to be perfect. Release early and improve based on feedback. Documentation can always improve.

Value reproducibility. Pin dependencies, test thoroughly, document assumptions, and version thoughtfully.

Looking ahead, Assignment 3

Throughout these weeks, you will work toward Assignment 3, a small published Python package that builds on your earlier course work. Choose a scope that solves a real problem, builds on what you already have, interests you, and is achievable in 3 to 4 weeks.

Course wrap-up, the poster showcase

The course culminates in a poster showcase on Tuesday 25 May (B301-G10), where you present your package.

Format, A1 poster (594 mm by 841 mm). Content, the package purpose, the design, key features, and example output. Audience, faculty, students, and visitors.

This is your chance to demonstrate the technical skills, analytical thinking, and professional communication you have built across the course.

Let’s begin

Package development moves you from a code user to a code creator. You will learn to build tools that last, share knowledge effectively, and contribute to the broader geospatial community.

Ready to publish your first package? Let’s start with the fundamentals in the next chapter.

Resources

Essential reading.

  • Python Packaging Guide, https://packaging.python.org/
  • uv documentation, https://docs.astral.sh/uv/
  • pytest documentation, https://docs.pytest.org/
  • Real Python, Python modules and packages, https://realpython.com/python-modules-packages/

Example packages to study.

  • akl-ped-counts, https://github.com/dataandcrowd/akl-ped-counts
  • osmnx, https://github.com/gboeing/osmnx
  • geopandas, https://github.com/geopandas/geopandas
  • momepy, https://github.com/pysal/momepy

Community.

  • PyPI, https://pypi.org/
  • TestPyPI, https://test.pypi.org/

What success looks like

By Week 12, you will be able to say the following.

  • I am a published Python package author.
  • My code is tested and documented.
  • Anyone can install my package with pip.
  • I understand package architecture and basic best practices.
  • I can maintain and version my package.
  • I have contributed to the open source ecosystem.

Most importantly, you will have created something that outlasts the course, a tool that you and others can use for years to come.

Let’s build something useful.