cf-bootstrap-instance 0.1.8__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.
- cf_bootstrap_instance/__init__.py +11 -0
- cf_bootstrap_instance/handoff.py +135 -0
- cf_bootstrap_instance/install.py +119 -0
- cf_bootstrap_instance/layout.py +156 -0
- cf_bootstrap_instance/model.py +322 -0
- cf_bootstrap_instance/process.py +28 -0
- cf_bootstrap_instance/provider.py +671 -0
- cf_bootstrap_instance/recovery.py +380 -0
- cf_bootstrap_instance/semantics/package.trig +36 -0
- cf_bootstrap_instance/semantics/service.trig +93 -0
- cf_bootstrap_instance/service_executor.py +178 -0
- cf_bootstrap_instance/transition_authority.py +136 -0
- cf_bootstrap_instance/uninstall_authority.py +119 -0
- cf_bootstrap_instance/verify.py +358 -0
- cf_bootstrap_instance-0.1.8.dist-info/METADATA +6 -0
- cf_bootstrap_instance-0.1.8.dist-info/RECORD +18 -0
- cf_bootstrap_instance-0.1.8.dist-info/WHEEL +4 -0
- cf_bootstrap_instance-0.1.8.dist-info/entry_points.txt +10 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
"""Independent target-environment inventory, provenance, and semantic checks."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
import re
|
|
8
|
+
|
|
9
|
+
from .model import InstanceError
|
|
10
|
+
from .process import run
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
_CHECK = r'''
|
|
14
|
+
import json, os, pathlib, stat, subprocess, sys
|
|
15
|
+
from importlib import metadata
|
|
16
|
+
|
|
17
|
+
environment = pathlib.Path(sys.argv[1]).resolve()
|
|
18
|
+
expected = json.loads(sys.argv[2])
|
|
19
|
+
checkout = pathlib.Path(sys.argv[3]).resolve() if sys.argv[3] else None
|
|
20
|
+
native_expected = json.loads(sys.argv[5])
|
|
21
|
+
native_by_name = {item["name"]: item for item in native_expected}
|
|
22
|
+
site = pathlib.Path(next(item for item in sys.path if item and "site-packages" in pathlib.Path(item).parts)).resolve()
|
|
23
|
+
scripts = environment / ("Scripts" if sys.platform == "win32" else "bin")
|
|
24
|
+
if pathlib.Path(sys.executable).resolve() != pathlib.Path(sys.argv[4]).resolve() or pathlib.Path(sys.prefix).resolve() != environment:
|
|
25
|
+
raise RuntimeError("target interpreter is not bound to the target environment")
|
|
26
|
+
if checkout and any(pathlib.Path(item).resolve() == checkout or checkout in pathlib.Path(item).resolve().parents for item in sys.path):
|
|
27
|
+
raise RuntimeError("checkout appears in target sys.path")
|
|
28
|
+
|
|
29
|
+
distributions = list(metadata.distributions())
|
|
30
|
+
actual = sorted([{"name": d.metadata.get("Name"), "version": d.version} for d in distributions], key=lambda item: item["name"].lower())
|
|
31
|
+
if actual != expected:
|
|
32
|
+
raise RuntimeError("installed distribution inventory differs from artifact set")
|
|
33
|
+
for distribution in distributions:
|
|
34
|
+
location = pathlib.Path(distribution.locate_file("")).resolve()
|
|
35
|
+
if site not in location.parents and location != site:
|
|
36
|
+
raise RuntimeError("distribution is outside target site-packages")
|
|
37
|
+
for file in distribution.files or ():
|
|
38
|
+
path = (location / file).resolve()
|
|
39
|
+
if site not in path.parents and path != site and scripts not in path.parents:
|
|
40
|
+
raise RuntimeError("distribution file escaped site-packages")
|
|
41
|
+
for file in distribution.files or ():
|
|
42
|
+
if file.name in ("direct_url.json",) or file.suffix == ".pth" or file.name.endswith(".egg-link"):
|
|
43
|
+
raise RuntimeError("forbidden editable/provenance metadata found")
|
|
44
|
+
for entry in distribution.entry_points:
|
|
45
|
+
if entry.group == "console_scripts":
|
|
46
|
+
command = scripts / entry.name
|
|
47
|
+
if sys.platform == "win32":
|
|
48
|
+
command = command.with_suffix(".exe")
|
|
49
|
+
if not command.is_file() or command.resolve().parent != scripts.resolve():
|
|
50
|
+
raise RuntimeError("console script is not in target Scripts directory")
|
|
51
|
+
|
|
52
|
+
semantic_entries = list(metadata.entry_points(group="cogniflow.semantic_sources"))
|
|
53
|
+
by_distribution = {}
|
|
54
|
+
semantic_files = {}
|
|
55
|
+
for entry in semantic_entries:
|
|
56
|
+
dist = entry.dist
|
|
57
|
+
if dist is None or not dist.metadata.get("Name") or entry.name in by_distribution:
|
|
58
|
+
raise RuntimeError("semantic source entry point is ambiguous")
|
|
59
|
+
by_distribution[entry.name] = entry
|
|
60
|
+
for expected_item in expected:
|
|
61
|
+
name = expected_item["name"]
|
|
62
|
+
if name in native_by_name or name == "cf-service-mcp-server":
|
|
63
|
+
continue
|
|
64
|
+
if not (name.lower().startswith("cf-") or name.lower() == "cogniflow"):
|
|
65
|
+
continue
|
|
66
|
+
matches = [entry for entry in semantic_entries if entry.dist.metadata.get("Name") == name]
|
|
67
|
+
if len(matches) != 1:
|
|
68
|
+
raise RuntimeError(f"expected distribution has no unique semantic source: {name}")
|
|
69
|
+
files = matches[0].load()()
|
|
70
|
+
if not files:
|
|
71
|
+
raise RuntimeError("semantic source is empty")
|
|
72
|
+
for file in files:
|
|
73
|
+
path = pathlib.Path(file).resolve()
|
|
74
|
+
if site not in path.parents or not path.is_file() or path.suffix != ".trig":
|
|
75
|
+
raise RuntimeError(f"semantic source escaped target package: {path} (site={site})")
|
|
76
|
+
semantic_files[name] = [str(path) for path in files]
|
|
77
|
+
|
|
78
|
+
for item in native_expected:
|
|
79
|
+
name = item["name"]
|
|
80
|
+
distribution = metadata.distribution(name)
|
|
81
|
+
if distribution.version != item["version"]:
|
|
82
|
+
raise RuntimeError("native distribution version differs from artifact metadata")
|
|
83
|
+
command = scripts / pathlib.PurePosixPath(item["executable"]).name
|
|
84
|
+
try:
|
|
85
|
+
info = command.lstat()
|
|
86
|
+
except OSError as error:
|
|
87
|
+
raise RuntimeError("native executable is missing") from error
|
|
88
|
+
if command.is_symlink() or not stat.S_ISREG(info.st_mode) or (sys.platform == "win32" and getattr(info, "st_file_attributes", 0) & 0x400):
|
|
89
|
+
raise RuntimeError("native executable is not a regular target file")
|
|
90
|
+
binary = command.read_bytes()
|
|
91
|
+
if (sys.platform == "win32" and not binary.startswith(b"MZ")) or (sys.platform != "win32" and not binary.startswith(b"\x7fELF")):
|
|
92
|
+
raise RuntimeError("installed native executable has the wrong file type")
|
|
93
|
+
version_env = os.environ.copy()
|
|
94
|
+
version_env.pop("COGNIFLOW_RUNTIME_MANIFEST", None)
|
|
95
|
+
version_env["PATH"] = str(scripts)
|
|
96
|
+
version_env["CARGO_HOME"] = str(environment / "missing-cargo-home")
|
|
97
|
+
version_env["RUSTUP_HOME"] = str(environment / "missing-rustup-home")
|
|
98
|
+
version_env.pop("RUSTUP_TOOLCHAIN", None)
|
|
99
|
+
result = subprocess.run([str(command), "--version"], cwd=environment, env=version_env, capture_output=True, text=True, check=False, timeout=10)
|
|
100
|
+
if result.returncode != 0 or result.stderr or result.stdout != f"{name} {item['version']}\n":
|
|
101
|
+
raise RuntimeError("installed native executable version check failed")
|
|
102
|
+
semantic_files["__native__"] = native_expected
|
|
103
|
+
print(json.dumps({"inventory": actual, "semantic_files": semantic_files}, sort_keys=True))
|
|
104
|
+
'''
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def inventory(executable: Path, environment: Path, artifact_set: dict[str, object], checkout: Path | None = None) -> list[dict[str, str]]:
|
|
108
|
+
expected = sorted([{"name": item["distribution"], "version": item["version"]} for item in artifact_set["artifacts"]], key=lambda item: item["name"].lower())
|
|
109
|
+
native_expected = [{"name": item["distribution"], "version": item["version"], "executable": item["executable"]} for item in artifact_set["artifacts"] if item.get("artifact_kind") == "native"]
|
|
110
|
+
result = run([str(executable), "-c", _CHECK, str(environment), json.dumps(expected, sort_keys=True), str(checkout or ""), str(executable), json.dumps(native_expected, sort_keys=True)], timeout=60, cwd=environment)
|
|
111
|
+
try:
|
|
112
|
+
report = json.loads(result.stdout)
|
|
113
|
+
actual = report["inventory"]
|
|
114
|
+
except ValueError as error:
|
|
115
|
+
raise InstanceError("VERIFY_FAILED", "target verification was not JSON") from error
|
|
116
|
+
if actual != expected:
|
|
117
|
+
raise InstanceError("VERIFY_FAILED", "target inventory differs from expected inventory")
|
|
118
|
+
_verify_semantics(report["semantic_files"], expected)
|
|
119
|
+
return actual
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _verify_semantics(files_by_distribution: object, expected: list[dict[str, str]]) -> None:
|
|
123
|
+
if not isinstance(files_by_distribution, dict):
|
|
124
|
+
raise InstanceError("VERIFY_FAILED", "semantic source report is invalid")
|
|
125
|
+
try:
|
|
126
|
+
from rdflib import Dataset, Literal, URIRef
|
|
127
|
+
except ModuleNotFoundError:
|
|
128
|
+
_verify_semantics_without_rdflib(files_by_distribution, expected)
|
|
129
|
+
return
|
|
130
|
+
cf = URIRef("https://cogniflow.odea-project.org/cf#")
|
|
131
|
+
rdf_type = URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
|
|
132
|
+
rdf_value = URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#value")
|
|
133
|
+
def objects(subject: object, predicate: object) -> list[object]:
|
|
134
|
+
return [obj for _, _, obj, _ in dataset.quads((subject, predicate, None, None))]
|
|
135
|
+
def subjects(predicate: object, obj: object) -> list[object]:
|
|
136
|
+
return [subject for subject, _, _, _ in dataset.quads((None, predicate, obj, None))]
|
|
137
|
+
for item in expected:
|
|
138
|
+
name = item["name"]
|
|
139
|
+
if name == "cf-service-mcp-server" or any(item.get("name") == name for item in files_by_distribution.get("__native__", [])):
|
|
140
|
+
continue
|
|
141
|
+
if not (name.lower().startswith("cf-") or name.lower() == "cogniflow"):
|
|
142
|
+
continue
|
|
143
|
+
files = files_by_distribution.get(name)
|
|
144
|
+
if not isinstance(files, list) or not files:
|
|
145
|
+
raise InstanceError("VERIFY_FAILED", f"semantic source is empty for {name}")
|
|
146
|
+
package_files = [Path(file) for file in files if Path(file).name == "package.trig"]
|
|
147
|
+
if len(package_files) != 1:
|
|
148
|
+
raise InstanceError("VERIFY_FAILED", f"semantic package manifest is not unique for {name}")
|
|
149
|
+
path = package_files[0]
|
|
150
|
+
try:
|
|
151
|
+
dataset = Dataset()
|
|
152
|
+
dataset.parse(path.as_posix(), format="trig")
|
|
153
|
+
except Exception as error:
|
|
154
|
+
raise InstanceError("VERIFY_FAILED", "semantic TriG is not parseable") from error
|
|
155
|
+
packages = subjects(rdf_type, cf + "CfPackage")
|
|
156
|
+
if len(packages) != 1:
|
|
157
|
+
raise InstanceError("VERIFY_FAILED", "semantic source does not contain exactly one CfPackage")
|
|
158
|
+
manifests = objects(packages[0], cf + "hasPackageManifest")
|
|
159
|
+
if len(manifests) != 1:
|
|
160
|
+
raise InstanceError("VERIFY_FAILED", "semantic source has no unique package manifest")
|
|
161
|
+
distributions = objects(manifests[0], cf + "hasDistributionName")
|
|
162
|
+
versions = objects(manifests[0], cf + "hasPackageVersion")
|
|
163
|
+
values = objects(distributions[0], rdf_value) if len(distributions) == 1 else []
|
|
164
|
+
version_values = objects(versions[0], rdf_value) if len(versions) == 1 else []
|
|
165
|
+
if values != [Literal(name)] or version_values != [Literal(item["version"])] or path.name != "package.trig":
|
|
166
|
+
raise InstanceError("VERIFY_FAILED", "semantic package manifest does not match distribution")
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _verify_semantics_without_rdflib(files_by_distribution: dict[str, object], expected: list[dict[str, str]]) -> None:
|
|
170
|
+
"""Keep installed-provider verification dependency-free when rdflib is absent."""
|
|
171
|
+
for item in expected:
|
|
172
|
+
name = item["name"]
|
|
173
|
+
if any(item.get("name") == name for item in files_by_distribution.get("__native__", [])):
|
|
174
|
+
continue
|
|
175
|
+
if not (name.lower().startswith("cf-") or name.lower() == "cogniflow"):
|
|
176
|
+
continue
|
|
177
|
+
files = files_by_distribution.get(name)
|
|
178
|
+
if not isinstance(files, list) or not files:
|
|
179
|
+
raise InstanceError("VERIFY_FAILED", f"semantic source is empty for {name}")
|
|
180
|
+
package_files = [Path(file) for file in files if Path(file).name == "package.trig"]
|
|
181
|
+
if len(package_files) != 1:
|
|
182
|
+
raise InstanceError("VERIFY_FAILED", f"semantic package manifest is not unique for {name}")
|
|
183
|
+
path = package_files[0]
|
|
184
|
+
if not path.is_file():
|
|
185
|
+
raise InstanceError("VERIFY_FAILED", "semantic source is not a package.trig file")
|
|
186
|
+
text = path.read_text(encoding="utf-8")
|
|
187
|
+
if not _minimal_trig_structure(text, name, item["version"]):
|
|
188
|
+
raise InstanceError("VERIFY_FAILED", "semantic source is missing required manifest data")
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _minimal_trig_structure(text: str, name: str, version: str) -> bool:
|
|
192
|
+
"""Parse the strict package-manifest TriG subset without rdflib."""
|
|
193
|
+
prefixes, body = _parse_prefixes(text)
|
|
194
|
+
if prefixes is None:
|
|
195
|
+
return False
|
|
196
|
+
tokens = _trig_tokens(body)
|
|
197
|
+
if tokens is None:
|
|
198
|
+
return False
|
|
199
|
+
parser = _ManifestParser(tokens, name, version)
|
|
200
|
+
return parser.parse() and parser.position == len(tokens)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def _parse_prefixes(text: str) -> tuple[dict[str, str], str] | tuple[None, str]:
|
|
204
|
+
prefix_pattern = re.compile(r"@prefix ([A-Za-z_][A-Za-z0-9_-]*): <([^>]+)> \.")
|
|
205
|
+
prefixes: dict[str, str] = {}
|
|
206
|
+
lines = text.splitlines()
|
|
207
|
+
body_start = 0
|
|
208
|
+
for index, line in enumerate(lines):
|
|
209
|
+
if not line.strip():
|
|
210
|
+
continue
|
|
211
|
+
match = prefix_pattern.fullmatch(line.strip())
|
|
212
|
+
if match is None:
|
|
213
|
+
body_start = index
|
|
214
|
+
break
|
|
215
|
+
prefix, namespace = match.groups()
|
|
216
|
+
if prefix in prefixes or prefix not in {"cf", "cfproc", "cfservice", "cfpkg", "rdf", "pkg", "contribution", "dcterms", "skos", "xsd"}:
|
|
217
|
+
return None, ""
|
|
218
|
+
prefixes[prefix] = namespace
|
|
219
|
+
body_start = index + 1
|
|
220
|
+
expected = {"cf": "https://cogniflow.odea-project.org/cf#", "cfproc": "https://cogniflow.odea-project.org/cf#", "cfservice": "https://cogniflow.odea-project.org/cf#", "cfpkg": "https://cogniflow.odea-project.org/cf#", "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "pkg": "urn:cf:pkg:", "contribution": "urn:cf:contribution:", "dcterms": "http://purl.org/dc/terms/", "skos": "http://www.w3.org/2004/02/skos/core#", "xsd": "http://www.w3.org/2001/XMLSchema#"}
|
|
221
|
+
if any(prefix in prefixes and prefixes[prefix] != value for prefix, value in expected.items()) or not {"cfpkg", "rdf", "pkg"} <= prefixes.keys():
|
|
222
|
+
return None, ""
|
|
223
|
+
return prefixes, "\n".join(lines[body_start:])
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _trig_tokens(text: str) -> list[str] | None:
|
|
227
|
+
token_pattern = re.compile(r'\s+|"(?:\\.|[^"\\])*"(?:\^\^[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z0-9_.-]+)?|<[^>]*>|[{}\[\];.]|[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z0-9_.-]+|a\b')
|
|
228
|
+
tokens: list[str] = []
|
|
229
|
+
position = 0
|
|
230
|
+
while position < len(text):
|
|
231
|
+
match = token_pattern.match(text, position)
|
|
232
|
+
if match is None:
|
|
233
|
+
return None
|
|
234
|
+
token = match.group(0)
|
|
235
|
+
if not token.isspace():
|
|
236
|
+
tokens.append(token)
|
|
237
|
+
position = match.end()
|
|
238
|
+
return tokens
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class _ManifestParser:
|
|
242
|
+
_manifest_fields = {"cfpkg:hasDistributionName": "DistributionName", "cfpkg:hasPythonPackageName": "PythonPackageName", "cfpkg:hasPackageVersion": "PackageVersion", "cfpkg:hasImplementationLanguage": "ImplementationLanguage"}
|
|
243
|
+
_top_fields = {"cfpkg:hasPackageRole", "cfpkg:hasPackageContribution", "skos:prefLabel", "skos:definition", "skos:scopeNote", "skos:example", "dcterms:created"}
|
|
244
|
+
|
|
245
|
+
def __init__(self, tokens: list[str], name: str, version: str) -> None:
|
|
246
|
+
self.tokens = tokens
|
|
247
|
+
self.position = 0
|
|
248
|
+
self.name = name
|
|
249
|
+
self.version = version
|
|
250
|
+
|
|
251
|
+
def take(self) -> str | None:
|
|
252
|
+
if self.position >= len(self.tokens):
|
|
253
|
+
return None
|
|
254
|
+
token = self.tokens[self.position]
|
|
255
|
+
self.position += 1
|
|
256
|
+
return token
|
|
257
|
+
|
|
258
|
+
def expect(self, expected: str) -> bool:
|
|
259
|
+
return self.take() == expected
|
|
260
|
+
|
|
261
|
+
def parse(self) -> bool:
|
|
262
|
+
if self.tokens.count("cfpkg:CfPackage") != 1:
|
|
263
|
+
return False
|
|
264
|
+
graph = self.take()
|
|
265
|
+
if graph is None or not graph.startswith("pkg:") or not self.expect("{") or self.take() != graph or not self.expect("a") or not self.expect("cfpkg:CfPackage") or not self.expect(";"):
|
|
266
|
+
return False
|
|
267
|
+
manifest_count = 0
|
|
268
|
+
package_terminated = False
|
|
269
|
+
while self.position < len(self.tokens) and self.tokens[self.position] != "}":
|
|
270
|
+
predicate = self.take()
|
|
271
|
+
if predicate == "cfpkg:hasPackageManifest":
|
|
272
|
+
manifest_count += 1
|
|
273
|
+
if not self.parse_manifest():
|
|
274
|
+
return False
|
|
275
|
+
elif predicate in self._top_fields:
|
|
276
|
+
if not self.skip_object():
|
|
277
|
+
return False
|
|
278
|
+
else:
|
|
279
|
+
return False
|
|
280
|
+
terminator = self.take()
|
|
281
|
+
if terminator not in {";", "."}:
|
|
282
|
+
return False
|
|
283
|
+
if terminator == ".":
|
|
284
|
+
package_terminated = True
|
|
285
|
+
break
|
|
286
|
+
if not package_terminated or manifest_count != 1:
|
|
287
|
+
return False
|
|
288
|
+
while self.position < len(self.tokens) and self.tokens[self.position] != "}":
|
|
289
|
+
if self.take() is None or not self.expect("a") or self.take() is None or not self.expect(";"):
|
|
290
|
+
return False
|
|
291
|
+
statement_terminated = False
|
|
292
|
+
while self.position < len(self.tokens):
|
|
293
|
+
if self.tokens[self.position] == ".":
|
|
294
|
+
self.take()
|
|
295
|
+
statement_terminated = True
|
|
296
|
+
break
|
|
297
|
+
if self.tokens[self.position] == "}":
|
|
298
|
+
return False
|
|
299
|
+
if self.take() is None or not self.skip_object():
|
|
300
|
+
return False
|
|
301
|
+
terminator = self.take()
|
|
302
|
+
if terminator not in {";", "."}:
|
|
303
|
+
return False
|
|
304
|
+
if terminator == ".":
|
|
305
|
+
statement_terminated = True
|
|
306
|
+
break
|
|
307
|
+
if not statement_terminated:
|
|
308
|
+
return False
|
|
309
|
+
return self.expect("}")
|
|
310
|
+
|
|
311
|
+
def parse_manifest(self) -> bool:
|
|
312
|
+
if not self.expect("[") or not self.expect("a") or not self.expect("cfpkg:PackageManifest") or not self.expect(";"):
|
|
313
|
+
return False
|
|
314
|
+
fields: dict[str, str] = {}
|
|
315
|
+
closed = False
|
|
316
|
+
while self.position < len(self.tokens) and self.tokens[self.position] != "]":
|
|
317
|
+
predicate = self.take()
|
|
318
|
+
expected_type = self._manifest_fields.get(predicate or "")
|
|
319
|
+
if expected_type is None or predicate in fields:
|
|
320
|
+
return False
|
|
321
|
+
value = self.parse_value_resource(expected_type)
|
|
322
|
+
if value is None:
|
|
323
|
+
return False
|
|
324
|
+
fields[predicate] = value
|
|
325
|
+
terminator = self.take()
|
|
326
|
+
if terminator not in {";", "]"}:
|
|
327
|
+
return False
|
|
328
|
+
if terminator == "]":
|
|
329
|
+
closed = True
|
|
330
|
+
break
|
|
331
|
+
required = {"cfpkg:hasDistributionName", "cfpkg:hasPackageVersion", "cfpkg:hasImplementationLanguage"}
|
|
332
|
+
if not closed and self.expect("]"):
|
|
333
|
+
closed = True
|
|
334
|
+
return closed and required <= fields.keys() and fields["cfpkg:hasDistributionName"] == self.name and fields["cfpkg:hasPackageVersion"] == self.version and fields["cfpkg:hasImplementationLanguage"] == "Python"
|
|
335
|
+
|
|
336
|
+
def parse_value_resource(self, expected_type: str) -> str | None:
|
|
337
|
+
if not self.expect("[") or not self.expect("a") or not self.expect(f"cfpkg:{expected_type}") or not self.expect(";") or not self.expect("rdf:value"):
|
|
338
|
+
return None
|
|
339
|
+
value = self.take()
|
|
340
|
+
if value is None or not value.startswith('"') or not self.expect("]"):
|
|
341
|
+
return None
|
|
342
|
+
return value[1:-1]
|
|
343
|
+
|
|
344
|
+
def skip_object(self) -> bool:
|
|
345
|
+
if self.position >= len(self.tokens):
|
|
346
|
+
return False
|
|
347
|
+
if self.tokens[self.position] != "[":
|
|
348
|
+
return self.take() is not None
|
|
349
|
+
depth = 0
|
|
350
|
+
while self.position < len(self.tokens):
|
|
351
|
+
token = self.take()
|
|
352
|
+
if token == "[":
|
|
353
|
+
depth += 1
|
|
354
|
+
elif token == "]":
|
|
355
|
+
depth -= 1
|
|
356
|
+
if depth == 0:
|
|
357
|
+
return True
|
|
358
|
+
return False
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
cf_bootstrap_instance/__init__.py,sha256=w8v2lK8uQkR8mUszqfItidsgEARz1GerYfqd1Sy_ELw,300
|
|
2
|
+
cf_bootstrap_instance/handoff.py,sha256=YeevOTt8sfp0yuZlhyP-sKS8Q20p04VjdB3ju2YzO1M,10504
|
|
3
|
+
cf_bootstrap_instance/install.py,sha256=MM6ASCEEL7wIczn_HTNcGws9UkV_8dQ15jcbdKV5GS4,5393
|
|
4
|
+
cf_bootstrap_instance/layout.py,sha256=doBDoAOmrmEJ9BS6i0Ocsy2ETjdIuIfddPsJqx5l2QQ,8581
|
|
5
|
+
cf_bootstrap_instance/model.py,sha256=D3I8X0D-MbNFPI-uzZQr_uTeZ3-WF7B4-j9itgXuV3Y,24606
|
|
6
|
+
cf_bootstrap_instance/process.py,sha256=_ZtyZF6RP2PHn3WcMuxA1wUzE7JKNiqXaSwdsgBliE0,2007
|
|
7
|
+
cf_bootstrap_instance/provider.py,sha256=9B0L4sm8NAODZ8veTL4bUG7xRjjdKJtv6pml7XIbZJU,41754
|
|
8
|
+
cf_bootstrap_instance/recovery.py,sha256=Q1iD3l4jJXV6JIj6IE4hERB_A4BzBR5DbbBJEcNe2J0,21703
|
|
9
|
+
cf_bootstrap_instance/service_executor.py,sha256=Wk2JYPRS4F5D5pg08RYouOiGcP3Ml5Y5ggS8zVmqD68,12139
|
|
10
|
+
cf_bootstrap_instance/transition_authority.py,sha256=CWDdUhnWgOK1OSglq3g7F26Gh8i5-gKHCYSlqrAp200,8471
|
|
11
|
+
cf_bootstrap_instance/uninstall_authority.py,sha256=EXUl3P0lL4LPRlUYvTw9qxRCKk4e237tWuWiCj3Cw9E,6134
|
|
12
|
+
cf_bootstrap_instance/verify.py,sha256=H5zHj59uu5uTY81RJZ6zvYd0QeqHfVMWXrLRq19To9Q,18836
|
|
13
|
+
cf_bootstrap_instance/semantics/package.trig,sha256=JORaCC2YX_8TkTV457YbZmh2i8x5z0EJAGz-s1ufkow,1436
|
|
14
|
+
cf_bootstrap_instance/semantics/service.trig,sha256=-27WTCCrUxubqyFF76s66Vv3fT7bofjRCfZyBCY9adY,13321
|
|
15
|
+
cf_bootstrap_instance-0.1.8.dist-info/METADATA,sha256=GNW6wI6En6k3f-sQfakys2wBFg_kb6ZoCwErSKUPx_s,204
|
|
16
|
+
cf_bootstrap_instance-0.1.8.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
17
|
+
cf_bootstrap_instance-0.1.8.dist-info/entry_points.txt,sha256=tcUsw9ZwYrt2PcaU1vxfybowlsvbWvRF5y7cNJiL3Zk,415
|
|
18
|
+
cf_bootstrap_instance-0.1.8.dist-info/RECORD,,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
[console_scripts]
|
|
2
|
+
cf-bootstrap-instance-handoff = cf_bootstrap_instance.handoff:main
|
|
3
|
+
cf-bootstrap-instance-provider = cf_bootstrap_instance.provider:main
|
|
4
|
+
cf-bootstrap-runtime-repair = cf_bootstrap_instance.recovery:main
|
|
5
|
+
|
|
6
|
+
[cogniflow.instance_providers.v1]
|
|
7
|
+
cf-bootstrap-instance-provider = cf_bootstrap_instance.provider:main
|
|
8
|
+
|
|
9
|
+
[cogniflow.semantic_sources]
|
|
10
|
+
cf-bootstrap-instance = cf_bootstrap_instance:semantic_files
|