Python SDK for Soi Gia
Project description
soigia
soigia is a Python SDK built around four practical workspaces:
DataTablefor dataframe-style work with a friendlier APIPipeLinefor repeatable business workflowsORMfor model-driven business data with backend adaptersUIfor lightweight internal screens on top of Streamlit
Quick Index
This README focuses on those four areas only.
Install
pip install soigia
For local development:
pip install -e .
1. DataTable
DataTable is the main table abstraction in soigia. It keeps the pandas mental model, but adds a more opinionated, workflow-friendly API for cleaning, filtering, joining, validating, and exporting data.
Use DataTable when you want:
- a table object that behaves like a dataframe
- chainable query-style operations
- simple data loading helpers
- schema checks before a dataset moves to the next step
- snapshot and version helpers for auditability
Typical workflow
- Load rows from records, CSV, JSON, Excel, Parquet, Feather, pickle, SQL, or Google Sheets.
- Clean and normalize the data.
- Filter, sort, deduplicate, or join with another table.
- Validate the final shape and types.
- Export or snapshot the result.
Example
from soigia.datatable import DataTable
orders = DataTable.from_records(
[
{"order_id": 1001, "customer": "Alice", "amount": 120.5, "city": "Hanoi"},
{"order_id": 1002, "customer": "Bob", "amount": 88.0, "city": "Saigon"},
{"order_id": 1003, "customer": "Carol", "amount": 240.0, "city": "Danang"},
]
)
adults = orders.objects.filter(amount__gte=100).order_by("amount")
print(adults.to_rows())
Practical things you can do
DataTable.from_records(records)for raw Python dataDataTable.from_csv(path)for flat filesDataTable.from_json(path)for payloads and exportsDataTable.from_excel(path)for business spreadsheetsDataTable.from_parquet(path)for analytics datasetsDataTable.from_sql(...)for database-backed loadingdf.objects.filter(...)for query-like row selectiondf.objects.exclude(...)for inverse filteringdf.objects.order_by(...)for sortingdf.objects.distinct(...)for deduplicationdf.objects.group_by(...)for grouped summariesdf.join(...)and related helpers for relational workdf.validate_schema(...)for checks before releasedf.snapshot(...)anddf.auto_version(...)for versioned outputs
When to use it
DataTable is a good fit when:
- you need dataframe behavior, but want a stricter workflow layer
- you are passing data between cleaning steps and business logic
- you want tests to assert shape and content more clearly
- you need small, readable transformations instead of scattered pandas calls
DataTable reference
For the full API list and examples, see:
2. PipeLine
PipeLine is the workflow layer for business processing. It is designed for repeatable jobs where data comes in, gets normalized, goes through a few stages, and then writes out artifacts and summary files.
Use PipeLine when you want:
- a predictable execution order
- stage-based processing
- automatic output files
- rollback hooks for side effects
- config-driven behavior
- a shared model namespace for computed results
Mental model
load_data()brings data into memory.- Each stage mutates or enriches the working dataset.
self.datatableis the main working dataset.self._datastores extra data loaded from DB tables.self.envsgives fast SQLite table access for ad-hoc reads.self.modelstores computed results.self.configexposes YAML values.save_outputs()writes final artifacts.on_rollback(...)protects side effects when a stage fails.
Example
from soigia.pipeline import Pipeline
from soigia.datatable import DataTable
class SalesPipeline(Pipeline):
stages = ["clean", "enrich", "save", "summarize"]
def load_data(self):
return DataTable(
[
{"id": 1, "amount": 100.0},
{"id": 2, "amount": 250.0},
]
)
def clean(self):
self.datatable = self.datatable.dropna().reset_index(drop=True)
def enrich(self):
self.datatable["net_amount"] = self.datatable["amount"] * 0.98
def save(self):
self.datatable.save_to_csv("data/sales/clean_sales.csv")
self.push("sales", self.datatable, mode="replace")
def summarize(self):
self.model.total_rows = len(self.datatable)
self.model.total_amount = float(self.datatable["amount"].sum())
pipeline = SalesPipeline(name="sales")
result = pipeline.run()
print(result.success)
print(result.summary_path)
print(result.csv_path)
What a pipeline usually includes
- input loading from files, databases, or APIs
- normalization and cleaning
- business-specific enrichment
- summary or scoring logic
- CSV, SQLite, and Parquet outputs
- a Markdown summary for traceability
- log files for debugging and audit
Recommended structure
- keep the pipeline class small and stage-oriented
- put reusable config in
config.yaml - use
config.example.yamlas the checked-in template - use
pipeline.config.example.yamlas the pipeline runtime template - use
self.modelfor computed values that later stages need - keep rollback handlers focused on external effects, not dataframe-only work
Pipeline DB defaults
Pipeline creates a SQLite database automatically on first use, so subclasses can read and write without extra setup.
The main working attribute is self.datatable. Extra tables loaded from DB are cached in self._data.
self.datatable is a DataTable, so you can use helpers like save_to_csv(), save_to_parquet(), load_from_db(), and save_to_db() directly. For SQLite, connection_string is optional; if you omit it, Soi Gia uses the default local DB:
self.datatable.save_to_csv("data/output.csv")
self.datatable.save_to_parquet("data/output.parquet")
self.datatable.save_to_db("sales")
self.datatable = DataTable.load_from_db("select * from sales")
For quick reads, self.envs exposes table handles:
orders = self.envs.orders.filter(self.envs.orders.id > 1)
You can also use keyword lookups:
orders = self.envs.orders.filter(id__gt=1)
class DemoPipeline(Pipeline):
stages = ["seed", "sync", "reload"]
def load_data(self):
return DataTable([{"id": 1, "name": "alice"}])
def seed(self):
self.db.set("users", self.datatable)
def sync(self):
self.db.upsert_rows(
"users",
[{"id": 1, "name": "alice-updated"}, {"id": 2, "name": "bob"}],
)
def reload(self):
self.datatable = DataTable.load_from_db("select * from users")
Short aliases are also available:
self.push("users", self.datatable)
self.pull("users")
self.push_datatable("users", self.datatable, mode="upsert")
self.pull_datatable("users")
Default upsert keys can be configured per table:
db_upsert_keys:
users:
- id
orders:
- order_id
Pipeline reference
For the end-to-end guide, see:
3. ORM
ORM is the model-driven data layer in soigia. It keeps the class-based model style of Odoo and Django, while separating storage through adapters like memory, pandas, and SQLite.
Use ORM when you want:
- declarative models with fields
- query helpers like
filter(),exclude(),order_by(), andlimit() - record creation, updates, deletes, and browsing by id
- model inheritance and Odoo-style
_inherit - business methods on the model itself
- a backend-agnostic API that can switch storage engines
Mental model
- Define a model with
class MyModel(Model). - Declare fields directly on the class.
- Bind the model to an
Env. - Use
env["model.name"]orModel.objectsto query data. - Let the backend handle storage, while the model handles business behavior.
Example
from soigia.db import Env, MemoryBackend, Model, fields
class Customer(Model):
_name = "demo.customer"
name = fields.String(required=True)
env = Env(backend=MemoryBackend())
customer = env["demo.customer"].create({"name": "Alice"})
print(customer.id)
print(env["demo.customer"].search([("name", "=", "Alice")]).ids)
ORM reference
For the full guide and API list, see:
If you only need the API surface, start here:
4. UI
soigia.ui is a declarative Streamlit layer for internal tools. It is meant for dashboards, admin screens, review pages, and lightweight operational views.
Use UI when you want:
- a single-file screen definition
- simple page composition
- forms, metrics, tables, and filters
- a fast way to expose operational workflows
Mental model
- Define a page with
ui.page(). - Compose layout blocks with
ui.sidebar(),ui.columns(),ui.tabs(), andui.form(). - Render data with
ui.table()andui.metric(). - Add inputs with
ui.text_input(),ui.select(), andui.number_input(). - Run the app with
ui.run().
Example
from soigia.ui import ui
orders = [
{"id": 1, "customer": "Alice", "amount": 120.0, "status": "paid"},
{"id": 2, "customer": "Bob", "amount": 88.5, "status": "pending"},
{"id": 3, "customer": "Carol", "amount": 220.0, "status": "paid"},
]
@ui.page("Orders Dashboard")
def orders_page(ctx):
ui.markdown("Track orders, filter data, and prepare quick actions.")
with ui.sidebar():
keyword = ui.text_input("Search customer")
status = ui.select("Status", ["all", "paid", "pending"])
min_amount = ui.number_input("Minimum amount", value=0)
filtered = [
row
for row in orders
if keyword.value.lower() in row["customer"].lower()
and (status.value == "all" or row["status"] == status.value)
and row["amount"] >= min_amount.value
]
ui.metric("Orders", len(filtered))
ui.metric("Total amount", sum(row["amount"] for row in filtered))
ui.table(filtered)
ui.run()
Common building blocks
ui.page()for page registrationui.sidebar()for filters and navigationui.columns()for split layoutsui.tabs()for grouped viewsui.form()for update flowsui.table()for records and resultsui.metric()for KPI cardsui.text(),ui.markdown(), and input widgets for interaction
When to use it
UI works best for:
- internal admin dashboards
- review screens for ops or business teams
- quick forms and compact workflows
- tools that should stay simple enough to maintain in one file
UI reference
For the end-to-end UI guide, see:
Quick Summary
- Use
DataTablewhen the problem is mostly table manipulation. - Use
PipeLinewhen the problem is a staged business workflow. - Use
UIwhen the problem is an internal screen or dashboard.
Need More Detail?
The focused docs live here:
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 soigia-0.1.12.tar.gz.
File metadata
- Download URL: soigia-0.1.12.tar.gz
- Upload date:
- Size: 131.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9aeaa4f39aaf9109c593dffaf18aa112b0d87c6a25fb9caea073b0314ee0ae93
|
|
| MD5 |
f5e1f55a922131908527ad75b9ac1c16
|
|
| BLAKE2b-256 |
199a39759338ef199818c3aa1a8c94d17c8c127010498d755b2882a6390f51d9
|
File details
Details for the file soigia-0.1.12-py3-none-any.whl.
File metadata
- Download URL: soigia-0.1.12-py3-none-any.whl
- Upload date:
- Size: 103.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
20f7743eeadd5278d0b6530329b9660e73ccf08667ca03a5284dfac8743325ac
|
|
| MD5 |
a852d7f48fa8646c76ae2e151f552893
|
|
| BLAKE2b-256 |
97f22c4d206c3e62aa56d12b35c3eefbbfb508c268145ac91703fd9e372df317
|