ndp-ep 0.1.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.
Files changed (38) hide show
  1. ndp_ep-0.1.0/LICENSE +21 -0
  2. ndp_ep-0.1.0/PKG-INFO +217 -0
  3. ndp_ep-0.1.0/README.md +177 -0
  4. ndp_ep-0.1.0/ndp_ep/__init__.py +40 -0
  5. ndp_ep-0.1.0/ndp_ep/api_client.py +63 -0
  6. ndp_ep-0.1.0/ndp_ep/client_base.py +147 -0
  7. ndp_ep-0.1.0/ndp_ep/delete_organization_method.py +46 -0
  8. ndp_ep-0.1.0/ndp_ep/delete_resource_method.py +78 -0
  9. ndp_ep-0.1.0/ndp_ep/get_kafka_details_method.py +39 -0
  10. ndp_ep-0.1.0/ndp_ep/get_system_status_method.py +104 -0
  11. ndp_ep-0.1.0/ndp_ep/list_organization_method.py +43 -0
  12. ndp_ep-0.1.0/ndp_ep/register_dataset_method.py +65 -0
  13. ndp_ep-0.1.0/ndp_ep/register_kafka_method.py +59 -0
  14. ndp_ep-0.1.0/ndp_ep/register_organization_method.py +55 -0
  15. ndp_ep-0.1.0/ndp_ep/register_s3_method.py +63 -0
  16. ndp_ep-0.1.0/ndp_ep/register_service_method.py +68 -0
  17. ndp_ep-0.1.0/ndp_ep/register_url_method.py +63 -0
  18. ndp_ep-0.1.0/ndp_ep/search_method.py +101 -0
  19. ndp_ep-0.1.0/ndp_ep/update_dataset_method.py +97 -0
  20. ndp_ep-0.1.0/ndp_ep/update_kafka_method.py +56 -0
  21. ndp_ep-0.1.0/ndp_ep/update_s3_method.py +50 -0
  22. ndp_ep-0.1.0/ndp_ep/update_url_method.py +63 -0
  23. ndp_ep-0.1.0/ndp_ep.egg-info/PKG-INFO +217 -0
  24. ndp_ep-0.1.0/ndp_ep.egg-info/SOURCES.txt +36 -0
  25. ndp_ep-0.1.0/ndp_ep.egg-info/dependency_links.txt +1 -0
  26. ndp_ep-0.1.0/ndp_ep.egg-info/requires.txt +13 -0
  27. ndp_ep-0.1.0/ndp_ep.egg-info/top_level.txt +1 -0
  28. ndp_ep-0.1.0/pyproject.toml +107 -0
  29. ndp_ep-0.1.0/setup.cfg +4 -0
  30. ndp_ep-0.1.0/setup.py +12 -0
  31. ndp_ep-0.1.0/tests/test_additional_methods.py +297 -0
  32. ndp_ep-0.1.0/tests/test_api_client.py +0 -0
  33. ndp_ep-0.1.0/tests/test_client_base.py +177 -0
  34. ndp_ep-0.1.0/tests/test_error_cases.py +303 -0
  35. ndp_ep-0.1.0/tests/test_init.py +0 -0
  36. ndp_ep-0.1.0/tests/test_register_methods.py +325 -0
  37. ndp_ep-0.1.0/tests/test_register_organization_method.py +189 -0
  38. ndp_ep-0.1.0/tests/test_search_method.py +205 -0
