opensecureconf-client 2.0.2__py3-none-any.whl → 2.3.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opensecureconf-client
3
- Version: 2.0.2
3
+ Version: 2.3.0
4
4
  Summary: Python client library for OpenSecureConf encrypted configuration management API with clustering support
5
5
  Author-email: Alessandro Pioli <alessandro.pioli+apioli-pypi@gmail.com>
6
6
  Maintainer-email: Alessandro Pioli <alessandro.pioli+apioli-pypi@gmail.com>
@@ -0,0 +1,6 @@
1
+ opensecureconf_client.py,sha256=9BfhPk3C7hFUy0wEB8P2-Xn69Zfrr8v2fhQmk4nEwqQ,27630
2
+ opensecureconf_client-2.3.0.dist-info/licenses/LICENSE,sha256=mvMdzinneV_-L01ddrHOBgbutNS8tjT1m7loT7VTWbI,1073
3
+ opensecureconf_client-2.3.0.dist-info/METADATA,sha256=d5bjvHAT8Vb6VQDDRTpjmOSDRcMQNy26U4eInosp0HY,33865
4
+ opensecureconf_client-2.3.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
5
+ opensecureconf_client-2.3.0.dist-info/top_level.txt,sha256=J7NP3hD92OUdqseJLlbzgPuG_ovqkURRyw7iBJJeDVE,22
6
+ opensecureconf_client-2.3.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
opensecureconf_client.py CHANGED
@@ -12,9 +12,10 @@ Enhanced Features:
12
12
  - Batch operations
13
13
  - Enhanced input validation
14
14
  - Health check utilities
15
+ - Support for multiple value types (dict, str, int, bool, list)
15
16
  """
16
17
 
17
- from typing import Any, Dict, List, Optional
18
+ from typing import Any, Dict, List, Optional, Union
18
19
  import logging
19
20
  import time
20
21
  import requests
@@ -22,7 +23,6 @@ from requests.adapters import HTTPAdapter
22
23
  from requests.exceptions import Timeout, RequestException
23
24
  from urllib3.util.retry import Retry
24
25
 
25
-
26
26
  # ============================================================================
27
27
  # EXCEPTIONS
28
28
  # ============================================================================
@@ -30,23 +30,18 @@ from urllib3.util.retry import Retry
30
30
  class OpenSecureConfError(Exception):
31
31
  """Base exception for OpenSecureConf client errors."""
32
32
 
33
-
34
33
  class AuthenticationError(OpenSecureConfError):
35
34
  """Raised when authentication fails (invalid or missing user key)."""
36
35
 
37
-
38
36
  class ConfigurationNotFoundError(OpenSecureConfError):
39
37
  """Raised when a requested configuration key does not exist."""
40
38
 
41
-
42
39
  class ConfigurationExistsError(OpenSecureConfError):
43
40
  """Raised when attempting to create a configuration that already exists."""
44
41
 
45
-
46
42
  class ClusterError(OpenSecureConfError):
47
43
  """Raised when cluster operations fail."""
48
44
 
49
-
50
45
  # ============================================================================
51
46
  # CLIENT
52
47
  # ============================================================================
@@ -73,9 +68,14 @@ class OpenSecureConfClient:
73
68
  ... enable_retry=True,
74
69
  ... log_level="INFO"
75
70
  ... )
71
+ >>> # Dict value
76
72
  >>> config = client.create("database", {"host": "localhost", "port": 5432})
77
- >>> print(config["value"])
78
- {'host': 'localhost', 'port': 5432}
73
+ >>> # String value
74
+ >>> config = client.create("api_token", "secret-token-123")
75
+ >>> # Int value
76
+ >>> config = client.create("max_connections", 100)
77
+ >>> # Bool value
78
+ >>> config = client.create("debug_mode", True)
79
79
  """
80
80
 
81
81
  def __init__(
@@ -171,12 +171,10 @@ class OpenSecureConfClient:
171
171
  "x-user-key": self.user_key,
172
172
  "Content-Type": "application/json"
173
173
  }
174
-
175
174
  if self.api_key:
176
175
  headers["X-API-Key"] = self.api_key
177
176
 
178
177
  self._session.headers.update(headers)
179
-
180
178
  self.logger.info(f"Client initialized for {self.base_url}")
181
179
 
182
180
  def _make_request(self, method: str, endpoint: str, **kwargs) -> Any:
@@ -208,7 +206,6 @@ class OpenSecureConfClient:
208
206
  try:
209
207
  response = self._session.request(method, url, **kwargs)
210
208
  duration = time.time() - start_time
211
-
212
209
  self.logger.info(
213
210
  f"{method} {endpoint} - Status: {response.status_code} - Duration: {duration:.3f}s"
214
211
  )
@@ -295,7 +292,7 @@ class OpenSecureConfClient:
295
292
  Example:
296
293
  >>> info = client.get_service_info()
297
294
  >>> print(info["version"])
