Skip to main content
myBasis logo

myBasis: Ergonomic Python Utilities

pipeline status license PyPI version

PyPI - Python Version PyPI - Wheel PyPI - Types pre-commit pyrefly ruff

The myBasis utility package — imported as my — is a broad extension of the Python standard library centered on text processing, functional programming, and runtime type coercion. The use cases are diverse enough to not enumerate them all here, but they all share a strong sense of discipline: all code is thoroughly typed, tested, and documented following my best pass at best practices (it does get easier!).

I made this module to streamline some patterns that seemed both A) frequently-relevant and feasible to streamline. The repo thus grew alongside my projects over time, a genesis which gives it the advantage of being in daily use by the original author in multiple examples right off the bat.

Left-rule blocks mark artificial prose; quotations retain their own attribution.

Documentation: basis.docs.doering.ai

Installation

In an activated Python 3.13+ environment:

uv pip install my-basis
# or:
python -m pip install my-basis

A first example

Start with ty: cast a value into a target type, check whether it already fits, or inspect the type itself. Casting and checking are deliberately different operations.

from my import ty, MyType

ty.cast('42', int)                            # -> 42
ty.cast(['1', '2', '3'], list[int])           # -> [1, 2, 3]
ty.cast({'a': '1', 'b': '2'}, dict[str, int]) # -> {'a': 1, 'b': 2}

ty.check(42, int)      # -> True
ty.check('42', int)    # -> False
ty.match('hello', str | int)  # -> True

t = MyType(dict[str, int])
t.main    # -> <class 'dict'>
t.args    # child MyType nodes for str and int
t.root    # -> dict[str, int]

ty is the shared Typist instance, combining cast, check, and match. Use the typing guide when the coercion rules themselves matter.

Find your corner

Seven public subpackages cover the main jobs. The root re-exports their public names, so from my import ut, ty, Span, Markdown is enough for the examples here. The heavier apis and files branches load lazily.

Area Start here Useful for API reference
Utilities ut Partitioning iterables, transforming text, working with syntax and system resources Hosted
Runtime typing ty, MyType, AutocastModel Coercion, conformance checks, and inspecting annotations Hosted
Reusable types Span, Buffer, Command Intervals, mutable text, and reusable shell invocations Hosted
Regular expressions RegexStore, MatchData Composing named patterns and inspecting matches Hosted
Caches Cache, NestedCache, FileCache, PickleCache In-memory, hierarchical, disk-backed, and expiring storage Hosted
Interfaces env, fs, GoogleSheet Typed environment access, named paths, and optional spreadsheet integration Hosted
File formats Markdown Parsing, walking, and editing a document tree Hosted

A short tour

Utilities

ut collects the utility families into one namespace. You can also import a family directly—IterUtils and iter_utils, for example, name the same class. One detail worth noticing below: find returns an index, not the matching value.

from my import ut

ut.partition([1, 2, 3, 4], lambda x: x % 2 == 0)  # -> ([1, 3], [2, 4])
ut.condense(['a', None, '', 'b', 0])              # -> ['a', 'b']
ut.find([3, 8, 2], lambda x: x > 5)               # -> 1

Runtime typing

AutocastModel applies the casting rules during Pydantic validation. It's useful when incoming values are close to the shape you need, including a scalar where your model expects a list. Use it where that permissiveness is intended.

from my import AutocastModel

class Settings(AutocastModel):
    port: int = 0
    debug: bool = False
    tags: list[str] = []

s = Settings(port='8080', debug='true', tags='solo')
(s.port, s.debug, s.tags)  # -> (8080, True, ['solo'])

Reusable types

The types branch gives recurring concepts their own objects. Span, for instance, represents a half-open interval and handles its length and overlap checks. The shared type vocabulary also pairs annotation aliases such as Atom with runtime tuples such as Atoms.

from my import Span

a, b = Span(3, 9), Span(8, 12)
a.delta          # -> 6
a.intersects(b)  # -> True

Regular expressions

RegexStore gives patterns names you can compose and reuse. MatchData keeps repeated groups accessible, and COMMON_RGXS supplies a collection of ready-made patterns. The meta layer is there when you need to inspect the expression itself.

from my import RegexStore, COMMON_RGXS

COMMON_RGXS.findall('url', 'visit https://example.com or www.foo.dev')
# -> [MatchData("https://example.com" -> {'url': ['example.com']}),
#     MatchData("www.foo.dev" -> {'url': ['foo.dev']})]

store = RegexStore()
store.define('greeting', r'hello (?P<name>\w+)')
print(store.search('greeting', 'hello world'))  # -> name: world

Caches

Choose a cache by its storage pattern: bounded memory, nested levels, memory over disk, or pickle-backed persistence with expiry. The simplest case is a Cache. If you use PickleCache, load only data you trust—unpickling can execute code.

from my import Cache

cache = Cache(maxsize=256)
cache['answer'] = 42
cache['answer']  # -> 42

Interfaces

env snapshots environment variables when it first loads; fs provides a named path registry. Set demonstration variables before importing env (or use a fresh process if you've already loaded it). GoogleSheet adds spreadsheet access through the optional google extra.

import os
os.environ['DEMO_FLAG'] = 'true'

from my import env

env.get('DEMO_FLAG')   # -> 'true'
env.flag('DEMO_FLAG')  # -> 1 (0 when unset)

File formats

Markdown parses a document into a hierarchy of sections while respecting fenced code. You can walk the nodes, edit them, and render the result.

from my import Markdown

root = Markdown.parse('# Title\n\nIntro prose\n\n## Section A\n\nBody\n')[0]
[str(node).splitlines()[0] for node in root.walk()]  # -> ['# Title', '## Section A']

Optional integrations

Install extras only for the integrations you use: uv pip install "my-basis[metrics]" or python -m pip install "my-basis[metrics]", for example. In a uv-managed project, the equivalent dependency declaration is uv add "my-basis[metrics]".

Extra Adds
metrics Logfire/OpenTelemetry logging, counters, and instrumentation helpers through MetricUtils
google GoogleSheet access, OAuth support, and pandas DataFrame conversion
myst MyST syntax support in Markdown.render()'s formatting pass
terminal The pyratatui-backed examples under my/scripts/tuitorii/
aiohttp An HTTP-client convenience dependency; it does not unlock a separate API by itself

Why this library

Its breadth is somewhat unusual: any given application will probably use a small subset of the contents, so it shines where dependency purity isn't paramount — personal projects, local dev scripts, offline data processing, prototypes, and the project you're working on right now are the ideal usecases. As a rough sense of scale: a bare pip install my-basis pulls a couple dozen distributions (on the order of ~80 MB unpacked), and turning on every optional extra can push a full environment past ~290 MB because of heavy common dependencies like pandas, numpy, and various pieces of rubble amongst the ruins Google's Python SDK ecosystem. I do still kinda recommend that for personal scripts/admin/env/dev projects, where having the ability to easily work with google sheets, cast types, or performantly write all kinds of filetypes is worth more than some disk space.

The 1.0 release has been cut, beyond which I intend to enforce strict semver; don't expect breaking changes any time in the foreseeable future. If you're like me (i.e. have ADHD?), this library will spark the most joy when you are vaguely aware of its contents and know it's at your fingertips at any time while coding; not only can it save you a bunch of time writing functions, but the prospect of attempting functions with it in hand is so much more approachable that a lot more ends up getting done.

If that makes sense? I guess I'm really trying to sell you the promise of bolder, quicker software engineering.

Refactor an existing repository

The package includes a read-only source scanner and the adopt-my-basis agent skill. From a Python repository you want to assess:

uvx --from my-basis my-basis-adopt skill path
uvx --from my-basis my-basis-adopt skill export .agents/skills/adopt-my-basis
uvx --from my-basis my-basis-adopt prepare .

Give the resulting intake.json path to your agent. The scanner inventories files, dependencies, Python compatibility, candidate checks, and regex structure without importing the target package or editing its source; prepare writes its intake artifacts. The agent can then assess a proposal and produce a MyST, HTML, or Typst/PDF report. A justified decline or no-op is a valid result.

skill path locates the packaged instructions; skill export copies them when your agent needs a local catalogue entry. See the full workflow and RegexStore adoption guide.

Documentation and development

The hosted documentation covers the package API; its sources are in docs/. From a checkout, install the development dependencies and build it with:

task sync
task docs

Use the test guide for the suite and its conventions. Python 3.13 is the current minimum; the source uses modern typing syntax throughout. Pydantic is a core dependency even when your own code does not use Pydantic models. The separate Typst package has its own installation path and is not part of the Python wheel.

GitLab is the development forge; the GitHub repository is a read-only source mirror. Report issues and propose changes at the GitLab project.

Contributing

The project was built over the course of 2025 for its author's own use, so it's definitely opinionated — influenced by a weathered respect for polymorphism, an addiction to ergonomic code in the Don-Norman sense, and a reliance on symbolic, deterministic devtools (heavy typing, even at runtime). If any of that resonates: get in touch, or open an issue or merge request on GitLab.

Licensed under MPL-2.0.

Metadata

Release files for my-basis 1.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for my-basis 1.2.2
File Size Uploaded
my_basis-1.2.2.tar.gz 331.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for my-basis 1.2.2
File Interpreter ABI Platform
my_basis-1.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 703.7 kB

Release files / my_basis-1.2.2.tar.gz

Download URL my_basis-1.2.2.tar.gz
Size 331.1 kB
Tags Source
SHA-256 checksum
How to use checksums
31da990b4e90e90a30308c7d3274f133ae664812c4b7e2bcfcd619e0d3b411d5
BLAKE2b-256 checksum
How to use checksums
ad34bcb57f683792e58e4d1288789bc511935eb0a2cd6f3770c273b011c6aaf3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / my_basis-1.2.2-py3-none-any.whl

Download URL my_basis-1.2.2-py3-none-any.whl
Size 372.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
114293d4c63e119436095c7119edd370fc45bc23ca88b16140537160af2a3158
BLAKE2b-256 checksum
How to use checksums
3fc15a0fac3272c50ed056a85bbd4de23dfc2367d0cf1e08c728a0852274b36c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

1.2.2 This release

2 release files

1.2.1

2 release files

1.0.0

2 release files

0.8.4

2 release files

0.8.3

2 release files

0.8.2

2 release files

0.8.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page