No description
  • Python 97.1%
  • Shell 1.7%
  • Dockerfile 1%
  • Mako 0.2%
Find a file
2025-09-20 15:56:03 -04:00
.direnv Add/update direnv config 2025-01-08 22:55:19 -05:00
.github/workflows Backup old lint pipeline. 2025-01-05 01:02:00 -05:00
.jobs chore(gitignore): Update gitignores in preparation for future merges 2025-06-21 01:08:46 -04:00
.vscode Update vscode settings extraPaths 2025-01-11 00:06:15 -05:00
applications fix(json): Add saving raw current weather response JSON to CLI 2025-06-21 19:50:37 -04:00
config Move openmeto settings into main settings.toml. 2025-04-03 00:18:04 -04:00
containers fix(overlays): Break into overlays 2025-08-26 22:48:49 -04:00
migrations Merge branch 'main' into feat/openmeteo 2025-09-20 15:50:28 -04:00
packages Merge branch 'main' into feat/openmeteo 2025-09-20 15:50:28 -04:00
sandbox Add openmeteo schemas 2025-04-23 01:24:26 -04:00
scripts fix(dev): Add script to bring up dev stack 2025-09-02 02:11:03 -04:00
.dockerignore Add Celery dockerfile, with build layers for beat & worker. 2025-01-06 01:35:07 -05:00
.envrc Attempt to start over on Dockerfile. 2025-01-10 00:02:05 -05:00
.gitignore fix(gitignore): Add gitignores for weird celery files 2025-08-25 01:01:17 -04:00
alembic.ini Add alembic ini file. 2024-12-27 20:54:12 -05:00
cli.py Lint code 2025-01-11 01:08:01 -05:00
noxfile.py Update noxfile init clone setup session. 2025-04-03 00:35:04 -04:00
pyproject.toml Add minio controller class 2025-04-23 01:40:49 -04:00
README.md Update repo README, add notes about memcached on Raspberry Pi 2025-04-03 00:35:38 -04:00
ruff.toml Add ruff.toml so vscode plugin works 2024-12-28 00:23:06 -05:00
uv.lock Add minio controller class 2025-04-23 01:40:49 -04:00

WeatherData Monorepo

GitHub Created At GitHub last commit GitHub commits this year GitHub repo size GitHub code size in bytes

I use weather APIs frequently to help me learn programming things. I'm continuing that trend by learning to build a monorepo with Python and uv.

Table of Contents

Requirements

  • uv: The packages (and the repository itself) are managed with uv.
    • If you haven't already tried it, you should!
    • uv can even install Python for you, meaning uv is the only dependency you need to install for this monorepo.
  • (Optional) Python: If you want to install Python (or already have it installed), uv will use the system version of your Python.

Setup

  • Clone this repository
    • git clone https://github.com/redjax/weatherdata
  • Create your configuration files
    • Copy the following files in config/:
      • General configurations:
        • settings.toml -> settings.local.toml
        • .secrets.toml -> .secrets.local.toml
      • Database configuration:
        • database/settings.toml -> database/settings.local.toml
        • database/.secrets.toml -> database/.secrets.local.toml
      • weatherapi configuration:
        • NOTE: You need to sign up for a free API key on WeatherAPI's site.
        • weatherapi/settings.toml -> weatherapi/settings.local.toml
        • weatherapi/.secrets.toml -> weatherapi/.secrets.local.toml
  • Run uv sync to install required packages
    • This repository uses uv workspaces to build modules in applications/ and packages.
    • Each of the projects in these directories is a Python package with a pyproject.toml file, intialized with uv init --package.
    • When uv runs any part of this repository, it will build everything and then execute the command you ran.
    • If you want to manually build the project, you can run uv build

Usage

Once you have installed the project (read the setup instructions), you can run different entrypoints with uv run.

You can also run the project's cli with: uv run cli --help.

For example, to launch the weather_cli app, you can run:

uv run python -m weather_cli

