csspin-python 5.0.0__py3-none-any.whl → 6.0.0__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.
- csspin_python/python.py +99 -63
- csspin_python/python_sbom.py +5 -1
- csspin_python/python_schema.yaml +13 -11
- csspin_python/uv_provisioner.py +23 -5
- {csspin_python-5.0.0.dist-info → csspin_python-6.0.0.dist-info}/METADATA +2 -2
- {csspin_python-5.0.0.dist-info → csspin_python-6.0.0.dist-info}/RECORD +9 -9
- {csspin_python-5.0.0.dist-info → csspin_python-6.0.0.dist-info}/WHEEL +0 -0
- {csspin_python-5.0.0.dist-info → csspin_python-6.0.0.dist-info}/licenses/LICENSE +0 -0
- {csspin_python-5.0.0.dist-info → csspin_python-6.0.0.dist-info}/top_level.txt +0 -0
csspin_python/python.py
CHANGED
|
@@ -81,6 +81,8 @@ from functools import cache
|
|
|
81
81
|
from subprocess import CalledProcessError, check_output
|
|
82
82
|
from textwrap import dedent, indent
|
|
83
83
|
from typing import Generator, Iterable, Type, Union
|
|
84
|
+
from urllib.error import HTTPError
|
|
85
|
+
from urllib.parse import urljoin, urlsplit
|
|
84
86
|
|
|
85
87
|
try:
|
|
86
88
|
from typing import Self # type: ignore[attr-defined]
|
|
@@ -162,11 +164,6 @@ defaults = config(
|
|
|
162
164
|
enabled=False,
|
|
163
165
|
memo="{spin.spin_dir}/aws_auth.memo",
|
|
164
166
|
key_duration=3600 * 10, # 10 hours
|
|
165
|
-
static_oidc=False,
|
|
166
|
-
index="16.0/simple",
|
|
167
|
-
# Need to set client secret to empty string, otherwise the string "None"
|
|
168
|
-
# would be handled as secret and obfucsated in logs.
|
|
169
|
-
client_secret="", # nosec: B106
|
|
170
167
|
),
|
|
171
168
|
index_url="https://pypi.org/simple",
|
|
172
169
|
skip_js_build=None,
|
|
@@ -187,6 +184,8 @@ def wheel(
|
|
|
187
184
|
) -> None:
|
|
188
185
|
"""Build a wheel of the current project and any additional wheels."""
|
|
189
186
|
setenv(PIP_INDEX_URL=cfg.python.index_url)
|
|
187
|
+
if cfg.python.extra_index_urls:
|
|
188
|
+
setenv(PIP_EXTRA_INDEX_URL=" ".join(cfg.python.extra_index_urls))
|
|
190
189
|
search_paths = paths or cfg.python.build_wheels
|
|
191
190
|
for build_path in {Path(path).absolute() for path in search_paths}:
|
|
192
191
|
try:
|
|
@@ -792,7 +791,9 @@ class PythonActivate(ActivateScriptPatcher):
|
|
|
792
791
|
|
|
793
792
|
|
|
794
793
|
@cache
|
|
795
|
-
def get_project_metadata(
|
|
794
|
+
def get_project_metadata( # type: ignore[return] # pylint: disable=inconsistent-return-statements # noqa: E501
|
|
795
|
+
project_path: str, index_url: str, extra_index_urls: tuple[str, ...] = ()
|
|
796
|
+
) -> dict:
|
|
796
797
|
"""
|
|
797
798
|
Retrieve project metadata of ``project_path`` via ``python -m build
|
|
798
799
|
--metadata``.
|
|
@@ -801,12 +802,16 @@ def get_project_metadata(project_path: str, index_url: str) -> dict: # type: ig
|
|
|
801
802
|
every caller within the same process.
|
|
802
803
|
"""
|
|
803
804
|
setenv(PIP_INDEX_URL=index_url)
|
|
805
|
+
if extra_index_urls:
|
|
806
|
+
setenv(PIP_EXTRA_INDEX_URL=" ".join(extra_index_urls))
|
|
804
807
|
kwargs = {}
|
|
805
808
|
if CONFIG.verbosity < Verbosity.INFO:
|
|
806
809
|
kwargs["stderr"] = subprocess.DEVNULL
|
|
807
810
|
raw_metadata = backtick(
|
|
808
811
|
"python", "-m", "build", "--metadata", project_path, **kwargs
|
|
809
812
|
)
|
|
813
|
+
if extra_index_urls:
|
|
814
|
+
setenv(PIP_EXTRA_INDEX_URL=None)
|
|
810
815
|
setenv(PIP_INDEX_URL=None)
|
|
811
816
|
|
|
812
817
|
if raw_metadata:
|
|
@@ -1125,21 +1130,78 @@ def _configure_pipconf(cfg: ConfigTree, update: bool = False) -> None:
|
|
|
1125
1130
|
"index_url" in config_parser["global"] or "index-url" in config_parser["global"]
|
|
1126
1131
|
):
|
|
1127
1132
|
config_parser["global"]["index_url"] = interpolate1(cfg.python.index_url)
|
|
1133
|
+
|
|
1134
|
+
# Extra index urls are only configured via 'python.extra_index_urls', not
|
|
1135
|
+
# 'python.pipconf', so drop whatever the pipconf template declares rather
|
|
1136
|
+
# than merging it in.
|
|
1137
|
+
for key in ("extra_index_url", "extra-index-url"):
|
|
1138
|
+
config_parser["global"].pop(key, None)
|
|
1139
|
+
|
|
1140
|
+
if cfg.python.extra_index_urls:
|
|
1141
|
+
config_parser["global"]["extra_index_url"] = "\n".join(
|
|
1142
|
+
interpolate1(url) for url in cfg.python.extra_index_urls
|
|
1143
|
+
)
|
|
1128
1144
|
with open(_get_pipconf(cfg), mode="w", encoding="utf-8") as fd:
|
|
1129
1145
|
config_parser.write(fd)
|
|
1130
1146
|
|
|
1131
1147
|
|
|
1132
1148
|
def _obfuscate_index_url(index_url: str) -> None:
|
|
1133
|
-
"""Add the
|
|
1149
|
+
"""Add the credentials of an index URL to the secrets."""
|
|
1134
1150
|
|
|
1135
1151
|
from csspin import secrets
|
|
1136
1152
|
|
|
1137
|
-
|
|
1153
|
+
if password := urlsplit(index_url).password:
|
|
1154
|
+
secrets.add(password)
|
|
1138
1155
|
|
|
1139
1156
|
|
|
1140
|
-
def
|
|
1141
|
-
|
|
1142
|
-
|
|
1157
|
+
def _merge_extra_index_urls(existing: Iterable[str], new: list[str]) -> list[str]:
|
|
1158
|
+
"""
|
|
1159
|
+
Merge `new` extra index URLs into `existing`, preserving order and dropping
|
|
1160
|
+
duplicates. Used so that a user-configured ``python.extra_index_urls``
|
|
1161
|
+
survives aws_auth resolving its own CodeArtifact-backed extra indexes.
|
|
1162
|
+
"""
|
|
1163
|
+
merged = list(existing)
|
|
1164
|
+
for url in new:
|
|
1165
|
+
if url not in merged:
|
|
1166
|
+
merged.append(url)
|
|
1167
|
+
return merged
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
def _resolve_extra_index_urls(cfg: ConfigTree, index_base_url: str) -> list[str]:
|
|
1171
|
+
"""
|
|
1172
|
+
Resolve ``python.aws_auth.extra_indexes`` into full, authenticated
|
|
1173
|
+
CodeArtifact index URLs, obfuscating each token along the way.
|
|
1174
|
+
"""
|
|
1175
|
+
|
|
1176
|
+
extra_index_urls = []
|
|
1177
|
+
for extra_index in cfg.python.aws_auth.extra_indexes:
|
|
1178
|
+
extra_index_url = urljoin(index_base_url + "/", interpolate1(extra_index))
|
|
1179
|
+
# Kinda redundant since index_url carries the same secret and is already
|
|
1180
|
+
# obfuscated. So this noop here just exists to make the obfucation
|
|
1181
|
+
# explicit.
|
|
1182
|
+
_obfuscate_index_url(extra_index_url)
|
|
1183
|
+
extra_index_urls.append(extra_index_url)
|
|
1184
|
+
return extra_index_urls
|
|
1185
|
+
|
|
1186
|
+
|
|
1187
|
+
def _apply_resolved_index_urls(cfg: ConfigTree, index_base_url: str) -> None:
|
|
1188
|
+
"""
|
|
1189
|
+
Set ``python.index_url`` and merge-resolve ``python.extra_index_urls`` from
|
|
1190
|
+
`index_base_url`, the CodeArtifact domain/repository base shared by the
|
|
1191
|
+
primary index and any ``aws_auth.extra_indexes``. Shared by both the
|
|
1192
|
+
fresh-token and cached-token paths of ``_check_aws_token_validity``.
|
|
1193
|
+
"""
|
|
1194
|
+
|
|
1195
|
+
index_url = urljoin(index_base_url + "/", interpolate1(cfg.python.aws_auth.index))
|
|
1196
|
+
cfg.python.index_url = index_url
|
|
1197
|
+
_obfuscate_index_url(index_url)
|
|
1198
|
+
cfg.python.extra_index_urls = _merge_extra_index_urls(
|
|
1199
|
+
cfg.python.extra_index_urls,
|
|
1200
|
+
_resolve_extra_index_urls(cfg, index_base_url),
|
|
1201
|
+
)
|
|
1202
|
+
|
|
1203
|
+
|
|
1204
|
+
def _check_aws_token_validity(cfg: ConfigTree) -> None:
|
|
1143
1205
|
"""
|
|
1144
1206
|
If csspin-python[aws_auth] is installed, we can use csaccess to get the
|
|
1145
1207
|
CodeArtifact authentication token.
|
|
@@ -1155,65 +1217,39 @@ def _check_aws_token_validity( # pylint: disable=too-many-locals
|
|
|
1155
1217
|
|
|
1156
1218
|
import time
|
|
1157
1219
|
|
|
1158
|
-
client_secret = interpolate1(cfg.python.aws_auth.client_secret) or os.getenv(
|
|
1159
|
-
"CS_AWS_OIDC_CLIENT_SECRET"
|
|
1160
|
-
)
|
|
1161
|
-
static_oidc = interpolate1(cfg.python.aws_auth.static_oidc).lower() == "true"
|
|
1162
|
-
|
|
1163
|
-
if static_oidc and not client_secret:
|
|
1164
|
-
die(
|
|
1165
|
-
"Please provide a client secret for CodeArtifact access via"
|
|
1166
|
-
" 'python.aws_auth.client_secret' when using static OIDC."
|
|
1167
|
-
)
|
|
1168
|
-
|
|
1169
1220
|
current_time = int(time.time())
|
|
1170
1221
|
timestamp_key = "aws_auth_timestamp"
|
|
1171
1222
|
|
|
1172
1223
|
with memoizer(cfg.python.aws_auth.memo) as memo:
|
|
1173
|
-
|
|
1174
|
-
if isinstance(item,
|
|
1175
|
-
|
|
1224
|
+
if memo.items() and (item := memo.items()[0]):
|
|
1225
|
+
if not isinstance(item, tuple):
|
|
1226
|
+
memo.clear()
|
|
1227
|
+
else:
|
|
1228
|
+
_, last_time, index_base_url = item
|
|
1176
1229
|
if current_time - last_time < int(
|
|
1177
1230
|
interpolate1(cfg.python.aws_auth.key_duration)
|
|
1178
1231
|
):
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
if index_url := (
|
|
1185
|
-
config_parser["global"].get("index_url")
|
|
1186
|
-
or config_parser["global"].get("index-url")
|
|
1187
|
-
):
|
|
1188
|
-
cfg.python.index_url = index_url
|
|
1189
|
-
_obfuscate_index_url(index_url)
|
|
1190
|
-
break
|
|
1191
|
-
memo.items().remove(item)
|
|
1192
|
-
else:
|
|
1193
|
-
info("Updating Codeartifact token.")
|
|
1194
|
-
from urllib.error import HTTPError
|
|
1195
|
-
from urllib.parse import urljoin
|
|
1196
|
-
|
|
1197
|
-
opts = {
|
|
1198
|
-
"client_secret": client_secret,
|
|
1199
|
-
"static_oidc": static_oidc,
|
|
1200
|
-
}
|
|
1201
|
-
if cfg.python.aws_auth.client_id:
|
|
1202
|
-
opts["client_id"] = interpolate1(cfg.python.aws_auth.client_id)
|
|
1203
|
-
if cfg.python.aws_auth.role_arn:
|
|
1204
|
-
opts["aws_role_arn"] = interpolate1(cfg.python.aws_auth.role_arn)
|
|
1232
|
+
info("Using cached CodeArtifact token.")
|
|
1233
|
+
_apply_resolved_index_urls(cfg, index_base_url)
|
|
1234
|
+
return
|
|
1235
|
+
memo.clear()
|
|
1205
1236
|
|
|
1206
|
-
|
|
1207
|
-
index_base_url = get_ca_pypi_url_programmatic(**opts)
|
|
1208
|
-
except HTTPError as e:
|
|
1209
|
-
die(f"Failed to establish CodeArtifact connection: {e}")
|
|
1237
|
+
info("Updating Codeartifact token.")
|
|
1210
1238
|
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
cfg.python.
|
|
1215
|
-
|
|
1239
|
+
opts = {}
|
|
1240
|
+
|
|
1241
|
+
if cfg.python.aws_auth.client_id:
|
|
1242
|
+
opts["client_id"] = interpolate1(cfg.python.aws_auth.client_id)
|
|
1243
|
+
if cfg.python.aws_auth.role_arn:
|
|
1244
|
+
opts["aws_role_arn"] = interpolate1(cfg.python.aws_auth.role_arn)
|
|
1245
|
+
|
|
1246
|
+
try:
|
|
1247
|
+
index_base_url = get_ca_pypi_url_programmatic(**opts)
|
|
1248
|
+
except HTTPError as e:
|
|
1249
|
+
die(f"Failed to establish CodeArtifact connection: {e}")
|
|
1250
|
+
|
|
1251
|
+
_apply_resolved_index_urls(cfg, index_base_url)
|
|
1216
1252
|
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1253
|
+
if exists(cfg.python.venv):
|
|
1254
|
+
_configure_pipconf(cfg, update=True)
|
|
1255
|
+
memo.add((timestamp_key, current_time, index_base_url))
|
csspin_python/python_sbom.py
CHANGED
|
@@ -71,7 +71,9 @@ def sbom(cfg: ConfigTree) -> None:
|
|
|
71
71
|
die(f"Project path '{project_path}' does not exist.")
|
|
72
72
|
|
|
73
73
|
project_path = Path(project_path).absolute()
|
|
74
|
-
metadata = get_project_metadata(
|
|
74
|
+
metadata = get_project_metadata(
|
|
75
|
+
project_path, cfg.python.index_url, tuple(cfg.python.extra_index_urls)
|
|
76
|
+
)
|
|
75
77
|
project_name, project_version = metadata.get("name"), metadata.get("version")
|
|
76
78
|
|
|
77
79
|
file_name = _predict_wheel_filename(
|
|
@@ -138,6 +140,7 @@ def _ensure_cyclonedx_venv(cfg: ConfigTree, binary_dir: str, quiet: str | None)
|
|
|
138
140
|
"install",
|
|
139
141
|
"--index-url",
|
|
140
142
|
cfg.python.index_url,
|
|
143
|
+
*[f"--extra-index-url={url}" for url in cfg.python.extra_index_urls],
|
|
141
144
|
"cyclonedx-bom==" + requested_version,
|
|
142
145
|
use_subprocess_environment=False,
|
|
143
146
|
)
|
|
@@ -168,6 +171,7 @@ def _run_cyclonedx(cfg: ConfigTree, third_party_deps: set[str], stderr: int) ->
|
|
|
168
171
|
"install",
|
|
169
172
|
"--index-url",
|
|
170
173
|
cfg.python.index_url,
|
|
174
|
+
*[f"--extra-index-url={url}" for url in cfg.python.extra_index_urls],
|
|
171
175
|
*[
|
|
172
176
|
f"--constraint={constraint}"
|
|
173
177
|
for constraint in cfg.python.constraints
|
csspin_python/python_schema.yaml
CHANGED
|
@@ -116,6 +116,13 @@ python:
|
|
|
116
116
|
The index url from where packages should get installed into the
|
|
117
117
|
venv. This value will also be put into cfg.python.pipconf, if
|
|
118
118
|
not already mentioned there.
|
|
119
|
+
extra_index_urls:
|
|
120
|
+
type: list
|
|
121
|
+
help: |
|
|
122
|
+
Additional package indexes to install from, alongside
|
|
123
|
+
'index_url'. If 'aws_auth.extra_indexes' is set, its
|
|
124
|
+
resolved, authenticated CodeArtifact URLs are merged into
|
|
125
|
+
this list.
|
|
119
126
|
build_wheels:
|
|
120
127
|
type: list
|
|
121
128
|
help: |
|
|
@@ -141,22 +148,17 @@ python:
|
|
|
141
148
|
Time in seconds defining how long the plugin should
|
|
142
149
|
consider the authentication token as valid before
|
|
143
150
|
issuing a new one.
|
|
144
|
-
static_oidc:
|
|
145
|
-
type: bool
|
|
146
|
-
help: |
|
|
147
|
-
Whether to static OIDC when authenticating with AWS
|
|
148
|
-
CodeArtifact.
|
|
149
151
|
index:
|
|
150
152
|
type: str
|
|
151
|
-
help: The CodeArtifact repository index (e.g. "
|
|
153
|
+
help: The CodeArtifact repository index (e.g. "2026.2/simple").
|
|
154
|
+
extra_indexes:
|
|
155
|
+
type: list
|
|
156
|
+
help: |
|
|
157
|
+
Additional CodeArtifact repository indexes to
|
|
158
|
+
authenticate against, alongside 'index'.
|
|
152
159
|
client_id:
|
|
153
160
|
type: str
|
|
154
161
|
help: The OIDC client ID to use.
|
|
155
|
-
client_secret:
|
|
156
|
-
type: secret
|
|
157
|
-
help: |
|
|
158
|
-
The OIDC client secret to use, defaults to the
|
|
159
|
-
environment variable 'CS_AWS_OIDC_CLIENT_SECRET'.
|
|
160
162
|
role_arn:
|
|
161
163
|
type: str
|
|
162
164
|
help: The role ARN to assume when authenticating.
|
csspin_python/uv_provisioner.py
CHANGED
|
@@ -161,16 +161,26 @@ class SimpleUvProvisioner(SimpleProvisioner):
|
|
|
161
161
|
self._uv_cmd("pip", "install", "pip")
|
|
162
162
|
|
|
163
163
|
|
|
164
|
+
def _set_extra_index_url(toml_content: dict, extra_index_urls: list[str]) -> None:
|
|
165
|
+
"""Set or drop the 'extra-index-url' key in `toml_content` in place."""
|
|
166
|
+
if extra_index_urls:
|
|
167
|
+
toml_content["extra-index-url"] = extra_index_urls
|
|
168
|
+
else:
|
|
169
|
+
toml_content.pop("extra-index-url", None)
|
|
170
|
+
|
|
171
|
+
|
|
164
172
|
def _configure_uv_toml(cfg: ConfigTree) -> None:
|
|
165
173
|
"""
|
|
166
174
|
Create a config file for uv, similar to the pip.conf of
|
|
167
175
|
csspin_python.python, since `uv` pip won't respect the pip.conf.
|
|
176
|
+
|
|
177
|
+
'index-url'/'extra-index-url' declared in the 'uv_provisioner.uv_toml'
|
|
178
|
+
template are ignored; 'python.index_url'/'python.extra_index_urls' are
|
|
179
|
+
the only supported way to configure these.
|
|
168
180
|
"""
|
|
169
181
|
toml_content = tomllib.loads(cfg.uv_provisioner.uv_toml or "")
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
else:
|
|
173
|
-
toml_content["index-url"] = toml_content.get("index-url", cfg.python.index_url)
|
|
182
|
+
toml_content["index-url"] = cfg.python.index_url
|
|
183
|
+
_set_extra_index_url(toml_content, cfg.python.extra_index_urls)
|
|
174
184
|
|
|
175
185
|
with open(cfg.uv_provisioner.uv_toml_path, mode="wb") as fd:
|
|
176
186
|
tomli_w.dump(toml_content, fd)
|
|
@@ -178,12 +188,20 @@ def _configure_uv_toml(cfg: ConfigTree) -> None:
|
|
|
178
188
|
|
|
179
189
|
def _update_index_url_in_toml(cfg: ConfigTree) -> None:
|
|
180
190
|
"""
|
|
181
|
-
Update the index-url in the uv.toml in case
|
|
191
|
+
Update the index-url and extra-index-url in the uv.toml in case they
|
|
192
|
+
changed.
|
|
182
193
|
"""
|
|
183
194
|
if (uv_toml_path := interpolate1(Path(cfg.uv_provisioner.uv_toml_path))).exists():
|
|
184
195
|
with open(uv_toml_path, mode="rb") as fd:
|
|
185
196
|
toml_content = tomllib.load(fd)
|
|
197
|
+
changed = False
|
|
186
198
|
if toml_content.get("index-url") != cfg.python.index_url:
|
|
187
199
|
toml_content["index-url"] = cfg.python.index_url
|
|
200
|
+
changed = True
|
|
201
|
+
|
|
202
|
+
if toml_content.get("extra-index-url", []) != cfg.python.extra_index_urls:
|
|
203
|
+
_set_extra_index_url(toml_content, cfg.python.extra_index_urls)
|
|
204
|
+
changed = True
|
|
205
|
+
if changed:
|
|
188
206
|
with open(uv_toml_path, mode="wb") as fd:
|
|
189
207
|
tomli_w.dump(toml_content, fd)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csspin-python
|
|
3
|
-
Version:
|
|
3
|
+
Version: 6.0.0
|
|
4
4
|
Summary: Plugin-package for csspin providing Python related plugins
|
|
5
5
|
Author-email: CONTACT Software GmbH <info@contact-software.com>
|
|
6
6
|
Maintainer-email: Waleri Enns <waleri.enns@contact-software.com>, Benjamin Thomas Schwertfeger <benjaminthomas.schwertfeger@contact-software.com>, Fabian Hafer <fabian.hafer@contact-software.com>
|
|
@@ -27,7 +27,7 @@ License-File: LICENSE
|
|
|
27
27
|
Requires-Dist: platformdirs~=4.3.8
|
|
28
28
|
Requires-Dist: virtualenv
|
|
29
29
|
Provides-Extra: aws-auth
|
|
30
|
-
Requires-Dist: csaccess>=0.
|
|
30
|
+
Requires-Dist: csaccess>=0.3.0; extra == "aws-auth"
|
|
31
31
|
Provides-Extra: uv
|
|
32
32
|
Requires-Dist: tomli; python_version < "3.11" and extra == "uv"
|
|
33
33
|
Requires-Dist: tomli-w; extra == "uv"
|
|
@@ -9,16 +9,16 @@ csspin_python/playwright.py,sha256=oFfphLqa4AB6K9vasCUFHN0kFXu63n3ocrsqVuRp4-0,5
|
|
|
9
9
|
csspin_python/playwright_schema.yaml,sha256=TSeR16YHa7m7bfO59F2eMV-jXcglluTJdEpUeL16saY,1178
|
|
10
10
|
csspin_python/pytest.py,sha256=vSLtmS-kNO0NPo_tszfEm5zGwJb6Yb5IGS-hA7CNguo,4544
|
|
11
11
|
csspin_python/pytest_schema.yaml,sha256=tzXtdF6MvGC9v59EVRJFfLeMMHqPsXcFXy2zJtRECBI,1535
|
|
12
|
-
csspin_python/python.py,sha256=
|
|
13
|
-
csspin_python/python_sbom.py,sha256=
|
|
12
|
+
csspin_python/python.py,sha256=uoWCm_X2_yGaOdnxAb_h2Mr8RjLd5MjuVL4cPF15E2E,41973
|
|
13
|
+
csspin_python/python_sbom.py,sha256=AT_dFEKoghZTVkkTECz0cOo-w3AZAYAgROx4prhAHKw,13603
|
|
14
14
|
csspin_python/python_sbom_schema.yaml,sha256=QysysjGJ6n1WEoLBqYHcdbojuEomUvL8QG4ZSWQW2_8,739
|
|
15
|
-
csspin_python/python_schema.yaml,sha256=
|
|
15
|
+
csspin_python/python_schema.yaml,sha256=RwJgbyIRenj18-s60HmqkwWCGtd6G1acpJ9TDI9QjBQ,6448
|
|
16
16
|
csspin_python/radon.py,sha256=uFqm6FEi5oWj-_XVaAm3s9cam0cUmr1_FwRf40K6xWs,1876
|
|
17
17
|
csspin_python/radon_schema.yaml,sha256=rlRzXw5z4XbjOVznRiUxWGP4E9hx1Jm-gGw1iQiYzE0,548
|
|
18
|
-
csspin_python/uv_provisioner.py,sha256=
|
|
18
|
+
csspin_python/uv_provisioner.py,sha256=2M1I8PqWTCUxqaOeJI5rchmly6t-MnOPQfIx-kKzdQU,6757
|
|
19
19
|
csspin_python/uv_provisioner_schema.yaml,sha256=Y8ZNC2OMnhR8Us3WUXAXK9hMjqGWAKFJB2puX4X5XNQ,727
|
|
20
|
-
csspin_python-
|
|
21
|
-
csspin_python-
|
|
22
|
-
csspin_python-
|
|
23
|
-
csspin_python-
|
|
24
|
-
csspin_python-
|
|
20
|
+
csspin_python-6.0.0.dist-info/licenses/LICENSE,sha256=4MAecetnRTQw5DlHtiikDSzKWO1xVLwzM5_DsPMYlnE,10172
|
|
21
|
+
csspin_python-6.0.0.dist-info/METADATA,sha256=a-NIDfoER1W6_3YNyaxS_RKPKLXmWp6tk-uApcS6Lr4,5254
|
|
22
|
+
csspin_python-6.0.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
23
|
+
csspin_python-6.0.0.dist-info/top_level.txt,sha256=QSeglMEGbFu1z4L6MCQYwo01NgL0KojWvC4rzgMQ8gU,14
|
|
24
|
+
csspin_python-6.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|