pam-python 0.2.6__tar.gz → 0.2.7__tar.gz

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.
Files changed (113) hide show
  1. {pam_python-0.2.6 → pam_python-0.2.7}/PKG-INFO +1 -1
  2. {pam_python-0.2.6 → pam_python-0.2.7}/pam/__init__.py +1 -1
  3. {pam_python-0.2.6 → pam_python-0.2.7}/pam/cli.py +24 -49
  4. {pam_python-0.2.6 → pam_python-0.2.7}/pam_python.egg-info/PKG-INFO +1 -1
  5. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_cli_templates.py +11 -5
  6. {pam_python-0.2.6 → pam_python-0.2.7}/LICENSE.txt +0 -0
  7. {pam_python-0.2.6 → pam_python-0.2.7}/README.md +0 -0
  8. {pam_python-0.2.6 → pam_python-0.2.7}/pam/api.py +0 -0
  9. {pam_python-0.2.6 → pam_python-0.2.7}/pam/interface_task_manager.py +0 -0
  10. {pam_python-0.2.6 → pam_python-0.2.7}/pam/logger.py +0 -0
  11. {pam_python-0.2.6 → pam_python-0.2.7}/pam/models/__init__.py +0 -0
  12. {pam_python-0.2.6 → pam_python-0.2.7}/pam/models/data_input_v2.py +0 -0
  13. {pam_python-0.2.6 → pam_python-0.2.7}/pam/models/request_command.py +0 -0
  14. {pam_python-0.2.6 → pam_python-0.2.7}/pam/models/sqlite_download.py +0 -0
  15. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/__init__.py +0 -0
  16. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/area.py +0 -0
  17. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/axis.py +0 -0
  18. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/bar.py +0 -0
  19. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/box_plot.py +0 -0
  20. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/bubble.py +0 -0
  21. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/candlestick.py +0 -0
  22. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/collection.py +0 -0
  23. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/definition.py +0 -0
  24. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/donut.py +0 -0
  25. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/errors.py +0 -0
  26. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/fields.py +0 -0
  27. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/heatmap.py +0 -0
  28. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/line.py +0 -0
  29. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/manager.py +0 -0
  30. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/metric.py +0 -0
  31. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/pie.py +0 -0
  32. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/polar_area.py +0 -0
  33. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/radar.py +0 -0
  34. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/radial_bar.py +0 -0
  35. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/range_area.py +0 -0
  36. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/range_bar.py +0 -0
  37. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/range_transform.py +0 -0
  38. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/record.py +0 -0
  39. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/report.py +0 -0
  40. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/scatter.py +0 -0
  41. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/schema.py +0 -0
  42. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/store.py +0 -0
  43. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/table.py +0 -0
  44. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/transport.py +0 -0
  45. {pam_python-0.2.6 → pam_python-0.2.7}/pam/reports/treemap.py +0 -0
  46. {pam_python-0.2.6 → pam_python-0.2.7}/pam/request_file_format.py +0 -0
  47. {pam_python-0.2.6 → pam_python-0.2.7}/pam/result_batch_uploader.py +0 -0
  48. {pam_python-0.2.6 → pam_python-0.2.7}/pam/server.py +0 -0
  49. {pam_python-0.2.6 → pam_python-0.2.7}/pam/service.py +0 -0
  50. {pam_python-0.2.6 → pam_python-0.2.7}/pam/sqlite.py +0 -0
  51. {pam_python-0.2.6 → pam_python-0.2.7}/pam/task_manager.py +0 -0
  52. {pam_python-0.2.6 → pam_python-0.2.7}/pam/temp_file_utils.py +0 -0
  53. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/buildcmd/pamb +0 -0
  54. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/buildcmd/pamb-base.sh +0 -0
  55. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/init/AGENT.md +0 -0
  56. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/init/REPORTS.md +0 -0
  57. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/init/dockerignore.tmpl +0 -0
  58. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/init/gitignore.tmpl +0 -0
  59. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/init/main.tmpl +0 -0
  60. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/init/pylintrc.tmpl +0 -0
  61. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/init/run_unit_test.bat +0 -0
  62. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/init/run_unit_test.ps1 +0 -0
  63. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/init/run_unit_test.sh +0 -0
  64. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/project/pip/Dockerfile +0 -0
  65. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/project/pip/requirements.txt +0 -0
  66. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/project/uv/Dockerfile +0 -0
  67. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/project/uv/pyproject.toml +0 -0
  68. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/project/uv/python-version +0 -0
  69. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/service/common/service.yaml +0 -0
  70. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/service/pandas/functions.tmpl +0 -0
  71. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/service/pandas/service.test.tmpl +0 -0
  72. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/service/pandas/service_class.tmpl +0 -0
  73. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/service/polars/functions.tmpl +0 -0
  74. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/service/polars/service.test.tmpl +0 -0
  75. {pam_python-0.2.6 → pam_python-0.2.7}/pam/templates/service/polars/service_class.tmpl +0 -0
  76. {pam_python-0.2.6 → pam_python-0.2.7}/pam/tester_task.py +0 -0
  77. {pam_python-0.2.6 → pam_python-0.2.7}/pam/utils.py +0 -0
  78. {pam_python-0.2.6 → pam_python-0.2.7}/pam_python.egg-info/SOURCES.txt +0 -0
  79. {pam_python-0.2.6 → pam_python-0.2.7}/pam_python.egg-info/dependency_links.txt +0 -0
  80. {pam_python-0.2.6 → pam_python-0.2.7}/pam_python.egg-info/entry_points.txt +0 -0
  81. {pam_python-0.2.6 → pam_python-0.2.7}/pam_python.egg-info/requires.txt +0 -0
  82. {pam_python-0.2.6 → pam_python-0.2.7}/pam_python.egg-info/top_level.txt +0 -0
  83. {pam_python-0.2.6 → pam_python-0.2.7}/pyproject.toml +0 -0
  84. {pam_python-0.2.6 → pam_python-0.2.7}/setup.cfg +0 -0
  85. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_api.py +0 -0
  86. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_data_error_v2.py +0 -0
  87. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_data_input_v2.py +0 -0
  88. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_data_timeout_v2.py +0 -0
  89. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_range_transform.py +0 -0
  90. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_report_store.py +0 -0
  91. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_request_data_v2.py +0 -0
  92. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_result_batch_uploader.py +0 -0
  93. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_service_dataframe_output.py +0 -0
  94. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_sqlite_download_v2.py +0 -0
  95. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_temp_file_utils.py +0 -0
  96. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_area_report.py +0 -0
  97. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_bar_report.py +0 -0
  98. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_box_plot_report.py +0 -0
  99. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_bubble_report.py +0 -0
  100. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_candlestick_report.py +0 -0
  101. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_donut_report.py +0 -0
  102. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_heatmap_report.py +0 -0
  103. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_line_report.py +0 -0
  104. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_metric_report.py +0 -0
  105. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_pie_report.py +0 -0
  106. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_polar_area_report.py +0 -0
  107. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_radar_report.py +0 -0
  108. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_radial_bar_report.py +0 -0
  109. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_range_area_report.py +0 -0
  110. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_range_bar_report.py +0 -0
  111. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_scatter_report.py +0 -0
  112. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_table_report.py +0 -0
  113. {pam_python-0.2.6 → pam_python-0.2.7}/tests/test_typed_treemap_report.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pam-python
