pam-python 0.2.16__py3-none-any.whl → 0.2.17__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 CHANGED
@@ -1,3 +1,3 @@
1
1
  """PAM Data Plugin framework."""
2
2
 
3
- __version__ = "0.2.16"
3
+ __version__ = "0.2.17"
@@ -71,21 +71,34 @@ class DataInputV2Dataset:
71
71
  for part in self.parts:
72
72
  yield from part.iter_csv_rows()
73
73
 
74
- def scan_polars(self) -> Any:
75
- """Return one lazy frame across all ordered CSV or Parquet parts."""
74
+ def scan_polars(self, empty_schema: dict[str, Any] | None = None) -> Any:
75
+ """Return one lazy frame across all ordered CSV or Parquet parts.
76
+
77
+ PAM represents a valid dataset with no rows as ``row_count=0`` and no
78
+ physical parts. In that case the plugin may provide its domain schema
79
+ so downstream computation can handle the empty input normally.
80
+ """
76
81
  pl = _import_polars()
77
82
  if not self.parts:
78
- return pl.LazyFrame(schema={"id": pl.String})
83
+ schema = {"id": pl.String} if empty_schema is None else empty_schema
84
+ return pl.LazyFrame(schema=schema)
79
85
  scans = [part.scan_polars() for part in self.parts]
80
86
  if len(scans) == 1:
81
87
  return scans[0]
82
88
  return pl.concat(scans, how="diagonal_relaxed")
83
89
 
84
- def read_pandas(self) -> Any:
85
- """Materialize and concatenate all verified parts using their metadata."""
90
+ def read_pandas(self, empty_dtypes: dict[str, Any] | None = None) -> Any:
91
+ """Materialize and concatenate all verified parts using their metadata.
92
+
93
+ ``empty_dtypes`` is used only for a declared empty dataset, allowing
94
+ the plugin to retain its domain columns without fabricating data rows.
95
+ """
86
96
  pd = _import_pandas()
87
97
  if not self.parts:
88
- return pd.DataFrame({"id": pd.Series(dtype="string")})
98
+ dtypes = {"id": "string"} if empty_dtypes is None else empty_dtypes
99
+ return pd.DataFrame(
100
+ {name: pd.Series(dtype=dtype) for name, dtype in dtypes.items()}
101
+ )
89
102
  frames = [part.read_pandas() for part in self.parts]
90
103
  if len(frames) == 1:
91
104
  return frames[0]
@@ -234,6 +234,11 @@ result = calculate(population, profile_frame, purchase_frame).collect()
234
234
 
235
235
  `scan_polars()` returns one lazy frame across ordered CSV or Parquet parts and
236
236
  uses verified manifest format metadata. CSV-only code may use `iter_rows()`.
237
+ `row_count=0` with `parts=[]` is a valid empty dataset. The plugin decides the
238
+ business result for the page population; it must not treat the absence of event
239
+ rows as a transport error. If computation requires domain columns on an empty
240
+ frame, call `scan_polars(empty_schema=...)` or
241
+ `read_pandas(empty_dtypes=...)` with the plugin-owned schema.
237
242
  The external customer key is `id`. The population file is authoritative: in
238
243
  `contacts` mode, contacts with no event rows remain visible there. Use the
239
244
  opaque `data.next` cursor for the next `_request_data_v2(...)` call and stop when
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pam-python
3
- Version: 0.2.16
3
+ Version: 0.2.17
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
@@ -1,4 +1,4 @@
1
- pam/__init__.py,sha256=LoP4I-KBWrMM_QqNfs0fqmpUa5YCxEYux-CKeWqFkDw,57
1
+ pam/__init__.py,sha256=AtsNzG3gAoah-CeCi8BDhJh2elhS6x0PVxL4RwGvHWA,57
2
2
  pam/api.py,sha256=T1plaZ1EyGFz59EdP5ibnl7n0NxduhBPN-jGYe20rCU,7844
3
3
  pam/cli.py,sha256=Ip4kYNbZ49WAkcMN4SuNc2qXxDeagOzJwE7GSb-BYlE,13831
4
4
  pam/datetime_utils.py,sha256=sDFxNRR46FsO61p-EzhmIRS6ARnfMPRquKee_RcQ_3E,664
@@ -14,7 +14,7 @@ pam/temp_file_utils.py,sha256=noMyF4SZ17AWtZcRkZtNtdObRWzykAMxeFr-WkOEQi4,9450
14
14
  pam/tester_task.py,sha256=SKRIut-kksIVWSMwzquqi7MxrZyTO6x2ggqlnRsVJQ4,11967
15
15
  pam/utils.py,sha256=-pfnQ00Ib-IXvrMz4S5lTlO36PtSaJoQOhwXpwet8h4,1744
