primitive 0.1.67__py3-none-any.whl → 0.1.69__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.
- primitive/__about__.py +1 -1
- primitive/agent/process.py +8 -1
- primitive/agent/runner.py +108 -100
- primitive/agent/uploader.py +6 -7
- primitive/cli.py +0 -4
- primitive/client.py +5 -8
- primitive/files/actions.py +192 -29
- primitive/files/commands.py +4 -1
- primitive/files/graphql/fragments.py +18 -0
- primitive/files/graphql/mutations.py +17 -1
- primitive/files/graphql/queries.py +31 -0
- primitive/utils/auth.py +25 -17
- primitive/utils/chunk_size.py +87 -0
- primitive/utils/files.py +10 -7
- {primitive-0.1.67.dist-info → primitive-0.1.69.dist-info}/METADATA +2 -1
- {primitive-0.1.67.dist-info → primitive-0.1.69.dist-info}/RECORD +19 -22
- primitive/lint/__init__.py +0 -0
- primitive/lint/actions.py +0 -76
- primitive/lint/commands.py +0 -17
- primitive/sim/__init__.py +0 -0
- primitive/sim/actions.py +0 -129
- primitive/sim/commands.py +0 -19
- {primitive-0.1.67.dist-info → primitive-0.1.69.dist-info}/WHEEL +0 -0
- {primitive-0.1.67.dist-info → primitive-0.1.69.dist-info}/entry_points.txt +0 -0
- {primitive-0.1.67.dist-info → primitive-0.1.69.dist-info}/licenses/LICENSE.txt +0 -0
primitive/lint/actions.py
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
from pathlib import Path
|
2
|
-
from primitive.utils.actions import BaseAction
|
3
|
-
import subprocess
|
4
|
-
from typing import Tuple
|
5
|
-
from loguru import logger
|
6
|
-
from ..utils.files import find_files_for_extension
|
7
|
-
from ..utils.verible import install_verible
|
8
|
-
from ..utils.cache import get_deps_cache
|
9
|
-
|
10
|
-
|
11
|
-
class Lint(BaseAction):
|
12
|
-
def execute(self, source: Path = Path.cwd()) -> Tuple[bool, str]:
|
13
|
-
logger.debug(f"Starting linter for source: {source}")
|
14
|
-
files = find_files_for_extension(source, ".sv")
|
15
|
-
if not files:
|
16
|
-
message = "No files found to lint."
|
17
|
-
logger.warning(message)
|
18
|
-
return False, message
|
19
|
-
|
20
|
-
logger.debug("Checking if verible is installed")
|
21
|
-
verible_path = Path("verible-verilog-lint")
|
22
|
-
try:
|
23
|
-
subprocess.run([str(verible_path), "--version"], capture_output=True)
|
24
|
-
except FileNotFoundError:
|
25
|
-
logger.debug("Verible not found in $PATH. Looking in deps cache...")
|
26
|
-
cache_dir = get_deps_cache()
|
27
|
-
|
28
|
-
possible_dirs = cache_dir.glob("verible*")
|
29
|
-
verible_dir = next(possible_dirs, None)
|
30
|
-
|
31
|
-
if verible_dir is not None:
|
32
|
-
verible_path = verible_dir / "bin" / verible_path
|
33
|
-
else:
|
34
|
-
logger.debug("Did not find verible. Installing...")
|
35
|
-
try:
|
36
|
-
system_info = self.primitive.hardware.get_system_info()
|
37
|
-
verible_bin = install_verible(system_info=system_info)
|
38
|
-
verible_path = verible_bin / verible_path
|
39
|
-
except Exception as exception:
|
40
|
-
message = f"Failed to install verible. {exception}"
|
41
|
-
logger.error(message)
|
42
|
-
return False, message
|
43
|
-
|
44
|
-
try:
|
45
|
-
subprocess.run([str(verible_path), "--version"], capture_output=True)
|
46
|
-
except FileNotFoundError:
|
47
|
-
message = "Verible is not installed. Please install it to run lint."
|
48
|
-
logger.error(message)
|
49
|
-
return False, message
|
50
|
-
|
51
|
-
# TODO:
|
52
|
-
# run is great for now! we will need to switch to Popen if we want to stream the output
|
53
|
-
logger.debug("Running linter...")
|
54
|
-
result = subprocess.run(
|
55
|
-
[str(verible_path), *files],
|
56
|
-
capture_output=True,
|
57
|
-
text=True,
|
58
|
-
)
|
59
|
-
|
60
|
-
logger.debug("Linting complete.")
|
61
|
-
|
62
|
-
message = ""
|
63
|
-
if result.stderr:
|
64
|
-
logger.error("\n" + result.stderr)
|
65
|
-
if result.stdout:
|
66
|
-
logger.info("\n" + result.stdout)
|
67
|
-
message = "See above logs for linter output."
|
68
|
-
|
69
|
-
if result.returncode != 0:
|
70
|
-
if not self.primitive.DEBUG:
|
71
|
-
message = result.stdout + result.stderr
|
72
|
-
return (False, message)
|
73
|
-
else:
|
74
|
-
message = "Linting successful."
|
75
|
-
|
76
|
-
return True, message
|
primitive/lint/commands.py
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
import click
|
2
|
-
from pathlib import Path
|
3
|
-
import typing
|
4
|
-
from ..utils.printer import print_result
|
5
|
-
|
6
|
-
if typing.TYPE_CHECKING:
|
7
|
-
from ..client import Primitive
|
8
|
-
|
9
|
-
|
10
|
-
@click.command("lint")
|
11
|
-
@click.pass_context
|
12
|
-
@click.argument("source", type=click.Path(exists=True), default=".")
|
13
|
-
def cli(context, source: str):
|
14
|
-
"""Lint"""
|
15
|
-
primitive: Primitive = context.obj.get("PRIMITIVE")
|
16
|
-
result, message = primitive.lint.execute(source=Path(source))
|
17
|
-
print_result(message=message, context=context)
|
primitive/sim/__init__.py
DELETED
File without changes
|
primitive/sim/actions.py
DELETED
@@ -1,129 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
import os
|
3
|
-
import subprocess
|
4
|
-
import xml.etree.ElementTree as ET
|
5
|
-
from pathlib import Path, PurePath
|
6
|
-
from typing import Tuple
|
7
|
-
|
8
|
-
from loguru import logger
|
9
|
-
from primitive_pal import process_vcd
|
10
|
-
|
11
|
-
from primitive.utils.actions import BaseAction
|
12
|
-
|
13
|
-
from ..utils.files import find_files_for_extension
|
14
|
-
|
15
|
-
|
16
|
-
class Sim(BaseAction):
|
17
|
-
def execute(
|
18
|
-
self, source: Path = Path.cwd(), cmd: Tuple[str] = ["make"]
|
19
|
-
) -> Tuple[bool, str]:
|
20
|
-
logger.debug(f"Starting simulation run for source: {source}")
|
21
|
-
|
22
|
-
os.chdir(source)
|
23
|
-
logger.debug(f"Changed to {source}, starting sim run")
|
24
|
-
try:
|
25
|
-
result = subprocess.run(cmd, capture_output=True, text=True, env=os.environ)
|
26
|
-
except FileNotFoundError:
|
27
|
-
message = f"Did not find {cmd}"
|
28
|
-
logger.error(message)
|
29
|
-
return False, message
|
30
|
-
|
31
|
-
logger.debug("Sim run complete.")
|
32
|
-
|
33
|
-
message = ""
|
34
|
-
if result.stderr:
|
35
|
-
logger.error("\n" + result.stderr)
|
36
|
-
if result.stdout:
|
37
|
-
logger.info("\n" + result.stdout)
|
38
|
-
message = "See above logs for sim output."
|
39
|
-
|
40
|
-
if result.returncode != 0:
|
41
|
-
if not self.primitive.DEBUG:
|
42
|
-
message = result.stderr
|
43
|
-
return False, message
|
44
|
-
else:
|
45
|
-
message = "Sim run successful."
|
46
|
-
|
47
|
-
return True, message
|
48
|
-
|
49
|
-
def collect_artifacts(self, source: Path, job_run_id: str) -> None:
|
50
|
-
# Parse VCD artifacts using rust binding
|
51
|
-
# TODO: eventually make this smarter, only parsing VCDs for failed tests
|
52
|
-
# For now we're uploading the last 10 MB of all VCD files
|
53
|
-
files = find_files_for_extension(source, ".vcd")
|
54
|
-
for file in files:
|
55
|
-
process_vcd(path=str(file.absolute()))
|
56
|
-
|
57
|
-
# Parse XML artifacts
|
58
|
-
files = find_files_for_extension(source, "results.xml")
|
59
|
-
for file in files:
|
60
|
-
self.parse_xml(path=file)
|
61
|
-
|
62
|
-
logger.debug("Uploading additional artifacts...")
|
63
|
-
# TODO: Figure out how to track ".log", ".history" files w/ analog stuff involved
|
64
|
-
file_ids = []
|
65
|
-
files = find_files_for_extension(
|
66
|
-
source, # ("results.xml", ".vcd", ".vcd.json", ".xml.json")
|
67
|
-
("results.xml", ".xml.json", ".vcd.json", ".vcd.parquet"),
|
68
|
-
)
|
69
|
-
for file_path in files:
|
70
|
-
try:
|
71
|
-
key_prefix = f"{job_run_id}/{str(PurePath(file_path).relative_to(Path(source)).parent)}"
|
72
|
-
file_upload_response = self.primitive.files.upload_file_via_api(
|
73
|
-
file_path, key_prefix=key_prefix
|
74
|
-
)
|
75
|
-
file_id = file_upload_response.json()["data"]["fileUpload"]["id"]
|
76
|
-
file_ids.append(file_id)
|
77
|
-
except FileNotFoundError:
|
78
|
-
logger.warning(f"{file_path} not found...")
|
79
|
-
|
80
|
-
logger.debug("Updating job run...")
|
81
|
-
if len(file_ids) > 0:
|
82
|
-
job_run_update_result = self.primitive.jobs.job_run_update(
|
83
|
-
id=job_run_id, file_ids=file_ids
|
84
|
-
)
|
85
|
-
logger.success(job_run_update_result.data)
|
86
|
-
|
87
|
-
def parse_xml(self, path: Path) -> None:
|
88
|
-
results = ET.parse(path)
|
89
|
-
testsuites = results.getroot()
|
90
|
-
|
91
|
-
parsed_results = {}
|
92
|
-
testsuites_name = testsuites.attrib["name"]
|
93
|
-
parsed_results[testsuites_name] = {}
|
94
|
-
|
95
|
-
for testsuite in testsuites.findall("testsuite"):
|
96
|
-
testsuite_name = testsuite.attrib["name"]
|
97
|
-
parsed_results[testsuites_name][testsuite_name] = {
|
98
|
-
"properties": {},
|
99
|
-
"testcases": {},
|
100
|
-
}
|
101
|
-
props = parsed_results[testsuites_name][testsuite_name]["properties"]
|
102
|
-
testcases = parsed_results[testsuites_name][testsuite_name]["testcases"]
|
103
|
-
|
104
|
-
for prop in testsuite.findall("property"):
|
105
|
-
props[prop.attrib["name"]] = prop.attrib["value"]
|
106
|
-
|
107
|
-
for testcase in testsuite.findall("testcase"):
|
108
|
-
testcases[testcase.attrib["name"]] = {
|
109
|
-
attr_key: attr_val for attr_key, attr_val in testcase.attrib.items()
|
110
|
-
}
|
111
|
-
|
112
|
-
failures = testcase.findall("failure")
|
113
|
-
|
114
|
-
if len(failures) > 0:
|
115
|
-
for failure in failures:
|
116
|
-
testcases[testcase.attrib["name"]]["status"] = {
|
117
|
-
"conclusion": "failure",
|
118
|
-
"message": failure.attrib["message"],
|
119
|
-
}
|
120
|
-
else:
|
121
|
-
testcases[testcase.attrib["name"]]["status"] = {
|
122
|
-
"conclusion": "success",
|
123
|
-
"message": "",
|
124
|
-
}
|
125
|
-
|
126
|
-
# Write parsed file
|
127
|
-
data_path = path.parent / f"{path.name}.json"
|
128
|
-
with open(data_path, "w") as f:
|
129
|
-
f.write(json.dumps(parsed_results))
|
primitive/sim/commands.py
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
import click
|
2
|
-
from pathlib import Path
|
3
|
-
import typing
|
4
|
-
from typing import Tuple
|
5
|
-
from ..utils.printer import print_result
|
6
|
-
|
7
|
-
if typing.TYPE_CHECKING:
|
8
|
-
from ..client import Primitive
|
9
|
-
|
10
|
-
|
11
|
-
@click.command("sim")
|
12
|
-
@click.pass_context
|
13
|
-
@click.argument("cmd", nargs=-1, required=True)
|
14
|
-
@click.option("--source", type=click.Path(exists=True), default=".")
|
15
|
-
def cli(context, source: str, cmd: Tuple[str]) -> None:
|
16
|
-
"""Sim"""
|
17
|
-
primitive: Primitive = context.obj.get("PRIMITIVE")
|
18
|
-
result, message = primitive.sim.execute(source=Path(source), cmd=cmd)
|
19
|
-
print_result(message=message, context=context)
|
File without changes
|
File without changes
|
File without changes
|