3
- Version: 0.2.6
3
+ Version: 0.2.7
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,3 +1,3 @@
1
1
  """PAM Data Plugin framework."""
2
2
 
3
- __version__ = "0.2.6"
3
+ __version__ = "0.2.7"
@@ -145,19 +145,10 @@ def _project_name(directory: Path) -> str:
145
145
 
146
146
 
147
147
  def _assert_new_project(directory: Path):
148
- known_project_files = set(COMMON_PROJECT_TEMPLATES.values())
149
- for templates in PACKAGE_MANAGER_TEMPLATES.values():
150
- known_project_files.update(templates.values())
151
- known_project_files.update({PROJECT_MARKER, "__init__.py", "uv.lock"})
152
- conflicts = [
153
- name for name in sorted(known_project_files)
154
- if (directory / name).exists()
155
- ]
156
- if conflicts:
157
- raise FileExistsError(
158
- "pam init only supports a new project directory; existing files: "
159
- + ", ".join(conflicts)
160
- )
148
+ # Kept for backward compatibility; collision handling is now in init_project
149
+ # via _prompt_overwrite_if_needed. Do not enforce allow-list here so
150
+ # unrelated files like .DS_Store are ignored.
151
+ return
161
152
 
162
153
 
163
154
  def _requirement_name(requirement: str) -> str:
@@ -180,45 +171,26 @@ def _assert_fresh_uv_project(directory: Path):
180
171
  "Run `uv add pam-python` before `uv run pam init`"
181
172
  )
182
173
 
183
- python_version = directory / ".python-version"
184
- if not python_version.is_file() or not python_version.read_text().strip().startswith("3.12"):
185
- raise FileExistsError(
186
- "A fresh uv project must pin Python 3.12; run `uv init --python 3.12`"
187
- )
188
174
 
