infisicalsdk 1.0.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.

Potentially problematic release.


This version of infisicalsdk might be problematic. Click here for more details.

@@ -0,0 +1,3 @@
1
+ from .client import InfisicalSDKClient # noqa
2
+ from .infisical_requests import InfisicalError # noqa
3
+ from .api_types import SingleSecretResponse, ListSecretsResponse, BaseSecret # noqa
@@ -0,0 +1,127 @@
1
+ from dataclasses import dataclass, field, fields
2
+ from typing import Optional, List, Any, Dict
3
+ from enum import Enum
4
+ import json
5
+
6
+
7
+ class ApprovalStatus(str, Enum):
8
+ """Enum for approval status"""
9
+ OPEN = "open"
10
+ APPROVED = "approved"
11
+ REJECTED = "rejected"
12
+
13
+
14
+ class BaseModel:
15
+ """Base class for all models"""
16
+ def to_dict(self) -> Dict:
17
+ """Convert model to dictionary"""
18
+ result = {}
19
+ for key, value in self.__dict__.items():
20
+ if value is not None: # Skip None values
21
+ if isinstance(value, BaseModel):
22
+ result[key] = value.to_dict()
23
+ elif isinstance(value, list):
24
+ result[key] = [
25
+ item.to_dict() if isinstance(item, BaseModel) else item
26
+ for item in value
27
+ ]
28
+ elif isinstance(value, Enum):
29
+ result[key] = value.value
30
+ else:
31
+ result[key] = value
32
+ return result
33
+
34
+ @classmethod
35
+ def from_dict(cls, data: Dict) -> 'BaseModel':
36
+ """Create model from dictionary"""
37
+ # Get only the fields that exist in the dataclass
38
+ valid_fields = {f.name for f in fields(cls)}
39
+ filtered_data = {k: v for k, v in data.items() if k in valid_fields}
40
+ return cls(**filtered_data)
41
+
42
+ def to_json(self) -> str:
43
+ """Convert model to JSON string"""
44
+ return json.dumps(self.to_dict())
45
+
46
+ @classmethod
47
+ def from_json(cls, json_str: str) -> 'BaseModel':
48
+ """Create model from JSON string"""
49
+ data = json.loads(json_str)
50
+ return cls.from_dict(data)
51
+
52
+
53
+ @dataclass(frozen=True)
54
+ class SecretTag(BaseModel):
55
+ """Model for secret tags"""
56
+ id: str
57
+ slug: str
58
+ name: str
59
+ color: Optional[str] = None
60
+
61
+
62
+ @dataclass
63
+ class BaseSecret(BaseModel):
64
+ """Infisical Secret"""
65
+ id: str
66
+ _id: str
67
+ workspace: str
68
+ environment: str
69
+ version: int
70
+ type: str
71
+ secretKey: str
72
+ secretValue: str
73
+ secretComment: str
74
+ createdAt: str
75
+ updatedAt: str
76
+ secretMetadata: Optional[Dict[str, Any]] = None
77
+ secretReminderNote: Optional[str] = None
78
+ secretReminderRepeatDays: Optional[int] = None
79
+ skipMultilineEncoding: Optional[bool] = False
80
+ metadata: Optional[Any] = None
81
+ secretPath: Optional[str] = None
82
+ tags: List[SecretTag] = field(default_factory=list)
83
+
84
+
85
+ @dataclass
86
+ class Import(BaseModel):
87
+ """Model for imports section"""
88
+ secretPath: str
89
+ environment: str
90
+ folderId: Optional[str] = None
91
+ secrets: List[BaseSecret] = field(default_factory=list)
92
+
93
+
94
+ @dataclass
95
+ class ListSecretsResponse(BaseModel):
96
+ """Complete response model for secrets API"""
97
+ secrets: List[BaseSecret]
98
+ imports: List[Import] = field(default_factory=list)
99
+
100
+ @classmethod
101
+ def from_dict(cls, data: Dict) -> 'ListSecretsResponse':
102
+ """Create model from dictionary with camelCase keys, handling nested objects"""
103
+ return cls(
104
+ secrets=[BaseSecret.from_dict(secret) for secret in data['secrets']],
105
+ imports=[Import.from_dict(imp) for imp in data.get('imports', [])]
106
+ )
107
+
108
+
109
+ @dataclass
110
+ class SingleSecretResponse(BaseModel):
111
+ """Response model for get secret API"""
112
+ secret: BaseSecret
113
+
114
+ @classmethod
115
+ def from_dict(cls, data: Dict) -> 'ListSecretsResponse':
116
+ return cls(
117
+ secret=BaseSecret.from_dict(data['secret']),
118
+ )
119
+
120
+
121
+ @dataclass
122
+ class MachineIdentityLoginResponse(BaseModel):
123
+ """Response model for machine identity login API"""
124
+ accessToken: str
125
+ expiresIn: int
126
+ accessTokenMaxTTL: int
127
+ tokenType: str
@@ -0,0 +1,345 @@
1
+ import base64
2
+ import json
3
+ from typing import List, Union
4
+ import os
5
+ import datetime
6
+ from typing import Dict, Any
7
+
8
+ import requests
9
+ import boto3
10
+ from botocore.auth import SigV4Auth
11
+ from botocore.awsrequest import AWSRequest
12
+ from botocore.exceptions import NoCredentialsError
13
+
14
+ from .infisical_requests import InfisicalRequests
15
+ from .api_types import ListSecretsResponse, MachineIdentityLoginResponse
16
+ from .api_types import SingleSecretResponse, BaseSecret
17
+
18
+
19
+ class InfisicalSDKClient:
20
+ def __init__(self, host: str, token: str = None):
21
+ self.host = host
22
+ self.access_token = token
23
+
24
+ self.api = InfisicalRequests(host=host, token=token)
25
+
26
+ self.auth = Auth(self)
27
+ self.secrets = V3RawSecrets(self)
28
+
29
+ def set_token(self, token: str):
30
+ """
31
+ Set the access token for future requests.
32
+ """
33
+ self.api.set_token(token)
34
+ self.access_token = token
35
+
36
+ def get_token(self):
37
+ """
38
+ Set the access token for future requests.
39
+ """
40
+ return self.access_token
41
+
42
+
43
+ class UniversalAuth:
44
+ def __init__(self, client: InfisicalSDKClient):
45
+ self.client = client
46
+
47
+ def login(self, client_id: str, client_secret: str) -> MachineIdentityLoginResponse:
48
+ """
49
+ Login with Universal Auth.
50
+
51
+ Args:
52
+ client_id (str): Your Machine Identity Client ID.
53
+ client_secret (str): Your Machine Identity Client Secret.
54
+
55
+ Returns:
56
+ Dict: A dictionary containing the access token and related information.
57
+ """
58
+
59
+ requestBody = {
60
+ "clientId": client_id,
61
+ "clientSecret": client_secret
62
+ }
63
+
64
+ result = self.client.api.post(
65
+ path="/api/v1/auth/universal-auth/login",
66
+ json=requestBody,
67
+ model=MachineIdentityLoginResponse
68
+ )
69
+
70
+ self.client.set_token(result.data.accessToken)
71
+
72
+ return result.data
73
+
74
+
75
+ class AWSAuth:
76
+ def __init__(self, client: InfisicalSDKClient) -> None:
77
+ self.client = client
78
+
79
+ def login(self, identity_id: str) -> MachineIdentityLoginResponse:
80
+ """
81
+ Login with AWS Authentication.
82
+
83
+ Args:
84
+ identity_id (str): Your Machine Identity ID that has AWS Auth configured.
85
+
86
+ Returns:
87
+ Dict: A dictionary containing the access token and related information.
88
+ """
89
+
90
+ identity_id = identity_id or os.getenv("INFISICAL_AWS_IAM_AUTH_IDENTITY_ID")
91
+ if not identity_id:
92
+ raise ValueError(
93
+ "Identity ID must be provided or set in the environment variable" +
94
+ "INFISICAL_AWS_IAM_AUTH_IDENTITY_ID."
95
+ )
96
+
97
+ aws_region = self.get_aws_region()
98
+ session = boto3.Session(region_name=aws_region)
99
+
100
+ credentials = self._get_aws_credentials(session)
101
+
102
+ iam_request_url = f"https://sts.{aws_region}.amazonaws.com/"
103
+ iam_request_body = "Action=GetCallerIdentity&Version=2011-06-15"
104
+
105
+ request_headers = self._prepare_aws_request(
106
+ iam_request_url,
107
+ iam_request_body,
108
+ credentials,
109
+ aws_region
110
+ )
111
+
112
+ requestBody = {
113
+ "identityId": identity_id,
114
+ "iamRequestBody": base64.b64encode(iam_request_body.encode()).decode(),
115
+ "iamRequestHeaders": base64.b64encode(json.dumps(request_headers).encode()).decode(),
116
+ "iamHttpRequestMethod": "POST"
117
+ }
118
+
119
+ result = self.client.api.post(
120
+ path="/api/v1/auth/aws-auth/login",
121
+ json=requestBody,
122
+ model=MachineIdentityLoginResponse
123
+ )
124
+
125
+ self.client.set_token(result.data.accessToken)
126
+
127
+ return result.data
128
+
129
+ def _get_aws_credentials(self, session: boto3.Session) -> Any:
130
+ try:
131
+ credentials = session.get_credentials()
132
+ if credentials is None:
133
+ raise NoCredentialsError("AWS credentials not found.")
134
+ return credentials.get_frozen_credentials()
135
+ except NoCredentialsError as e:
136
+ raise RuntimeError(f"AWS IAM Auth Login failed: {str(e)}")
137
+
138
+ def _prepare_aws_request(
139
+ self,
140
+ url: str,
141
+ body: str,
142
+ credentials: Any,
143
+ region: str) -> Dict[str, str]:
144
+
145
+ current_time = datetime.datetime.now(datetime.timezone.utc)
146
+ amz_date = current_time.strftime('%Y%m%dT%H%M%SZ')
147
+
148
+ request = AWSRequest(method="POST", url=url, data=body)
149
+ request.headers["X-Amz-Date"] = amz_date
150
+ request.headers["Host"] = f"sts.{region}.amazonaws.com"
151
+ request.headers["Content-Type"] = "application/x-www-form-urlencoded; charset=utf-8"
152
+ request.headers["Content-Length"] = str(len(body))
153
+
154
+ signer = SigV4Auth(credentials, "sts", region)
155
+ signer.add_auth(request)
156
+
157
+ return {k: v for k, v in request.headers.items() if k.lower() != "content-length"}
158
+
159
+ @staticmethod
160
+ def get_aws_region() -> str:
161
+ region = os.getenv("AWS_REGION") # Typically found in lambda runtime environment
162
+ if region:
163
+ return region
164
+
165
+ try:
166
+ return AWSAuth._get_aws_ec2_identity_document_region()
167
+ except Exception as e:
168
+ raise Exception("Failed to retrieve AWS region") from e
169
+
170
+ @staticmethod
171
+ def _get_aws_ec2_identity_document_region(timeout: int = 5000) -> str:
172
+ session = requests.Session()
173
+ token_response = session.put(
174
+ "http://169.254.169.254/latest/api/token",
175
+ headers={"X-aws-ec2-metadata-token-ttl-seconds": "21600"},
176
+ timeout=timeout / 1000
177
+ )
178
+ token_response.raise_for_status()
179
+ metadata_token = token_response.text
180
+
181
+ identity_response = session.get(
182
+ "http://169.254.169.254/latest/dynamic/instance-identity/document",
183
+ headers={"X-aws-ec2-metadata-token": metadata_token, "Accept": "application/json"},
184
+ timeout=timeout / 1000
185
+ )
186
+
187
+ identity_response.raise_for_status()
188
+ return identity_response.json().get("region")
189
+
190
+
191
+ class Auth:
192
+ def __init__(self, client):
193
+ self.client = client
194
+ self.aws_auth = AWSAuth(client)
195
+ self.universal_auth = UniversalAuth(client)
196
+
197
+
198
+ class V3RawSecrets:
199
+ def __init__(self, client: InfisicalSDKClient) -> None:
200
+ self.client = client
201
+
202
+ def list_secrets(
203
+ self,
204
+ project_id: str,
205
+ environment_slug: str,
206
+ secret_path: str,
207
+ expand_secret_references: bool = True,
208
+ recursive: bool = False,
209
+ include_imports: bool = True,
210
+ tag_filters: List[str] = []) -> ListSecretsResponse:
211
+
212
+ params = {
213
+ "workspaceId": project_id,
214
+ "environment": environment_slug,
215
+ "secretPath": secret_path,
216
+ "expandSecretReferences": str(expand_secret_references).lower(),
217
+ "recursive": str(recursive).lower(),
218
+ "include_imports": str(include_imports).lower(),
219
+ }
220
+
221
+ if tag_filters:
222
+ params["tag_slugs"] = ",".join(tag_filters)
223
+
224
+ result = self.client.api.get(
225
+ path="/api/v3/secrets/raw",
226
+ params=params,
227
+ model=ListSecretsResponse
228
+ )
229
+
230
+ return result.data
231
+
232
+ def get_secret_by_name(
233
+ self,
234
+ secret_name: str,
235
+ project_id: str,
236
+ environment_slug: str,
237
+ secret_path: str,
238
+ expand_secret_references: bool = True,
239
+ include_imports: bool = True,
240
+ version: str = None) -> BaseSecret:
241
+
242
+ params = {
243
+ "workspaceId": project_id,
244
+ "environment": environment_slug,
245
+ "secretPath": secret_path,
246
+ "expandSecretReferences": str(expand_secret_references).lower(),
247
+ "include_imports": str(include_imports).lower(),
248
+ "version": version
249
+ }
250
+
251
+ result = self.client.api.get(
252
+ path=f"/api/v3/secrets/raw/{secret_name}",
253
+ params=params,
254
+ model=SingleSecretResponse
255
+ )
256
+
257
+ return result.data.secret
258
+
259
+ def create_secret_by_name(
260
+ self,
261
+ secret_name: str,
262
+ project_id: str,
263
+ secret_path: str,
264
+ environment_slug: str,
265
+ secret_value: str = None,
266
+ secret_comment: str = None,
267
+ skip_multiline_encoding: bool = False,
268
+ secret_reminder_repeat_days: Union[float, int] = None,
269
+ secret_reminder_note: str = None) -> BaseSecret:
270
+
271
+ requestBody = {
272
+ "workspaceId": project_id,
273
+ "environment": environment_slug,
274
+ "secretPath": secret_path,
275
+ "secretValue": secret_value,
276
+ "secretComment": secret_comment,
277
+ "tagIds": None,
278
+ "skipMultilineEncoding": skip_multiline_encoding,
279
+ "type": "shared",
280
+ "secretReminderRepeatDays": secret_reminder_repeat_days,
281
+ "secretReminderNote": secret_reminder_note
282
+ }
283
+ result = self.client.api.post(
284
+ path=f"/api/v3/secrets/raw/{secret_name}",
285
+ json=requestBody,
286
+ model=SingleSecretResponse
287
+ )
288
+
289
+ return result.data.secret
290
+
291
+ def update_secret_by_name(
292
+ self,
293
+ current_secret_name: str,
294
+ project_id: str,
295
+ secret_path: str,
296
+ environment_slug: str,
297
+ secret_value: str = None,
298
+ secret_comment: str = None,
299
+ skip_multiline_encoding: bool = False,
300
+ secret_reminder_repeat_days: Union[float, int] = None,
301
+ secret_reminder_note: str = None,
302
+ new_secret_name: str = None) -> BaseSecret:
303
+
304
+ requestBody = {
305
+ "workspaceId": project_id,
306
+ "environment": environment_slug,
307
+ "secretPath": secret_path,
308
+ "secretValue": secret_value,
309
+ "secretComment": secret_comment,
310
+ "new_secret_name": new_secret_name,
311
+ "tagIds": None,
312
+ "skipMultilineEncoding": skip_multiline_encoding,
313
+ "type": "shared",
314
+ "secretReminderRepeatDays": secret_reminder_repeat_days,
315
+ "secretReminderNote": secret_reminder_note
316
+ }
317
+
318
+ result = self.client.api.patch(
319
+ path=f"/api/v3/secrets/raw/{current_secret_name}",
320
+ json=requestBody,
321
+ model=SingleSecretResponse
322
+ )
323
+ return result.data.secret
324
+
325
+ def delete_secret_by_name(
326
+ self,
327
+ secret_name: str,
328
+ project_id: str,
329
+ secret_path: str,
330
+ environment_slug: str) -> BaseSecret:
331
+
332
+ requestBody = {
333
+ "workspaceId": project_id,
334
+ "environment": environment_slug,
335
+ "secretPath": secret_path,
336
+ "type": "shared",
337
+ }
338
+
339
+ result = self.client.api.delete(
340
+ path=f"/api/v3/secrets/raw/{secret_name}",
341
+ json=requestBody,
342
+ model=SingleSecretResponse
343
+ )
344
+
345
+ return result.data.secret
@@ -0,0 +1,186 @@
1
+ from typing import Any, Dict, Generic, Optional, TypeVar
2
+ from urllib.parse import urljoin
3
+ import requests
4
+ from dataclasses import dataclass
5
+
6
+ T = TypeVar("T")
7
+
8
+
9
+ class InfisicalError(Exception):
10
+ """Base exception for Infisical client errors"""
11
+ pass
12
+
13
+
14
+ class APIError(InfisicalError):
15
+ """API-specific errors"""
16
+ def __init__(self, message: str, status_code: int, response: Dict[str, Any]):
17
+ self.status_code = status_code
18
+ self.response = response
19
+ super().__init__(f"{message} (Status: {status_code})")
20
+
21
+
22
+ @dataclass
23
+ class APIResponse(Generic[T]):
24
+ """Generic API response wrapper"""
25
+ data: T
26
+ status_code: int
27
+ headers: Dict[str, str]
28
+
29
+ def to_dict(self) -> Dict:
30
+ """Convert to dictionary with camelCase keys"""
31
+ return {
32
+ 'data': self.data.to_dict() if hasattr(self.data, 'to_dict') else self.data,
33
+ 'statusCode': self.status_code,
34
+ 'headers': self.headers
35
+ }
36
+
37
+ @classmethod
38
+ def from_dict(cls, data: Dict) -> 'APIResponse[T]':
39
+ """Create from dictionary with camelCase keys"""
40
+ return cls(
41
+ data=data['data'],
42
+ status_code=data['statusCode'],
43
+ headers=data['headers']
44
+ )
45
+
46
+
47
+ class InfisicalRequests:
48
+ def __init__(self, host: str, token: Optional[str] = None):
49
+ self.host = host.rstrip("/")
50
+ self.session = requests.Session()
51
+
52
+ # Set common headers
53
+ self.session.headers.update({
54
+ "Content-Type": "application/json",
55
+ "Accept": "application/json",
56
+ })
57
+
58
+ if token:
59
+ self.set_token(token)
60
+
61
+ def _build_url(self, path: str) -> str:
62
+ """Construct full URL from path"""
63
+ return urljoin(self.host, path.lstrip("/"))
64
+
65
+ def set_token(self, token: str):
66
+ """Set authorization token"""
67
+ self.session.headers["Authorization"] = f"Bearer {token}"
68
+
69
+ def _handle_response(self, response: requests.Response) -> Dict[str, Any]:
70
+ """Handle API response and raise appropriate errors"""
71
+ try:
72
+ response.raise_for_status()
73
+ return response.json()
74
+ except requests.exceptions.HTTPError:
75
+ try:
76
+ error_data = response.json()
77
+ except ValueError:
78
+ error_data = {"message": response.text}
79
+
80
+ raise APIError(
81
+ message=error_data.get("message", "Unknown error"),
82
+ status_code=response.status_code,
83
+ response=error_data
84
+ )
85
+ except requests.exceptions.RequestException as e:
86
+ raise InfisicalError(f"Request failed: {str(e)}")
87
+ except ValueError:
88
+ raise InfisicalError("Invalid JSON response")
89
+
90
+ def get(
91
+ self,
92
+ path: str,
93
+ model: type[T],
94
+ params: Optional[Dict[str, Any]] = None
95
+ ) -> APIResponse[T]:
96
+
97
+ """
98
+ Make a GET request and parse response into given model
99
+
100
+ Args:
101
+ path: API endpoint path
102
+ model: model class to parse response into
103
+ params: Optional query parameters
104
+ """
105
+ response = self.session.get(self._build_url(path), params=params)
106
+ data = self._handle_response(response)
107
+
108
+ parsed_data = model.from_dict(data) if hasattr(model, 'from_dict') else data
109
+
110
+ return APIResponse(
111
+ data=parsed_data,
112
+ status_code=response.status_code,
113
+ headers=dict(response.headers)
114
+ )
115
+
116
+ def post(
117
+ self,
118
+ path: str,
119
+ model: type[T],
120
+ json: Optional[Dict[str, Any]] = None
121
+ ) -> APIResponse[T]:
122
+
123
+ """Make a POST request with JSON data"""
124
+
125
+ if json is not None:
126
+ # Filter out None values
127
+ json = {k: v for k, v in json.items() if v is not None}
128
+
129
+ response = self.session.post(self._build_url(path), json=json)
130
+ data = self._handle_response(response)
131
+
132
+ parsed_data = model.from_dict(data) if hasattr(model, 'from_dict') else data
133
+
134
+ return APIResponse(
135
+ data=parsed_data,
136
+ status_code=response.status_code,
137
+ headers=dict(response.headers)
138
+ )
139
+
140
+ def patch(
141
+ self,
142
+ path: str,
143
+ model: type[T],
144
+ json: Optional[Dict[str, Any]] = None
145
+ ) -> APIResponse[T]:
146
+
147
+ """Make a PATCH request with JSON data"""
148
+
149
+ if json is not None:
150
+ # Filter out None values
151
+ json = {k: v for k, v in json.items() if v is not None}
152
+
153
+ response = self.session.patch(self._build_url(path), json=json)
154
+ data = self._handle_response(response)
155
+
156
+ parsed_data = model.from_dict(data) if hasattr(model, 'from_dict') else data
157
+
158
+ return APIResponse(
159
+ data=parsed_data,
160
+ status_code=response.status_code,
161
+ headers=dict(response.headers)
162
+ )
163
+
164
+ def delete(
165
+ self,
166
+ path: str,
167
+ model: type[T],
168
+ json: Optional[Dict[str, Any]] = None
169
+ ) -> APIResponse[T]:
170
+
171
+ """Make a PATCH request with JSON data"""
172
+
173
+ if json is not None:
174
+ # Filter out None values
175
+ json = {k: v for k, v in json.items() if v is not None}
176
+
177
+ response = self.session.delete(self._build_url(path), json=json)
178
+ data = self._handle_response(response)
179
+
180
+ parsed_data = model.from_dict(data) if hasattr(model, 'from_dict') else data
181
+
182
+ return APIResponse(
183
+ data=parsed_data,
184
+ status_code=response.status_code,
185
+ headers=dict(response.headers)
186
+ )
@@ -0,0 +1,26 @@
1
+ Metadata-Version: 2.2
2
+ Name: infisicalsdk
3
+ Version: 1.0.3
4
+ Summary: Infisical API Client
5
+ Home-page: https://github.com/Infisical/python-sdk-official
6
+ Author: Infisical
7
+ Author-email: support@infisical.com
8
+ Keywords: Infisical,Infisical API,Infisical SDK
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: urllib3<2.1.0,>=1.25.3
11
+ Requires-Dist: python-dateutil
12
+ Requires-Dist: aenum
13
+ Requires-Dist: requests~=2.32
14
+ Requires-Dist: boto3~=1.35
15
+ Requires-Dist: botocore~=1.35
16
+ Dynamic: author
17
+ Dynamic: author-email
18
+ Dynamic: description
19
+ Dynamic: description-content-type
20
+ Dynamic: home-page
21
+ Dynamic: keywords
22
+ Dynamic: requires-dist
23
+ Dynamic: summary
24
+
25
+ Infisical SDK client for Python. To view documentation, please visit https://github.com/Infisical/python-sdk-official
26
+
@@ -0,0 +1,8 @@
1
+ infisical_sdk/__init__.py,sha256=UzssDXpMhK79mFBW4fpSea1bOVjoD_UILjvizFkLNz4,183
2
+ infisical_sdk/api_types.py,sha256=FjyDQ71pOYiyYA9oGAPsW5jW7LGe5L7yDuOvCr4UxwQ,3651
3
+ infisical_sdk/client.py,sha256=i1poZEz2tiGJLYZuRePfWONs7hQyP_A5QJJt1UeW8WQ,10936
4
+ infisical_sdk/infisical_requests.py,sha256=mROtB1fuF3E39fU9J6MiH0gQ-LhsK10W-zzEH0knePU,5655
5
+ infisicalsdk-1.0.3.dist-info/METADATA,sha256=LuJqI82C7DTQdeYLCpixwYmYF49y_RfdDlVrSFDBpW4,763
6
+ infisicalsdk-1.0.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
7
+ infisicalsdk-1.0.3.dist-info/top_level.txt,sha256=FvJjMGD1FvxwipO_qFajdH20yNV8n3lJ7G3DkQoPJNU,14
8
+ infisicalsdk-1.0.3.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.8.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ infisical_sdk