pam-python 0.1.16__tar.gz → 0.1.18__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 (35) hide show
  1. {pam_python-0.1.16 → pam_python-0.1.18}/PKG-INFO +1 -1
  2. {pam_python-0.1.16 → pam_python-0.1.18}/pam/api.py +37 -3
  3. {pam_python-0.1.16 → pam_python-0.1.18}/pam/service.py +75 -0
  4. {pam_python-0.1.16 → pam_python-0.1.18}/pam_python.egg-info/PKG-INFO +1 -1
  5. {pam_python-0.1.16 → pam_python-0.1.18}/setup.py +1 -1
  6. {pam_python-0.1.16 → pam_python-0.1.18}/LICENSE.txt +0 -0
  7. {pam_python-0.1.16 → pam_python-0.1.18}/README.md +0 -0
  8. {pam_python-0.1.16 → pam_python-0.1.18}/pam/__init__.py +0 -0
  9. {pam_python-0.1.16 → pam_python-0.1.18}/pam/cli.py +0 -0
  10. {pam_python-0.1.16 → pam_python-0.1.18}/pam/interface_task_manager.py +0 -0
  11. {pam_python-0.1.16 → pam_python-0.1.18}/pam/models/__init__.py +0 -0
  12. {pam_python-0.1.16 → pam_python-0.1.18}/pam/models/request_command.py +0 -0
  13. {pam_python-0.1.16 → pam_python-0.1.18}/pam/server.py +0 -0
  14. {pam_python-0.1.16 → pam_python-0.1.18}/pam/task_manager.py +0 -0
  15. {pam_python-0.1.16 → pam_python-0.1.18}/pam/temp_file_utils.py +0 -0
  16. {pam_python-0.1.16 → pam_python-0.1.18}/pam/templates/buildcmd/pamb +0 -0
  17. {pam_python-0.1.16 → pam_python-0.1.18}/pam/templates/buildcmd/pamb-base.sh +0 -0
  18. {pam_python-0.1.16 → pam_python-0.1.18}/pam/templates/docker/Dockerfile +0 -0
  19. {pam_python-0.1.16 → pam_python-0.1.18}/pam/templates/init/dockerignore.tmpl +0 -0
  20. {pam_python-0.1.16 → pam_python-0.1.18}/pam/templates/init/gitignore.tmpl +0 -0
  21. {pam_python-0.1.16 → pam_python-0.1.18}/pam/templates/init/main.tmpl +0 -0
  22. {pam_python-0.1.16 → pam_python-0.1.18}/pam/templates/init/pylintrc.tmpl +0 -0
  23. {pam_python-0.1.16 → pam_python-0.1.18}/pam/templates/init/run_test.sh +0 -0
  24. {pam_python-0.1.16 → pam_python-0.1.18}/pam/templates/service/functions.tmpl +0 -0
  25. {pam_python-0.1.16 → pam_python-0.1.18}/pam/templates/service/service.test.tmpl +0 -0
  26. {pam_python-0.1.16 → pam_python-0.1.18}/pam/templates/service/service.yaml +0 -0
  27. {pam_python-0.1.16 → pam_python-0.1.18}/pam/templates/service/service_class.tmpl +0 -0
  28. {pam_python-0.1.16 → pam_python-0.1.18}/pam/tester_task.py +0 -0
  29. {pam_python-0.1.16 → pam_python-0.1.18}/pam/utils.py +0 -0
  30. {pam_python-0.1.16 → pam_python-0.1.18}/pam_python.egg-info/SOURCES.txt +0 -0
  31. {pam_python-0.1.16 → pam_python-0.1.18}/pam_python.egg-info/dependency_links.txt +0 -0
  32. {pam_python-0.1.16 → pam_python-0.1.18}/pam_python.egg-info/entry_points.txt +0 -0
  33. {pam_python-0.1.16 → pam_python-0.1.18}/pam_python.egg-info/requires.txt +0 -0
  34. {pam_python-0.1.16 → pam_python-0.1.18}/pam_python.egg-info/top_level.txt +0 -0
  35. {pam_python-0.1.16 → pam_python-0.1.18}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pam-python
3
- Version: 0.1.16
3
+ Version: 0.1.18
4
4
  Summary: Pam Python Library
5
5
  Home-page: https://github.com/heart/pam-python
6
6
  Author: Narongrit Kanhanoi
@@ -26,12 +26,13 @@ class API:
26
26
  log(f"HTTP POST request failed. URL: {url}, Error: {e}")
27
27
  return None
28
28
 
29
- def http_upload(self, url: str, file_path: str) -> requests.Response | None:
29
+ def http_upload(self, url: str, file_path: str, payload: dict = None) -> requests.Response | None:
30
30
  """
31
- Uploads a file to the specified URL.
31
+ Uploads a file to the specified URL with optional form data (payload).
32
32
 
33
33
  :param url: The URL to upload the file to.
34
34
  :param file_path: The path to the file to be uploaded.
35
+ :param payload: Optional dictionary of form fields to include in the request.
35
36
  :return: The response from the server, or None if an error occurred.
36
37
  """
37
38
  if not Path(file_path).is_file():
@@ -41,13 +42,46 @@ class API:
41
42
  try:
42
43
  with open(file_path, 'rb') as file:
43
44
  files = {'file': file}
44
- response = self.session.post(url, files=files, timeout=300)
45
+ response = self.session.post(
46
+ url,
47
+ files=files,
48
+ data=payload or {}, # optional form data
49
+ timeout=300
50
+ )
45
51
  response.raise_for_status()
46
52
  return response