298
- 2.1.0
295
+ 2.2.0
299
296
  """
300
297
  return self._make_request("GET", "/")
301
298
 
@@ -350,9 +347,9 @@ class OpenSecureConfClient:
350
347
  # ========================================================================
351
348
 
352
349
  def create(
353
- self,
354
- key: str,
355
- value: Dict[str, Any],
350
+ self,
351
+ key: str,
352
+ value: Union[Dict[str, Any], str, int, bool, list],
356
353
  category: Optional[str] = None
357
354
  ) -> Dict[str, Any]:
358
355
  """
@@ -360,7 +357,7 @@ class OpenSecureConfClient:
360
357
 
361
358
  Args:
362
359
  key: Unique configuration key (1-255 characters)
363
- value: Configuration data as dictionary (will be encrypted)
360
+ value: Configuration data (dict, string, int, bool, or list - will be encrypted)
364
361
  category: Optional category for grouping (max 100 characters)
365
362
 
366
363
  Returns:
@@ -372,22 +369,25 @@ class OpenSecureConfClient:
372
369
 
373
370
  Raises:
374
371
  ConfigurationExistsError: If configuration key already exists
375
- ValueError: If key or value is invalid
372
+ ValueError: If key is invalid
376
373
 
377
374
  Example:
378
- >>> config = client.create(
379
- ... key="database",
380
- ... value={"host": "localhost", "port": 5432},
381
- ... category="production"
382
- ... )
375
+ >>> # Dict value
376
+ >>> config = client.create("database", {"host": "localhost", "port": 5432}, "prod")
377
+ >>> # String value
378
+ >>> config = client.create("api_token", "secret-token-123", "auth")
379
+ >>> # Integer value
380
+ >>> config = client.create("max_retries", 3)
381
+ >>> # Boolean value
382
+ >>> config = client.create("debug_enabled", False)
383
+ >>> # List value
384
+ >>> config = client.create("allowed_ips", ["192.168.1.1", "10.0.0.1"])
383
385
  """
384
386
  # Enhanced validation
385
387
  if not key or not isinstance(key, str):
386
388
  raise ValueError("Key must be a non-empty string")
387
389
  if len(key) > 255:
388
390
  raise ValueError("Key must be between 1 and 255 characters")
389
- if not isinstance(value, dict):
390
- raise ValueError("Value must be a dictionary")
391
391
  if category and len(category) > 100:
392
392
  raise ValueError("Category must be max 100 characters")
393
393
 
@@ -403,6 +403,7 @@ class OpenSecureConfClient:
403
403
 
404
404
  Returns:
405
405
  Dictionary containing the configuration with decrypted value
406
+ The value can be dict, str, int, bool, or list depending on what was stored
406
407
 
407
408
  Raises:
408
409
  ConfigurationNotFoundError: If configuration key does not exist
@@ -410,8 +411,7 @@ class OpenSecureConfClient:
410
411
 
411
412
  Example:
412
413
  >>> config = client.read("database")
413
- >>> print(config["value"]["host"])
414
- localhost
414
+ >>> print(config["value"]) # Could be any supported type
415
415
  """
416
416
  if not key or not isinstance(key, str):
417
417
  raise ValueError("Key must be a non-empty string")
@@ -419,9 +419,9 @@ class OpenSecureConfClient:
419
419
  return self._make_request("GET", f"/configs/{key}")
420
420
 
421
421
  def update(
422
- self,
423
- key: str,
424
- value: Dict[str, Any],
422
+ self,
423
+ key: str,
424
+ value: Union[Dict[str, Any], str, int, bool, list],
425
425
  category: Optional[str] = None
426
426
  ) -> Dict[str, Any]:
427
427
  """
@@ -429,7 +429,7 @@ class OpenSecureConfClient:
429
429
 
430
430
  Args:
431
431
  key: Configuration key to update
432
- value: New configuration data as dictionary (will be encrypted)
432
+ value: New configuration data (dict, string, int, bool, or list - will be encrypted)
433
433
  category: Optional new category
434
434
 
435
435
  Returns:
@@ -437,18 +437,18 @@ class OpenSecureConfClient:
437
437
 
438
438
  Raises:
439
439
  ConfigurationNotFoundError: If configuration key does not exist
440
- ValueError: If parameters are invalid
440
+ ValueError: If key is invalid
441
441
 
442
442
  Example:
443
- >>> config = client.update(
444
- ... key="database",
445
- ... value={"host": "db.example.com", "port": 5432}
446
- ... )
443
+ >>> # Update with dict
444
+ >>> config = client.update("database", {"host": "db.example.com", "port": 5432})
445
+ >>> # Update with string
446
+ >>> config = client.update("api_token", "new-token-456")
447
+ >>> # Update with int
448
+ >>> config = client.update("timeout", 60)
447
449
  """
448
450
  if not key or not isinstance(key, str):
449
451
  raise ValueError("Key must be a non-empty string")
450
- if not isinstance(value, dict):
451
- raise ValueError("Value must be a dictionary")
452
452
  if category and len(category) > 100:
453
453
  raise ValueError("Category must be max 100 characters")
454
454
 
@@ -489,6 +489,7 @@ class OpenSecureConfClient:
489
489
 
490
490
  Returns:
491
491
  List of configuration dictionaries with decrypted values
492
+ Each value can be dict, str, int, bool, or list
492
493
 
493
494
  Example:
494
495
  >>> configs = client.list_all(category="production")
@@ -503,8 +504,8 @@ class OpenSecureConfClient:
503
504
  # ========================================================================
504
505
 
505
506
  def bulk_create(
506
- self,
507
- configs: List[Dict[str, Any]],
507
+ self,
508
+ configs: List[Dict[str, Any]],
508
509
  ignore_errors: bool = False
509
510
  ) -> List[Dict[str, Any]]:
510
511
  """
@@ -512,6 +513,7 @@ class OpenSecureConfClient:
512
513
 
513
514
  Args:
514
515
  configs: List of configuration dictionaries with 'key', 'value', and optional 'category'
516
+ Value can be dict, str, int, bool, or list
515
517
  ignore_errors: If True, continue on errors and return partial results
516
518
 
517
519
  Returns:
@@ -524,7 +526,8 @@ class OpenSecureConfClient:
524
526
  Example:
525
527
  >>> configs = [
526
528
  ... {"key": "db1", "value": {"host": "localhost"}, "category": "prod"},
527
- ... {"key": "db2", "value": {"host": "remote"}, "category": "prod"}
529
+ ... {"key": "token", "value": "secret-123", "category": "auth"},
530
+ ... {"key": "retries", "value": 3, "category": "config"}
528
531
  ... ]
529
532
  >>> results = client.bulk_create(configs)
530
533
  >>> print(f"Created {len(results)} configurations")
@@ -562,8 +565,8 @@ class OpenSecureConfClient:
562
565
  return results
563
566
 
564
567
  def bulk_read(
565
- self,
566
- keys: List[str],
568
+ self,
569
+ keys: List[str],
567
570
  ignore_errors: bool = False
568
571
  ) -> List[Dict[str, Any]]:
569
572
  """
@@ -577,7 +580,7 @@ class OpenSecureConfClient:
577
580
  List of configuration dictionaries
578
581
 
579
582
  Example:
580
- >>> configs = client.bulk_read(["db1", "db2", "api"])
583
+ >>> configs = client.bulk_read(["db1", "token", "retries"])
581
584
  >>> print(f"Retrieved {len(configs)} configurations")
582
585
  """
583
586
  if not isinstance(keys, list):
@@ -604,8 +607,8 @@ class OpenSecureConfClient:
604
607
  return results
605
608
 
606
609
  def bulk_delete(
607
- self,
608
- keys: List[str],
610
+ self,
611
+ keys: List[str],
609
612
  ignore_errors: bool = False
610
613
  ) -> Dict[str, Any]:
611
614
  """
@@ -666,25 +669,25 @@ class OpenSecureConfClient:
666
669
  return False
667
670
 
668
671
  def get_or_default(
669
- self,
670
- key: str,
671
- default: Dict[str, Any]
672
+ self,
673
+ key: str,
674
+ default: Union[Dict[str, Any], str, int, bool, list]
672
675
  ) -> Dict[str, Any]:
673
676
  """
674
677
  Get configuration value or return default if not found.
675
678
 
676
679
  Args:
677
680
  key: Configuration key to retrieve
678
- default: Default value to return if key not found
681
+ default: Default value to return if key not found (any supported type)
679
682
 
680
683
  Returns:
681
- Configuration dictionary or default value
684
+ Configuration dictionary or default value wrapped in dict format
682
685
 
683
686
  Example:
684
- >>> config = client.get_or_default(
685
- ... "database",
686
- ... {"host": "localhost", "port": 5432}
687
- ... )
687
+ >>> # Dict default
688
+ >>> config = client.get_or_default("database", {"host": "localhost", "port": 5432})
689
+ >>> # String default
690
+ >>> config = client.get_or_default("token", "default-token")
688
691
  """
689
692
  try:
690
693
  return self.read(key)
@@ -1,6 +0,0 @@
1
- opensecureconf_client.py,sha256=hb7GGTHoRjMdK0KACtYkZUUlqbxPHVVidLDZkFqMB9o,26560
2
- opensecureconf_client-2.0.2.dist-info/licenses/LICENSE,sha256=mvMdzinneV_-L01ddrHOBgbutNS8tjT1m7loT7VTWbI,1073
3
- opensecureconf_client-2.0.2.dist-info/METADATA,sha256=2xWbal_tTrf3yaYysEqgsedMmqCnhqcDl-kSj0Zyprs,33865
4
- opensecureconf_client-2.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
- opensecureconf_client-2.0.2.dist-info/top_level.txt,sha256=J7NP3hD92OUdqseJLlbzgPuG_ovqkURRyw7iBJJeDVE,22
6
- opensecureconf_client-2.0.2.dist-info/RECORD,,