automizor 0.3.1__py3-none-any.whl → 0.4.1__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,9 +1,9 @@
1
- import os
2
1
  from typing import Dict, List, Union
3
2
 
4
3
  import requests
5
4
 
6
- from ._exceptions import AutomizorStorageError
5
+ from automizor.exceptions import AutomizorError, NotFound
6
+ from automizor.utils import get_api_config, get_headers
7
7
 
8
8
  JSON = Union[str, int, float, bool, None, Dict[str, "JSON"], List["JSON"]]
9
9
 
@@ -23,8 +23,7 @@ class Storage:
23
23
  To use this class effectively, ensure that the following environment variables are
24
24
  set in your environment:
25
25
 
26
- - ``AUTOMIZOR_API_HOST``: Specifies the host URL of the `Automizor Storage API`.
27
- - ``AUTOMIZOR_API_TOKEN``: Provides the token required for API authentication.
26
+ - ``AUTOMIZOR_AGENT_TOKEN``: The token for authenticating against the `Automizor API`.
28
27
 
29
28
  Example usage:
30
29
 
@@ -32,30 +31,82 @@ class Storage:
32
31
 
33
32
  from automizor import storage
34
33
 
35
- # To get bytes of an asset
36
- bytes_data = storage.get_bytes("asset_name")
34
+ # To list all assets
35
+ asset_names = storage.list_assets()
37
36
 
38
- # To save an asset to a file
39
- file_path = storage.get_file("asset_name", "/path/to/save/file")
37
+ # To delete an asset
38
+ storage.delete_asset("AssetName")
40
39
 
41
- # To retrieve an asset as JSON
42
- json_data = storage.get_json("asset_name")
40
+ # Save an asset
41
+ storage.set_bytes("AssetName", b"Hello, World!")
42
+ storage.set_file("AssetName", "/path/to/file")
43
+ storage.set_json("AssetName", {"key": "value"})
44
+ storage.set_text("AssetName", "Hello, World!")
43
45
 
44
- # To get the text content of an asset
45
- text_data = storage.get_text("asset_name")
46
+ # Get an asset
47
+ bytes_data = storage.get_bytes("AssetName")
48
+ file_path = storage.get_file("AssetName", "/path/to/save/file")
49
+ json_data = storage.get_json("AssetName")
50
+ text_data = storage.get_text("AssetName")
46
51
  """
47
52
 
48
53
  def __init__(self):
49
- self._api_host = os.getenv("AUTOMIZOR_API_HOST")
50
- self._api_token = os.getenv("AUTOMIZOR_API_TOKEN")
51
-
54
+ self.url, self.token = get_api_config()
52
55
  self.session = requests.Session()
53
- self.session.headers.update(
54
- {
55
- "Authorization": f"Token {self._api_token}",
56
- "Content-Type": "application/json",
57
- }
58
- )
56
+ self.session.headers.update(get_headers(self.token))
57
+
58
+ def list_assets(self) -> List[str]:
59
+ """
60
+ Retrieves a list of all asset names.
61
+
62
+ This function fetches the names of all assets stored in the storage service,
63
+ providing a convenient way to list and identify the available assets.
64
+
65
+ Returns:
66
+ A list of all asset names.
67
+ """
68
+ url = f"https://{self.url}/api/v1/storage/asset/"
69
+ asset_names = []
70
+
71
+ try:
72
+ while url:
73
+ response = self.session.get(url, timeout=10)
74
+ response.raise_for_status()
75
+ data = response.json()
76
+
77
+ for asset in data["results"]:
78
+ asset_names.append(asset["name"])
79
+ url = data["next"]
80
+ except requests.HTTPError as exc:
81
+ raise AutomizorError.from_response(
82
+ exc.response, "Failed to list assets"
83
+ ) from exc
84
+ except Exception as exc:
85
+ raise AutomizorError("Failed to list assets") from exc
86
+ return asset_names
87
+
88
+ def delete_asset(self, name: str):
89
+ """
90
+ Deletes the specified asset.
91
+
92
+ This function deletes the asset identified by `name` from the storage service.
93
+ It is useful for removing assets that are no longer needed or should be cleaned
94
+ up to free up storage space.
95
+
96
+ Parameters:
97
+ name: The name identifier of the asset to delete.
98
+ """
99
+
100
+ url = f"https://{self.url}/api/v1/storage/asset/{name}/"
101
+ try:
102
+ response = self.session.delete(url, timeout=10)
103
+ response.raise_for_status()
104
+ except requests.HTTPError as exc:
105
+ raise AutomizorError.from_response(
106
+ exc.response, "Failed to delete asset"
107
+ ) from exc
108
+ except Exception as exc:
109
+ raise AutomizorError("Failed to delete asset") from exc
59
110
 
60
111
  def get_bytes(self, name: str) -> bytes:
61
112
  """