Or to see the sandbox demo, you can just run:

uv run sandbox/demo/demo.py

You can omit python in your uv run commands; uv knows what you're trying to do when you run a .py file 😉 The exception to this rule is when running packages as a module, as you would with python -m. You still need to add that to your uv command.

Using the monorepo

Developing in a monorepo is different from developing in other "flatter" repositories. In a regular repository, you might only have 1 service or application defined in your code. In a monorepo, you can define many services/applications and shared dependencies. You can bring various parts of the application together by installing modules in other modules (like the depends package, which import its settings in the [tool.uv.sources] section from the settings module: settings = { workspace = true }), import from other areas of the monorepo, and share code more easily between different applications and services.

Each type of repository has its purpose and place; I am choosing to structure this project as a monorepo so I can learn how to manage and work with them. Neither is better than the other, a good developer will choose when a monorepository format is right for their project.

Adding packages

To add new packages to the app, create a path in packages/ and initialize it with uv init --package. Note that if you're using VSCode and want type completion to work, you also need to edit the settings.json file in the .vscode/ directory, adding the path to "python.analysis.extraPaths": [].

For example, to add a package named nb_functions, you might run the following commands:

## Create the directory where the package will live
mkdir -pv ./packages/notebook-functions
cd ./packages/notebook-functions

## Create the src directory & __init__.py/main.py files
mkdir -pv ./src/nb_functions
touch ./src/nb_functions/{__init__,main}.py

## Initialize the uv package
uv init --package

## Add code from another module in this repository, i.e. http-lib
uv add http-lib

Note that the source code name (nb_functions) differs from the parent path name (notebook-functions). You need to modify the new pyproject.toml file that was created when you ran uv init --package.

When a package's name differs from the parent directory like this, you will see an error like this when you try to add packages, build, or run anything with uv:

ValueError: Unable to determine which files to ship inside the wheel using the following heuristics: https://hatch.pypa.io/latest/plugins/builder/wheel/#default-file-selection

The most likely cause of this is that there is no directory that matches the name of your project (notebook-functions).

At least one file selection option must be defined in the `tool.hatch.build.targets.wheel` table, see: https://hatch.pypa.io/latest/config/build/

As an example, if you intend to ship a directory named `foo` that resides within a `src` directory located at the root of your project, you can define the following:

[tool.hatch.build.targets.wheel]
packages = ["src/foo"]

The fix for this is details in that last part of the error message. We need to add a section like the following to tell uv where the code it needs to build for this package lives:

## packages/notebook-functions/src/nb_functions/pyproject.toml

...

[tool.hatch.build.targets.wheel]
packages = ["src/nb_functions"]

...

This fixes the build error. Remember this when you are naming package and application parent directories.

Finally, if you're using VSCode, add the new path to your settings.json file:

{
    ...,
    "python.analysis.extraPaths": [
        ...,
        "./packages/notebook-functions/src",
    ]
}

Adding applications

Applications import from packages/ and other areas of the repository, joining different parts of the code into functional apps meant to be built, distributed, and used.

For example, the weather_cli application exposes a CLI written in cyclopts that a user can run to call different parts of the code, like requesting the current weather.

Building an application is pretty much the same as a package. The main difference is when you initialize it, you run:

uv init --application --package

The 'sandbox'

The sandbox/ path is a place where I can prototype or test small portions of the repository. The demo application is a constantly evolving file I use put together pre-packaged function calls by importing code from applications, packages, etc, and writing scripts like I might if I were to install these packages outside of this repository.

Sandbox code is just that; it is not packaged, it's not meant to be distributed, and scripts may come and go (I often delete things in the sandbox once I've integrated the code into the app somewhere else).

Notes

Fix memcached crash on Raspberry Pi

On Raspberry Pi (and probably other ARM CPUs), the libmemcached package must be installed on the host.

  • Debian: apt install -y libmemcached-dev
  • RedHat: dnf install -y memcached libmemcached