spaceforge 0.0.5__py3-none-any.whl → 0.0.7__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.
- spaceforge/_version_scm.py +2 -2
- spaceforge/cls.py +4 -1
- spaceforge/generator.py +16 -8
- spaceforge/plugin.py +22 -17
- spaceforge/schema.json +7 -0
- spaceforge/templates/ensure_spaceforge_and_run.sh.j2 +3 -1
- spaceforge/test_generator.py +2 -2
- spaceforge/test_plugin.py +7 -7
- {spaceforge-0.0.5.dist-info → spaceforge-0.0.7.dist-info}/METADATA +2 -1
- {spaceforge-0.0.5.dist-info → spaceforge-0.0.7.dist-info}/RECORD +14 -14
- {spaceforge-0.0.5.dist-info → spaceforge-0.0.7.dist-info}/WHEEL +0 -0
- {spaceforge-0.0.5.dist-info → spaceforge-0.0.7.dist-info}/entry_points.txt +0 -0
- {spaceforge-0.0.5.dist-info → spaceforge-0.0.7.dist-info}/licenses/LICENSE +0 -0
- {spaceforge-0.0.5.dist-info → spaceforge-0.0.7.dist-info}/top_level.txt +0 -0
spaceforge/_version_scm.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 0,
|
|
31
|
+
__version__ = version = '0.0.7'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 0, 7)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
spaceforge/cls.py
CHANGED
|
@@ -149,6 +149,9 @@ class Webhook:
|
|
|
149
149
|
labels: Optional[List[str]] = optional_field
|
|
150
150
|
|
|
151
151
|
|
|
152
|
+
PolicyTypes = Literal["PUSH", "PLAN", "TRIGGER", "APPROVAL", "NOTIFICATION"]
|
|
153
|
+
|
|
154
|
+
|
|
152
155
|
@pydantic_dataclass
|
|
153
156
|
class Policy:
|
|
154
157
|
"""
|
|
@@ -162,7 +165,7 @@ class Policy:
|
|
|
162
165
|
"""
|
|
163
166
|
|
|
164
167
|
name_prefix: str
|
|
165
|
-
type:
|
|
168
|
+
type: PolicyTypes
|
|
166
169
|
body: str
|
|
167
170
|
labels: Optional[List[str]] = optional_field
|
|
168
171
|
|
spaceforge/generator.py
CHANGED
|
@@ -8,6 +8,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, Union
|
|
|
8
8
|
|
|
9
9
|
import yaml
|
|
10
10
|
from jinja2 import Environment, PackageLoader, select_autoescape
|
|
11
|
+
from mergedeep import Strategy, merge # type: ignore
|
|
11
12
|
|
|
12
13
|
if TYPE_CHECKING:
|
|
13
14
|
from .plugin import SpaceforgePlugin
|
|
@@ -83,7 +84,8 @@ class PluginGenerator:
|
|
|
83
84
|
self.plugin_class = plugin_class
|
|
84
85
|
self.plugin_instance = plugin_class()
|
|
85
86
|
self.plugin_working_directory = (
|
|
86
|
-
"/mnt/workspace/plugins/"
|
|
87
|
+
"/mnt/workspace/plugins/"
|
|
88
|
+
+ plugin_class.__plugin_name__.lower().replace(" ", "_")
|
|
87
89
|
)
|
|
88
90
|
self.config = {
|
|
89
91
|
"setup_virtual_env": (
|
|
@@ -185,7 +187,10 @@ class PluginGenerator:
|
|
|
185
187
|
)
|
|
186
188
|
|
|
187
189
|
def _add_spaceforge_hooks(
|
|
188
|
-
self,
|
|
190
|
+
self,
|
|
191
|
+
hooks: Dict[str, List[str]],
|
|
192
|
+
mounted_files: List[MountedFile],
|
|
193
|
+
has_binaries: bool,
|
|
189
194
|
) -> None:
|
|
190
195
|
# Add the spaceforge hook to actually run the plugin
|
|
191
196
|
if self.config is None:
|
|
@@ -203,6 +208,7 @@ class PluginGenerator:
|
|
|
203
208
|
plugin_path=directory,
|
|
204
209
|
plugin_file=self.config["plugin_mounted_path"],
|
|
205
210
|
phase=hook,
|
|
211
|
+
has_binaries=has_binaries,
|
|
206
212
|
)
|
|
207
213
|
self._add_to_mounted_files(hooks, mounted_files, hook, f"{hook}.sh", render)
|
|
208
214
|
|
|
@@ -244,8 +250,8 @@ class PluginGenerator:
|
|
|
244
250
|
|
|
245
251
|
self._update_with_requirements(mounted_files)
|
|
246
252
|
self._update_with_python_file(mounted_files)
|
|
247
|
-
self._generate_binary_install_command(hooks, mounted_files)
|
|
248
|
-
self._add_spaceforge_hooks(hooks, mounted_files)
|
|
253
|
+
has_binaries = self._generate_binary_install_command(hooks, mounted_files)
|
|
254
|
+
self._add_spaceforge_hooks(hooks, mounted_files, has_binaries)
|
|
249
255
|
|
|
250
256
|
# Get the contexts and append the hooks and mounted files to it.
|
|
251
257
|
if self.plugin_class is None:
|
|
@@ -270,8 +276,8 @@ class PluginGenerator:
|
|
|
270
276
|
contexts[0].env = []
|
|
271
277
|
|
|
272
278
|
# Add the hooks and mounted files to the first context
|
|
273
|
-
contexts[0].hooks.
|
|
274
|
-
contexts[0].mounted_files
|
|
279
|
+
merge(contexts[0].hooks, hooks, strategy=Strategy.TYPESAFE_ADDITIVE)
|
|
280
|
+
contexts[0].mounted_files += mounted_files
|
|
275
281
|
|
|
276
282
|
self._map_variables_to_parameters(contexts)
|
|
277
283
|
|
|
@@ -279,10 +285,10 @@ class PluginGenerator:
|
|
|
279
285
|
|
|
280
286
|
def _generate_binary_install_command(
|
|
281
287
|
self, hooks: Dict[str, List[str]], mounted_files: List[MountedFile]
|
|
282
|
-
) ->
|
|
288
|
+
) -> bool:
|
|
283
289
|
binaries = self.get_plugin_binaries()
|
|
284
290
|
if binaries is None:
|
|
285
|
-
return
|
|
291
|
+
return False
|
|
286
292
|
|
|
287
293
|
for i, binary in enumerate(binaries):
|
|
288
294
|
amd64_url = binary.download_urls.get("amd64", None)
|
|
@@ -309,6 +315,8 @@ class PluginGenerator:
|
|
|
309
315
|
render,
|
|
310
316
|
)
|
|
311
317
|
|
|
318
|
+
return True
|
|
319
|
+
|
|
312
320
|
def get_plugin_binaries(self) -> Optional[List[Binary]]:
|
|
313
321
|
"""Get binary definitions from the plugin class."""
|
|
314
322
|
return getattr(self.plugin_class, "__binaries__", None)
|
spaceforge/plugin.py
CHANGED
|
@@ -36,21 +36,21 @@ class SpaceforgePlugin(ABC):
|
|
|
36
36
|
self.logger = self._setup_logger()
|
|
37
37
|
|
|
38
38
|
self._api_token = os.environ.get("SPACELIFT_API_TOKEN") or False
|
|
39
|
-
self.
|
|
39
|
+
self.spacelift_domain = (
|
|
40
40
|
os.environ.get("TF_VAR_spacelift_graphql_endpoint") or False
|
|
41
41
|
)
|
|
42
|
-
self._api_enabled = bool(self._api_token and self.
|
|
42
|
+
self._api_enabled = bool(self._api_token and self.spacelift_domain)
|
|
43
43
|
self._workspace_root = os.getcwd()
|
|
44
44
|
self._spacelift_markdown_endpoint = None
|
|
45
45
|
|
|
46
46
|
# This should be the last thing we do in the constructor
|
|
47
47
|
# because we set api_enabled to false if the domain is set up incorrectly.
|
|
48
|
-
if self.
|
|
48
|
+
if self.spacelift_domain and isinstance(self.spacelift_domain, str):
|
|
49
49
|
# this must occur after we check if spacelift domain is false
|
|
50
50
|
# because the domain could be set but not start with https://
|
|
51
|
-
if self.
|
|
52
|
-
if self.
|
|
53
|
-
self.
|
|
51
|
+
if self.spacelift_domain.startswith("https://"):
|
|
52
|
+
if self.spacelift_domain.endswith("/"):
|
|
53
|
+
self.spacelift_domain = self.spacelift_domain[:-1]
|
|
54
54
|
else:
|
|
55
55
|
self.logger.warning(
|
|
56
56
|
"SPACELIFT_DOMAIN does not start with https://, api calls will fail."
|
|
@@ -58,7 +58,7 @@ class SpaceforgePlugin(ABC):
|
|
|
58
58
|
self._api_enabled = False
|
|
59
59
|
|
|
60
60
|
if self._api_enabled:
|
|
61
|
-
self._spacelift_markdown_endpoint = self.
|
|
61
|
+
self._spacelift_markdown_endpoint = self.spacelift_domain.replace(
|
|
62
62
|
"/graphql", "/worker/plugin_logs_url"
|
|
63
63
|
)
|
|
64
64
|
|
|
@@ -200,7 +200,7 @@ class SpaceforgePlugin(ABC):
|
|
|
200
200
|
data["variables"] = variables
|
|
201
201
|
|
|
202
202
|
req = urllib.request.Request(
|
|
203
|
-
self.
|
|
203
|
+
self.spacelift_domain, # type: ignore[arg-type]
|
|
204
204
|
json.dumps(data).encode("utf-8"),
|
|
205
205
|
headers,
|
|
206
206
|
)
|
|
@@ -287,8 +287,8 @@ class SpaceforgePlugin(ABC):
|
|
|
287
287
|
headers = resp["headers"]
|
|
288
288
|
headers["Content-Type"] = "text/markdown"
|
|
289
289
|
headers["Content-Length"] = str(len(markdown))
|
|
290
|
-
except
|
|
291
|
-
self.logger.error(f"HTTP error occurred: {e
|
|
290
|
+
except Exception as e:
|
|
291
|
+
self.logger.error(f"HTTP error occurred: {e}")
|
|
292
292
|
return False
|
|
293
293
|
|
|
294
294
|
# Now we upload the markdown content to the signed URL
|
|
@@ -299,13 +299,18 @@ class SpaceforgePlugin(ABC):
|
|
|
299
299
|
method="PUT",
|
|
300
300
|
)
|
|
301
301
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
302
|
+
try:
|
|
303
|
+
with urllib.request.urlopen(req) as put_response:
|
|
304
|
+
if put_response.status != 200:
|
|
305
|
+
self.logger.error(
|
|
306
|
+
f"Error uploading markdown content: {put_response.status}"
|
|
307
|
+
)
|
|
308
|
+
return False
|
|
309
|
+
self.logger.debug("Markdown content uploaded successfully.")
|
|
310
|
+
except Exception as e:
|
|
311
|
+
self.logger.error(f"HTTP error occurred during upload: {e}")
|
|
312
|
+
return False
|
|
313
|
+
|
|
309
314
|
return True
|
|
310
315
|
|
|
311
316
|
def add_to_policy_input(self, input_name: str, data: Dict[str, Any]) -> None:
|
spaceforge/schema.json
CHANGED
|
@@ -17,6 +17,8 @@ if [ -f requirements.txt ] && [ ! -f .spaceforge_installed_requirements ]; then
|
|
|
17
17
|
pip install -r requirements.txt
|
|
18
18
|
touch .spaceforge_installed_requirements
|
|
19
19
|
fi
|
|
20
|
-
|
|
20
|
+
{% if has_binaries %}
|
|
21
|
+
export PATH="/mnt/workspace/plugins/plugin_binaries:$PATH"
|
|
22
|
+
{% endif %}
|
|
21
23
|
cd /mnt/workspace/source/$TF_VAR_spacelift_project_root
|
|
22
24
|
spaceforge runner --plugin-file {{plugin_file}} {{phase}}
|
spaceforge/test_generator.py
CHANGED
|
@@ -72,7 +72,7 @@ class PluginExample(SpaceforgePlugin):
|
|
|
72
72
|
__policies__ = [
|
|
73
73
|
Policy(
|
|
74
74
|
name_prefix="test_policy",
|
|
75
|
-
type="
|
|
75
|
+
type="NOTIFICATION",
|
|
76
76
|
body="package test",
|
|
77
77
|
labels=["type:security"],
|
|
78
78
|
)
|
|
@@ -396,7 +396,7 @@ class NotAPlugin:
|
|
|
396
396
|
assert policies is not None
|
|
397
397
|
assert len(policies) == 1
|
|
398
398
|
assert policies[0].name_prefix == "test_policy"
|
|
399
|
-
assert policies[0].type == "
|
|
399
|
+
assert policies[0].type == "NOTIFICATION"
|
|
400
400
|
assert policies[0].body == "package test"
|
|
401
401
|
|
|
402
402
|
def test_get_plugin_webhooks(self) -> None:
|
spaceforge/test_plugin.py
CHANGED
|
@@ -21,7 +21,7 @@ class TestSpaceforgePluginInitialization:
|
|
|
21
21
|
|
|
22
22
|
# Assert
|
|
23
23
|
assert plugin._api_token is False
|
|
24
|
-
assert plugin.
|
|
24
|
+
assert plugin.spacelift_domain is False
|
|
25
25
|
assert plugin._api_enabled is False
|
|
26
26
|
assert plugin._workspace_root == os.getcwd()
|
|
27
27
|
assert isinstance(plugin.logger, logging.Logger)
|
|
@@ -36,7 +36,7 @@ class TestSpaceforgePluginInitialization:
|
|
|
36
36
|
|
|
37
37
|
# Assert
|
|
38
38
|
assert plugin._api_token == "test_token"
|
|
39
|
-
assert plugin.
|
|
39
|
+
assert plugin.spacelift_domain == "https://test.spacelift.io"
|
|
40
40
|
assert plugin._api_enabled is True
|
|
41
41
|
assert plugin._workspace_root == os.getcwd()
|
|
42
42
|
|
|
@@ -53,7 +53,7 @@ class TestSpaceforgePluginInitialization:
|
|
|
53
53
|
plugin = SpaceforgePlugin()
|
|
54
54
|
|
|
55
55
|
# Assert
|
|
56
|
-
assert plugin.
|
|
56
|
+
assert plugin.spacelift_domain == "https://test.spacelift.io"
|
|
57
57
|
assert plugin._api_enabled is True
|
|
58
58
|
|
|
59
59
|
def test_should_disable_api_when_domain_has_no_https_prefix(self) -> None:
|
|
@@ -69,7 +69,7 @@ class TestSpaceforgePluginInitialization:
|
|
|
69
69
|
plugin = SpaceforgePlugin()
|
|
70
70
|
|
|
71
71
|
# Assert
|
|
72
|
-
assert plugin.
|
|
72
|
+
assert plugin.spacelift_domain == "test.spacelift.io"
|
|
73
73
|
assert plugin._api_enabled is False
|
|
74
74
|
|
|
75
75
|
def test_should_disable_api_when_only_token_provided(self) -> None:
|
|
@@ -271,7 +271,7 @@ class TestSpaceforgePluginAPI:
|
|
|
271
271
|
plugin = SpaceforgePlugin()
|
|
272
272
|
plugin._api_enabled = True
|
|
273
273
|
plugin._api_token = "test_token"
|
|
274
|
-
plugin.
|
|
274
|
+
plugin.spacelift_domain = "https://test.spacelift.io"
|
|
275
275
|
|
|
276
276
|
expected_data = {"data": {"test": "result"}}
|
|
277
277
|
mock_api_response.read.return_value = json.dumps(expected_data).encode("utf-8")
|
|
@@ -305,7 +305,7 @@ class TestSpaceforgePluginAPI:
|
|
|
305
305
|
plugin = SpaceforgePlugin()
|
|
306
306
|
plugin._api_enabled = True
|
|
307
307
|
plugin._api_token = "test_token"
|
|
308
|
-
plugin.
|
|
308
|
+
plugin.spacelift_domain = "https://test.spacelift.io"
|
|
309
309
|
|
|
310
310
|
mock_response_data = {"data": {"test": "result"}}
|
|
311
311
|
mock_response = Mock()
|
|
@@ -331,7 +331,7 @@ class TestSpaceforgePluginAPI:
|
|
|
331
331
|
plugin = SpaceforgePlugin()
|
|
332
332
|
plugin._api_enabled = True
|
|
333
333
|
plugin._api_token = "test_token"
|
|
334
|
-
plugin.
|
|
334
|
+
plugin.spacelift_domain = "https://test.spacelift.io"
|
|
335
335
|
|
|
336
336
|
mock_response_data = {"errors": [{"message": "Test error"}]}
|
|
337
337
|
mock_response = Mock()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: spaceforge
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.7
|
|
4
4
|
Summary: A Python framework for building Spacelift plugins
|
|
5
5
|
Home-page: https://github.com/spacelift-io/plugins
|
|
6
6
|
Author: Spacelift
|
|
@@ -29,6 +29,7 @@ Requires-Dist: PyYAML>=6.0
|
|
|
29
29
|
Requires-Dist: click>=8.0.0
|
|
30
30
|
Requires-Dist: pydantic>=2.11.7
|
|
31
31
|
Requires-Dist: Jinja2>=3.1.0
|
|
32
|
+
Requires-Dist: mergedeep>=1.3.4
|
|
32
33
|
Provides-Extra: dev
|
|
33
34
|
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
34
35
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -2,20 +2,20 @@ spaceforge/README.md,sha256=8o1Nuyasb4OxX3E7ZycyducOrR4J19bZcHrLvFeoFNg,7730
|
|
|
2
2
|
spaceforge/__init__.py,sha256=TU-vvm15dK1ucixNW0V42eTT72x3_hmKSyxP4MC1Occ,589
|
|
3
3
|
spaceforge/__main__.py,sha256=c3nAw4WBnHXIcfMlRV6Ja7r87pEhSeK-SAqiSYIasIY,643
|
|
4
4
|
spaceforge/_version.py,sha256=RP_LfUd4ODnrfwn9nam8wB6bR3lM4VwmoRxK08Tkiiw,2155
|
|
5
|
-
spaceforge/_version_scm.py,sha256=
|
|
6
|
-
spaceforge/cls.py,sha256=
|
|
5
|
+
spaceforge/_version_scm.py,sha256=AV58KqMkBGaCvmPdbd3g9huyNXfIVxjw8QbCMdaeivU,704
|
|
6
|
+
spaceforge/cls.py,sha256=lCGtlMv-rFFVnvfFaq36-GRqLiINswLD78amZigZo7I,6068
|
|
7
7
|
spaceforge/conftest.py,sha256=U-xCavCsgRAQXqflIIOMeq9pcGbeqRviUNkEXgZol8g,2141
|
|
8
|
-
spaceforge/generator.py,sha256=
|
|
9
|
-
spaceforge/plugin.py,sha256=
|
|
8
|
+
spaceforge/generator.py,sha256=7tt0zpqrD2pZsoVxQa0BfzBH1ZtGr6o3r_LmpBjrOJk,16739
|
|
9
|
+
spaceforge/plugin.py,sha256=h2qQNNSwAnqJQW9q9v0nbtXqPO7pWx_0FZlw3jj4_Vw,13460
|
|
10
10
|
spaceforge/runner.py,sha256=aBQQLG8MFVrqCzM0X8HgERYbhLKbmlOHUPKjV7-xvpA,3163
|
|
11
|
-
spaceforge/schema.json,sha256=
|
|
11
|
+
spaceforge/schema.json,sha256=scQyV71IlbB5kipAhc880n-PG-FH8BeVk9FWFoA3Wtw,10483
|
|
12
12
|
spaceforge/test_cls.py,sha256=nXAgbnFnGdFxrtA7vNXiePjNUASuoYW-lEuQGx9WMGs,468
|
|
13
|
-
spaceforge/test_generator.py,sha256=
|
|
13
|
+
spaceforge/test_generator.py,sha256=Nst3YVu_iZbFopH6ajjxCfqYrZvybteGbwMfZzjBFnI,32615
|
|
14
14
|
spaceforge/test_generator_binaries.py,sha256=X_7pPLGE45eQt-Kv9_ku__LsyLgOvViHc_BvVpSCMp0,7263
|
|
15
15
|
spaceforge/test_generator_core.py,sha256=gOqRx0rnME-srGMHun4KidXMN-iaqfKKTyoQ0Tw6b9Q,6253
|
|
16
16
|
spaceforge/test_generator_hooks.py,sha256=2lJs8dYlFb7QehWcYF0O4qg38s5UudEpzJyBi1XiS3k,2542
|
|
17
17
|
spaceforge/test_generator_parameters.py,sha256=77az9rcocFny2AC4O2eTzjCW712fR1DBHzGrgBKeR4w,1878
|
|
18
|
-
spaceforge/test_plugin.py,sha256=
|
|
18
|
+
spaceforge/test_plugin.py,sha256=Q4ztmpDV8Xpr0HVvYXHyAm_VHv8TzLXdN5PHeMI9KnI,13039
|
|
19
19
|
spaceforge/test_plugin_file_operations.py,sha256=B0qvIo5EcfKMiHLhBv-hAnpSonn83ojcmJHXasydojA,3782
|
|
20
20
|
spaceforge/test_plugin_hooks.py,sha256=rNCZZyd_SDMkm1x3yl5mjQ5tBMGm3YNd1U6h_niWRQs,2962
|
|
21
21
|
spaceforge/test_plugin_inheritance.py,sha256=WHfvU5s-2GtfcI9-1bHXH7bacr77ikq68V3Z3BBQKvQ,3617
|
|
@@ -24,10 +24,10 @@ spaceforge/test_runner_cli.py,sha256=Sf5X0O9Wc9EhGB5L8SzvlmO7QmgQZQoClSdNYefa-lQ
|
|
|
24
24
|
spaceforge/test_runner_core.py,sha256=eNR9YOwJwv7LsMtNQ4WXXMPIW6RE_A7hUp4bCpzz1Rk,3941
|
|
25
25
|
spaceforge/test_runner_execution.py,sha256=BRlOApCmlpjE9YYvqHc8creSRu2vyPubzOCVXv-on0w,5335
|
|
26
26
|
spaceforge/templates/binary_install.sh.j2,sha256=UjP_kAdvkkATKds2nqk4ouqLhuIfCgM_x0WQIl1hbIo,477
|
|
27
|
-
spaceforge/templates/ensure_spaceforge_and_run.sh.j2,sha256=
|
|
28
|
-
spaceforge-0.0.
|
|
29
|
-
spaceforge-0.0.
|
|
30
|
-
spaceforge-0.0.
|
|
31
|
-
spaceforge-0.0.
|
|
32
|
-
spaceforge-0.0.
|
|
33
|
-
spaceforge-0.0.
|
|
27
|
+
spaceforge/templates/ensure_spaceforge_and_run.sh.j2,sha256=g5BldIEve0IkZ-mCzTXfB_rFvyWqUJqymRRaaMrpp0s,550
|
|
28
|
+
spaceforge-0.0.7.dist-info/licenses/LICENSE,sha256=wyljRrfnWY2ggQKkSCg3Nw2hxwPMmupopaKs9Kpgys8,1065
|
|
29
|
+
spaceforge-0.0.7.dist-info/METADATA,sha256=e87JTyOInYhVID_Fb0UxKfTufsdisG0rri1ZQkdxOZk,16803
|
|
30
|
+
spaceforge-0.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
31
|
+
spaceforge-0.0.7.dist-info/entry_points.txt,sha256=qawuuKBSNTGg-njnQnhxxFldFvXYAPej6bF_f3iyQ48,56
|
|
32
|
+
spaceforge-0.0.7.dist-info/top_level.txt,sha256=eVw-Lw4Th0oHM8Gx1Y8YetyNgbNbMBU00yWs-kwGeSs,11
|
|
33
|
+
spaceforge-0.0.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|