@@ -72,8 +123,7 @@ class Storage:
72
123
  The raw byte content of the asset.
73
124
  """
74
125
 
75
- url = self._get_asset_url(name)
76
- return self._download_file(url, mode="content")
126
+ return self._download_file(name, mode="content")
77
127
 
78
128
  def get_file(self, name: str, path: str) -> str:
79
129
  """
@@ -92,8 +142,7 @@ class Storage:
92
142
  The path to the saved file, confirming the operation's success.
93
143
  """
94
144
 
95
- url = self._get_asset_url(name)
96
- content = self._download_file(url, mode="content")
145
+ content = self._download_file(name, mode="content")
97
146
  with open(path, "wb") as file:
98
147
  file.write(content)
99
148
  return path
@@ -113,8 +162,7 @@ class Storage:
113
162
  The parsed JSON data, which can be a dict, list, or primitive data type.
114
163
  """
115
164
 
116
- url = self._get_asset_url(name)
117
- return self._download_file(url, mode="json")
165
+ return self._download_file(name, mode="json")
118
166
 
119
167
  def get_text(self, name: str) -> str:
120
168
  """
@@ -131,13 +179,62 @@ class Storage:
131
179
  The content of the asset as a text string.
132
180
  """
133
181
 
182
+ return self._download_file(name, mode="text")
183
+
184
+ def set_bytes(self, name: str, content: bytes, content_type: str):
185
+ """
186
+ Uploads the specified content as a new asset.
187
+
188
+ This function uploads the provided `content` as a new asset with the specified
189
+ `name`. It is useful for creating new assets or updating existing ones with
190
+ fresh content.
191
+
192
+ Parameters:
193
+ name: The name identifier of the asset to create.
194
+ content: The raw byte content of the asset.
195
+ content_type: The MIME type of the asset content.
196
+ """
197
+
198
+ try:
199
+ self._update_asset(name, content, content_type)
200
+ except NotFound:
201
+ self._create_asset(name, content, content_type)
202
+
203
+ def _create_asset(self, name: str, content: bytes, content_type: str):
204
+ """
205
+ Creates a new asset with the specified content.
206
+
207
+ This function creates a new asset with the specified `name` and `content` in the
208
+ storage service. It is useful for uploading new assets or updating existing ones
209
+ with fresh content.
210
+
211
+ Parameters:
212
+ name: The name identifier of the asset to create.
213
+ content: The raw byte content of the asset.
214
+ content_type: The MIME type of the asset content.
215
+ """
216
+
217
+ url = f"https://{self.url}/api/v1/storage/asset/"
218
+ try:
219
+ data = {
220
+ "content_type": content_type,
221
+ "name": name,
222
+ }
223
+ files = {"file": ("text.txt", content, content_type)}
224
+ response = self.session.post(url, files=files, data=data, timeout=10)
225
+ response.raise_for_status()
226
+ except requests.HTTPError as exc:
227
+ raise AutomizorError.from_response(
228
+ exc.response, "Failed to create asset"
229
+ ) from exc
230
+ except Exception as exc:
231
+ raise AutomizorError("Failed to create asset") from exc
232
+
233
+ def _download_file(self, name: str, mode: str = "content"):
134
234
  url = self._get_asset_url(name)
135
- return self._download_file(url, mode="text")
136
235
 
137
- def _download_file(self, url: str, mode: str = "content"):
138
236
  try:
139
- session = requests.Session()
140
- response = session.get(url, timeout=10)
237
+ response = requests.get(url=url, timeout=10)
141
238
  response.raise_for_status()
142
239
 
143
240
  match mode:
@@ -148,11 +245,15 @@ class Storage:
148
245
  case "text":
149
246
  return response.text
150
247
  raise RuntimeError(f"Invalid mode {mode}")
248
+ except requests.HTTPError as exc:
249
+ raise AutomizorError.from_response(
250
+ exc.response, "Failed to download asset"
251
+ ) from exc
151
252
  except Exception as exc:
152
- raise AutomizorStorageError(f"Failed to download asset: {exc}") from exc
253
+ raise AutomizorError("Failed to download asset") from exc
153
254
 
154
255
  def _get_asset_url(self, name: str) -> str:
155
- url = f"https://{self._api_host}/api/v1/storage/asset/{name}/"
256
+ url = f"https://{self.url}/api/v1/storage/asset/{name}/"
156
257
  try:
157
258
  response = self.session.get(url, timeout=10)
158
259
  response.raise_for_status()
@@ -161,5 +262,39 @@ class Storage:
161
262
  if url:
162
263
  return url
163
264
  raise RuntimeError("Url not found")
265
+ except requests.HTTPError as exc:
266
+ raise AutomizorError.from_response(
267
+ exc.response, "Failed to get asset URL"
268
+ ) from exc
269
+ except Exception as exc:
270
+ raise AutomizorError("Failed to get asset URL") from exc
271
+
272
+ def _update_asset(self, name: str, content: bytes, content_type: str):
273
+ """
274
+ Updates the specified asset with new content.
275
+
276
+ This function updates the asset identified by `name` with fresh content
277
+ provided as `content`. It is useful for modifying existing assets without
278
+ creating a new asset, ensuring that the asset's content is up-to-date.
279
+
280
+ Parameters:
281
+ name: The name identifier of the asset to update.
282
+ content: The raw byte content of the asset.
283
+ content_type: The MIME type of the asset content.
284
+ """
285
+
286
+ url = f"https://{self.url}/api/v1/storage/asset/{name}/"
287
+ try:
288
+ data = {
289
+ "content_type": content_type,
290
+ "name": name,
291
+ }
292
+ files = {"file": ("text.txt", content, content_type)}
293
+ response = self.session.put(url, files=files, data=data, timeout=10)
294
+ response.raise_for_status()
295
+ except requests.HTTPError as exc:
296
+ raise AutomizorError.from_response(
297
+ exc.response, "Failed to update asset"
298
+ ) from exc
164
299
  except Exception as exc:
165
- raise AutomizorStorageError(f"Failed to get asset url: {exc}") from exc
300
+ raise AutomizorError("Failed to update asset") from exc
@@ -0,0 +1,31 @@
1
+ import os
2
+ import platform
3
+
4
+ from automizor import version
5
+ from automizor.exceptions import AutomizorError
6
+
7
+ OS_SYSTEM, OS_RELEASE, _ = platform.system_alias(
8
+ platform.system(), platform.release(), platform.version()
9
+ )
10
+
11
+
12
+ def get_api_config() -> tuple[str, str]:
13
+ token_string = os.getenv("AUTOMIZOR_AGENT_TOKEN")
14
+
15
+ if not token_string:
16
+ raise AutomizorError("AUTOMIZOR_AGENT_TOKEN is not set.")
17
+
18
+ try:
19
+ token, url = token_string.strip().split("@")
20
+ except ValueError as exc:
21
+ raise AutomizorError(
22
+ "AUTOMIZOR_AGENT_TOKEN is not in the correct format."
23
+ ) from exc
24
+ return url, token
25
+
26
+
27
+ def get_headers(token: str) -> dict:
28
+ return {
29
+ "Authorization": f"Token {token}",
30
+ "User-Agent": f"Automizor/{version} {OS_SYSTEM}/{OS_RELEASE}",
31
+ }
@@ -1,7 +1,7 @@
1
1
  from functools import lru_cache
2
+ from typing import Any, Dict
2
3
 
3
4
  from ._container import SecretContainer
4
- from ._exceptions import AutomizorVaultError
5
5
 
6
6
 
7
7
  @lru_cache
@@ -11,10 +11,40 @@ def _get_vault():
11
11
  return Vault()
12
12
 
13
13
 
14
+ def create_secret(
15
+ name: str,
16
+ value: Dict[str, Any],
17
+ description: str = "",
18
+ ) -> SecretContainer:
19
+ """
20
+ Creates a new secret. Stores the secret in the `Automizor API`.
21
+ If the secret already exists, it will be updated.
22
+
23
+ Args:
24
+ name: The name of the secret.
25
+ value: The value of the secret.
26
+ description: The description of the secret.
27
+
28
+ Returns:
29
+ The created secret.
30
+
31
+ Raises:
32
+ AutomizorVaultError: If creating the secret fails.
33
+ """
34
+
35
+ secret = SecretContainer(
36
+ name=name,
37
+ description=description,
38
+ value=value,
39
+ )
40
+
41
+ vault = _get_vault()
42
+ return vault.create_secret(secret)
43
+
44
+
14
45
  def get_secret(name: str) -> SecretContainer:
15
46
  """
16
- Retrieves a secret by its name. Fetches from a local file or queries the
17
- `Automizor API`, based on configuration.
47
+ Retrieves a secret by its name. Fetches from the `Automizor API`.
18
48
 
19
49
  Args:
20
50
  name: The name of the secret to retrieve.
@@ -32,8 +62,7 @@ def get_secret(name: str) -> SecretContainer:
32
62
 
33
63
  def set_secret(secret: SecretContainer) -> SecretContainer:
34
64
  """
35
- Updates an existing secret. Updates to a local file or to the
36
- `Automizor API`, based on configuration.
65
+ Updates an existing secret. Updates to the `Automizor API`.
37
66
 
38
67
  Args:
39
68
  secret: The secret to update.
@@ -50,8 +79,8 @@ def set_secret(secret: SecretContainer) -> SecretContainer:
50
79
 
51
80
 
52
81
  __all__ = [
53
- "AutomizorVaultError",
54
82
  "SecretContainer",
83
+ "create_secret",
55
84
  "get_secret",
56
85
  "set_secret",
57
86
  ]
@@ -1,4 +1,5 @@
1
1
  from dataclasses import dataclass, fields
2
+ from typing import Any, Dict
2
3
 
3
4
 
4
5
  def ignore_extra_fields(cls):
@@ -29,7 +30,7 @@ class SecretContainer:
29
30
  """
30
31
 
31
32
  name: str
32
- value: dict
33
+ value: Dict[str, Any]
33
34
  description: str = ""
34
35
 
35
36
  def get(self, key, default=None):
@@ -44,7 +45,7 @@ class SecretContainer:
44
45
  """Secret.keys() -> a set-like object providing a view on secret's keys."""
45
46
  return self.value.keys()
46
47
 
47
- def update(self, pairs: dict) -> None:
48
+ def update(self, pairs: Dict[str, Any]):
48
49
  """Update the secret's dictionary with the key-value pairs from pairs."""
49
50
  self.value.update(pairs)
50
51
 
automizor/vault/_vault.py CHANGED
@@ -1,42 +1,26 @@
1
- import json
2
- import os
3
1
  from dataclasses import asdict
4
2
 
5
3
  import requests
6
4
 
5
+ from automizor.exceptions import AutomizorError, NotFound
6
+ from automizor.utils import get_api_config, get_headers
7
+
7
8
  from ._container import SecretContainer
8
- from ._exceptions import AutomizorVaultError
9
9
 
10
10
 
11
11
  class Vault:
12
12
  """
13
13
  `Vault` is a secure storage class within the `Automizor Platform` for managing
14
14
  secrets such as API keys, passwords, and other sensitive information. It offers
15
- functionality to securely retrieve and update secrets, either through direct
16
- interaction with the `Automizor API` or via a local secrets file, depending on
17
- the operational environment and configuration.
15
+ functionality to securely retrieve and update secrets through direct interaction
16
+ with the `Automizor API`.
18
17
 
19
18
  Configuration for accessing and manipulating these secrets is driven by environment
20
19
  variables, which are essential for specifying the API's host and token for
21
- authentication purposes, alongside the location of a local secrets file, should
22
- local storage be preferred over API interaction.
20
+ authentication purposes.
23
21
 
24
22
  Environment variables requisite for operation include:
25
- - ``AUTOMIZOR_API_HOST``: The host URL for the `Automizor API`.
26
- - ``AUTOMIZOR_API_TOKEN``: The token for authenticate against the `Automizor API`.
27
- - ``AUTOMIZOR_SECRET_FILE``: Optionally specifies the path to a local file where
28
- secrets are stored, enabling operations in environments where direct API access
29
- may be restricted or unavailable.
30
-
31
- Example of a local secret file:
32
-
33
- .. code-block:: json
34
-
35
- {
36
- "my_secret_name": {
37
- "key": "value"
38
- }
39
- }
23
+ - ``AUTOMIZOR_AGENT_TOKEN``: The token for authenticating against the `Automizor API`.
40
24
 
41
25
  Example usage:
42
26
 
@@ -44,33 +28,48 @@ class Vault:
44
28
 
45
29
  from automizor import vault
46
30
 
31
+ # Create a new secret
32
+ vault.create_secret(name="MySecret", value={"username": "admin", "password": "*****"})
33
+
47
34
  # Retrieve a secret by its name
48
- secret = vault.get_secret("my_secret_name")
49
- print(secret["key"]) # Output: "value"
35
+ secret = vault.get_secret("MySecret")
36
+ print(secret.get("username")) # Output: "admin"
37
+ print(secret.get("password")) # Output: "*****"
50
38
 
51
39
  # Update a existing secret
52
- secret = vault.get_secret("my_secret_name")
53
- secret["new_key"] = "new_value"
40
+ secret = vault.get_secret("MySecret")
41
+ secret.update({"username": "user"})
54
42
  vault.set_secret(secret)
55
43
  """
