A tiny and simple library for Strongly typed Plain Old Data Structures.
Project description
strongpods
strongpods is a tiny and simple library for Strongly typed Plain Old Data Structures (PODS).
Using it you can create a simple PODS using a decorator and C-style attribute declaration using type annotations:
from strongpods import PODS
@PODS
class MyPODS:
an_int: int
a_list: list
You can then initialize it using keyword arguments and an error will be emitted if the provided values don't have the specified typed and cannot be cast to these types. See the Error reporting section for more details.
pods_instance = MyPODS(an_int=127, a_list=["brains"]) # works
pods_instance_2 = MyPODS(an_int="an irrational number", a_list=["brains"]) # raises a TypeError because "an irrational number" cannot be converted to an int
pods_instance_3 = MyPODS(an_int=127, a_list="brains") # raises a TypeError because "brains" cannot be converted to a list
Installation
Using pip:
pip3 install strongpods
or using uv (recommended):
uv pip install strongpods
Main features
strongpods relies on type annotations of the attributes to enforce the types at runtime.
If a given value can be cast to it (using the type casting rules described below), it will, otherwise an error will be emitted (see section strongpods errors for more details).
The following types are supported:
- primitive types
- numpy arrays
- enumerations
- unions
- optionals (which are special types of unions)
One can also define default values for attributes.
The PODS defined with strongpods can also be subclassed and the attributes of the parent class will be inherited by the child class, while still maintaining the type enforcement at runtime.
from strongpods import PODS
@PODS
class ParentPODS:
an_int: int
a_list: list
@PODS
class ChildPODS(ParentPODS):
a_str: str
Type casting rules
Suppose we have defined a PODS as
@PODS
class MyPODS:
attr: Typ
and try to construct an instance of MyPODS using MyPODS(attr=val).
If val is of type Typ, the attribute attr will be initialized with the value val.
Otherwise, strongpods will try to cast val to Typ using the following rules:
- If
Typis a simple type (e.g.int,str,float,bool,list,tupleornp.ndarray), the type cast will be performed usingTyp(val). - If
Typis an enumeration, we can convertvalif it is a string representing a member of the enumeraion. For example, if we definedclass Typ(Enum): Typ0 = 0 Typ1 = 1 Typ2 = 2
then the following are validMyPODS(attr="Typ0") MyPODS(attr="Typ1") MyPODS(attr="Typ2")
- If
Typis an union, we first check if the provided value has the exact type of any of the types of the union, and if does not, we cast it to the first type it can be cast to. For the following PODS
the intialization@PODS class MyPODS: a: Union[int, str]MyPODS(a="hello")initializesawith typestr(the actual type of"hello") andMyPODS(a=0.0)initializes it with typeint(and value0).
Error reporting
The way the errors are handled depends on the value of the global parameter
strongpods.VERBOSITY_LEVEL of type strongpods.VerbosityLevel:
SILENT: all errors are ignoredWARNINGS: warnings are raised viawarnings.warnERRORS: exceptions are raised
You can manually change this value at any time in your code with
strongpods.set_verbosity_level().
Alternatives
I created this package around 2022, when I started working at the EPFL Racing Team on big Python projects (an autonomous racing software stack).
I wanted to create simple data structures to encapsulate input/output data in a safe and simple way. I didn't like the idea of using plain dicts and relying on my
memory to remember the exact name of the keys, so I started looking into dedicated solutions, part of the Python standard library. Neither
dataclasses, TypedDicts
nor NamedTuples seemed to fit my needs, mainly because of their lack of strong typing that I missed
from C and C++.
At the time, the simplest solution for me was to write my own small library. I since discovered other mainstream alternatives, such as
pydantic. Comparatively, this project offers substantially fewer options and a more limited and opinionated set of supported types.
One important example is the direct support for numpy arrays, which was of great use in my projects.
It is not designed to rival with pydantic, but rather to be a simple and lightweight alternative that suits my needs.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file strongpods-2.1.0.tar.gz.
File metadata
- Download URL: strongpods-2.1.0.tar.gz
- Upload date:
- Size: 21.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac94cb2aac4b0be0142cdae6c2cfee5f8ab65a44bd4cf0a679265df1ca46359a
|
|
| MD5 |
c331ea639b49d83505818ab7bb7ae439
|
|
| BLAKE2b-256 |
729c6d5215c56f633fcb41b98db4ea9c7f8642e81c22936fbc60e053a5d15f90
|
File details
Details for the file strongpods-2.1.0-py3-none-any.whl.
File metadata
- Download URL: strongpods-2.1.0-py3-none-any.whl
- Upload date:
- Size: 7.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e8f890175cb5bb0a15b2bb4fc50f3f1bf79e2f5e4e235f5a9a55463b9c1e3553
|
|
| MD5 |
f15d8ddf5cb1adfb9c77f36a1996ba1b
|
|
| BLAKE2b-256 |
2adbc4900ed761d7c0dc5b2e8165412651d5bb03398592336be7b2b22a640c7f
|