kiarina-lib-google-cloud-storage 1.6.2__py3-none-any.whl → 1.6.3__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,3 +1,4 @@
1
+ import re
1
2
  from typing import Any
2
3
 
3
4
  from google.cloud import storage # type: ignore[import-untyped]
@@ -38,10 +39,10 @@ def get_blob(
38
39
  blob = get_blob(placeholders={"user_id": "123", "basename": "profile.json"})
39
40
  # With pattern "users/{user_id}/{basename}" -> "users/123/profile.json"
40
41
 
41
- # Using default pattern from settings
42
- blob = get_blob() # Uses settings.blob_name_pattern without placeholders
42
+ # Using fixed pattern from settings (no placeholders)
43
+ blob = get_blob() # Uses settings.blob_name_pattern if it has no placeholders
43
44
  """
44
- settings = settings_manager.get_settings_by_key(config_key)
45
+ settings = settings_manager.get_settings(config_key)
45
46
 
46
47
  # Priority 1: Explicit blob_name
47
48
  if blob_name is not None:
@@ -65,7 +66,6 @@ def get_blob(
65
66
 
66
67
  # Priority 3: Default pattern from settings
67
68
  elif settings.blob_name_pattern is not None:
68
- # Pattern without placeholders (fixed name)
69
69
  final_blob_name = settings.blob_name_pattern
70
70
 
71
71
  else:
@@ -74,5 +74,17 @@ def get_blob(
74
74
  "and blob_name_pattern is not set in settings"
75
75
  )
76
76
 
77
+ # Safety check: Ensure no unresolved placeholders remain
78
+ if _has_placeholders(final_blob_name):
79
+ raise ValueError(
80
+ f"Unresolved placeholders found in blob name: {final_blob_name}. "
81
+ f"Please provide placeholders argument to resolve them."
82
+ )
83
+
77
84
  bucket = get_bucket(config_key, auth_config_key=auth_config_key, **kwargs)
78
85
  return bucket.blob(final_blob_name)
86
+
87
+
88
+ def _has_placeholders(pattern: str) -> bool:
89
+ """Check if a pattern contains placeholders like {key}."""
90
+ return bool(re.search(r"\{[^}]+\}", pattern))
@@ -12,10 +12,6 @@ def get_bucket(
12
12
  auth_config_key: str | None = None,
13
13
  **kwargs: Any,
14
14
  ) -> storage.Bucket:
15
- settings = settings_manager.get_settings_by_key(config_key)
16
-
17
- if settings.bucket_name is None:
18
- raise ValueError("bucket_name is not set in the settings")
19
-
15
+ settings = settings_manager.get_settings(config_key)
20
16
  client = get_storage_client(auth_config_key, **kwargs)
21
17
  return client.bucket(settings.bucket_name)
@@ -3,16 +3,16 @@ from pydantic_settings_manager import SettingsManager
3
3
 
4
4
 
5
5
  class GoogleCloudStorageSettings(BaseSettings):
6
- bucket_name: str | None = None
6
+ bucket_name: str
7
7
 
8
8
  blob_name_pattern: str | None = None
9
9
  """
10
10
  Blob name pattern with placeholders.
11
-
11
+
12
12
  Examples:
13
13
  - "data.json" (fixed name)
14
14
  - "files/{basename}" (single placeholder)
15
- - "web/{user_id}/{agent_id}/files/{basename}" (multiple placeholders)
15
+ - "my-service/{tenant_id}/users/{user_id}/files/{basename}" (multiple placeholders)
16
16
  """
17
17
 
18
18
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kiarina-lib-google-cloud-storage
3
- Version: 1.6.2
3
+ Version: 1.6.3
4
4
  Summary: Google Cloud Storage client library for kiarina namespace
5
5
  Project-URL: Homepage, https://github.com/kiarina/kiarina-python
6
6
  Project-URL: Repository, https://github.com/kiarina/kiarina-python
@@ -22,7 +22,7 @@ Classifier: Typing :: Typed
22
22
  Requires-Python: >=3.12
23
23
  Requires-Dist: google-cloud-storage>=2.19.0
24
24
  Requires-Dist: kiarina-lib-google-auth>=1.4.0
25
- Requires-Dist: pydantic-settings-manager>=2.1.0
25
+ Requires-Dist: pydantic-settings-manager>=2.3.0
26
26
  Requires-Dist: pydantic-settings>=2.10.1
27
27
  Description-Content-Type: text/markdown
28
28
 
@@ -115,18 +115,18 @@ New requirement: Add agent-level isolation for multi-tenancy.
115
115
 
116
116
  **Updated Security Rules:**
117
117
  ```javascript
118
- match /web/{user_id}/{agent_id}/files/{basename} {
119
- allow read, write: if request.auth.uid == user_id
120
- && request.auth.token.agent_id == agent_id;
118
+ match /my-service/{tenant_id}/users/{user_id}/files/{basename} {
119
+ allow read, write: if request.auth.uid == user_id
120
+ && request.auth.token.tenant_id == tenant_id;
121
121
  }
122
122
  ```
123
123
 
124
124
  **Problem**: You must now update **every place** in your application code that constructs these paths:
125
125
  ```python
126
126
  # Must change all of these
127
- blob_name = f"web/{user_id}/{agent_id}/files/{file_name}" # Changed!
128
- blob_name = f"web/{user_id}/{agent_id}/thumbnails/{file_name}" # Changed!
129
- blob_name = f"web/{user_id}/{agent_id}/exports/{file_name}" # Changed!
127
+ blob_name = f"my-service/{tenant_id}/users/{user_id}/files/{file_name}" # Changed!
128
+ blob_name = f"my-service/{tenant_id}/users/{user_id}/thumbnails/{file_name}" # Changed!
129
+ blob_name = f"my-service/{tenant_id}/users/{user_id}/exports/{file_name}" # Changed!
130
130
  # ... and many more
131
131
  ```
132
132
 
@@ -138,14 +138,14 @@ blob_name = f"web/{user_id}/{agent_id}/exports/{file_name}" # Changed!
138
138
  google_cloud_storage:
139
139
  default:
140
140
  bucket_name: "my-app-data"
141
- blob_name_pattern: "web/{user_id}/{agent_id}/files/{basename}"
141
+ blob_name_pattern: "my-service/{tenant_id}/users/{user_id}/files/{basename}"
142
142
  ```
143
143
 
144
144
  **GCS Security Rules (Infrastructure Concern):**
145
145
  ```javascript
146
- match /web/{user_id}/{agent_id}/files/{basename} {
147
- allow read, write: if request.auth.uid == user_id
148
- && request.auth.token.agent_id == agent_id;
146
+ match /my-service/{tenant_id}/users/{user_id}/files/{basename} {
147
+ allow read, write: if request.auth.uid == user_id
148
+ && request.auth.token.tenant_id == tenant_id;
149
149
  }
150
150
  ```
151
151
 
@@ -368,14 +368,14 @@ def save_document(tenant_id: str, doc_id: str, content: bytes):
368
368
  def list_documents(tenant_id: str) -> list[str]:
369
369
  """List documents for any tenant"""
370
370
  from kiarina.lib.google.cloud_storage import get_bucket
371
-
371
+
372
372
  config_key = f"tenant_{tenant_id}"
373
373
  bucket = get_bucket(config_key=config_key, auth_config_key=config_key)
374
-
374
+
375
375
  # Get prefix from settings
376
- settings = settings_manager.get_settings_by_key(config_key)
376
+ settings = settings_manager.get_settings(config_key)
377
377
  prefix = f"{settings.blob_name_prefix}/documents/" if settings.blob_name_prefix else "documents/"
378
-
378
+
379
379
  blobs = bucket.list_blobs(prefix=prefix)
380
380
  return [blob.name for blob in blobs]
381
381
  ```
@@ -409,10 +409,10 @@ def mock_storage_config():
409
409
  def test_save_user_profile(mock_storage_config):
410
410
  """Test user profile saving"""
411
411
  from myapp.services import save_user_profile
412
-
412
+
413
413
  # Application code uses test configuration automatically
414
414
  save_user_profile("user123", {"name": "Alice"})
415
-
415
+
416
416
  # Verify using the same configuration
417
417
  from kiarina.lib.google.cloud_storage import get_blob
418
418
  blob = get_blob(blob_name="users/user123/profile.json")
@@ -428,20 +428,20 @@ from kiarina.lib.google.cloud_storage import settings_manager
428
428
 
429
429
  def debug_storage_config(config_key: str | None = None):
430
430
  """Show actual storage paths for debugging"""
431
- settings = settings_manager.get_settings_by_key(config_key)
432
-
431
+ settings = settings_manager.get_settings(config_key)
432
+
433
433
  print(f"Configuration: {config_key or 'default'}")
434
434
  print(f" Bucket: {settings.bucket_name}")
435
435
  print(f" Prefix: {settings.blob_name_prefix or '(none)'}")
436
436
  print(f" Auth: {settings.google_auth_config_key}")
437
-
437
+
438
438
  # Example paths
439
439
  example_blob = "users/123/profile.json"
440
440
  if settings.blob_name_prefix:
441
441
  full_path = f"{settings.blob_name_prefix}/{example_blob}"
442
442
  else:
443
443
  full_path = example_blob
444
-
444
+
445
445
  print(f" Example: gs://{settings.bucket_name}/{full_path}")
446
446
 
447
447
  # Usage
@@ -665,13 +665,14 @@ blob = get_blob()
665
665
  # Actual: gs://bucket/data/fixed.json
666
666
 
667
667
  # Complex pattern
668
- # If blob_name_pattern="web/{user_id}/{agent_id}/files/{basename}"
668
+ # If blob_name_pattern="my-service/{tenant_id}/users/{user_id}/files/{basename}"
669
669
  blob = get_blob(placeholders={
670
+ "tenant_id": "tenant123",
670
671
  "user_id": "user123",
671
672
  "agent_id": "agent456",
672
673
  "basename": "document.pdf"
673
674
  })
674
- # Actual: gs://bucket/web/user123/agent456/files/document.pdf
675
+ # Actual: gs://bucket/my-service/tenant123/users/user123/files/document.pdf
675
676
 
676
677
  # With custom configurations
677
678
  blob = get_blob(
@@ -700,7 +701,7 @@ settings_manager: SettingsManager[GoogleCloudStorageSettings]
700
701
  - `active_key`: Get/set active configuration key
701
702
 
702
703
  **Methods:**
703
- - `get_settings_by_key(key: str)`: Get settings by specific key
704
+ - `get_settings(key: str)`: Get settings by specific key
704
705
  - `clear()`: Clear cached settings
705
706
 
706
707
  ## Common Operations
@@ -0,0 +1,9 @@
1
+ kiarina/lib/google/cloud_storage/__init__.py,sha256=q2AdOOOHUj_D-eot8_1-atrIaCKsCg0YatUOdq3kVVE,1184
2
+ kiarina/lib/google/cloud_storage/_get_blob.py,sha256=j74xGy9ZlAFs2EwywQBVACprRcGOU63wd9FKWlE39dk,3065
3
+ kiarina/lib/google/cloud_storage/_get_bucket.py,sha256=1fBIuohwQzpsxaANpVTExQly3smwaYD2wtnDe7yg6Uo,484
4
+ kiarina/lib/google/cloud_storage/_get_storage_client.py,sha256=lmBR2I9_vcyb0PfsiSz0BPFYBwQ6zVci75cmk9GUN5U,359
5
+ kiarina/lib/google/cloud_storage/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ kiarina/lib/google/cloud_storage/settings.py,sha256=vKYeiVRL0qOPCJEbwJfdEUPU8KwpgMLLBzJ3eGpaqOI,536
7
+ kiarina_lib_google_cloud_storage-1.6.3.dist-info/METADATA,sha256=PByhsHVLVhbX9IwQdDhSqSo48ThFkC5H-T7rB2gA6JM,27553
8
+ kiarina_lib_google_cloud_storage-1.6.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
+ kiarina_lib_google_cloud_storage-1.6.3.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- kiarina/lib/google/cloud_storage/__init__.py,sha256=q2AdOOOHUj_D-eot8_1-atrIaCKsCg0YatUOdq3kVVE,1184
2
- kiarina/lib/google/cloud_storage/_get_blob.py,sha256=J8GFQIx_xQWgqvd2LscI83u6xmzS7uPBIshyUDgBZEI,2644
3
- kiarina/lib/google/cloud_storage/_get_bucket.py,sha256=SaGIQqRb9UOJaosGf2pXduAEYscE_T21AHCNTaZtRGo,597
4
- kiarina/lib/google/cloud_storage/_get_storage_client.py,sha256=lmBR2I9_vcyb0PfsiSz0BPFYBwQ6zVci75cmk9GUN5U,359
5
- kiarina/lib/google/cloud_storage/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- kiarina/lib/google/cloud_storage/settings.py,sha256=2ZG2AmWe6mM8wq-OHTqSneTIvoraIxh2Q1W7umLOFvI,540
7
- kiarina_lib_google_cloud_storage-1.6.2.dist-info/METADATA,sha256=y16n-HD2RzseJezOZHujIS4xhzrds78eWEXKJK-p3-E,27462
8
- kiarina_lib_google_cloud_storage-1.6.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
- kiarina_lib_google_cloud_storage-1.6.2.dist-info/RECORD,,