4. Creating packages

DishPy 0.5.0 shipped with a beta (extremely experimental) version of package management through a registry-based system (somewhat similar to PROS' approach, but much simpler and more limited in scope).

v1.0 finally stabilizes the API for those commands, so we can begin writing tutorials!

Philosophy

DishPy has a somewhat simple but possibly unfamiliar methodology for its package management. There are a few key things to understand:

This may seem more complex than the centralized PyPI solution, but it actually isn't much harder. Even uv add (think pip alternative) maintains a "warm cache" of recently fetched packages from PyPI. It also saves me (Aadish) from all of the costs and investment of running my own centralized registry.

Creating your first package

Let's actually start working. As we go, keep these points from the philosophy in mind:

Recall the create command:

uvx dishpy create --name "my-robot"

You can also specify which slot on the V5 brain your program should use (defaults to slot 1):

uvx dishpy create --name "my-robot" --slot 2

One option we didn't mention before is the --package option. You can use it as a flag, which will initialize the project with a package whose name is the project name converted to snake case, or pass a string as the package name.

# create a project "DP Test Project" with package "dp_test_project"
uvx dishpy create --name "my-robot" --package
# create a project "DP Test Project" with package "add_two_nums"
uvx dishpy create --name "my-robot" --package "add_two_nums"
# create a project "Add Two Numbers" with package "add_two_nums" that uploads to slot 2
uvx dishpy create --name "Add Two Numbers" --package "add_two_nums" --slot 2

Let's run the last option.

$ uv run dishpy create --name "Add Two Numbers" --package add_two_nums --slot 2
✨ Created and initialized project in Add Two Numbers/ with package Add Two Numbers/src/add_two_nums/
$ tree "Add Two Numbers/"
Add Two Numbers/
├── dishpy.toml
└── src
    ├── add_two_nums
    │   └── __init__.py
    ├── main.py
    └── vex
        └── __init__.py

4 directories, 4 files

Great. Most of this looks familiar, but there are two changed files to look out for.

dishpy.toml

[project]
name = "Add Two Numbers"
slot = 2

[package]
package_name = "add_two_nums"
version = "0.1.0"

The project section is nearly identical, but now there is an all-new package section. This is the "decentralized metadata," which DishPy ues to get information about a package when fetching it.

src/add_two_nums/__init__.py

As previous noted, your package will live in src/add_two_nums. __init__.py is the entrypoint for your package. If you write

import add_two_nums

in main.py, that's basically shorthand for

import "add_two_nums/__init__.py" as add_two_nums

Right now, your __init__.py just looks like this:

"Put your package code!"


def add_two_numbers(a, b):
    return a + b

which is honestly pretty boring, but a good starting point. Now, in your main.py, you can write code such as

from add_two_nums import add_two_numbers
from vex import Brain
brain = Brain()
brain.screen.print(str("10 + 3 = ") + str(add_two_numbers(10, 3)))

to import the function from your package and call it.

Your package doesn't only have to be one file! Using the multifile capabilities of DishPy, you can have extra files (src/add_two_nums/validation.py) or even submodules (src/add_two_nums/some_submodule/__init__.py). Just make sure your src/add_two_nums/__init__.py imports those so it is available to whoever imports add_two_nums.

Anything in the add_two_nums directory is part of the source code of your package and will be copied into projects that import it.