56
44
 
57
45
  def __init__(self):
58
- self._api_host = os.getenv("AUTOMIZOR_API_HOST")
59
- self._api_token = os.getenv("AUTOMIZOR_API_TOKEN")
60
- self._secret_file = os.getenv("AUTOMIZOR_SECRET_FILE")
61
-
46
+ self.url, self.token = get_api_config()
62
47
  self.session = requests.Session()
63
- self.session.headers.update(
64
- {
65
- "Authorization": f"Token {self._api_token}",
66
- "Content-Type": "application/json",
67
- }
68
- )
48
+ self.session.headers.update(get_headers(self.token))
49
+
50
+ def create_secret(self, secret: SecretContainer) -> SecretContainer:
51
+ """
52
+ Creates a new secret. Stores the secret in the `Automizor API`.
53
+ If the secret already exists, it will be updated.
54
+
55
+ Args:
56
+ secret: The secret to create.
57
+
58
+ Returns:
59
+ The created secret.
60
+
61
+ Raises:
62
+ AutomizorVaultError: If creating the secret fails.
63
+ """
64
+
65
+ try:
66
+ return self._update_secret(secret)
67
+ except NotFound:
68
+ return self._create_secret(secret)
69
69
 
70
70
  def get_secret(self, name) -> SecretContainer:
71
71
  """
72
- Retrieves a secret by its name. Fetches from a local file or queries the
73
- `Automizor API`, based on configuration.
72
+ Retrieves a secret by its name. Fetches from the `Automizor API`.
74
73
 
75
74
  Args:
76
75
  name: The name of the secret to retrieve.
@@ -82,14 +81,11 @@ class Vault:
82
81
  AutomizorVaultError: If retrieving the secret fails.
83
82
  """
84
83
 
85
- if self._secret_file:
86
- return self._read_file_secret(name)
87
- return self._read_vault_secret(name)
84
+ return self._get_secret(name)
88
85
 
89
86
  def set_secret(self, secret: SecretContainer) -> SecretContainer:
90
87
  """
91
- Updates an existing secret. Updates to a local file or to the
92
- `Automizor API`, based on configuration.
88
+ Updates an existing secret. Updates to the `Automizor API`.
93
89
 
94
90
  Args:
95
91
  secret: The secret to update.
@@ -101,39 +97,43 @@ class Vault:
101
97
  AutomizorVaultError: If updating the secret fails.
102
98
  """
103
99
 
104
- if self._secret_file:
105
- return self._write_file_secret(secret)
106
- return self._write_vault_secret(secret)
100
+ return self._update_secret(secret)
107
101
 
108
- def _read_file_secret(self, name: str) -> SecretContainer:
109
- with open(self._secret_file, "r", encoding="utf-8") as file:
110
- secrets = json.load(file)
111
- value = secrets.get(name, {})
112
- return SecretContainer(name=name, value=value)
102
+ def _create_secret(self, secret: SecretContainer) -> SecretContainer:
103
+ url = f"https://{self.url}/api/v1/vault/secret/"
104
+ try:
105
+ response = self.session.post(url, timeout=10, json=asdict(secret))
106
+ response.raise_for_status()
107
+ return SecretContainer(**response.json())
108
+ except requests.HTTPError as exc:
109
+ raise AutomizorError.from_response(
110
+ exc.response, "Failed to create secret"
111
+ ) from exc
112
+ except Exception as exc:
113
+ raise AutomizorError("Failed to create secret") from exc
113
114
 
114
- def _read_vault_secret(self, name: str) -> SecretContainer:
115
- url = f"https://{self._api_host}/api/v1/vault/secret/{name}/"
115
+ def _get_secret(self, name: str) -> SecretContainer:
116
+ url = f"https://{self.url}/api/v1/vault/secret/{name}/"
116
117
  try:
117
118
  response = self.session.get(url, timeout=10)
118
119
  response.raise_for_status()
119
120
  return SecretContainer(**response.json())
