pam-python 0.2.7__py3-none-any.whl → 0.2.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pam/__init__.py +1 -1
- pam/cli.py +5 -0
- pam/models/data_input_v2.py +10 -4
- pam/templates/init/AGENT.md +8 -0
- pam/templates/project/uv/Dockerfile +1 -1
- {pam_python-0.2.7.dist-info → pam_python-0.2.9.dist-info}/METADATA +4 -4
- {pam_python-0.2.7.dist-info → pam_python-0.2.9.dist-info}/RECORD +11 -11
- {pam_python-0.2.7.dist-info → pam_python-0.2.9.dist-info}/WHEEL +0 -0
- {pam_python-0.2.7.dist-info → pam_python-0.2.9.dist-info}/entry_points.txt +0 -0
- {pam_python-0.2.7.dist-info → pam_python-0.2.9.dist-info}/licenses/LICENSE.txt +0 -0
- {pam_python-0.2.7.dist-info → pam_python-0.2.9.dist-info}/top_level.txt +0 -0
pam/__init__.py
CHANGED
pam/cli.py
CHANGED
|
@@ -59,6 +59,8 @@ ENGINE_DEPENDENCIES = {
|
|
|
59
59
|
"pandas": ["pandas>=2.2.3", "pyarrow>=19.0.1"],
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
UV_RUNTIME_DEPENDENCIES = ["Flask>=3.0.2", "gunicorn>=23.0.0"]
|
|
63
|
+
|
|
62
64
|
|
|
63
65
|
def main(argv=None):
|
|
64
66
|
args = list(sys.argv[1:] if argv is None else argv)
|
|
@@ -238,6 +240,9 @@ def init_project(package_manager: str | None = None):
|
|
|
238
240
|
if not _prompt_overwrite_if_needed(destination, templates):
|
|
239
241
|
return
|
|
240
242
|
|
|
243
|
+
if preinitialized_uv:
|
|
244
|
+
_run_uv(["add", *UV_RUNTIME_DEPENDENCIES], destination)
|
|
245
|
+
|
|
241
246
|
with tempfile.TemporaryDirectory(prefix=".pam-init-", dir=destination) as temp_dir:
|
|
242
247
|
staging = Path(temp_dir)
|
|
243
248
|
for src, dest in templates.items():
|
pam/models/data_input_v2.py
CHANGED
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import csv
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from datetime import datetime
|
|
5
|
+
from datetime import datetime, timezone
|
|
6
6
|
from hashlib import sha256
|
|
7
7
|
import json
|
|
8
8
|
from pathlib import Path
|
|
@@ -15,6 +15,7 @@ V2_PROTOCOL_VERSION = "data-plugin-input/v2"
|
|
|
15
15
|
V2_MANIFEST_FILE_NAME = "manifest.json"
|
|
16
16
|
V2_MAX_DATASETS = 5
|
|
17
17
|
V2_POPULATION_MODES = {"contacts", "event_any", "event_all"}
|
|
18
|
+
PAM_TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S"
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
@dataclass(frozen=True)
|
|
@@ -364,6 +365,11 @@ def _required_optional_string(source: dict[str, Any], key: str) -> str:
|
|
|
364
365
|
return value
|
|
365
366
|
|
|
366
367
|
|
|
368
|
+
def _parse_pam_timestamp(value: str) -> datetime:
|
|
369
|
+
"""Parse PAM's suffix-free timestamp as UTC+0 without shifting it."""
|
|
370
|
+
return datetime.strptime(value, PAM_TIMESTAMP_FORMAT).replace(tzinfo=timezone.utc)
|
|
371
|
+
|
|
372
|
+
|
|
367
373
|
def _parse_time_window(raw_time_window: Any) -> DataInputV2TimeWindow | None:
|
|
368
374
|
if raw_time_window is None:
|
|
369
375
|
return None
|
|
@@ -374,11 +380,11 @@ def _parse_time_window(raw_time_window: Any) -> DataInputV2TimeWindow | None:
|
|
|
374
380
|
start_inclusive = _required_bool(raw_time_window, "start_inclusive")
|
|
375
381
|
end_inclusive = _required_bool(raw_time_window, "end_inclusive")
|
|
376
382
|
try:
|
|
377
|
-
start_time =
|
|
378
|
-
end_time =
|
|
383
|
+
start_time = _parse_pam_timestamp(start)
|
|
384
|
+
end_time = _parse_pam_timestamp(end)
|
|
379
385
|
except ValueError as error:
|
|
380
386
|
raise ValueError("V2 manifest time_window timestamps are invalid") from error
|
|
381
|
-
if start_time
|
|
387
|
+
if start_time >= end_time:
|
|
382
388
|
raise ValueError("V2 manifest time_window order is invalid")
|
|
383
389
|
if not start_inclusive or end_inclusive:
|
|
384
390
|
raise ValueError("V2 manifest time_window must be half-open")
|
pam/templates/init/AGENT.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# AGENT
|
|
2
2
|
|
|
3
|
+
## PAM date and time contract
|
|
4
|
+
|
|
5
|
+
PAM timestamps are UTC+0 strings in the exact format `%Y-%m-%d %H:%M:%S`, for
|
|
6
|
+
example `2026-03-31 02:37:44`. The timezone suffix is intentionally omitted.
|
|
7
|
+
Interpret these values as UTC without shifting the clock value. Do not emit or
|
|
8
|
+
expect RFC3339, ISO-8601, `T`, `Z`, or explicit timezone suffixes in internal PAM
|
|
9
|
+
contracts.
|
|
10
|
+
|
|
3
11
|
This document defines the **data plugin runtime specification** and execution contract so developers and agents can create services and understand runtime behavior inside the CDP environment.
|
|
4
12
|
|
|
5
13
|
This is not a tutorial.
|
|
@@ -17,4 +17,4 @@ RUN mkdir -p "$DATA_FOLDER"
|
|
|
17
17
|
EXPOSE 8000
|
|
18
18
|
|
|
19
19
|
# Keep one worker: service lifecycle state is local to the process.
|
|
20
|
-
CMD ["gunicorn", "-w", "1", "-b", "0.0.0.0:8000", "main:app"]
|
|
20
|
+
CMD ["uv", "run", "--no-sync", "gunicorn", "-w", "1", "-b", "0.0.0.0:8000", "main:app"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pam-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: Pam Python Library
|
|
5
5
|
Author-email: Narongrit Kanhanoi <narongrit@pams.ai>
|
|
6
6
|
Project-URL: Homepage, https://github.com/heart/pam-python
|
|
@@ -70,9 +70,9 @@ uv add pam-python
|
|
|
70
70
|
uv run pam init
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
`pam init` recognizes a fresh uv project, keeps its uv configuration,
|
|
74
|
-
|
|
75
|
-
been edited.
|
|
73
|
+
`pam init` recognizes a fresh uv project, keeps its uv configuration, adds the
|
|
74
|
+
Flask and Gunicorn runtime dependencies, and adds the PAM scaffold. It refuses
|
|
75
|
+
projects whose generated source files have already been edited.
|
|
76
76
|
|
|
77
77
|
Pip remains supported for new projects that do not use uv:
|
|
78
78
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
pam/__init__.py,sha256=
|
|
1
|
+
pam/__init__.py,sha256=WEZJbeetmhwTurBIMc09FICFV6I2Hl6A8nMFuH6CaXI,56
|
|
2
2
|
pam/api.py,sha256=T1plaZ1EyGFz59EdP5ibnl7n0NxduhBPN-jGYe20rCU,7844
|
|
3
|
-
pam/cli.py,sha256=
|
|
3
|
+
pam/cli.py,sha256=fCtqVfMjmxNuJWzpwc51zHdjepyW10GT38u27QdUq3o,13788
|
|
4
4
|
pam/interface_task_manager.py,sha256=V6WMifh5t0tIq9m46eH0RlXDmhbRNPc7XVs6R2rOejE,1985
|
|
5
5
|
pam/logger.py,sha256=JYPfIpaQZy6QrfVKrzEMrxOgTzWIEhoegvIZgHTGWoc,3021
|
|
6
6
|
pam/request_file_format.py,sha256=fSRlJagbvVGqdIEqhINSeqBNUTNQdm8GL5JfqgX9bxU,317
|
|
@@ -13,7 +13,7 @@ pam/temp_file_utils.py,sha256=noMyF4SZ17AWtZcRkZtNtdObRWzykAMxeFr-WkOEQi4,9450
|
|
|
13
13
|
pam/tester_task.py,sha256=6hiCvNSWvx43tLGKSbiAyNTvlcp1E0QaJ_DH4LMUDZg,11156
|
|
14
14
|
pam/utils.py,sha256=-pfnQ00Ib-IXvrMz4S5lTlO36PtSaJoQOhwXpwet8h4,1744
|
|
15
15
|
pam/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
pam/models/data_input_v2.py,sha256=
|
|
16
|
+
pam/models/data_input_v2.py,sha256=Ons3SqxMOcBQVtdjD9MgaZ8C_-2zhHhKG8A81RjQi_A,16614
|
|
17
17
|
pam/models/request_command.py,sha256=6QBJyQfu75bMfhqBUILE1chvhjRdZ8WHWiBbX3k8K5s,14211
|
|
18
18
|
pam/models/sqlite_download.py,sha256=7JMWwLp_5LSCMR5Ppk1RgbgcOaX_2LmRFrJiADAnIfs,678
|
|
19
19
|
pam/reports/__init__.py,sha256=g6F1r52vyAOg9nGB2sTyKSCCla7E1IPwh7epHmaSBoI,2302
|
|
@@ -49,7 +49,7 @@ pam/reports/transport.py,sha256=t3oEVptS9msnNafia1G8vmTUCdhxvV5L2-0AY-8SKFk,2062
|
|
|
49
49
|
pam/reports/treemap.py,sha256=W_VwxbiRMSvkNpY2z1HfbZtGKWXNr6FdbVdI0grVesw,4251
|
|
50
50
|
pam/templates/buildcmd/pamb,sha256=58GCN59ysvHGNhPvTD3nkF4aLg-kM1WfWmH7CL3eQVo,530
|
|
51
51
|
pam/templates/buildcmd/pamb-base.sh,sha256=Q0DkbeHtPx33PIjc68EeI7ZIwBOLlwcSmPhpxALXxVY,518
|
|
52
|
-
pam/templates/init/AGENT.md,sha256=
|
|
52
|
+
pam/templates/init/AGENT.md,sha256=VxwD-aPfwcUAaZSt7JnhKpr7rJbuaCZ4KkJYrbOePNE,20952
|
|
53
53
|
pam/templates/init/REPORTS.md,sha256=rg9oi0_xDYr0BZBluJh0vPF8lSx7mCRFpDCpUgNl68A,42851
|
|
54
54
|
pam/templates/init/dockerignore.tmpl,sha256=Ht1eCgQLqalEwpUjih0FQavzhYJbT2jH-FP4btM3960,52
|
|
55
55
|
pam/templates/init/gitignore.tmpl,sha256=xi8KBrPKSCPiuwtKP8xsF4shQbYowh1_LGW3fKbl09M,917
|
|
@@ -60,7 +60,7 @@ pam/templates/init/run_unit_test.ps1,sha256=4O9fciyt04j1XjwOJELPwGTv0XOd2CmZ1e7u
|
|
|
60
60
|
pam/templates/init/run_unit_test.sh,sha256=4yVDKgI3bLK6CujRViF9UBOdNGoLFwcluZvmpYyi6kg,161
|
|
61
61
|
pam/templates/project/pip/Dockerfile,sha256=VSfnPGRwuq-WoJ0ddfdnteJJM2eUlTJPdhTQfYhFWMw,382
|
|
62
62
|
pam/templates/project/pip/requirements.txt,sha256=2hwbTfQsI_AEPWdsym2q0y5uTyO6Cekth_k2RZxYGx8,56
|
|
63
|
-
pam/templates/project/uv/Dockerfile,sha256=
|
|
63
|
+
pam/templates/project/uv/Dockerfile,sha256=MTeMf2g8-gShxK7s4Iw5jvNN8uOklm8NVnK7jkS7T8M,466
|
|
64
64
|
pam/templates/project/uv/pyproject.toml,sha256=30a2hJn6oN1AGvmgEBdxLETOBlHY8L-IIpIy8637yJM,208
|
|
65
65
|
pam/templates/project/uv/python-version,sha256=e1X45ntWI8S-8_ppEojalDfXnTq6FW3kjUgdsyrH0W0,5
|
|
66
66
|
pam/templates/service/common/service.yaml,sha256=ceyFswXjTh07vB4hrJEu7pj3mjlq3NPD4GPYTmvGwmE,44
|
|
@@ -70,9 +70,9 @@ pam/templates/service/pandas/service_class.tmpl,sha256=qaq9tqRhxogWQlqi09dbX5vLu
|
|
|
70
70
|
pam/templates/service/polars/functions.tmpl,sha256=7Qlwsd5Q1vdkOvXHtlltjb2oS-i7JuNKPor2iNDSsQg,701
|
|
71
71
|
pam/templates/service/polars/service.test.tmpl,sha256=nC6VoauZMYy_UTTXxxergfWbXvUD_VWwpM7-7A3aKqE,6881
|
|
72
72
|
pam/templates/service/polars/service_class.tmpl,sha256=jMGeruXduu0eBB7FPDEkZu8b4mSIO3uRt5TiDuNq5T4,3688
|
|
73
|
-
pam_python-0.2.
|
|
74
|
-
pam_python-0.2.
|
|
75
|
-
pam_python-0.2.
|
|
76
|
-
pam_python-0.2.
|
|
77
|
-
pam_python-0.2.
|
|
78
|
-
pam_python-0.2.
|
|
73
|
+
pam_python-0.2.9.dist-info/licenses/LICENSE.txt,sha256=yeHD2-gzrkkET2ZkMe22WyUGpDjlwTrqA4POb0FoZi4,1138
|
|
74
|
+
pam_python-0.2.9.dist-info/METADATA,sha256=Blclje6yaOK_mrU0q8jfgnw9rK8Altzgmm4qtmTXwLw,10024
|
|
75
|
+
pam_python-0.2.9.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
76
|
+
pam_python-0.2.9.dist-info/entry_points.txt,sha256=xqYpsIqvNlO0j8elZc02bDwR-12dLK9FU2B1ACsLYxw,37
|
|
77
|
+
pam_python-0.2.9.dist-info/top_level.txt,sha256=0EOjbyc3hQyzjhn6iyMgsEseqA66Xz0p27iBN7G7W1w,4
|
|
78
|
+
pam_python-0.2.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|