189
- allowed = {
190
- ".git",
191
- ".gitignore",
192
- ".python-version",
193
- ".venv",
194
- "README.md",
195
- "main.py",
196
- "pyproject.toml",
197
- "uv.lock",
198
- }
199
- unexpected = sorted(path.name for path in directory.iterdir() if path.name not in allowed)
200
- if unexpected:
175
+ def _prompt_overwrite_if_needed(directory: Path, templates: dict[str, str]) -> bool:
176
+ dest_names = set(templates.values()) | {PROJECT_MARKER, "__init__.py"}
177
+ conflicts = sorted(name for name in dest_names if (directory / name).exists())
178
+ if not conflicts:
179
+ return True
180
+ print("The following files will be overwritten:")
181
+ for name in conflicts:
182
+ print(f" - {name}")
183
+ # Single confirmation round as requested: list collisions once, ask once.
184
+ if not sys.stdin.isatty():
201
185
  raise FileExistsError(
202
- "pam init only accepts a fresh uv project; existing files: "
203
- + ", ".join(unexpected)
204
- )
205
-
206
- readme = directory / "README.md"
207
- if readme.is_file() and readme.read_text(encoding="utf-8").strip():
208
- raise FileExistsError("pam init will not overwrite a non-empty README.md")
209
-
210
- main_file = directory / "main.py"
211
- if main_file.is_file():
212
- source = main_file.read_text(encoding="utf-8")
213
- uv_placeholder = re.fullmatch(
214
- r'def main\(\):\n'
215
- r' print\("Hello from [a-z0-9-]+!"\)\n\n\n'
216
- r'if __name__ == "__main__":\n'
217
- r' main\(\)\n?',
218
- source,
186
+ "pam init will overwrite existing files: " + ", ".join(conflicts) + ". "
187
+ "Run in an interactive terminal and confirm to overwrite."
219
188
  )
220
- if uv_placeholder is None:
221
- raise FileExistsError("pam init will not overwrite an edited main.py")
189
+ response = input("มีไฟล์ที่จะถูกเขียนทับตามรายการข้างบน ดำเนินการต่อหรือไม่? (y/N): ").strip().lower()
190
+ if response != "y":
191
+ print("Cancelled.")
192
+ return False
193
+ return True
222
194
 
223
195
 
224
196
  def _run_uv(args: list[str], cwd: Path):
@@ -263,6 +235,9 @@ def init_project(package_manager: str | None = None):
263
235
  if dest not in preserved_uv_files
264
236
  }
265
237
 
238
+ if not _prompt_overwrite_if_needed(destination, templates):
239
+ return
240
+
266
241
  with tempfile.TemporaryDirectory(prefix=".pam-init-", dir=destination) as temp_dir:
267
242
  staging = Path(temp_dir)
268
243
  for src, dest in templates.items():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pam-python
3
- Version: 0.2.6
3
+ Version: 0.2.7
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
@@ -186,6 +186,8 @@ if __name__ == "__main__":
186
186
 
187
187
  with mock.patch.object(cli.shutil, "which", return_value="/usr/bin/uv"), mock.patch.object(
188
188
  cli, "_run_uv", side_effect=lambda args, cwd: calls.append(list(args))
189
+ ), mock.patch.object(cli.sys.stdin, "isatty", return_value=True), mock.patch(
190
+ "builtins.input", return_value="y"
189
191
  ):
190
192
  cli.init_project()
191
193
 
@@ -217,7 +219,9 @@ if __name__ == "__main__":
217
219
  (root / "README.md").touch()
218
220
  (root / "main.py").write_text(uv_main)
219
221
 
220
- with mock.patch.object(cli.shutil, "which", return_value="/usr/bin/uv"):
222
+ with mock.patch.object(cli.shutil, "which", return_value="/usr/bin/uv"), mock.patch.object(
223
+ cli.sys.stdin, "isatty", return_value=True
224
+ ), mock.patch("builtins.input", return_value="y"):
221
225
  cli.init_project()
222
226
 
223
227
  gitignore = (root / ".gitignore").read_text()
@@ -242,15 +246,17 @@ if __name__ == "__main__":
242
246
  (root / ".python-version").write_text("3.12\n")
243
247
  (root / "main.py").write_text("print('real code')\n")
244
248
 
245
- with self.assertRaisesRegex(FileExistsError, "edited main.py"):
246
- cli.init_project()
249
+ with mock.patch.object(cli.sys.stdin, "isatty", return_value=False):
250
+ with self.assertRaisesRegex(FileExistsError, "will overwrite existing files: main.py"):
251
+ cli.init_project()
247
252
 
248
253
  def test_init_rejects_an_existing_project_without_overwriting(self):
249
254
  with tempfile.TemporaryDirectory() as temp_dir, WorkingDirectory(temp_dir):
250
255
  original = Path("main.py")
251
256
  original.write_text("keep me\n")
252
- with self.assertRaises(FileExistsError):
253
- cli.init_project("pip")
257
+ with mock.patch.object(cli.sys.stdin, "isatty", return_value=False):
258
+ with self.assertRaises(FileExistsError):
259
+ cli.init_project("pip")
254
260
  self.assertEqual("keep me\n", original.read_text())
255
261
 
256
262
  def test_service_name_validation_rejects_paths_and_hyphens(self):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes