catapa-private 1.0.0__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.
@@ -0,0 +1,276 @@
1
+ Metadata-Version: 2.4
2
+ Name: catapa-private
3
+ Version: 1.0.0
4
+ Summary: Python client library for CATAPA Private API
5
+ Author-email: Catapa Team <dev@catapa.com>
6
+ Project-URL: Homepage, https://github.com/GDP-ADMIN/CATAPA-API
7
+ Project-URL: Documentation, https://api-docs.catapa.com/
8
+ Project-URL: Repository, https://github.com/GDP-ADMIN/CATAPA-API
9
+ Keywords: catapa,api,client,hr,payroll,private
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Requires-Python: >=3.11
18
+ Description-Content-Type: text/markdown
19
+ Requires-Dist: requests>=2.32.0
20
+ Requires-Dist: pydantic>=2.0.0
21
+ Requires-Dist: typing-extensions>=4.7.1
22
+ Requires-Dist: flake8<7.3.0
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
25
+ Requires-Dist: pytest-cov; extra == "dev"
26
+ Requires-Dist: coverage>=7.0.0; extra == "dev"
27
+ Requires-Dist: pre-commit>=4.2.0; extra == "dev"
28
+ Requires-Dist: ruff>=0.14.0; extra == "dev"
29
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
30
+
31
+ # CATAPA Private Python SDK
32
+
33
+ A Python client library for the CATAPA Private API with session-based authentication.
34
+
35
+ ## Features
36
+
37
+ - 🔐 **Session-Based Authentication** - Automatic login and session management with cookie handling
38
+ - 🚀 **Simple API** - Clean interface for making authenticated requests to CATAPA Private API
39
+ - 🔄 **Automatic Session Management** - Sessions are automatically maintained and refreshed
40
+
41
+ ## Installation
42
+
43
+ **Using pip**
44
+ ```bash
45
+ pip install catapa-private
46
+ ```
47
+
48
+ **Using poetry**
49
+ ```bash
50
+ poetry add catapa-private
51
+ ```
52
+
53
+ **Using uv**
54
+ ```bash
55
+ uv add catapa-private
56
+ ```
57
+
58
+ ## Quick Start
59
+
60
+ A complete Hello World example to get you started immediately.
61
+
62
+ ```python
63
+ from catapa_private import CatapaPrivate
64
+
65
+ def main() -> None:
66
+ client = CatapaPrivate(
67
+ tenant="zfrl",
68
+ username="demo",
69
+ password="dmo-password"
70
+ )
71
+
72
+ response = client.get("/core/countries", params={"page": 0, "size": 10})
73
+ response.raise_for_status()
74
+ data = response.json()
75
+ print(f"Found {len(data.get('content', []))} countries")
76
+
77
+ if __name__ == "__main__":
78
+ main()
79
+ ```
80
+
81
+ > **💡 Tip:** By default, the SDK connects to `https://api.catapa.com`. To use a different base URL (e.g., for staging or testing), pass the `base_url` parameter:
82
+ >
83
+ > ```python
84
+ > client = CatapaPrivate(
85
+ > tenant="your-tenant",
86
+ > username="your-username",
87
+ > password="your-password",
88
+ > base_url="https://staging-api.catapa.com" # Optional: override default base URL
89
+ > )
90
+ > ```
91
+
92
+ ## Getting Your Credentials
93
+
94
+ To use the SDK with your own account, you'll need the following authentication credentials:
95
+
96
+ ### Tenant ID
97
+
98
+ Your **tenant ID** is your organization's unique identifier in CATAPA. To obtain it, please contact [support@catapa.com](mailto:support@catapa.com).
99
+
100
+ ### Username and Password
101
+
102
+ Your **username** and **password** are your CATAPA account credentials used for session-based authentication.
103
+
104
+ > **⚠️ Important:** Keep your credentials secure and never commit them to version control. Consider using environment variables or a secrets management system.
105
+
106
+ ## Tutorials
107
+
108
+ More intermediate examples to help you learn the SDK.
109
+
110
+ ### Tutorial 1: Complete CRUD Operations
111
+
112
+ A complete example showing how to perform Create, Read, Update, and Delete operations.
113
+
114
+ ```python
115
+ import random
116
+ import string
117
+
118
+ from catapa_private import CatapaPrivate
119
+
120
+ def main() -> None:
121
+ """Main function demonstrating CRUD operations."""
122
+ client = CatapaPrivate(
123
+ tenant="zfrl",
124
+ username="demo",
125
+ password="dmo-password"
126
+ )
127
+
128
+ # Step 1: GET - Retrieve list of countries
129
+ response = client.get("/core/countries", params={"page": 0, "size": 10})
130
+ response.raise_for_status()
131
+ data = response.json()
132
+ countries = data.get("content", [])
133
+ print(f"Found {len(countries)} countries")
134
+
135
+ # Step 2: POST - Create a new country
136
+ random_suffix = "".join(random.choices(string.ascii_lowercase + string.digits, k=6))
137
+ new_country = {
138
+ "code": f"IDN{random_suffix[:3].upper()}",
139
+ "callingCode": "+62",
140
+ "name": f"Indonesia_{random_suffix}",
141
+ "taxTreaty": True,
142
+ }
143
+ response = client.post("/core/countries", json=new_country)
144
+ response.raise_for_status()
145
+ created_country = response.json()
146
+ country_id = created_country.get("id")
147
+ print(f"Created country: {created_country.get('name')} (ID: {country_id})")
148
+
149
+ # Step 3: GET - Retrieve the created country by ID
150
+ response = client.get(f"/core/countries/{country_id}")
151
+ response.raise_for_status()
152
+ retrieved_country = response.json()
153
+ print(f"Retrieved country: {retrieved_country.get('name')}")
154
+
155
+ # Step 4: PUT - Update the country
156
+ retrieved_country["name"] = f"Indonesia_{random_suffix}_updated"
157
+ response = client.put(f"/core/countries/{country_id}", json=retrieved_country)
158
+ response.raise_for_status()
159
+ updated_country = response.json()
160
+ print(f"Updated country: {updated_country.get('name')}")
161
+
162
+ # Step 5: DELETE - Delete the country
163
+ payload = [{"id": country_id}]
164
+ response = client.delete("/core/countries", json=payload)
165
+ response.raise_for_status()
166
+ print(f"Deleted country (ID: {country_id})")
167
+
168
+ if __name__ == "__main__":
169
+ main()
170
+ ```
171
+
172
+ ### Tutorial 2: Error Handling and Response Management
173
+
174
+ A complete example showing how to handle errors and manage responses properly.
175
+
176
+ ```python
177
+ from catapa_private import CatapaPrivate
178
+ from requests.exceptions import HTTPError, RequestException
179
+
180
+ def main() -> None:
181
+ """Main function demonstrating error handling."""
182
+ client = CatapaPrivate(
183
+ tenant="zfrl",
184
+ username="demo",
185
+ password="dmo-password"
186
+ )
187
+
188
+ try:
189
+ response = client.get("/core/countries", params={"page": 0, "size": 10})
190
+ response.raise_for_status()
191
+ data = response.json()
192
+ print(f"Success: Retrieved {len(data.get('content', []))} countries")
193
+ except HTTPError as e:
194
+ print(f"HTTP Error {e.response.status_code}: {e.response.text}")
195
+ except RequestException as e:
196
+ print(f"Request failed: {e}")
197
+
198
+ if __name__ == "__main__":
199
+ main()
200
+ ```
201
+
202
+ ## Cookbook
203
+
204
+ Intermediate to Advanced examples for real-world scenarios.
205
+
206
+ ### Cookbook 1: Concurrent API Calls
207
+
208
+ A complete example for making concurrent API calls efficiently.
209
+
210
+ ```python
211
+ from catapa_private import CatapaPrivate
212
+ from concurrent.futures import ThreadPoolExecutor, as_completed
213
+
214
+ def main() -> None:
215
+ """Main function for concurrent API calls example."""
216
+ client = CatapaPrivate(
217
+ tenant="zfrl",
218
+ username="demo",
219
+ password="dmo-password"
220
+ )
221
+
222
+ # Define API call functions
223
+ def get_countries():
224
+ response = client.get("/core/countries", params={"page": 0, "size": 10})
225
+ response.raise_for_status()
226
+ return response.json()
227
+
228
+ def get_banks():
229
+ response = client.get("/core/banks", params={"page": 0, "size": 10})
230
+ response.raise_for_status()
231
+ return response.json()
232
+
233
+ def get_companies():
234
+ response = client.get("/core/companies", params={"page": 0, "size": 10})
235
+ response.raise_for_status()
236
+ return response.json()
237
+
238
+ # Execute API calls concurrently
239
+ with ThreadPoolExecutor(max_workers=3) as executor:
240
+ futures = {
241
+ executor.submit(get_countries): "countries",
242
+ executor.submit(get_banks): "banks",
243
+ executor.submit(get_companies): "companies"
244
+ }
245
+
246
+ results = {}
247
+ for future in as_completed(futures):
248
+ task_name = futures[future]
249
+ try:
250
+ results[task_name] = future.result()
251
+ print(f"✅ {task_name} retrieved successfully")
252
+ except Exception as e:
253
+ print(f"❌ {task_name} failed: {e}")
254
+
255
+ # Use the results
256
+ if "countries" in results:
257
+ data = results["countries"]
258
+ print(f"Countries: {len(data.get('content', []))}")
259
+ if "banks" in results:
260
+ data = results["banks"]
261
+ print(f"Banks: {len(data.get('content', []))}")
262
+ if "companies" in results:
263
+ data = results["companies"]
264
+ print(f"Companies: {len(data.get('content', []))}")
265
+
266
+ if __name__ == "__main__":
267
+ main()
268
+ ```
269
+
270
+ ## More Examples
271
+
272
+ For additional examples including tutorials, cookbooks, and advanced usage patterns, please see the [`examples/`](examples/) directory in this repository.
273
+
274
+ ## Requirements
275
+
276
+ - Python 3.11+
@@ -0,0 +1,246 @@
1
+ # CATAPA Private Python SDK
2
+
3
+ A Python client library for the CATAPA Private API with session-based authentication.
4
+
5
+ ## Features
6
+
7
+ - 🔐 **Session-Based Authentication** - Automatic login and session management with cookie handling
8
+ - 🚀 **Simple API** - Clean interface for making authenticated requests to CATAPA Private API
9
+ - 🔄 **Automatic Session Management** - Sessions are automatically maintained and refreshed
10
+
11
+ ## Installation
12
+
13
+ **Using pip**
14
+ ```bash
15
+ pip install catapa-private
16
+ ```
17
+
18
+ **Using poetry**
19
+ ```bash
20
+ poetry add catapa-private
21
+ ```
22
+
23
+ **Using uv**
24
+ ```bash
25
+ uv add catapa-private
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ A complete Hello World example to get you started immediately.
31
+
32
+ ```python
33
+ from catapa_private import CatapaPrivate
34
+
35
+ def main() -> None:
36
+ client = CatapaPrivate(
37
+ tenant="zfrl",
38
+ username="demo",
39
+ password="dmo-password"
40
+ )
41
+
42
+ response = client.get("/core/countries", params={"page": 0, "size": 10})
43
+ response.raise_for_status()
44
+ data = response.json()
45
+ print(f"Found {len(data.get('content', []))} countries")
46
+
47
+ if __name__ == "__main__":
48
+ main()
49
+ ```
50
+
51
+ > **💡 Tip:** By default, the SDK connects to `https://api.catapa.com`. To use a different base URL (e.g., for staging or testing), pass the `base_url` parameter:
52
+ >
53
+ > ```python
54
+ > client = CatapaPrivate(
55
+ > tenant="your-tenant",
56
+ > username="your-username",
57
+ > password="your-password",
58
+ > base_url="https://staging-api.catapa.com" # Optional: override default base URL
59
+ > )
60
+ > ```
61
+
62
+ ## Getting Your Credentials
63
+
64
+ To use the SDK with your own account, you'll need the following authentication credentials:
65
+
66
+ ### Tenant ID
67
+
68
+ Your **tenant ID** is your organization's unique identifier in CATAPA. To obtain it, please contact [support@catapa.com](mailto:support@catapa.com).
69
+
70
+ ### Username and Password
71
+
72
+ Your **username** and **password** are your CATAPA account credentials used for session-based authentication.
73
+
74
+ > **⚠️ Important:** Keep your credentials secure and never commit them to version control. Consider using environment variables or a secrets management system.
75
+
76
+ ## Tutorials
77
+
78
+ More intermediate examples to help you learn the SDK.
79
+
80
+ ### Tutorial 1: Complete CRUD Operations
81
+
82
+ A complete example showing how to perform Create, Read, Update, and Delete operations.
83
+
84
+ ```python
85
+ import random
86
+ import string
87
+
88
+ from catapa_private import CatapaPrivate
89
+
90
+ def main() -> None:
91
+ """Main function demonstrating CRUD operations."""
92
+ client = CatapaPrivate(
93
+ tenant="zfrl",
94
+ username="demo",
95
+ password="dmo-password"
96
+ )
97
+
98
+ # Step 1: GET - Retrieve list of countries
99
+ response = client.get("/core/countries", params={"page": 0, "size": 10})
100
+ response.raise_for_status()
101
+ data = response.json()
102
+ countries = data.get("content", [])
103
+ print(f"Found {len(countries)} countries")
104
+
105
+ # Step 2: POST - Create a new country
106
+ random_suffix = "".join(random.choices(string.ascii_lowercase + string.digits, k=6))
107
+ new_country = {
108
+ "code": f"IDN{random_suffix[:3].upper()}",
109
+ "callingCode": "+62",
110
+ "name": f"Indonesia_{random_suffix}",
111
+ "taxTreaty": True,
112
+ }
113
+ response = client.post("/core/countries", json=new_country)
114
+ response.raise_for_status()
115
+ created_country = response.json()
116
+ country_id = created_country.get("id")
117
+ print(f"Created country: {created_country.get('name')} (ID: {country_id})")
118
+
119
+ # Step 3: GET - Retrieve the created country by ID
120
+ response = client.get(f"/core/countries/{country_id}")
121
+ response.raise_for_status()
122
+ retrieved_country = response.json()
123
+ print(f"Retrieved country: {retrieved_country.get('name')}")
124
+
125
+ # Step 4: PUT - Update the country
126
+ retrieved_country["name"] = f"Indonesia_{random_suffix}_updated"
127
+ response = client.put(f"/core/countries/{country_id}", json=retrieved_country)
128
+ response.raise_for_status()
129
+ updated_country = response.json()
130
+ print(f"Updated country: {updated_country.get('name')}")
131
+
132
+ # Step 5: DELETE - Delete the country
133
+ payload = [{"id": country_id}]
134
+ response = client.delete("/core/countries", json=payload)
135
+ response.raise_for_status()
136
+ print(f"Deleted country (ID: {country_id})")
137
+
138
+ if __name__ == "__main__":
139
+ main()
140
+ ```
141
+
142
+ ### Tutorial 2: Error Handling and Response Management
143
+
144
+ A complete example showing how to handle errors and manage responses properly.
145
+
146
+ ```python
147
+ from catapa_private import CatapaPrivate
148
+ from requests.exceptions import HTTPError, RequestException
149
+
150
+ def main() -> None:
151
+ """Main function demonstrating error handling."""
152
+ client = CatapaPrivate(
153
+ tenant="zfrl",
154
+ username="demo",
155
+ password="dmo-password"
156
+ )
157
+
158
+ try:
159
+ response = client.get("/core/countries", params={"page": 0, "size": 10})
160
+ response.raise_for_status()
161
+ data = response.json()
162
+ print(f"Success: Retrieved {len(data.get('content', []))} countries")
163
+ except HTTPError as e:
164
+ print(f"HTTP Error {e.response.status_code}: {e.response.text}")
165
+ except RequestException as e:
166
+ print(f"Request failed: {e}")
167
+
168
+ if __name__ == "__main__":
169
+ main()
170
+ ```
171
+
172
+ ## Cookbook
173
+
174
+ Intermediate to Advanced examples for real-world scenarios.
175
+
176
+ ### Cookbook 1: Concurrent API Calls
177
+
178
+ A complete example for making concurrent API calls efficiently.
179
+
180
+ ```python
181
+ from catapa_private import CatapaPrivate
182
+ from concurrent.futures import ThreadPoolExecutor, as_completed
183
+
184
+ def main() -> None:
185
+ """Main function for concurrent API calls example."""
186
+ client = CatapaPrivate(
187
+ tenant="zfrl",
188
+ username="demo",
189
+ password="dmo-password"
190
+ )
191
+
192
+ # Define API call functions
193
+ def get_countries():
194
+ response = client.get("/core/countries", params={"page": 0, "size": 10})
195
+ response.raise_for_status()
196
+ return response.json()
197
+
198
+ def get_banks():
199
+ response = client.get("/core/banks", params={"page": 0, "size": 10})
200
+ response.raise_for_status()
201
+ return response.json()
202
+
203
+ def get_companies():
204
+ response = client.get("/core/companies", params={"page": 0, "size": 10})
205
+ response.raise_for_status()
206
+ return response.json()
207
+
208
+ # Execute API calls concurrently
209
+ with ThreadPoolExecutor(max_workers=3) as executor:
210
+ futures = {
211
+ executor.submit(get_countries): "countries",
212
+ executor.submit(get_banks): "banks",
213
+ executor.submit(get_companies): "companies"
214
+ }
215
+
216
+ results = {}
217
+ for future in as_completed(futures):
218
+ task_name = futures[future]
219
+ try:
220
+ results[task_name] = future.result()
221
+ print(f"✅ {task_name} retrieved successfully")
222
+ except Exception as e:
223
+ print(f"❌ {task_name} failed: {e}")
224
+
225
+ # Use the results
226
+ if "countries" in results:
227
+ data = results["countries"]
228
+ print(f"Countries: {len(data.get('content', []))}")
229
+ if "banks" in results:
230
+ data = results["banks"]
231
+ print(f"Banks: {len(data.get('content', []))}")
232
+ if "companies" in results:
233
+ data = results["companies"]
234
+ print(f"Companies: {len(data.get('content', []))}")
235
+
236
+ if __name__ == "__main__":
237
+ main()
238
+ ```
239
+
240
+ ## More Examples
241
+
242
+ For additional examples including tutorials, cookbooks, and advanced usage patterns, please see the [`examples/`](examples/) directory in this repository.
243
+
244
+ ## Requirements
245
+
246
+ - Python 3.11+
@@ -0,0 +1,30 @@
1
+ """CATAPA Private Python Client.
2
+
3
+ Main entry point for the CATAPA Private Python SDK with session-based authentication.
4
+
5
+ This package provides:
6
+ - CatapaPrivate: Main wrapper class with automatic session-based authentication.
7
+ - CatapaPrivateAuth & CatapaPrivateConfig: Authentication utilities.
8
+ - SessionClient: Low-level session-based HTTP client.
9
+
10
+ Authors:
11
+ Handrian Alandi (handrian.alandi@gdplabs.id)
12
+
13
+ References:
14
+ NONE
15
+ """
16
+
17
+ from catapa_private.auth.catapa_private_auth import CatapaPrivateAuth, CatapaPrivateConfig
18
+ from catapa_private.client import CatapaPrivate
19
+ from catapa_private.session_client import SessionClient
20
+
21
+ __version__ = "1.0.0"
22
+ __author__ = "Catapa Team"
23
+ __email__ = "dev@catapa.com"
24
+
25
+ __all__ = [
26
+ "CatapaPrivate",
27
+ "CatapaPrivateAuth",
28
+ "CatapaPrivateConfig",
29
+ "SessionClient",
30
+ ]
@@ -0,0 +1,18 @@
1
+ """CATAPA Private Authentication Module.
2
+
3
+ This module provides authentication utilities for the CATAPA Private API.
4
+
5
+ Authors:
6
+ Handrian Alandi (handrian.alandi@gdplabs.id)
7
+
8
+ References:
9
+ NONE
10
+ """
11
+
12
+ from catapa_private.auth.catapa_private_auth import CatapaPrivateAuth, CatapaPrivateConfig
13
+
14
+ __all__ = ["CatapaPrivateAuth", "CatapaPrivateConfig"]
15
+
16
+
17
+
18
+