121
+ except requests.HTTPError as exc:
122
+ raise AutomizorError.from_response(
123
+ exc.response, "Failed to get secret"
124
+ ) from exc
120
125
  except Exception as exc:
121
- raise AutomizorVaultError(f"Failed to get secret: {exc}") from exc
122
-
123
- def _write_file_secret(self, secret: SecretContainer):
124
- with open(self._secret_file, "r+", encoding="utf-8") as file:
125
- secrets = json.load(file)
126
- secrets[secret.name] = secret.value
127
- file.seek(0)
128
- file.write(json.dumps(secrets, indent=4))
129
- file.truncate()
130
- return secret
131
-
132
- def _write_vault_secret(self, secret: SecretContainer) -> SecretContainer:
133
- url = f"https://{self._api_host}/api/v1/vault/secret/{secret.name}/"
126
+ raise AutomizorError("Failed to get secret") from exc
127
+
128
+ def _update_secret(self, secret: SecretContainer) -> SecretContainer:
129
+ url = f"https://{self.url}/api/v1/vault/secret/{secret.name}/"
134
130
  try:
135
131
  response = self.session.put(url, timeout=10, json=asdict(secret))
136
132
  response.raise_for_status()
137
133
  return SecretContainer(**response.json())
134
+ except requests.HTTPError as exc:
135
+ raise AutomizorError.from_response(
136
+ exc.response, "Failed to update secret"
137
+ ) from exc
138
138
  except Exception as exc:
139
- raise AutomizorVaultError(f"Failed to set secret: {exc}") from exc
139
+ raise AutomizorError("Failed to update secret") from exc
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: automizor
3
- Version: 0.3.1
3
+ Version: 0.4.1
4
4
  Summary: Python Automizor framework
5
- Home-page: https://github.com/automizor/automizor
5
+ Home-page: https://github.com/automizor/automizor-python
6
6
  Author: Christian Fischer
7
7
  Author-email: christian@automizor.io
8
8
  License: Apache License
@@ -0,0 +1,17 @@
1
+ automizor/__init__.py,sha256=FBeN5tbWV0BpBmjJ3d3pzaNRlEg_Blp421Tbg8X3cAI,18
2
+ automizor/exceptions.py,sha256=P5imySIOtG3ZIk2kh41Yod4RnlgTj7Vf0P3M-RuxQJs,1382
3
+ automizor/job/__init__.py,sha256=DNRuT6cyPQBaPRG4vNalCmEvcJQl-73b5ZDFOfNOwIg,1019
4
+ automizor/job/_job.py,sha256=_-ehqPwJdY89mWm3_VAuh7KRJdv-8iUu6iMAzwGLHM0,5235
5
+ automizor/log/__init__.py,sha256=SVCIoKAQfXMIb99_204dgSqFSHO9T74RXpTZq33akKc,1978
6
+ automizor/log/_log.py,sha256=CI40pFMhSymeIcBFUoW3zIvYd2WMLDxekNapNIra62M,2651
7
+ automizor/storage/__init__.py,sha256=bEY2R0Vk0cqscKYNnX-MM222XrxbLXOvOSBDgFmVPLo,3984
8
+ automizor/storage/_storage.py,sha256=DXcARkFZ3edoDRrDiR02zkO7LmGkRtcKTHmgPsal0lc,10989
9
+ automizor/utils/__init__.py,sha256=2trRoR5lljYKbYdxmioSlvzajjQM0Wnoq3bvF9lEZ6w,811
10
+ automizor/vault/__init__.py,sha256=UjRiW3J0R9ABXc1gXIPyS3cqNCwMWxx0l-C0PsIg7R0,1699
11
+ automizor/vault/_container.py,sha256=-2y7kASigoIVAebuQBk-0R_sI4gfmvjsMLuMg_tR1xA,1945
12
+ automizor/vault/_vault.py,sha256=uRsjOjzsstZpYwJoHNg_cpv803Dzo4T2oF6hwiG3Eww,4688
13
+ automizor-0.4.1.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
14
+ automizor-0.4.1.dist-info/METADATA,sha256=aEGhSTMMVvV0XGcs2edBG3bhjHl8UAEu1Pe2ecN7EuU,668
15
+ automizor-0.4.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
16
+ automizor-0.4.1.dist-info/top_level.txt,sha256=gScDy4I3tP6BMYAsTAlBXrxVh3E00zV0UioxwXJOI3Y,10
17
+ automizor-0.4.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,2 +0,0 @@
1
- class AutomizorJobError(RuntimeError):
2
- """Exception raised for errors encountered while interacting with the Job."""