16
16
  pam/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- pam/models/data_input_v2.py,sha256=1SXNz4SZ_cqRXUMIglWWW41SbXcpRpwxvALHYDKRQZo,16834
17
+ pam/models/data_input_v2.py,sha256=0mkZHPjb0RLmc-v4W5Su8_bAw-3U5qL-YU1yF5Z-oCI,17536
18
18
  pam/models/request_command.py,sha256=6QBJyQfu75bMfhqBUILE1chvhjRdZ8WHWiBbX3k8K5s,14211
19
19
  pam/models/sqlite_download.py,sha256=7JMWwLp_5LSCMR5Ppk1RgbgcOaX_2LmRFrJiADAnIfs,678
20
20
  pam/reports/__init__.py,sha256=vdAzsUN0bmYPGjqKveg9HjNWe_MnBZj3b42TsDBE6_w,2368
@@ -51,7 +51,7 @@ pam/reports/transport.py,sha256=iDm63RQnPfhCJ1zFbr1uAVYHz3ondNfp2scz21JAnL8,2111
51
51
  pam/reports/treemap.py,sha256=W_VwxbiRMSvkNpY2z1HfbZtGKWXNr6FdbVdI0grVesw,4251
52
52
  pam/templates/buildcmd/pamb,sha256=58GCN59ysvHGNhPvTD3nkF4aLg-kM1WfWmH7CL3eQVo,530
53
53
  pam/templates/buildcmd/pamb-base.sh,sha256=Q0DkbeHtPx33PIjc68EeI7ZIwBOLlwcSmPhpxALXxVY,518
54
- pam/templates/init/AGENT.md,sha256=60AukAd1jyD21eKfvPL7H1UL05EUPHq9PRx7fklCXu0,26684
54
+ pam/templates/init/AGENT.md,sha256=yOtdr5aSsqPbjh7gWbyfoFYnCZ7opVSF9ol0LbONCTw,27030
55
55
  pam/templates/init/REPORTS-th.md,sha256=tKL8za7nxIG6jxBPzwqK00nfDdh8xe-lM34ueAU4WAQ,35752
56
56
  pam/templates/init/REPORTS.md,sha256=7yYbC2A7A92_NZloozJSkJaFL-bIddrrgcsSDpuIWaA,49561
57
57
  pam/templates/init/dockerignore.tmpl,sha256=Ht1eCgQLqalEwpUjih0FQavzhYJbT2jH-FP4btM3960,52
@@ -73,9 +73,9 @@ pam/templates/service/pandas/service_class.tmpl,sha256=qaq9tqRhxogWQlqi09dbX5vLu
73
73
  pam/templates/service/polars/functions.tmpl,sha256=7Qlwsd5Q1vdkOvXHtlltjb2oS-i7JuNKPor2iNDSsQg,701
74
74
  pam/templates/service/polars/service.test.tmpl,sha256=nC6VoauZMYy_UTTXxxergfWbXvUD_VWwpM7-7A3aKqE,6881
75
75
  pam/templates/service/polars/service_class.tmpl,sha256=jMGeruXduu0eBB7FPDEkZu8b4mSIO3uRt5TiDuNq5T4,3688
76
- pam_python-0.2.16.dist-info/licenses/LICENSE.txt,sha256=yeHD2-gzrkkET2ZkMe22WyUGpDjlwTrqA4POb0FoZi4,1138
77
- pam_python-0.2.16.dist-info/METADATA,sha256=yzpu7apkhIjvcHE5jsFr4VMSiYxsLRej8BB3Pdf2d0Y,10076
78
- pam_python-0.2.16.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
79
- pam_python-0.2.16.dist-info/entry_points.txt,sha256=xqYpsIqvNlO0j8elZc02bDwR-12dLK9FU2B1ACsLYxw,37
80
- pam_python-0.2.16.dist-info/top_level.txt,sha256=0EOjbyc3hQyzjhn6iyMgsEseqA66Xz0p27iBN7G7W1w,4
81
- pam_python-0.2.16.dist-info/RECORD,,
76
+ pam_python-0.2.17.dist-info/licenses/LICENSE.txt,sha256=yeHD2-gzrkkET2ZkMe22WyUGpDjlwTrqA4POb0FoZi4,1138
77
+ pam_python-0.2.17.dist-info/METADATA,sha256=oXW4FAnN_LT7C9qmONs8hJPOlbTm7MZP5n4Pcn7ml0w,10076
78
+ pam_python-0.2.17.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
79
+ pam_python-0.2.17.dist-info/entry_points.txt,sha256=xqYpsIqvNlO0j8elZc02bDwR-12dLK9FU2B1ACsLYxw,37
80
+ pam_python-0.2.17.dist-info/top_level.txt,sha256=0EOjbyc3hQyzjhn6iyMgsEseqA66Xz0p27iBN7G7W1w,4
81
+ pam_python-0.2.17.dist-info/RECORD,,