stackmachine 0.2.1__tar.gz → 0.3.1__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 (35) hide show
  1. stackmachine-0.3.1/PKG-INFO +195 -0
  2. stackmachine-0.3.1/README.md +173 -0
  3. stackmachine-0.3.1/examples/async_usage.py +16 -0
  4. stackmachine-0.3.1/examples/basic_usage.py +13 -0
  5. stackmachine-0.3.1/examples/deploy_app.py +31 -0
  6. stackmachine-0.3.1/examples/list_apps.py +10 -0
  7. {stackmachine-0.2.1 → stackmachine-0.3.1}/pyproject.toml +33 -5
  8. stackmachine-0.3.1/src/stackmachine/__init__.py +144 -0
  9. stackmachine-0.3.1/src/stackmachine/_async_client.py +186 -0
  10. stackmachine-0.3.1/src/stackmachine/_client.py +184 -0
  11. stackmachine-0.3.1/src/stackmachine/_config.py +31 -0
  12. stackmachine-0.3.1/src/stackmachine/_errors.py +97 -0
  13. stackmachine-0.3.1/src/stackmachine/_graphql/__init__.py +1 -0
  14. stackmachine-0.3.1/src/stackmachine/_graphql/operations.py +551 -0
  15. stackmachine-0.3.1/src/stackmachine/_models.py +229 -0
  16. stackmachine-0.3.1/src/stackmachine/_pagination.py +388 -0
  17. stackmachine-0.3.1/src/stackmachine/_transport.py +590 -0
  18. stackmachine-0.3.1/src/stackmachine/_types.py +268 -0
  19. stackmachine-0.3.1/src/stackmachine/_uploads.py +373 -0
  20. stackmachine-0.3.1/src/stackmachine/_utils.py +77 -0
  21. stackmachine-0.3.1/src/stackmachine/resources/__init__.py +12 -0
  22. stackmachine-0.3.1/src/stackmachine/resources/_shared.py +44 -0
  23. stackmachine-0.3.1/src/stackmachine/resources/apps.py +284 -0
  24. stackmachine-0.3.1/src/stackmachine/resources/deployments.py +405 -0
  25. stackmachine-0.3.1/src/stackmachine/resources/domains.py +301 -0
  26. stackmachine-0.3.1/src/stackmachine/resources/files.py +82 -0
  27. stackmachine-0.3.1/src/stackmachine/resources/ssh.py +649 -0
  28. stackmachine-0.3.1/src/stackmachine/resources/versions.py +218 -0
  29. stackmachine-0.3.1/tests/test_package.py +282 -0
  30. stackmachine-0.2.1/PKG-INFO +0 -42
  31. stackmachine-0.2.1/README.md +0 -24
  32. stackmachine-0.2.1/src/stackmachine/__init__.py +0 -10
  33. stackmachine-0.2.1/tests/test_package.py +0 -7
  34. {stackmachine-0.2.1 → stackmachine-0.3.1}/.gitignore +0 -0
  35. {stackmachine-0.2.1 → stackmachine-0.3.1}/src/stackmachine/py.typed +0 -0