ndp_ep-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 NDP EP Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
ndp_ep-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,217 @@
1
+ Metadata-Version: 2.4
2
+ Name: ndp-ep
3
+ Version: 0.1.0
4
+ Summary: Python client library for NDP EP API
5
+ Author-email: Your Name <your.email@example.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/sci-ndp/ndp-ep-py
8
+ Project-URL: Repository, https://github.com/sci-ndp/ndp-ep-py
9
+ Project-URL: Documentation, https://github.com/sci-ndp/ndp-ep-py#readme
10
+ Project-URL: Bug Tracker, https://github.com/sci-ndp/ndp-ep-py/issues
11
+ Keywords: api,client,ndp,ep
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: requests>=2.25.0
28
+ Requires-Dist: urllib3>=1.26.0
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
31
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
32
+ Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
33
+ Requires-Dist: requests-mock>=1.9.0; extra == "dev"
34
+ Requires-Dist: black>=22.0.0; extra == "dev"
35
+ Requires-Dist: flake8>=5.0.0; extra == "dev"
36
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
37
+ Requires-Dist: twine>=4.0.0; extra == "dev"
38
+ Requires-Dist: build>=0.10.0; extra == "dev"
39
+ Dynamic: license-file
40
+
41
+ # ndp-ep
42
+
43
+ [![CI](https://github.com/sci-ndp/ndp-ep-py/workflows/CI/badge.svg)](https://github.com/sci-ndp/ndp-ep-py/actions)
44
+ [![codecov](https://codecov.io/gh/sci-ndp/ndp-ep-py/branch/main/graph/badge.svg)](https://codecov.io/gh/sci-ndp/ndp-ep-py)
45
+ [![PyPI version](https://badge.fury.io/py/ndp-ep.svg)](https://badge.fury.io/py/ndp-ep)
46
+ [![Python versions](https://img.shields.io/pypi/pyversions/ndp-ep.svg)](https://pypi.org/project/ndp-ep/)
47
+
48
+ A Python client library for interacting with the NDP EP API. This library provides a simple and intuitive interface for managing datasets, organizations, resources, and services through the API.
49
+
50
+ ## Features
51
+
52
+ - **Complete API Coverage**: Support for all API endpoints including Kafka topics, S3 resources, URL resources, organizations, and services
53
+ - **Authentication**: Token-based and username/password authentication
54
+ - **Search Functionality**: Advanced search capabilities across datasets and resources
55
+ - **Error Handling**: Comprehensive error handling with meaningful error messages
56
+ - **Type Hints**: Full type hint support for better IDE integration
57
+ - **Testing**: Extensive test coverage (>70%) with unit and integration tests
58
+
59
+ ## Installation
60
+
61
+ ```bash
62
+ pip install ndp-ep
63
+ ```
64
+
65
+ ## Quick Start
66
+
67
+ ```python
68
+ from ndp_ep import APIClient
69
+
70
+ # Initialize client with token
71
+ client = APIClient(
72
+ base_url="https://your-api-endpoint.com",
73
+ token="your-access-token"
74
+ )
75
+
76
+ # Or with username/password
77
+ client = APIClient(
78
+ base_url="https://your-api-endpoint.com",
79
+ username="your-username",
80
+ password="your-password"
81
+ )
82
+
83
+ # List organizations
84
+ organizations = client.list_organizations()
85
+ print(organizations)
86
+
87
+ # Search datasets
88
+ results = client.search_datasets(
89
+ terms=["climate", "temperature"],
90
+ server="global"
91
+ )
92
+
93
+ # Register a new organization
94
+ org_data = {
95
+ "name": "my_organization",
96
+ "title": "My Organization",
97
+ "description": "A sample organization"
98
+ }
99
+ response = client.register_organization(org_data)
100
+
101
+ # Register a service
102
+ service_data = {
103
+ "service_name": "user_auth_api",
104
+ "service_title": "User Authentication API",
105
+ "owner_org": "services",
106
+ "service_url": "https://api.example.com/auth",
107
+ "service_type": "API",
108
+ "notes": "RESTful API for user authentication"
109
+ }
110
+ response = client.register_service(service_data)
111
+ ```
112
+
113
+ ## API Coverage
114
+
115
+ ### Authentication
116
+ - Token-based authentication
117
+ - Username/password authentication
118
+
119
+ ### Organizations
120
+ - `list_organizations()` - List all organizations
121
+ - `register_organization()` - Create new organization
122
+ - `delete_organization()` - Delete organization
123
+
124
+ ### Datasets and Resources
125
+ - `search_datasets()` - Search datasets with advanced filters
126
+ - `advanced_search()` - Advanced search with POST method
127
+ - `register_url()` - Register URL resources
128
+ - `register_s3_link()` - Register S3 resources
129
+ - `register_kafka_topic()` - Register Kafka topics
130
+ - `register_general_dataset()` - Register general datasets
131
+ - `update_url_resource()` - Update URL resources
132
+ - `update_s3_resource()` - Update S3 resources
133
+ - `update_kafka_topic()` - Update Kafka topics
134
+ - `update_general_dataset()` - Update general datasets (PUT)
135
+ - `patch_general_dataset()` - Partially update general datasets (PATCH)
136
+ - `delete_resource_by_id()` - Delete resource by ID
137
+ - `delete_resource_by_name()` - Delete resource by name
138
+
139
+ ### Services
140
+ - `register_service()` - Register new services
141
+
142
+ ### System Information
143
+ - `get_kafka_details()` - Get Kafka connection details
144
+ - `get_system_status()` - Check system status
145
+ - `get_system_metrics()` - Get system metrics
146
+ - `get_jupyter_details()` - Get Jupyter connection details
147
+
148
+ ## Development
149
+
150
+ ### Setting up development environment
151
+
152
+ ```bash
153
+ # Clone the repository
154
+ git clone https://github.com/sci-ndp/ndp-ep-py.git
155
+ cd ndp-ep-py
156
+
157
+ # Create virtual environment
158
+ python -m venv venv
159
+ source venv/bin/activate # On Windows: venv\Scripts\activate
160
+
161
+ # Install development dependencies
162
+ pip install -e .
163
+ pip install -r requirements-dev.txt
164
+ ```
165
+
166
+ ### Running tests
167
+
168
+ ```bash
169
+ # Run all tests
170
+ pytest
171
+
172
+ # Run with coverage
173
+ pytest --cov=ndp_ep --cov-report=html
174
+
175
+ # Run specific test categories
176
+ pytest -m unit # Unit tests only
177
+ pytest -m integration # Integration tests only
178
+ ```
179
+
180
+ ### Code formatting and linting
181
+
182
+ ```bash
183
+ # Format code
184
+ black ndp_ep tests
185
+
186
+ # Lint code
187
+ flake8 ndp_ep
188
+
189
+ # Type checking
190
+ mypy ndp_ep
191
+ ```
192
+
193
+ ## Contributing
194
+
195
+ 1. Fork the repository
196
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
197
+ 3. Make your changes
198
+ 4. Add tests for your changes
199
+ 5. Ensure all tests pass and coverage is maintained
200
+ 6. Commit your changes (`git commit -m 'Add amazing feature'`)
201
+ 7. Push to the branch (`git push origin feature/amazing-feature`)
202
+ 8. Open a Pull Request
203
+
204
+ ## License
205
+
206
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
207
+
208
+ ## Changelog
209
+
210
+ ### v0.1.0
211
+ - Initial release
212
+ - Complete API coverage for all endpoints
213
+ - Authentication support (token and username/password)
214
+ - Search functionality
215
+ - Resource management (URL, S3, Kafka)
216
+ - Organization management
217
+ - Comprehensive testing suite
ndp_ep-0.1.0/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # ndp-ep
2
+
3
+ [![CI](https://github.com/sci-ndp/ndp-ep-py/workflows/CI/badge.svg)](https://github.com/sci-ndp/ndp-ep-py/actions)
4
+ [![codecov](https://codecov.io/gh/sci-ndp/ndp-ep-py/branch/main/graph/badge.svg)](https://codecov.io/gh/sci-ndp/ndp-ep-py)
5
+ [![PyPI version](https://badge.fury.io/py/ndp-ep.svg)](https://badge.fury.io/py/ndp-ep)
6
+ [![Python versions](https://img.shields.io/pypi/pyversions/ndp-ep.svg)](https://pypi.org/project/ndp-ep/)
7
+
8
+ A Python client library for interacting with the NDP EP API. This library provides a simple and intuitive interface for managing datasets, organizations, resources, and services through the API.
9
+
10
+ ## Features
11
+
12
+ - **Complete API Coverage**: Support for all API endpoints including Kafka topics, S3 resources, URL resources, organizations, and services
13
+ - **Authentication**: Token-based and username/password authentication
14
+ - **Search Functionality**: Advanced search capabilities across datasets and resources
15
+ - **Error Handling**: Comprehensive error handling with meaningful error messages
16
+ - **Type Hints**: Full type hint support for better IDE integration
17
+ - **Testing**: Extensive test coverage (>70%) with unit and integration tests
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ pip install ndp-ep
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ```python
28
+ from ndp_ep import APIClient
29
+
30
+ # Initialize client with token
31
+ client = APIClient(
32
+ base_url="https://your-api-endpoint.com",
33
+ token="your-access-token"
34
+ )
35
+
36
+ # Or with username/password
37
+ client = APIClient(
38
+ base_url="https://your-api-endpoint.com",
39
+ username="your-username",
40
+ password="your-password"
41
+ )
42
+
43
+ # List organizations
44
+ organizations = client.list_organizations()
45
+ print(organizations)
46
+
47
+ # Search datasets
48
+ results = client.search_datasets(
49
+ terms=["climate", "temperature"],
50
+ server="global"
51
+ )
52
+
53
+ # Register a new organization
54
+ org_data = {
55
+ "name": "my_organization",
56
+ "title": "My Organization",
57
+ "description": "A sample organization"
58
+ }
59
+ response = client.register_organization(org_data)
60
+
61
+ # Register a service
62
+ service_data = {
63
+ "service_name": "user_auth_api",
64
+ "service_title": "User Authentication API",
65
+ "owner_org": "services",
66
+ "service_url": "https://api.example.com/auth",
67
+ "service_type": "API",
68
+ "notes": "RESTful API for user authentication"
69
+ }
70
+ response = client.register_service(service_data)
71
+ ```
72
+
73
+ ## API Coverage
74
+
75
+ ### Authentication
76
+ - Token-based authentication
77
+ - Username/password authentication
78
+
79
+ ### Organizations
80
+ - `list_organizations()` - List all organizations
81
+ - `register_organization()` - Create new organization
82
+ - `delete_organization()` - Delete organization
83
+
84
+ ### Datasets and Resources
85
+ - `search_datasets()` - Search datasets with advanced filters
86
+ - `advanced_search()` - Advanced search with POST method
87
+ - `register_url()` - Register URL resources
88
+ - `register_s3_link()` - Register S3 resources
89
+ - `register_kafka_topic()` - Register Kafka topics
90
+ - `register_general_dataset()` - Register general datasets
91
+ - `update_url_resource()` - Update URL resources
92
+ - `update_s3_resource()` - Update S3 resources
93
+ - `update_kafka_topic()` - Update Kafka topics
94
+ - `update_general_dataset()` - Update general datasets (PUT)
95
+ - `patch_general_dataset()` - Partially update general datasets (PATCH)
96
+ - `delete_resource_by_id()` - Delete resource by ID
97
+ - `delete_resource_by_name()` - Delete resource by name
98
+
99
+ ### Services
100
+ - `register_service()` - Register new services
101
+
102
+ ### System Information
103
+ - `get_kafka_details()` - Get Kafka connection details
104
+ - `get_system_status()` - Check system status
105
+ - `get_system_metrics()` - Get system metrics
106
+ - `get_jupyter_details()` - Get Jupyter connection details
107
+
108
+ ## Development
109
+
110
+ ### Setting up development environment
111
+
112
+ ```bash
113
+ # Clone the repository
114
+ git clone https://github.com/sci-ndp/ndp-ep-py.git
115
+ cd ndp-ep-py
116
+
117
+ # Create virtual environment
118
+ python -m venv venv
119
+ source venv/bin/activate # On Windows: venv\Scripts\activate
120
+
121
+ # Install development dependencies
122
+ pip install -e .
123
+ pip install -r requirements-dev.txt
124
+ ```
125
+
126
+ ### Running tests
127
+
128
+ ```bash
129
+ # Run all tests
130
+ pytest
131
+
132
+ # Run with coverage
133
+ pytest --cov=ndp_ep --cov-report=html
134
+
135
+ # Run specific test categories
136
+ pytest -m unit # Unit tests only
137
+ pytest -m integration # Integration tests only
138
+ ```
139
+
140
+ ### Code formatting and linting
141
+
142
+ ```bash
143
+ # Format code
144
+ black ndp_ep tests
145
+
146
+ # Lint code
147
+ flake8 ndp_ep
148
+
149
+ # Type checking
150
+ mypy ndp_ep
151
+ ```
152
+
153
+ ## Contributing
154
+
155
+ 1. Fork the repository
156
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
157
+ 3. Make your changes
158
+ 4. Add tests for your changes
159
+ 5. Ensure all tests pass and coverage is maintained
160
+ 6. Commit your changes (`git commit -m 'Add amazing feature'`)
161
+ 7. Push to the branch (`git push origin feature/amazing-feature`)
162
+ 8. Open a Pull Request
163
+
164
+ ## License
165
+
166
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
167
+
168
+ ## Changelog
169
+
170
+ ### v0.1.0
171
+ - Initial release
172
+ - Complete API coverage for all endpoints
173
+ - Authentication support (token and username/password)
174
+ - Search functionality
175
+ - Resource management (URL, S3, Kafka)
176
+ - Organization management
177
+ - Comprehensive testing suite
@@ -0,0 +1,40 @@
1
+ """
2
+ NDP EP Python Client Library.
3
+
4
+ A Python client library for interacting with the NDP EP API.
5
+ This library provides a simple and intuitive interface for managing
6
+ datasets, organizations, resources, and services through the API.
7
+ """
8
+
9
+ from .client_base import APIClientBase
10
+ from .search_method import APIClientSearch
11
+ from .register_organization_method import APIClientOrganizationRegister
12
+ from .register_kafka_method import APIClientKafkaRegister
13
+ from .register_s3_method import APIClientS3Register
14
+ from .register_url_method import APIClientURLRegister
15
+ from .register_service_method import APIClientServiceRegister
16
+ from .register_dataset_method import APIClientDatasetRegister
17
+ from .list_organization_method import APIClientOrganizationList
18
+ from .update_kafka_method import APIClientKafkaUpdate
19
+ from .update_s3_method import APIClientS3Update
20
+ from .update_url_method import APIClientURLUpdate
21
+ from .update_dataset_method import APIClientDatasetUpdate
22
+ from .delete_organization_method import APIClientOrganizationDelete
23
+ from .delete_resource_method import APIClientResourceDelete
24
+ from .get_kafka_details_method import APIClientKafkaDetails
25
+ from .get_system_status_method import APIClientSystemStatus
26
+ from .api_client import APIClient
27
+
28
+ __version__ = "0.1.0"
29
+ __description__ = "Python client library for NDP EP API"
30
+
31
+ # Main exports
32
+ __all__ = [
33
+ "APIClient",
34
+ "APIClientBase",
35
+ "__version__",
36
+ "__description__",
37
+ ]
38
+
39
+ # Default client for backward compatibility
40
+ Client = APIClient
@@ -0,0 +1,63 @@
1
+ """Unified API Client combining all functionality."""
2
+
3
+ from .register_kafka_method import APIClientKafkaRegister
4
+ from .register_organization_method import APIClientOrganizationRegister
5
+ from .register_s3_method import APIClientS3Register
6
+ from .register_url_method import APIClientURLRegister
7
+ from .register_service_method import APIClientServiceRegister
8
+ from .register_dataset_method import APIClientDatasetRegister
9
+ from .list_organization_method import APIClientOrganizationList
10
+ from .search_method import APIClientSearch
11
+ from .update_kafka_method import APIClientKafkaUpdate
12
+ from .update_s3_method import APIClientS3Update
13
+ from .update_url_method import APIClientURLUpdate
14
+ from .update_dataset_method import APIClientDatasetUpdate
15
+ from .delete_organization_method import APIClientOrganizationDelete
16
+ from .delete_resource_method import APIClientResourceDelete
17
+ from .get_kafka_details_method import APIClientKafkaDetails
18
+ from .get_system_status_method import APIClientSystemStatus
19
+
20
+
21
+ class APIClient(
22
+ APIClientKafkaRegister,
23
+ APIClientOrganizationRegister,
24
+ APIClientS3Register,
25
+ APIClientURLRegister,
26
+ APIClientServiceRegister,
27
+ APIClientDatasetRegister,
28
+ APIClientOrganizationList,
29
+ APIClientSearch,
30
+ APIClientKafkaUpdate,
31
+ APIClientS3Update,
32
+ APIClientURLUpdate,
33
+ APIClientDatasetUpdate,
34
+ APIClientOrganizationDelete,
35
+ APIClientResourceDelete,
36
+ APIClientKafkaDetails,
37
+ APIClientSystemStatus,
38
+ ):
39
+ """
40
+ Unified API Client with comprehensive functionality.
41
+
42
+ This class combines all the individual API client mixins to provide
43
+ a complete interface for interacting with the NDP EP API.
44
+
45
+ Features:
46
+ - Organization management (create, list, delete)
47
+ - Resource registration (Kafka, S3, URL, Services, General datasets)
48
+ - Resource updates (Kafka, S3, URL, General datasets)
49
+ - Resource deletion (by ID and name)
50
+ - Search functionality (simple and advanced)
51
+ - System information (status, metrics, Kafka details, Jupyter details)
52
+ - Authentication (token-based and username/password)
53
+
54
+ Example:
55
+ >>> client = APIClient(
56
+ ... base_url="https://api.example.com",
57
+ ... token="your-token"
58
+ ... )
59
+ >>> organizations = client.list_organizations()
60
+ >>> results = client.search_datasets(["climate"], server="global")
61
+ """
62
+
63
+ pass
@@ -0,0 +1,147 @@
1
+ """Base class for the API client."""
2
+
3
+ import requests
4
+ from typing import Optional
5
+ from urllib.parse import urlparse
6
+
7
+
8
+ class APIClientBase:
9
+ """Base class for the API client."""
10
+
11
+ def __init__(
12
+ self,
13
+ base_url: str,
14
+ token: Optional[str] = None,
15
+ username: Optional[str] = None,
16
+ password: Optional[str] = None,
17
+ ) -> None:
18
+ """
19
+ Initialize the API client.
20
+
21
+ Args:
22
+ base_url: Base URL of the API.
23
+ token: Access token for authentication.
24
+ username: Username for authentication.
25
+ password: Password for authentication.
26
+
27
+ Raises:
28
+ ValueError: If invalid authentication combination is provided
29
+ or if API is not reachable.
30
+ """
31
+ self.base_url = self._ensure_protocol(base_url).rstrip("/")
32
+ self.session = requests.Session()
33
+
34
+ # Initialize token to None by default
35
+ self.token: Optional[str] = None
36
+
37
+ # Validate input combinations
38
+ if token and (username or password):
39
+ raise ValueError(
40
+ "Provide either a token or username/password, not both."
41
+ )
42
+
43
+ # Initialize with token if provided
44
+ if token:
45
+ self.token = token
46
+ self.session.headers.update(
47
+ {"Authorization": f"Bearer {self.token}"}
48
+ )
49
+ # Fallback to username/password authentication
50
+ elif username and password:
51
+ self.get_token(username, password)
52
+ # Check API availability if no authentication details are provided
53
+ else:
54
+ self._check_api_availability()
55
+
56
+ @staticmethod
57
+ def _ensure_protocol(url: str) -> str:
58
+ """
59
+ Ensure the URL contains a valid protocol.
60
+
61
+ If missing, prepend 'http://'.
62
+
63
+ Args:
64
+ url: The URL to validate.
65
+
66
+ Returns:
67
+ The URL with a protocol.
68
+ """
69
+ parsed_url = urlparse(url)
70
+ if not parsed_url.scheme:
71
+ return f"http://{url}"
72
+ return url
73
+
74
+ def _check_api_availability(self) -> None:
75
+ """
76
+ Check if the API is reachable.
77
+
78
+ Makes a GET request to the base URL.
79
+
80
+ Raises:
81
+ ValueError: If the connection fails or response is not 200.
82
+ """
83
+ try:
84
+ response = self.session.get(self.base_url)
85
+ response.raise_for_status()
86
+ except requests.exceptions.ConnectionError:
87
+ raise ValueError(
88
+ f"Failed to connect to the API at {self.base_url}. "
89
+ "Please check if the URL is correct and reachable."
90
+ )
91
+ except requests.exceptions.HTTPError as http_err:
92
+ raise ValueError(
93
+ "API connection check failed with "
94
+ f"status code {response.status_code}: {http_err}"
95
+ )
96
+ except requests.exceptions.RequestException as req_err:
97
+ raise ValueError(
98
+ "An error occurred while attempting to connect "
99
+ f"to the API: {req_err}"
100
+ )
101
+
102
+ def get_token(self, username: str, password: str) -> None:
103
+ """
104
+ Obtain authentication token.
105
+
106
+ Args:
107
+ username: Username for authentication.
108
+ password: Password for authentication.
109
+
110
+ Raises:
111
+ ValueError: If authentication fails or connection error occurs.
112
+ """
113
+ url = f"{self.base_url}/token"
114
+ try:
115
+ response = self.session.post(
116
+ url, data={"username": username, "password": password}
117
+ )
118
+ response.raise_for_status()
119
+ token_data = response.json()
120
+ self.token = token_data.get("access_token")
121
+ if not self.token:
122
+ raise ValueError(
123
+ "Authentication failed: No access token received."
124
+ )
125
+ # Update session headers with the token
126
+ self.session.headers.update(
127
+ {"Authorization": f"Bearer {self.token}"}
128
+ )
129
+ except requests.exceptions.ConnectionError:
130
+ raise ValueError(
131
+ f"Failed to connect to the API at {self.base_url}. "
132
+ "Please check if the URL is correct and reachable."
133
+ )
134
+ except requests.exceptions.HTTPError as http_err:
135
+ if response.status_code == 401:
136
+ raise ValueError(
137
+ "Authentication failed: Invalid username or password."
138
+ ) from http_err
139
+ else:
140
+ raise ValueError(
141
+ f"HTTP error occurred: {http_err}"
142
+ ) from http_err
143
+ except requests.exceptions.RequestException as req_err:
144
+ raise ValueError(
145
+ "An error occurred while attempting to obtain "
146
+ f"the token: {req_err}"
147
+ ) from req_err