jac-scale 0.1.1__py3-none-any.whl → 0.1.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.
- jac_scale/abstractions/config/app_config.jac +5 -2
- jac_scale/context.jac +2 -1
- jac_scale/factories/storage_factory.jac +75 -0
- jac_scale/google_sso_provider.jac +85 -0
- jac_scale/impl/context.impl.jac +3 -0
- jac_scale/impl/serve.impl.jac +82 -234
- jac_scale/impl/user_manager.impl.jac +349 -0
- jac_scale/memory_hierarchy.jac +3 -1
- jac_scale/plugin.jac +46 -3
- jac_scale/plugin_config.jac +27 -0
- jac_scale/serve.jac +3 -12
- jac_scale/sso_provider.jac +72 -0
- jac_scale/targets/kubernetes/kubernetes_config.jac +9 -15
- jac_scale/targets/kubernetes/kubernetes_target.jac +174 -15
- jac_scale/tests/fixtures/scale-feats/components/Button.cl.jac +32 -0
- jac_scale/tests/fixtures/scale-feats/main.jac +147 -0
- jac_scale/tests/fixtures/test_api.jac +29 -0
- jac_scale/tests/fixtures/test_restspec.jac +37 -0
- jac_scale/tests/test_deploy_k8s.py +2 -1
- jac_scale/tests/test_examples.py +180 -5
- jac_scale/tests/test_hooks.py +39 -0
- jac_scale/tests/test_restspec.py +192 -0
- jac_scale/tests/test_serve.py +54 -0
- jac_scale/tests/test_sso.py +273 -284
- jac_scale/tests/test_storage.py +274 -0
- jac_scale/user_manager.jac +49 -0
- {jac_scale-0.1.1.dist-info → jac_scale-0.1.3.dist-info}/METADATA +9 -2
- {jac_scale-0.1.1.dist-info → jac_scale-0.1.3.dist-info}/RECORD +31 -20
- {jac_scale-0.1.1.dist-info → jac_scale-0.1.3.dist-info}/WHEEL +1 -1
- {jac_scale-0.1.1.dist-info → jac_scale-0.1.3.dist-info}/entry_points.txt +0 -0
- {jac_scale-0.1.1.dist-info → jac_scale-0.1.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
"""Tests for the storage abstraction."""
|
|
2
|
+
|
|
3
|
+
import io
|
|
4
|
+
import os
|
|
5
|
+
import shutil
|
|
6
|
+
import tempfile
|
|
7
|
+
from collections.abc import Generator
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from jaclang.runtimelib.storage import LocalStorage # type: ignore[attr-defined]
|
|
14
|
+
except ImportError as e:
|
|
15
|
+
pytest.skip(f"Jac modules not compiled: {e}", allow_module_level=True)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.fixture
|
|
19
|
+
def temp_storage_dir() -> Generator[str, None, None]:
|
|
20
|
+
"""Create a temporary directory for storage tests."""
|
|
21
|
+
temp_dir = tempfile.mkdtemp()
|
|
22
|
+
yield temp_dir
|
|
23
|
+
if os.path.exists(temp_dir):
|
|
24
|
+
shutil.rmtree(temp_dir)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.fixture
|
|
28
|
+
def local_storage(temp_storage_dir: str) -> Generator[LocalStorage, None, None]:
|
|
29
|
+
"""Create a LocalStorage instance with temp directory."""
|
|
30
|
+
storage = LocalStorage(base_path=temp_storage_dir)
|
|
31
|
+
yield storage
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class TestLocalStorage:
|
|
35
|
+
"""Tests for LocalStorage implementation."""
|
|
36
|
+
|
|
37
|
+
def test_upload_from_file_path(
|
|
38
|
+
self, local_storage: LocalStorage, temp_storage_dir: str
|
|
39
|
+
) -> None:
|
|
40
|
+
"""Test uploading a file from a file path."""
|
|
41
|
+
source_file = Path(temp_storage_dir) / "source.txt"
|
|
42
|
+
source_file.write_text("Hello, World!")
|
|
43
|
+
|
|
44
|
+
result = local_storage.upload(str(source_file), "uploaded/file.txt")
|
|
45
|
+
|
|
46
|
+
assert local_storage.exists("uploaded/file.txt")
|
|
47
|
+
assert Path(result).exists()
|
|
48
|
+
|
|
49
|
+
def test_upload_from_file_object(self, local_storage: LocalStorage) -> None:
|
|
50
|
+
"""Test uploading from a file-like object."""
|
|
51
|
+
file_obj = io.BytesIO(b"Binary content here")
|
|
52
|
+
|
|
53
|
+
local_storage.upload(file_obj, "binary/data.bin")
|
|
54
|
+
|
|
55
|
+
assert local_storage.exists("binary/data.bin")
|
|
56
|
+
content = local_storage.download("binary/data.bin")
|
|
57
|
+
assert content == b"Binary content here"
|
|
58
|
+
|
|
59
|
+
def test_download_returns_bytes(self, local_storage: LocalStorage) -> None:
|
|
60
|
+
"""Test download returns bytes when no destination specified."""
|
|
61
|
+
file_obj = io.BytesIO(b"Test content")
|
|
62
|
+
local_storage.upload(file_obj, "test.txt")
|
|
63
|
+
|
|
64
|
+
content = local_storage.download("test.txt")
|
|
65
|
+
|
|
66
|
+
assert content == b"Test content"
|
|
67
|
+
|
|
68
|
+
def test_download_to_file_path(
|
|
69
|
+
self, local_storage: LocalStorage, temp_storage_dir: str
|
|
70
|
+
) -> None:
|
|
71
|
+
"""Test download to a file path."""
|
|
72
|
+
file_obj = io.BytesIO(b"Download me")
|
|
73
|
+
local_storage.upload(file_obj, "source.txt")
|
|
74
|
+
dest_path = Path(temp_storage_dir) / "downloaded.txt"
|
|
75
|
+
|
|
76
|
+
local_storage.download("source.txt", str(dest_path))
|
|
77
|
+
|
|
78
|
+
assert dest_path.exists()
|
|
79
|
+
assert dest_path.read_bytes() == b"Download me"
|
|
80
|
+
|
|
81
|
+
def test_download_to_file_object(self, local_storage: LocalStorage) -> None:
|
|
82
|
+
"""Test download to a file-like object."""
|
|
83
|
+
file_obj = io.BytesIO(b"Stream me")
|
|
84
|
+
local_storage.upload(file_obj, "stream.txt")
|
|
85
|
+
output = io.BytesIO()
|
|
86
|
+
|
|
87
|
+
local_storage.download("stream.txt", output)
|
|
88
|
+
|
|
89
|
+
output.seek(0)
|
|
90
|
+
assert output.read() == b"Stream me"
|
|
91
|
+
|
|
92
|
+
def test_download_nonexistent_file_raises(
|
|
93
|
+
self, local_storage: LocalStorage
|
|
94
|
+
) -> None:
|
|
95
|
+
"""Test that downloading a non-existent file raises FileNotFoundError."""
|
|
96
|
+
with pytest.raises(FileNotFoundError):
|
|
97
|
+
local_storage.download("nonexistent.txt")
|
|
98
|
+
|
|
99
|
+
def test_delete_existing_file(self, local_storage: LocalStorage) -> None:
|
|
100
|
+
"""Test deleting an existing file."""
|
|
101
|
+
file_obj = io.BytesIO(b"Delete me")
|
|
102
|
+
local_storage.upload(file_obj, "to_delete.txt")
|
|
103
|
+
assert local_storage.exists("to_delete.txt")
|
|
104
|
+
|
|
105
|
+
result = local_storage.delete("to_delete.txt")
|
|
106
|
+
|
|
107
|
+
assert result is True
|
|
108
|
+
assert not local_storage.exists("to_delete.txt")
|
|
109
|
+
|
|
110
|
+
def test_delete_nonexistent_file(self, local_storage: LocalStorage) -> None:
|
|
111
|
+
"""Test deleting a non-existent file returns False."""
|
|
112
|
+
result = local_storage.delete("nonexistent.txt")
|
|
113
|
+
|
|
114
|
+
assert result is False
|
|
115
|
+
|
|
116
|
+
def test_exists_returns_true_for_existing(
|
|
117
|
+
self, local_storage: LocalStorage
|
|
118
|
+
) -> None:
|
|
119
|
+
"""Test exists returns True for existing file."""
|
|
120
|
+
file_obj = io.BytesIO(b"I exist")
|
|
121
|
+
local_storage.upload(file_obj, "exists.txt")
|
|
122
|
+
|
|
123
|
+
assert local_storage.exists("exists.txt") is True
|
|
124
|
+
|
|
125
|
+
def test_exists_returns_false_for_nonexistent(
|
|
126
|
+
self, local_storage: LocalStorage
|
|
127
|
+
) -> None:
|
|
128
|
+
"""Test exists returns False for non-existent file."""
|
|
129
|
+
assert local_storage.exists("nonexistent.txt") is False
|
|
130
|
+
|
|
131
|
+
def test_list_files_non_recursive(self, local_storage: LocalStorage) -> None:
|
|
132
|
+
"""Test listing files non-recursively."""
|
|
133
|
+
local_storage.upload(io.BytesIO(b"1"), "folder/file1.txt")
|
|
134
|
+
local_storage.upload(io.BytesIO(b"2"), "folder/file2.txt")
|
|
135
|
+
local_storage.upload(io.BytesIO(b"3"), "folder/sub/file3.txt")
|
|
136
|
+
|
|
137
|
+
files = list(local_storage.list_files("folder", recursive=False))
|
|
138
|
+
|
|
139
|
+
# Should include file1, file2, and sub directory
|
|
140
|
+
assert len(files) == 3
|
|
141
|
+
|
|
142
|
+
def test_list_files_recursive(self, local_storage: LocalStorage) -> None:
|
|
143
|
+
"""Test listing files recursively."""
|
|
144
|
+
local_storage.upload(io.BytesIO(b"1"), "folder/file1.txt")
|
|
145
|
+
local_storage.upload(io.BytesIO(b"2"), "folder/file2.txt")
|
|
146
|
+
local_storage.upload(io.BytesIO(b"3"), "folder/sub/file3.txt")
|
|
147
|
+
|
|
148
|
+
files = list(local_storage.list_files("folder", recursive=True))
|
|
149
|
+
|
|
150
|
+
# Should only include files (not directories) recursively
|
|
151
|
+
assert len(files) == 3
|
|
152
|
+
assert any("file1.txt" in f for f in files)
|
|
153
|
+
assert any("file2.txt" in f for f in files)
|
|
154
|
+
assert any("file3.txt" in f for f in files)
|
|
155
|
+
|
|
156
|
+
def test_get_metadata(self, local_storage: LocalStorage) -> None:
|
|
157
|
+
"""Test getting file metadata."""
|
|
158
|
+
content = b"Metadata test content"
|
|
159
|
+
local_storage.upload(io.BytesIO(content), "meta.txt")
|
|
160
|
+
|
|
161
|
+
metadata = local_storage.get_metadata("meta.txt")
|
|
162
|
+
|
|
163
|
+
assert metadata["size"] == len(content)
|
|
164
|
+
assert "modified" in metadata
|
|
165
|
+
assert "created" in metadata
|
|
166
|
+
assert metadata["is_dir"] is False
|
|
167
|
+
assert metadata["name"] == "meta.txt"
|
|
168
|
+
|
|
169
|
+
def test_get_metadata_nonexistent_raises(self, local_storage: LocalStorage) -> None:
|
|
170
|
+
"""Test that getting metadata of non-existent file raises error."""
|
|
171
|
+
with pytest.raises(FileNotFoundError):
|
|
172
|
+
local_storage.get_metadata("nonexistent.txt")
|
|
173
|
+
|
|
174
|
+
def test_copy_file(self, local_storage: LocalStorage) -> None:
|
|
175
|
+
"""Test copying a file."""
|
|
176
|
+
local_storage.upload(io.BytesIO(b"Copy me"), "original.txt")
|
|
177
|
+
|
|
178
|
+
result = local_storage.copy("original.txt", "copied.txt")
|
|
179
|
+
|
|
180
|
+
assert result is True
|
|
181
|
+
assert local_storage.exists("original.txt")
|
|
182
|
+
assert local_storage.exists("copied.txt")
|
|
183
|
+
assert local_storage.download("copied.txt") == b"Copy me"
|
|
184
|
+
|
|
185
|
+
def test_copy_nonexistent_returns_false(self, local_storage: LocalStorage) -> None:
|
|
186
|
+
"""Test copying non-existent file returns False."""
|
|
187
|
+
result = local_storage.copy("nonexistent.txt", "dest.txt")
|
|
188
|
+
|
|
189
|
+
assert result is False
|
|
190
|
+
|
|
191
|
+
def test_move_file(self, local_storage: LocalStorage) -> None:
|
|
192
|
+
"""Test moving a file."""
|
|
193
|
+
local_storage.upload(io.BytesIO(b"Move me"), "to_move.txt")
|
|
194
|
+
|
|
195
|
+
result = local_storage.move("to_move.txt", "moved.txt")
|
|
196
|
+
|
|
197
|
+
assert result is True
|
|
198
|
+
assert not local_storage.exists("to_move.txt")
|
|
199
|
+
assert local_storage.exists("moved.txt")
|
|
200
|
+
assert local_storage.download("moved.txt") == b"Move me"
|
|
201
|
+
|
|
202
|
+
def test_move_nonexistent_returns_false(self, local_storage: LocalStorage) -> None:
|
|
203
|
+
"""Test moving non-existent file returns False."""
|
|
204
|
+
result = local_storage.move("nonexistent.txt", "dest.txt")
|
|
205
|
+
|
|
206
|
+
assert result is False
|
|
207
|
+
|
|
208
|
+
def test_creates_directories_automatically(self, temp_storage_dir: str) -> None:
|
|
209
|
+
"""Test that directories are created when create_dirs is True."""
|
|
210
|
+
new_path = os.path.join(temp_storage_dir, "new", "nested", "dir")
|
|
211
|
+
LocalStorage(base_path=new_path, create_dirs=True)
|
|
212
|
+
|
|
213
|
+
assert os.path.exists(new_path)
|
|
214
|
+
|
|
215
|
+
def test_upload_creates_parent_directories(
|
|
216
|
+
self, local_storage: LocalStorage
|
|
217
|
+
) -> None:
|
|
218
|
+
"""Test that upload creates parent directories as needed."""
|
|
219
|
+
file_obj = io.BytesIO(b"Nested content")
|
|
220
|
+
|
|
221
|
+
local_storage.upload(file_obj, "deep/nested/folder/file.txt")
|
|
222
|
+
|
|
223
|
+
assert local_storage.exists("deep/nested/folder/file.txt")
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class TestStorageIntegration:
|
|
227
|
+
"""Integration tests for storage operations."""
|
|
228
|
+
|
|
229
|
+
def test_full_file_lifecycle(self, local_storage: LocalStorage) -> None:
|
|
230
|
+
"""Test complete file lifecycle: upload, read, copy, move, delete."""
|
|
231
|
+
# Upload
|
|
232
|
+
content = b"Lifecycle test content"
|
|
233
|
+
local_storage.upload(io.BytesIO(content), "lifecycle.txt")
|
|
234
|
+
assert local_storage.exists("lifecycle.txt")
|
|
235
|
+
|
|
236
|
+
# Read
|
|
237
|
+
downloaded = local_storage.download("lifecycle.txt")
|
|
238
|
+
assert downloaded == content
|
|
239
|
+
|
|
240
|
+
# Copy
|
|
241
|
+
local_storage.copy("lifecycle.txt", "lifecycle_copy.txt")
|
|
242
|
+
assert local_storage.exists("lifecycle_copy.txt")
|
|
243
|
+
|
|
244
|
+
# Move
|
|
245
|
+
local_storage.move("lifecycle_copy.txt", "lifecycle_moved.txt")
|
|
246
|
+
assert not local_storage.exists("lifecycle_copy.txt")
|
|
247
|
+
assert local_storage.exists("lifecycle_moved.txt")
|
|
248
|
+
|
|
249
|
+
# Delete
|
|
250
|
+
local_storage.delete("lifecycle.txt")
|
|
251
|
+
local_storage.delete("lifecycle_moved.txt")
|
|
252
|
+
assert not local_storage.exists("lifecycle.txt")
|
|
253
|
+
assert not local_storage.exists("lifecycle_moved.txt")
|
|
254
|
+
|
|
255
|
+
def test_upload_large_file(self, local_storage: LocalStorage) -> None:
|
|
256
|
+
"""Test uploading a larger file (1MB)."""
|
|
257
|
+
large_content = b"x" * (1024 * 1024) # 1MB
|
|
258
|
+
file_obj = io.BytesIO(large_content)
|
|
259
|
+
|
|
260
|
+
local_storage.upload(file_obj, "large_file.bin")
|
|
261
|
+
|
|
262
|
+
metadata = local_storage.get_metadata("large_file.bin")
|
|
263
|
+
assert metadata["size"] == 1024 * 1024
|
|
264
|
+
|
|
265
|
+
downloaded = local_storage.download("large_file.bin")
|
|
266
|
+
assert downloaded == large_content
|
|
267
|
+
|
|
268
|
+
def test_special_characters_in_filename(self, local_storage: LocalStorage) -> None:
|
|
269
|
+
"""Test handling files with special characters in name."""
|
|
270
|
+
content = b"Special chars"
|
|
271
|
+
local_storage.upload(io.BytesIO(content), "file-with_special.chars.txt")
|
|
272
|
+
|
|
273
|
+
assert local_storage.exists("file-with_special.chars.txt")
|
|
274
|
+
assert local_storage.download("file-with_special.chars.txt") == content
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import jwt;
|
|
2
|
+
import from datetime { UTC, datetime, timedelta }
|
|
3
|
+
import from typing { Any }
|
|
4
|
+
import from fastapi { Request, Response }
|
|
5
|
+
import from jaclang.runtimelib.server { UserManager }
|
|
6
|
+
import from jaclang.runtimelib.transport { TransportResponse, Meta }
|
|
7
|
+
import from jac_scale.serve { Platforms, Operations }
|
|
8
|
+
import from jac_scale.utils { generate_random_password }
|
|
9
|
+
import from jac_scale.config_loader { get_scale_config }
|
|
10
|
+
import from jac_scale.sso_provider { SSOProvider, SSOUserInfo }
|
|
11
|
+
import from jac_scale.google_sso_provider { GoogleSSOProvider }
|
|
12
|
+
|
|
13
|
+
# Load configuration
|
|
14
|
+
glob _jwt_config = get_scale_config().get_jwt_config(),
|
|
15
|
+
_sso_config = get_scale_config().get_sso_config(),
|
|
16
|
+
JWT_SECRET = _jwt_config['secret'],
|
|
17
|
+
JWT_ALGORITHM = _jwt_config['algorithm'],
|
|
18
|
+
JWT_EXP_DELTA_DAYS = _jwt_config['exp_delta_days'],
|
|
19
|
+
SSO_HOST = _sso_config['host'];
|
|
20
|
+
|
|
21
|
+
obj JacScaleUserManager(UserManager) {
|
|
22
|
+
has SUPPORTED_PLATFORMS: dict = {};
|
|
23
|
+
|
|
24
|
+
def postinit -> None;
|
|
25
|
+
# JWT methods
|
|
26
|
+
def create_jwt_token(username: str) -> str;
|
|
27
|
+
def validate_jwt_token(token: str) -> (str | None);
|
|
28
|
+
def refresh_jwt_token(token: str) -> (str | None);
|
|
29
|
+
# SSO methods
|
|
30
|
+
def get_sso(platform: str, operation: str) -> (SSOProvider | None);
|
|
31
|
+
async def sso_initiate(
|
|
32
|
+
platform: str, operation: str
|
|
33
|
+
) -> (Response | TransportResponse);
|
|
34
|
+
|
|
35
|
+
async def sso_callback(
|
|
36
|
+
request: Request, platform: str, operation: str
|
|
37
|
+
) -> TransportResponse;
|
|
38
|
+
|
|
39
|
+
# SSO Account Linking methods
|
|
40
|
+
def link_sso_account(
|
|
41
|
+
user_id: str, platform: str, external_id: str, email: str
|
|
42
|
+
) -> dict[str, str];
|
|
43
|
+
|
|
44
|
+
def unlink_sso_account(user_id: str, platform: str) -> dict[str, str];
|
|
45
|
+
def get_sso_accounts(user_id: str) -> list[dict[str, str]];
|
|
46
|
+
def get_user_by_sso(platform: str, external_id: str) -> (dict[str, str] | None);
|
|
47
|
+
# Override validate_token to use JWT
|
|
48
|
+
def validate_token(token: str) -> (str | None);
|
|
49
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jac-scale
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Author-email: Jason Mars <jason@mars.ninja>
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: jaclang>=0.9.
|
|
7
|
+
Requires-Dist: jaclang>=0.9.12
|
|
8
8
|
Requires-Dist: python-dotenv<2.0.0,>=1.2.1
|
|
9
9
|
Requires-Dist: docker<8.0.0,>=7.1.0
|
|
10
10
|
Requires-Dist: kubernetes<35.0.0,>=34.1.0
|
|
@@ -43,6 +43,13 @@ Requires-Dist: python-multipart<1.0.0,>=0.0.21
|
|
|
43
43
|
|
|
44
44
|
Whether you're developing locally with `jac start` or deploying to production with `jac start --scale`, you get the same powerful features with the flexibility to choose your deployment strategy.
|
|
45
45
|
|
|
46
|
+
### 4. Single Sign-On (SSO) Support
|
|
47
|
+
|
|
48
|
+
- **Google SSO**: Built-in support for Google Sign-In out of the box
|
|
49
|
+
- **Extensible Architecture**: Easily add other providers (GitHub, Microsoft, etc.)
|
|
50
|
+
- **Secure Authentication**: Integrated with JWT for secure session management
|
|
51
|
+
- **User Management**: Automatic account creation and linking
|
|
52
|
+
|
|
46
53
|
## Prerequisites
|
|
47
54
|
|
|
48
55
|
- kubenetes(K8s) installed
|
|
@@ -1,29 +1,34 @@
|
|
|
1
1
|
jac_scale/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
jac_scale/config_loader.jac,sha256=oOOOFcFfEP89Y3A-AI4cLqrEaO6g0jJqZglBsCoKM84,1222
|
|
3
|
-
jac_scale/context.jac,sha256=
|
|
4
|
-
jac_scale/
|
|
5
|
-
jac_scale/
|
|
6
|
-
jac_scale/
|
|
7
|
-
jac_scale/
|
|
3
|
+
jac_scale/context.jac,sha256=SIqQineAlLHJV3yWtYkeTIfcnqS0Oj15n8CWVSIqwJ8,529
|
|
4
|
+
jac_scale/google_sso_provider.jac,sha256=UUTDgQrBHXp0eqHxiw7v_VkQyFMMza0UDM6S4T5e4OM,2473
|
|
5
|
+
jac_scale/memory_hierarchy.jac,sha256=GuydhwujsH71TAkxeJ6Wfutp4v6GjDj23vGMreRj4yg,4533
|
|
6
|
+
jac_scale/plugin.jac,sha256=E1Ou_sQ8RV35emY9-gM295Uu-Eg4w4qSEJYm3TTYsWY,9585
|
|
7
|
+
jac_scale/plugin_config.jac,sha256=Gxvyy8V0uP1I4XARfHaHqoz0oeZ0LbHibri3gi5Odp8,8700
|
|
8
|
+
jac_scale/serve.jac,sha256=IU1a6ijW19FCBx53P_d-fzgukuZzS6MDTdazkhbtuzQ,4430
|
|
9
|
+
jac_scale/sso_provider.jac,sha256=Kky8cxm5gR2Sbg-CFrWTILKSZrV6Ju-DCEgfG4Akxb8,2092
|
|
10
|
+
jac_scale/user_manager.jac,sha256=UBApt_znhVEyxtfAdJ9sp_gslkHel4GGwXCBcNen_as,1932
|
|
8
11
|
jac_scale/utils.jac,sha256=zpxA08_NlDDSd1oVlbknQ_UOwHWGBbhzjmT_u6UYN04,491
|
|
9
12
|
jac_scale/abstractions/database_provider.jac,sha256=NZbFmcESulYsmG-27f8GY9nxVs3JflGIEb3aDDOIPu0,1454
|
|
10
13
|
jac_scale/abstractions/deployment_target.jac,sha256=5rJOd25FUXZZCNmDSUkyMljcXTAVJJDmelKw8WdPZm0,2071
|
|
11
14
|
jac_scale/abstractions/image_registry.jac,sha256=UCOwwuts5e1emsdDIlHJOiyW2ePA7k7D8UJdzd2kN10,1386
|
|
12
15
|
jac_scale/abstractions/logger.jac,sha256=YnXn8_jCpZ0IOBkJ7bFBMqo6WXO6BaDNVBqPq0lHbjk,652
|
|
13
|
-
jac_scale/abstractions/config/app_config.jac,sha256=
|
|
16
|
+
jac_scale/abstractions/config/app_config.jac,sha256=yxXlTOFRNBq5yFMgYm1LjEzobwxP_k2EG4zXcoHf688,912
|
|
14
17
|
jac_scale/abstractions/config/base_config.jac,sha256=ePT-up-63QGu2Jifi_CpPhd7_V9cPcHkInqGKDFryC4,785
|
|
15
18
|
jac_scale/abstractions/models/deployment_result.jac,sha256=3Mx8TVvL74AF8LLnhMbuCyHTTu-DXesYWMvht1HoGFs,704
|
|
16
19
|
jac_scale/abstractions/models/resource_status.jac,sha256=H6I9ZF92ia56bNmHR9dLMGsaFG4BafGh4sY-YwVRPu0,1031
|
|
17
20
|
jac_scale/factories/database_factory.jac,sha256=-8QfF1vDUqsdDKnldmayxvB-Z6DwQeNMOlo7HgTaouQ,1736
|
|
18
21
|
jac_scale/factories/deployment_factory.jac,sha256=1pzQ2HkqpKaeoycbRxdZ05McgTLpgj5Y5hmKhFTm1AY,1673
|
|
19
22
|
jac_scale/factories/registry_factory.jac,sha256=qWgwEH75EtjXGj3d9NGeg7D9Yx2S_RW9udlCFvOOCqU,1210
|
|
23
|
+
jac_scale/factories/storage_factory.jac,sha256=FVlx-f1BOq6H1yLWXT7OLSG-ZCENvlBPNr0OwFdo-VU,2661
|
|
20
24
|
jac_scale/factories/utility_factory.jac,sha256=64gMv_N_pFeq5E7z3gXrLIqeRGS_RGIF5eLT8RxNl_I,1262
|
|
21
25
|
jac_scale/impl/config_loader.impl.jac,sha256=j8YngI4mdcBKCBtly-8vN0WYXDwzdhwZ6bmmMc9Kza4,4769
|
|
22
|
-
jac_scale/impl/context.impl.jac,sha256=
|
|
26
|
+
jac_scale/impl/context.impl.jac,sha256=D8B7K-Y1VdbqBfGjYtGA5BDBiizlL8MmvAqxO8xMLwE,1106
|
|
23
27
|
jac_scale/impl/memory_hierarchy.main.impl.jac,sha256=Jc4Cy-5cy0TtK2uQ6rdYruxa0ZfZKSYgo3jOoXv4ER4,2339
|
|
24
28
|
jac_scale/impl/memory_hierarchy.mongo.impl.jac,sha256=APh7YloOj7bWGtv6DTBm7ekX13w_fectbZiFY0btwWU,6626
|
|
25
29
|
jac_scale/impl/memory_hierarchy.redis.impl.jac,sha256=x27TzeBI87vz72s7esQvFz8EPk3EfhVMNKU8sP4s2hk,4900
|
|
26
|
-
jac_scale/impl/serve.impl.jac,sha256=
|
|
30
|
+
jac_scale/impl/serve.impl.jac,sha256=UX7GIoB27kHeyq1JxtkM4CYC1BnhGpipCu0qOGaePRM,61376
|
|
31
|
+
jac_scale/impl/user_manager.impl.jac,sha256=7xGoLMweQuoVW-na7XbK3bctfUHaSEnT9nB7DLgSlgw,11817
|
|
27
32
|
jac_scale/jserver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
33
|
jac_scale/jserver/jfast_api.jac,sha256=Ez7EZ883TS9IIACzK8QMqTgVTtNoaOenbmwNKnekBuc,5561
|
|
29
34
|
jac_scale/jserver/jserver.jac,sha256=8gWh22nX9Z5rJp3D1AxOSU8lBhoX4-kBZ0uvJPPNqX8,3356
|
|
@@ -32,26 +37,32 @@ jac_scale/jserver/impl/jserver.impl.jac,sha256=4NOzfys4WQmGt6vttTTh6By12hEJqdvOz
|
|
|
32
37
|
jac_scale/providers/database/kubernetes_mongo.jac,sha256=nP43b-ePR8XInhhk7gzdvJvOJMZcTZanm1VALdiCqXA,4952
|
|
33
38
|
jac_scale/providers/database/kubernetes_redis.jac,sha256=qF9HkNLLgiymxiCXbmETbVVDs5Wqs1m4s3O6xFR7jRA,3778
|
|
34
39
|
jac_scale/providers/registry/dockerhub.jac,sha256=7KlgQJGGUeDF7zP8-KNF8HTShB4td1946OtIdS57EHI,2282
|
|
35
|
-
jac_scale/targets/kubernetes/kubernetes_config.jac,sha256=
|
|
36
|
-
jac_scale/targets/kubernetes/kubernetes_target.jac,sha256=
|
|
40
|
+
jac_scale/targets/kubernetes/kubernetes_config.jac,sha256=Xk3EjKTEjptlctD2C5cTYjgw9V8i8mfsO-jKAa2IZZs,9406
|
|
41
|
+
jac_scale/targets/kubernetes/kubernetes_target.jac,sha256=itICKs_sA4jOs7_wrFgpj5QhupjKVXRSvkaJMBL6t9g,35523
|
|
37
42
|
jac_scale/targets/kubernetes/utils/kubernetes_utils.impl.jac,sha256=CPSlFlhCE3qdzPWiPVa7KbHkL_h5Gle5ySvq7UkwR4k,15756
|
|
38
43
|
jac_scale/targets/kubernetes/utils/kubernetes_utils.jac,sha256=Nr257oCyduodJbxkLJeNYphFzz9NxviFfW1Tpc5dQKk,2129
|
|
39
44
|
jac_scale/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
40
45
|
jac_scale/tests/conftest.py,sha256=uiS352_HVmMf7V6T0BZl-Kn8svkKbj3jhNr-hEKrcPw,820
|
|
41
46
|
jac_scale/tests/test_abstractions.py,sha256=gb5ueNcUcxpq0U0r_nEize9v027gRR_XiZlCEooAW6U,2612
|
|
42
|
-
jac_scale/tests/test_deploy_k8s.py,sha256=
|
|
43
|
-
jac_scale/tests/test_examples.py,sha256=
|
|
47
|
+
jac_scale/tests/test_deploy_k8s.py,sha256=rX9kJohqTeaRch-KSruWYF8eUnPGtJ_p6zy0sPkBXIA,9164
|
|
48
|
+
jac_scale/tests/test_examples.py,sha256=2xOTf0rBiT_9w92ku7k9Pfv4A7ohLZpZdpAH0VHM86E,24044
|
|
44
49
|
jac_scale/tests/test_factories.py,sha256=cf1gLrBdK9q8SlHyocZqtixyPtO2dLlrgNYeX5-_RYM,5073
|
|
45
50
|
jac_scale/tests/test_file_upload.py,sha256=JooF-9rgwOqtNkWRfvfHu4W5x-gzk91bHVi13J9mnNE,16595
|
|
51
|
+
jac_scale/tests/test_hooks.py,sha256=TzikM6dd1uKg1G2L1MtgXYzzjY6YhrbAQXZah-TO33Y,1366
|
|
46
52
|
jac_scale/tests/test_k8s_utils.py,sha256=Oqocwl4m2IFgM27Lgsi96WJeHS8hnx9WDOcxq9YkqJU,4613
|
|
47
53
|
jac_scale/tests/test_memory_hierarchy.py,sha256=q_DsKyPIuQymab_sEtXojDW0GOyunRxZJsNTJDrGA7s,8324
|
|
48
|
-
jac_scale/tests/
|
|
49
|
-
jac_scale/tests/
|
|
50
|
-
jac_scale/tests/
|
|
54
|
+
jac_scale/tests/test_restspec.py,sha256=ynkDlu9mHl98hUL49UYwcJNXbsLhBd8yPL9TTw12xN0,6582
|
|
55
|
+
jac_scale/tests/test_serve.py,sha256=LsLgGGS5_52wtB0EyBEsIzX6KwIQ4m5hTVoOq3dYnWc,67299
|
|
56
|
+
jac_scale/tests/test_sso.py,sha256=9h2AUC9JBM74O6xfpyIcl98iXyZWcDIGdKRtlb_5uqo,28104
|
|
57
|
+
jac_scale/tests/test_storage.py,sha256=Y7CIbKrH3OmJQlBeV9A965-7TtxL6nuZtfkfoeqIeS4,10514
|
|
58
|
+
jac_scale/tests/fixtures/test_api.jac,sha256=78tw_0lFR2k7uI0nrU_e8fdJJOcOG2z0J5C47MQ42DU,4744
|
|
59
|
+
jac_scale/tests/fixtures/test_restspec.jac,sha256=bE8-7qyDXkNGGhv0HqQCKFpLWCDa5ciRzrJS-bkqWDo,1173
|
|
51
60
|
jac_scale/tests/fixtures/todo_app.jac,sha256=beI6AiRutmXsXxuzU9nIZTE-AuoBBP-WqbRA2ux1pN4,1216
|
|
61
|
+
jac_scale/tests/fixtures/scale-feats/main.jac,sha256=QN8Opodha9jLWdRGCASByIogePr1XKphgKjyE9Pp73c,4205
|
|
62
|
+
jac_scale/tests/fixtures/scale-feats/components/Button.cl.jac,sha256=e8tvNzW_QikFJMSTcbkziKP69NF00DqQVxcjLPkAW-w,903
|
|
52
63
|
jac_scale/utilities/loggers/standard_logger.jac,sha256=6XL5ETAOBwbsFCOp0VN_7TOnqcQDmbLZVzubA-JR3vA,1376
|
|
53
|
-
jac_scale-0.1.
|
|
54
|
-
jac_scale-0.1.
|
|
55
|
-
jac_scale-0.1.
|
|
56
|
-
jac_scale-0.1.
|
|
57
|
-
jac_scale-0.1.
|
|
64
|
+
jac_scale-0.1.3.dist-info/METADATA,sha256=zRQUUOCa0B6p2qC4Fo-sptUZbayDW85aS51iX1SvSI4,20457
|
|
65
|
+
jac_scale-0.1.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
66
|
+
jac_scale-0.1.3.dist-info/entry_points.txt,sha256=n-Wm8JEtGOqy_IY_kgIOi3-uYnuVK-iWsvKiLkxlG4E,105
|
|
67
|
+
jac_scale-0.1.3.dist-info/top_level.txt,sha256=PpgR0R8z9qoFbSser2K20r5Is4K6TxVwguoN6LfTEKU,10
|
|
68
|
+
jac_scale-0.1.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|