@@ -0,0 +1,195 @@
1
+ Metadata-Version: 2.4
2
+ Name: stackmachine
3
+ Version: 0.3.1
4
+ Summary: Python SDK for StackMachine.
5
+ Project-URL: Homepage, https://github.com/stackmachine/sdks/tree/main/python
6
+ Project-URL: Repository, https://github.com/stackmachine/sdks
7
+ Project-URL: Issues, https://github.com/stackmachine/sdks/issues
8
+ Classifier: Development Status :: 2 - Pre-Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Typing :: Typed
16
+ Requires-Python: >=3.9
17
+ Requires-Dist: httpx<1,>=0.27
18
+ Requires-Dist: typing-extensions<5,>=4.10
19
+ Requires-Dist: websocket-client<2,>=1.8
20
+ Requires-Dist: websockets<16,>=12
21
+ Description-Content-Type: text/markdown
22
+
23
+ # StackMachine Python SDK
24
+
25
+ Python SDK for StackMachine. It mirrors the JavaScript SDK surface with a
26
+ Pythonic sync client and a native async client.
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ uv add stackmachine
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ```python
37
+ from stackmachine import StackMachine
38
+
39
+ with StackMachine("sk_stackmachine_...") as stackmachine:
40
+ app = stackmachine.apps.retrieve_by_name("my-app")
41
+ print(app.url)
42
+ ```
43
+
44
+ ```python
45
+ from stackmachine import AsyncStackMachine
46
+
47
+ async with AsyncStackMachine("sk_stackmachine_...") as stackmachine:
48
+ app = await stackmachine.apps.retrieve_by_name("my-app")
49
+ print(app.url)
50
+ ```
51
+
52
+ ## Clients
53
+
54
+ `StackMachine` exposes sync methods. `AsyncStackMachine` exposes the same
55
+ resource tree with awaitable methods.
56
+
57
+ ```python
58
+ from stackmachine import AsyncStackMachine, StackMachine
59
+
60
+ stackmachine = StackMachine("sk_stackmachine_...")
61
+ async_stackmachine = AsyncStackMachine("sk_stackmachine_...")
62
+ ```
63
+
64
+ Both clients accept JavaScript-style aliases during initialization:
65
+
66
+ ```python
67
+ stackmachine = StackMachine.init(
68
+ {
69
+ "token": "sk_stackmachine_...",
70
+ "apiUrl": "https://api.stackmachine.com/graphql",
71
+ "maxNetworkRetries": 2,
72
+ }
73
+ )
74
+ ```
75
+
76
+ ## Apps
77
+
78
+ ```python
79
+ apps = stackmachine.apps.list(limit=10)
80
+
81
+ for app in apps:
82
+ print(app.id, app.name)
83
+
84
+ app = stackmachine.apps.retrieve("app_id")
85
+ app = stackmachine.apps.retrieve_by_name("my-app")
86
+ apps = stackmachine.apps.retrieve_many(["app_1", "app_2"])
87
+ stackmachine.apps.delete("app_id")
88
+ ```
89
+
90
+ Async lists can either be awaited for the first page or iterated directly:
91
+
92
+ ```python
93
+ apps = async_stackmachine.apps.list(limit=10)
94
+ first_page = await apps
95
+
96
+ async for app in apps:
97
+ print(app.name)
98
+ ```
99
+
100
+ ## Deployments
101
+
102
+ ```python
103
+ deployment = stackmachine.deployments.create(
104
+ {
105
+ "file": "https://example.com/app.zip",
106
+ "name": "my-app",
107
+ }
108
+ )
109
+
110
+ version = deployment.wait()
111
+ ```
112
+
113
+ ```python
114
+ deployment = stackmachine.apps.autobuild(
115
+ {
116
+ "file": "https://example.com/app.zip",
117
+ "name": "my-app",
118
+ }
119
+ )
120
+ ```
121
+
122
+ ## Files
123
+
124
+ ```python
125
+ from stackmachine import create_zip
126
+
127
+ zip_bytes = create_zip({"index.html": "<h1>Hello</h1>"})
128
+ url = stackmachine.files.upload(zip_bytes)
129
+ ```
130
+
131
+ ## Domains
132
+
133
+ ```python
134
+ domain = stackmachine.apps.domains.create(
135
+ app="app_id",
136
+ hostname="example.com",
137
+ )
138
+
139
+ is_verified = stackmachine.apps.domains.verify(domain.id)
140
+ stackmachine.apps.domains.delete(domain.id)
141
+ ```
142
+
143
+ ## SSH
144
+
145
+ ```python
146
+ server = stackmachine.apps.ssh.retrieve("app_id")
147
+ server = stackmachine.apps.ssh.update("app_id", enabled=True)
148
+ token = stackmachine.apps.ssh.tokens.create(app="app_id")
149
+
150
+ users = stackmachine.apps.ssh.users.list(app="app_id")
151
+ user = stackmachine.apps.ssh.users.retrieve("ssh_user_id")
152
+ password = stackmachine.apps.ssh.users.passwords.rotate("ssh_user_id")
153
+
154
+ key = stackmachine.apps.ssh.users.authorized_keys.create(
155
+ user="ssh_user_id",
156
+ public_key="ssh-ed25519 AAAA...",
157
+ )
158
+ ```
159
+
160
+ ## Request Options
161
+
162
+ Most methods accept `request_options` for per-request configuration:
163
+
164
+ ```python
165
+ app = stackmachine.apps.retrieve(
166
+ "app_id",
167
+ request_options={
168
+ "api_key": "sk_stackmachine_other",
169
+ "timeout": 30,
170
+ "idempotency_key": "deploy-123",
171
+ },
172
+ )
173
+ ```
174
+
175
+ ## Development
176
+
177
+ ```bash
178
+ cd python
179
+ uv sync --dev
180
+ uv run ruff check src examples tests
181
+ uv run mypy
182
+ uv run pytest
183
+ uv build --no-sources
184
+ ```
185
+
186
+ ## Manual Publish
187
+
188
+ Use this path only for manual package uploads:
189
+
190
+ ```bash
191
+ cd python
192
+ uv sync --dev
193
+ uv build --no-sources
194
+ uv publish
195
+ ```
@@ -0,0 +1,173 @@
1
+ # StackMachine Python SDK
2
+
3
+ Python SDK for StackMachine. It mirrors the JavaScript SDK surface with a
4
+ Pythonic sync client and a native async client.
5
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ uv add stackmachine
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ ```python
15
+ from stackmachine import StackMachine
16
+
17
+ with StackMachine("sk_stackmachine_...") as stackmachine:
18
+ app = stackmachine.apps.retrieve_by_name("my-app")
19
+ print(app.url)
20
+ ```
21
+
22
+ ```python
23
+ from stackmachine import AsyncStackMachine
24
+
25
+ async with AsyncStackMachine("sk_stackmachine_...") as stackmachine:
26
+ app = await stackmachine.apps.retrieve_by_name("my-app")
27
+ print(app.url)
28
+ ```
29
+
30
+ ## Clients
31
+
32
+ `StackMachine` exposes sync methods. `AsyncStackMachine` exposes the same
33
+ resource tree with awaitable methods.
34
+
35
+ ```python
36
+ from stackmachine import AsyncStackMachine, StackMachine
37
+
38
+ stackmachine = StackMachine("sk_stackmachine_...")
39
+ async_stackmachine = AsyncStackMachine("sk_stackmachine_...")
40
+ ```
41
+
42
+ Both clients accept JavaScript-style aliases during initialization:
43
+
44
+ ```python
45
+ stackmachine = StackMachine.init(
46
+ {
47
+ "token": "sk_stackmachine_...",
48
+ "apiUrl": "https://api.stackmachine.com/graphql",
49
+ "maxNetworkRetries": 2,
50
+ }
51
+ )
52
+ ```
53
+
54
+ ## Apps
55
+
56
+ ```python
57
+ apps = stackmachine.apps.list(limit=10)
58
+
59
+ for app in apps:
60
+ print(app.id, app.name)
61
+
62
+ app = stackmachine.apps.retrieve("app_id")
63
+ app = stackmachine.apps.retrieve_by_name("my-app")
64
+ apps = stackmachine.apps.retrieve_many(["app_1", "app_2"])
65
+ stackmachine.apps.delete("app_id")
66
+ ```
67
+
68
+ Async lists can either be awaited for the first page or iterated directly:
69
+
70
+ ```python
71
+ apps = async_stackmachine.apps.list(limit=10)
72
+ first_page = await apps
73
+
74
+ async for app in apps:
75
+ print(app.name)
76
+ ```
77
+
78
+ ## Deployments
79
+
80
+ ```python
81
+ deployment = stackmachine.deployments.create(
82
+ {
83
+ "file": "https://example.com/app.zip",
84
+ "name": "my-app",
85
+ }
86
+ )
87
+
88
+ version = deployment.wait()
89
+ ```
90
+
91
+ ```python
92
+ deployment = stackmachine.apps.autobuild(
93
+ {
94
+ "file": "https://example.com/app.zip",
95
+ "name": "my-app",
96
+ }
97
+ )
98
+ ```
99
+
100
+ ## Files
101
+
102
+ ```python
103
+ from stackmachine import create_zip
104
+
105
+ zip_bytes = create_zip({"index.html": "<h1>Hello</h1>"})
106
+ url = stackmachine.files.upload(zip_bytes)
107
+ ```
108
+
109
+ ## Domains
110
+
111
+ ```python
112
+ domain = stackmachine.apps.domains.create(
113
+ app="app_id",
114
+ hostname="example.com",
115
+ )
116
+
117
+ is_verified = stackmachine.apps.domains.verify(domain.id)
118
+ stackmachine.apps.domains.delete(domain.id)
119
+ ```
120
+
121
+ ## SSH
122
+
123
+ ```python
124
+ server = stackmachine.apps.ssh.retrieve("app_id")
125
+ server = stackmachine.apps.ssh.update("app_id", enabled=True)
126
+ token = stackmachine.apps.ssh.tokens.create(app="app_id")
127
+
128
+ users = stackmachine.apps.ssh.users.list(app="app_id")
129
+ user = stackmachine.apps.ssh.users.retrieve("ssh_user_id")
130
+ password = stackmachine.apps.ssh.users.passwords.rotate("ssh_user_id")
131
+
132
+ key = stackmachine.apps.ssh.users.authorized_keys.create(
133
+ user="ssh_user_id",
134
+ public_key="ssh-ed25519 AAAA...",
135
+ )
136
+ ```
137
+
138
+ ## Request Options
139
+
140
+ Most methods accept `request_options` for per-request configuration:
141
+
142
+ ```python
143
+ app = stackmachine.apps.retrieve(
144
+ "app_id",
145
+ request_options={
146
+ "api_key": "sk_stackmachine_other",
147
+ "timeout": 30,
148
+ "idempotency_key": "deploy-123",
149
+ },
150
+ )
151
+ ```
152
+
153
+ ## Development
154
+
155
+ ```bash
156
+ cd python
157
+ uv sync --dev
158
+ uv run ruff check src examples tests
159
+ uv run mypy
160
+ uv run pytest
161
+ uv build --no-sources
162
+ ```
163
+
164
+ ## Manual Publish
165
+
166
+ Use this path only for manual package uploads:
167
+
168
+ ```bash
169
+ cd python
170
+ uv sync --dev
171
+ uv build --no-sources
172
+ uv publish
173
+ ```
@@ -0,0 +1,16 @@
1
+ import asyncio
2
+ import os
3
+
4
+ from stackmachine import AsyncStackMachine
5
+
6
+
7
+ async def main():
8
+ async with AsyncStackMachine(os.environ["STACKMACHINE_API_KEY"]) as client:
9
+ viewer = await client.viewer()
10
+ print(viewer.username if viewer else "anonymous")
11
+
12
+ async for app in client.apps.list(limit=10):
13
+ print(app.name, app.url)
14
+
15
+
16
+ asyncio.run(main())
@@ -0,0 +1,13 @@
1
+ import os
2
+
3
+ from stackmachine import StackMachine
4
+
5
+ client = StackMachine(os.environ["STACKMACHINE_API_KEY"])
6
+
7
+ viewer = client.viewer()
8
+ print(viewer.username if viewer else "anonymous")
9
+
10
+ for app in client.apps.list(limit=10):
11
+ print(app.name, app.url)
12
+
13
+ client.close()
@@ -0,0 +1,31 @@
1
+ import os
2
+
3
+ from stackmachine import StackMachine, create_zip
4
+
5
+ client = StackMachine(os.environ["STACKMACHINE_API_KEY"])
6
+
7
+ zip_file = create_zip(
8
+ {
9
+ "index.php": "<html><body><h1>Hello StackMachine</h1></body></html>",
10
+ }
11
+ )
12
+
13
+ upload_url = client.files.upload(
14
+ zip_file,
15
+ on_progress=lambda progress: print("Uploading", progress.percent * 100, "%"),
16
+ )
17
+
18
+ deployment = client.deployments.create(
19
+ app_name="hello-stackmachine",
20
+ owner="stackmachine",
21
+ upload_url=upload_url,
22
+ )
23
+
24
+ app_version = deployment.wait(
25
+ on_progress=lambda event: print(
26
+ event.datetime, event.stream, event.kind, event.message
27
+ )
28
+ )
29
+
30
+ print(app_version.app.url)
31
+ client.close()
@@ -0,0 +1,10 @@
1
+ import os
2
+
3
+ from stackmachine import StackMachine
4
+
5
+ with StackMachine(os.environ["STACKMACHINE_API_KEY"]) as client:
6
+ apps = client.apps.list(limit=25)
7
+ print("First page:", len(apps.data))
8
+
9
+ for app in apps:
10
+ print(app.name, app.url)
@@ -4,11 +4,16 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "stackmachine"
7
- version = "0.2.1"
7
+ version = "0.3.1"
8
8
  description = "Python SDK for StackMachine."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
11
- dependencies = []
11
+ dependencies = [
12
+ "httpx>=0.27,<1",
13
+ "typing-extensions>=4.10,<5",
14
+ "websocket-client>=1.8,<2",
15
+ "websockets>=12,<16",
16
+ ]
12
17
  classifiers = [
13
18
  "Development Status :: 2 - Pre-Alpha",
14
19
  "Intended Audience :: Developers",
@@ -27,19 +32,42 @@ Issues = "https://github.com/stackmachine/sdks/issues"
27
32
 
28
33
  [dependency-groups]
29
34
  dev = [
35
+ "mypy>=1.13,<2",
30
36
  "pytest>=8.0",
37
+ "pytest-asyncio>=0.24",
38
+ "ruff>=0.8",
31
39
  ]
32
40
 
41
+ [tool.ruff]
42
+ line-length = 88
43
+ target-version = "py39"
44
+
45
+ [tool.ruff.lint]
46
+ select = ["E", "F", "I", "B"]
47
+
48
+ [tool.mypy]
49
+ python_version = "3.9"
50
+ files = ["src", "examples", "tests"]
51
+ pretty = true
52
+ show_error_codes = true
53
+ warn_unused_ignores = true
54
+
55
+ [[tool.mypy.overrides]]
56
+ module = ["pytest", "pytest.*"]
57
+ follow_imports = "skip"
58
+
59
+ [tool.pytest.ini_options]
60
+ testpaths = ["tests"]
61
+ asyncio_mode = "auto"
62
+
33
63
  [tool.hatch.build.targets.wheel]
34
64
  packages = ["src/stackmachine"]
35
65
 
36
66
  [tool.hatch.build.targets.sdist]
37
67
  include = [
38
68
  "/README.md",
69
+ "/examples",
39
70
  "/pyproject.toml",
40
71
  "/src",
41
72
  "/tests",
42
73
  ]
43
-
44
- [tool.pytest.ini_options]
45
- testpaths = ["tests"]
@@ -0,0 +1,144 @@
1
+ """StackMachine Python SDK."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ from ._async_client import AsyncStackMachine
6
+ from ._client import StackMachine
7
+ from ._config import RequestOptions
8
+ from ._errors import (
9
+ StackMachineAPIError,
10
+ StackMachineAuthenticationError,
11
+ StackMachineConnectionError,
12
+ StackMachineError,
13
+ StackMachineGraphQLError,
14
+ StackMachineInvalidRequestError,
15
+ StackMachinePermissionError,
16
+ StackMachineRateLimitError,
17
+ StackMachineValidationError,
18
+ is_stackmachine_error,
19
+ )
20
+ from ._models import (
21
+ AppAlias,
22
+ AppSshServer,
23
+ DeployApp,
24
+ DeployAppKindWordPress,
25
+ DeployAppVersion,
26
+ DeploymentProgress,
27
+ ExpectedDNSRecord,
28
+ Log,
29
+ SshAuthorizedKey,
30
+ SshUser,
31
+ UploadProgress,
32
+ Viewer,
33
+ )
34
+ from ._pagination import AsyncStackMachineList, StackMachineList
35
+ from ._types import (
36
+ AppAliasSortBy,
37
+ AppsDomainsCreateInput,
38
+ AppsDomainsListInput,
39
+ AppsSshAuthorizedKeysCreateInput,
40
+ AppsSshAuthorizedKeysDeleteInput,
41
+ AppsSshAuthorizedKeysListInput,
42
+ AppsSshServerUpdateInput,
43
+ AppsSshUsersListInput,
44
+ AppsSshUsersUpdateInput,
45
+ AppsVersionsListInput,
46
+ AppsVersionsLogsListInput,
47
+ AsyncStackMachineInitSettings,
48
+ CreateZipFiles,
49
+ DeployAppAutobuildExtraData,
50
+ DeployAppAutobuildInput,
51
+ DeployAppEnvVarInput,
52
+ DeployAppJobDefinitionInput,
53
+ DeployAppsListInput,
54
+ DeployAppsSortBy,
55
+ DeployAppVersionsSortBy,
56
+ DeployAppWordPressExtraData,
57
+ DeploymentProgressCallback,
58
+ FileInput,
59
+ Headers,
60
+ LogStream,
61
+ PaginationOptions,
62
+ Readable,
63
+ RequestOptionsInput,
64
+ RequestOptionsLike,
65
+ SshAuthenticationMethod,
66
+ SshTokenCreateResult,
67
+ SshUserPasswordRevealResult,
68
+ SshUserPasswordRotateResult,
69
+ StackMachineInitSettings,
70
+ UploadProgressCallback,
71
+ )
72
+ from ._uploads import create_zip
73
+
74
+ try:
75
+ __version__ = version("stackmachine")
76
+ except PackageNotFoundError:
77
+ __version__ = "0.3.1"
78
+
79
+ __all__ = [
80
+ "AppAlias",
81
+ "AppAliasSortBy",
82
+ "AppSshServer",
83
+ "AppsDomainsCreateInput",
84
+ "AppsDomainsListInput",
85
+ "AppsSshAuthorizedKeysCreateInput",
86
+ "AppsSshAuthorizedKeysDeleteInput",
87
+ "AppsSshAuthorizedKeysListInput",
88
+ "AppsSshServerUpdateInput",
89
+ "AppsSshUsersListInput",
90
+ "AppsSshUsersUpdateInput",
91
+ "AppsVersionsListInput",
92
+ "AppsVersionsLogsListInput",
93
+ "AsyncStackMachine",
94
+ "AsyncStackMachineInitSettings",
95
+ "AsyncStackMachineList",
96
+ "CreateZipFiles",
97
+ "DeployApp",
98
+ "DeployAppAutobuildExtraData",
99
+ "DeployAppAutobuildInput",
100
+ "DeployAppEnvVarInput",
101
+ "DeployAppJobDefinitionInput",
102
+ "DeployAppKindWordPress",
103
+ "DeployAppVersion",
104
+ "DeployAppVersionsSortBy",
105
+ "DeployAppWordPressExtraData",
106
+ "DeployAppsListInput",
107
+ "DeployAppsSortBy",
108
+ "DeploymentProgress",
109
+ "DeploymentProgressCallback",
110
+ "ExpectedDNSRecord",
111
+ "FileInput",
112
+ "Headers",
113
+ "Log",
114
+ "LogStream",
115
+ "PaginationOptions",
116
+ "Readable",
117
+ "RequestOptions",
118
+ "RequestOptionsInput",
119
+ "RequestOptionsLike",
120
+ "SshAuthenticationMethod",
121
+ "SshAuthorizedKey",
122
+ "SshTokenCreateResult",
123
+ "SshUser",
124
+ "SshUserPasswordRevealResult",
125
+ "SshUserPasswordRotateResult",
126
+ "StackMachine",
127
+ "StackMachineAPIError",
128
+ "StackMachineAuthenticationError",
129
+ "StackMachineConnectionError",
130
+ "StackMachineError",
131
+ "StackMachineGraphQLError",
132
+ "StackMachineInvalidRequestError",
133
+ "StackMachineList",
134
+ "StackMachineInitSettings",
135
+ "StackMachinePermissionError",
136
+ "StackMachineRateLimitError",
137
+ "StackMachineValidationError",
138
+ "UploadProgress",
139
+ "UploadProgressCallback",
140
+ "Viewer",
141
+ "__version__",
142
+ "create_zip",
143
+ "is_stackmachine_error",
144
+ ]