import datetime as dt, json, sys
import requests, pandas as pd
from tenacity import retry, stop_after_attempt, wait_exponential
from dotenv import load_dotenv
import helpers
load_dotenv()
CITIES = {"Buenos Aires": (-34.61, -58.38), "Santiago": (-33.45, -70.67), "Lima": (-12.05, -77.04), "Bogotá": (4.71, -74.07), "Madrid": (40.42, -3.70)}
@retry(stop=stop_after_attempt(4), wait=wait_exponential(min=1, max=10))
def fetch(lat, lon, start, end):
r = requests.get("https://archive-api.open-meteo.com/v1/archive", params={"latitude": lat, "longitude": lon, "start_date": start,
"end_date": end, "daily": "temperature_2m_max,precipitation_sum", "timezone": "auto"}, timeout=30)
r.raise_for_status()
return r.json()["daily"]
end = dt.date(2026, 10, 10); start = end - dt.timedelta(days=29)
rows = []
for city, (lat, lon) in CITIES.items():
d = fetch(lat, lon, start.isoformat(), end.isoformat())
rows += [{"city": city, "date": f, "tmax": t, "rain": p} for f, t, p in zip(d["time"], d["temperature_2m_max"], d["precipitation_sum"])]
df = pd.DataFrame(rows)
df.to_parquet(sys.argv[1] + "/weather_python.parquet", index=False)
summary = df.groupby("city").agg(tmax_mean=("tmax", "mean"), rain_total=("rain", "sum")).reset_index()
summary["tmax_mean"] = summary["tmax_mean"].map(helpers.round1)
summary.to_csv(sys.argv[1] + "/summary_python.csv", index=False)
print(summary.to_string(index=False))
print("what the imported module can do:", json.dumps(helpers.capabilities(), ensure_ascii=False))← All cases
Case 3 · Measured on 2026-10-16 · Synsema 0.6.44 · same data, same model on both sides
What a dependency can do
Your ETL imports a helper module. What can that module do with your program's permissions?
14 vs 0
third-party packages in the same 29-line ETL
The same ETL: 14 packages and 169 MB of other people's code in Python, zero in Synsema.
The problem
Poisoned packages on npm and PyPI that steal tokens and CI secrets are now a monthly event.
In Python or Node, any imported module runs with every permission the process has. A small ETL pulls in a dozen packages nobody reads.
What we built
- A real ETL, written twice in 29 lines: daily weather for five cities from Open-Meteo to Parquet plus a CSV summary. Both produce the same numbers.
- Each version imports a helper module that stands for any dependency. It formats numbers and also reports what it could do: read .env, open a connection to an undeclared host.
- Dependency count, size and known vulnerabilities (pip-audit) on the Python side; synsema code caps and synsema build on the Synsema side.
Results
| Python | Synsema | |
|---|---|---|
| Packages, direct and transitive | ✗14 | ✓0 |
| Third-party code on disk | ✗169 MB · 2,156 .py files · 99 native binaries | ✓none |
| Known vulnerabilities (pip-audit) | ✗3 advisories in requests, pyarrow, python-dotenv | ✓nothing to audit |
| The imported module can read .env | ✗yes | ✓no |
| The imported module can reach an undeclared host | ✗yes | ✓no |
| Know what it touches before running | ✗no, read all 14 packages | ✓yes, code caps flags MISSING file.read(".env") and net("example.com") |
| Distribution | ·interpreter + venv + 14 packages | ✓one 45.9 MB binary |
| Run time | ·6.8 to 9.3 s (1.3 s just importing; cities fetched in sequence) | ·1.4 s (cities fetched in parallel) |
The code, side by side
The usual way
Synsema
use "./helpers.syn" as helpers
require net("archive-api.open-meteo.com")
require file.write("./cases/03-supply-chain/results/*")
let CITIES be [{"c": "Buenos Aires", "lat": -34.61, "lon": -58.38}, {"c": "Santiago", "lat": -33.45, "lon": -70.67},
{"c": "Lima", "lat": -12.05, "lon": -77.04}, {"c": "Bogotá", "lat": 4.71, "lon": -74.07}, {"c": "Madrid", "lat": 40.42, "lon": -3.70}]
let END be date("2026-10-10")
let START be END - duration(days = 29)
task fetch(x)
let n be 0
while n < 4
let r be http_get("https://archive-api.open-meteo.com/v1/archive", {}, {"latitude": text(x.lat), "longitude": text(x.lon),
"start_date": text(START), "end_date": text(END), "daily": "temperature_2m_max,precipitation_sum", "timezone": "auto"}, 30)
when r.ok
let d be (json of r).daily
give apply((e) => {"city": x.c, "date": e.item, "tmax": d.temperature_2m_max[e.index], "rain": d.precipitation_sum[e.index]}, enumerate(d.time))
set n to n + 1
raise(`could not fetch {x.c}`)
let rows be flatten(parallel_map(fetch, CITIES, 5))
write_file("./cases/03-supply-chain/results/weather_synsema.parquet", parquet_write(rows))
let summary be apply((r) => merge(r, {"tmax_mean": helpers.round1(r.tmax_mean)}), summarize(rows, "city", {"tmax_mean": mean_of("tmax"), "rain_total": sum_of("rain")}))
write_file("./cases/03-supply-chain/results/summary_synsema.csv", csv_encode(summary))
each r in summary
print(`{r.city}: {r.tmax_mean} °C, {round_to(r.rain_total, 1)} mm`)
print(`what the imported module can do: {helpers.capabilities()}`)Why Synsema
- There is no package manager and no third-party code. Modules are local files.
- A module only gets the capabilities the entry file declared. If the ETL declares one host, no module can talk to another.
- synsema code caps is a static review: it shows what each task needs and what is missing, before anything runs.
What it does not solve
- The pip-audit advisories go away by upgrading, which is exactly the continuous upkeep Python asks for.
- A local Synsema module inherits the program's capabilities. If the program declares too much, the module gets it too.
- The run-time gap is mostly sequential versus parallel downloads, not the language.
Reproduce it
git clone https://github.com/synsema/why-synsema && cd why-synsema # cases/03-supply-chain synsema run cases/03-supply-chain/synsema/etl.syn synsema code caps cases/03-supply-chain/synsema/etl.syn uv run --with-requirements cases/03-supply-chain/python/requirements.txt python cases/03-supply-chain/python/etl.py cases/03-supply-chain/results uvx pip-audit -r cases/03-supply-chain/python/requirements.txt
github.com/synsema/why-synsema/tree/main/cases/03-supply-chain