47
53
  except requests.RequestException as e:
48
54
  log(f"File upload failed. URL: {url}, File: {file_path}, Error: {e}")
49
55
  return None
50
56
 
57
+ def download_sqlite_from_post(self, url: str, data: dict, output_path: str) -> bool:
58
+ """
59
+ Sends a POST request with JSON data and expects a SQLite file in response.
60
+ Saves the response content as a .sqlite file.
61
+
62
+ :param url: The URL to send the POST request to.
63
+ :param data: Dictionary to send as JSON in the body.
64
+ :param output_path: File path to save the .sqlite file.
65
+ :return: True if successful, False otherwise.
66
+ """
67
+ headers = {'Content-Type': 'application/json'}
68
+ try:
69
+ response = self.session.post(url, json=data, timeout=60, headers=headers)
70
+ response.raise_for_status()
71
+
72
+ # Save response content to file
73
+ with open(output_path, "wb") as f:
74
+ f.write(response.content)
75
+
76
+ log(f"SQLite file saved to {output_path}")
77
+ return True
78
+ except requests.RequestException as e:
79
+ log(f"Failed to download SQLite. URL: {url}, Error: {e}")
80
+ return False
81
+ except IOError as e:
82
+ log(f"Failed to save SQLite file. Path: {output_path}, Error: {e}")
83
+ return False
84
+
51
85
  def close(self):
52
86
  """Close the session."""
53
87
  self.session.close()
@@ -1,4 +1,6 @@
1
1
  from abc import abstractmethod
2
+ from pathlib import Path
3
+ from datetime import datetime
2
4
  import json
3
5
  from typing import TYPE_CHECKING, Union
4
6
  import pandas as pd
@@ -95,6 +97,79 @@ class Service:
95
97
 
96
98
  return report_csv_path
97
99
 
100
+ def _request_sqlite(self, file_name: str = "", is_shared: bool = False) -> str | None:
101
+ """Requests last sqlite file that this plugin has uploaded from the last time.
102
+
103
+ Returns:
104
+ The file path to the downloaded SQLite file, or None if the download failed.
105
+ """
106
+ log(f"{self.request.service_name}: Requesting sqlite for file_name={file_name}")
107
+
108
+ endpoint = self.request.sqlite_download
109
+ token = self.request.token
110
+ json_data = {"file_name": file_name, "is_shared": is_shared, "token": token}
111
+
112
+ # Create a unique suffix using current datetime
113
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
114
+ unique_file_name = f"{file_name or 'latest'}_{timestamp}"
115
+
116
+ # Create a temp file path for the downloaded .sqlite file
117
+ output_path = TempfileUtils.get_temp_file_name(
118
+ self.request.service_name,
119
+ token,
120
+ f"sqlite_{unique_file_name}_",
121
+ ".sqlite"
122
+ )
123
+
124
+ # Download SQLite file
125
+ success = self.task_manager.api.download_sqlite_from_post(endpoint, json_data, output_path)
126
+
127
+ if success:
128
+ log(f"{self.request.service_name}: Successfully downloaded SQLite file to {output_path}")
129
+ return output_path
130
+ else:
131
+ log(f"{self.request.service_name}: Failed to download SQLite file.")
132
+ return None
133
+
134
+
135
+ def _upload_sqlite(self, file_name: str = "", is_shared: bool = False, sqlite_file: str = "") -> str:
136
+ """
137
+ Uploads the result SQLite file to CDP.
138
+
139
+ :param file_name: The logical file name being uploaded.
140
+ :param is_shared: Whether this file should be treated as shared.
141
+ :param sqlite_file: Path to the SQLite file to upload.
142
+ :return: The uploaded file name if successful, or empty string if failed.
143
+ """
144
+ if not sqlite_file:
145
+ log(f"{self.request.service_name}: No sqlite file provided for upload.")
146
+ return ""
147
+
148
+ if not Path(sqlite_file).is_file():
149
+ log(f"{self.request.service_name}: SQLite file does not exist: {sqlite_file}")
150
+ return ""
151
+
152
+ endpoint = self.request.sqlite_upload
153
+ payload = {
154
+ "file_name": file_name,
155
+ "is_shared": str(is_shared).lower(), # form data values must be string
156
+ "token": self.request.token
157
+ }
158
+
159
+ try:
160
+ log(f"{self.request.service_name}: Uploading sqlite file: {sqlite_file} with payload: {payload}")
161
+ response = self.task_manager.api.http_upload(endpoint, sqlite_file, payload)
162
+
163
+ if response and response.ok:
164
+ log(f"{self.request.service_name}: SQLite file uploaded successfully.")
165
+ return file_name or Path(sqlite_file).name
166
+ else:
167
+ log(f"{self.request.service_name}: Failed to upload sqlite. Status: {response.status_code if response else 'N/A'}")
168
+ return ""
169
+ except Exception as e:
170
+ log(f"{self.request.service_name}: Exception while uploading sqlite: {e}")
171
+ return ""
172
+
98
173
  def _exit(self) -> None:
99
174
  """Signals the task manager to exit the service."""
100
175
  self.task_manager.service_exit(self)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pam-python
3
- Version: 0.1.16
3
+ Version: 0.1.18
4
4
  Summary: Pam Python Library
5
5
  Home-page: https://github.com/heart/pam-python
6
6
  Author: Narongrit Kanhanoi
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="pam-python",
5
- version="0.1.16",
5
+ version="0.1.18",
6
6
  author="Narongrit Kanhanoi",
7
7
  author_email="narongrit@pams.ai",
8
8
  description="Pam Python Library",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes