primitive 0.1.92__py3-none-any.whl → 0.1.94__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/actions.py +33 -11
- primitive/agent/runner.py +11 -6
- primitive/hardware/actions.py +97 -22
- primitive/hardware/android.py +5 -0
- primitive/hardware/commands.py +43 -20
- primitive/hardware/graphql/queries.py +2 -0
- primitive/utils/text.py +24 -0
- {primitive-0.1.92.dist-info → primitive-0.1.94.dist-info}/METADATA +1 -1
- {primitive-0.1.92.dist-info → primitive-0.1.94.dist-info}/RECORD +13 -12
- {primitive-0.1.92.dist-info → primitive-0.1.94.dist-info}/WHEEL +0 -0
- {primitive-0.1.92.dist-info → primitive-0.1.94.dist-info}/entry_points.txt +0 -0
- {primitive-0.1.92.dist-info → primitive-0.1.94.dist-info}/licenses/LICENSE.txt +0 -0
primitive/__about__.py
CHANGED
primitive/agent/actions.py
CHANGED
@@ -17,6 +17,13 @@ class Agent(BaseAction):
|
|
17
17
|
self,
|
18
18
|
):
|
19
19
|
logger.enable("primitive")
|
20
|
+
logger.remove()
|
21
|
+
logger.add(
|
22
|
+
sink=sys.stderr,
|
23
|
+
# catch=True,
|
24
|
+
backtrace=True,
|
25
|
+
diagnose=True,
|
26
|
+
)
|
20
27
|
logger.info(" [*] primitive")
|
21
28
|
logger.info(f" [*] Version: {__version__}")
|
22
29
|
|
@@ -34,8 +41,8 @@ class Agent(BaseAction):
|
|
34
41
|
# setting is_available of the parent also effects the children,
|
35
42
|
# which may have active reservations as well
|
36
43
|
self.primitive.hardware.check_in_http(is_online=True)
|
37
|
-
except Exception as
|
38
|
-
logger.
|
44
|
+
except Exception as exception:
|
45
|
+
logger.exception(f"Error checking in hardware: {exception}")
|
39
46
|
sys.exit(1)
|
40
47
|
|
41
48
|
try:
|
@@ -43,10 +50,14 @@ class Agent(BaseAction):
|
|
43
50
|
active_reservation_pk = None
|
44
51
|
|
45
52
|
while True:
|
53
|
+
logger.debug("Syncing children...")
|
54
|
+
self.primitive.hardware._sync_children()
|
55
|
+
|
46
56
|
logger.debug("Scanning for files to upload...")
|
47
57
|
uploader.scan()
|
48
58
|
|
49
59
|
hardware = self.primitive.hardware.get_own_hardware_details()
|
60
|
+
|
50
61
|
if hardware["activeReservation"]:
|
51
62
|
if (
|
52
63
|
hardware["activeReservation"]["id"] != active_reservation_id
|
@@ -125,14 +136,23 @@ class Agent(BaseAction):
|
|
125
136
|
)
|
126
137
|
)
|
127
138
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
139
|
+
try:
|
140
|
+
downloaded_git_repository_dir = (
|
141
|
+
self.primitive.git.download_git_repository_at_ref(
|
142
|
+
git_repo_full_name=git_repo_full_name,
|
143
|
+
git_ref=git_ref,
|
144
|
+
github_access_token=github_access_token,
|
145
|
+
destination=cache_dir,
|
146
|
+
)
|
134
147
|
)
|
135
|
-
|
148
|
+
except Exception as exception:
|
149
|
+
logger.error(
|
150
|
+
f"Error downloading source: {exception}"
|
151
|
+
)
|
152
|
+
self.primitive.jobs.job_run_update(
|
153
|
+
job_run["id"], status="request_completed", conclusion="failure"
|
154
|
+
)
|
155
|
+
continue
|
136
156
|
|
137
157
|
source_dir = downloaded_git_repository_dir.joinpath(
|
138
158
|
job_run["jobSettings"]["rootDirectory"]
|
@@ -146,9 +166,11 @@ class Agent(BaseAction):
|
|
146
166
|
job_run=job_run,
|
147
167
|
max_log_size=500 * 1024,
|
148
168
|
)
|
149
|
-
except Exception as
|
169
|
+
except Exception as exception:
|
150
170
|
# Log Error
|
151
|
-
logger.
|
171
|
+
logger.exception(
|
172
|
+
f"Error initializing agent runner: {exception}"
|
173
|
+
)
|
152
174
|
else:
|
153
175
|
# Execute job
|
154
176
|
runner.execute()
|
primitive/agent/runner.py
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
import os
|
2
2
|
import threading
|
3
3
|
import typing
|
4
|
+
from enum import IntEnum
|
4
5
|
from pathlib import Path, PurePath
|
5
6
|
from time import sleep
|
6
|
-
from typing import Dict, Iterable, List, Optional, TypedDict
|
7
|
-
from enum import IntEnum
|
7
|
+
from typing import Callable, Dict, Iterable, List, Optional, TypedDict
|
8
8
|
|
9
9
|
import yaml
|
10
10
|
from loguru import logger
|
11
|
-
|
12
|
-
from .provision import ProvisionPython
|
11
|
+
|
13
12
|
from ..utils.cache import get_artifacts_cache, get_logs_cache
|
14
13
|
from ..utils.files import find_files_for_extension
|
14
|
+
from .process import Process
|
15
|
+
from .provision import ProvisionPython
|
15
16
|
|
16
17
|
try:
|
17
18
|
from yaml import CLoader as Loader
|
@@ -74,6 +75,8 @@ class AgentRunner:
|
|
74
75
|
Path(get_logs_cache(self.job_id) / log_name),
|
75
76
|
rotation=self.max_log_size,
|
76
77
|
format=AgentRunner.log_serializer(),
|
78
|
+
backtrace=True,
|
79
|
+
diagnose=True,
|
77
80
|
)
|
78
81
|
|
79
82
|
logger.info(f"Scanning directory for job file {self.job_slug}")
|
@@ -165,8 +168,10 @@ class AgentRunner:
|
|
165
168
|
|
166
169
|
try:
|
167
170
|
proc.start()
|
168
|
-
except Exception as
|
169
|
-
logger.
|
171
|
+
except Exception as exception:
|
172
|
+
logger.exception(
|
173
|
+
f"Error while attempting to run process {exception}"
|
174
|
+
)
|
170
175
|
self.primitive.jobs.job_run_update(
|
171
176
|
self.job_id, status="request_completed", conclusion="failure"
|
172
177
|
)
|
primitive/hardware/actions.py
CHANGED
@@ -42,12 +42,7 @@ from primitive.utils.shell import does_executable_exist
|
|
42
42
|
class Hardware(BaseAction):
|
43
43
|
def __init__(self, *args, **kwargs) -> None:
|
44
44
|
super().__init__(*args, **kwargs)
|
45
|
-
self.
|
46
|
-
"isHealthy": False,
|
47
|
-
"isQuarantined": False,
|
48
|
-
"isAvailable": False,
|
49
|
-
"isOnline": False,
|
50
|
-
}
|
45
|
+
self.status_cache = {}
|
51
46
|
self.children = []
|
52
47
|
|
53
48
|
def _get_darwin_system_profiler_values(self) -> Dict[str, str]:
|
@@ -81,7 +76,7 @@ class Hardware(BaseAction):
|
|
81
76
|
)
|
82
77
|
except subprocess.CalledProcessError as exception:
|
83
78
|
message = f"Error running system_profiler: {exception}"
|
84
|
-
logger.
|
79
|
+
logger.exception(message)
|
85
80
|
return supported_metal_device
|
86
81
|
|
87
82
|
try:
|
@@ -90,7 +85,7 @@ class Hardware(BaseAction):
|
|
90
85
|
)
|
91
86
|
except json.JSONDecodeError as exception:
|
92
87
|
message = f"Error decoding JSON: {exception}"
|
93
|
-
logger.
|
88
|
+
logger.exception(message)
|
94
89
|
return supported_metal_device
|
95
90
|
|
96
91
|
# Checks if any attached displays have metal support
|
@@ -121,7 +116,7 @@ class Hardware(BaseAction):
|
|
121
116
|
)
|
122
117
|
except subprocess.CalledProcessError as exception:
|
123
118
|
message = f"Command {nvidia_smi_query_gpu_csv_command} failed with exception: {exception}" # noqa
|
124
|
-
logger.
|
119
|
+
logger.exception(message)
|
125
120
|
raise exception
|
126
121
|
|
127
122
|
try:
|
@@ -133,7 +128,7 @@ class Hardware(BaseAction):
|
|
133
128
|
)
|
134
129
|
except UnicodeDecodeError as exception:
|
135
130
|
message = f"Error decoding: {exception}"
|
136
|
-
logger.
|
131
|
+
logger.exception(message)
|
137
132
|
raise exception
|
138
133
|
|
139
134
|
nvidia_smi_query_gpu_csv_dict_reader = csv.DictReader(
|
@@ -164,7 +159,7 @@ class Hardware(BaseAction):
|
|
164
159
|
)
|
165
160
|
except subprocess.CalledProcessError as exception:
|
166
161
|
message = f"Error running {system_profiler_hardware_data_type_command}: {exception}" # noqa
|
167
|
-
logger.
|
162
|
+
logger.exception(message)
|
168
163
|
raise exception
|
169
164
|
|
170
165
|
try:
|
@@ -173,7 +168,7 @@ class Hardware(BaseAction):
|
|
173
168
|
)
|
174
169
|
except json.JSONDecodeError as exception:
|
175
170
|
message = f"Error decoding JSON: {exception}" # noqa
|
176
|
-
logger.
|
171
|
+
logger.exception(message)
|
177
172
|
raise exception
|
178
173
|
|
179
174
|
metal_device_json = system_profiler_hardware_data_type_json[
|
@@ -373,7 +368,7 @@ class Hardware(BaseAction):
|
|
373
368
|
)
|
374
369
|
except client_exceptions.ClientConnectorError as exception:
|
375
370
|
message = " [*] Failed to update hardware system info! "
|
376
|
-
logger.
|
371
|
+
logger.exception(message)
|
377
372
|
raise exception
|
378
373
|
|
379
374
|
message = " [*] Updated hardware system info successfully! "
|
@@ -388,8 +383,11 @@ class Hardware(BaseAction):
|
|
388
383
|
is_quarantined: bool = False,
|
389
384
|
is_available: bool = False,
|
390
385
|
is_online: bool = True,
|
386
|
+
fingerprint: Optional[str] = None,
|
391
387
|
):
|
392
|
-
fingerprint
|
388
|
+
# if no fingerprint supplied from argument try from the host_config
|
389
|
+
if not fingerprint:
|
390
|
+
fingerprint = self.primitive.host_config.get("fingerprint", None)
|
393
391
|
|
394
392
|
if not fingerprint:
|
395
393
|
message = (
|
@@ -421,12 +419,22 @@ class Hardware(BaseAction):
|
|
421
419
|
logger.debug(message.get("message"))
|
422
420
|
|
423
421
|
if checkin_success:
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
422
|
+
if self.status_cache.get(fingerprint):
|
423
|
+
previous_status = self.status_cache[fingerprint]
|
424
|
+
else:
|
425
|
+
previous_status = {
|
426
|
+
"isHealthy": False,
|
427
|
+
"isQuarantined": False,
|
428
|
+
"isAvailable": False,
|
429
|
+
"isOnline": False,
|
430
|
+
}
|
431
|
+
self.status_cache[fingerprint] = new_state.copy()
|
432
|
+
|
433
|
+
message = f" [*] Checked in successfully for {fingerprint}: "
|
434
|
+
is_new_status = False
|
428
435
|
for key, value in new_state.items():
|
429
|
-
if value !=
|
436
|
+
if value != previous_status.get(key, None):
|
437
|
+
is_new_status = True
|
430
438
|
if value is True:
|
431
439
|
message = (
|
432
440
|
message
|
@@ -441,6 +449,8 @@ class Hardware(BaseAction):
|
|
441
449
|
+ click.style("✅")
|
442
450
|
+ click.style(" ==> 💤 ", fg="yellow")
|
443
451
|
)
|
452
|
+
if is_new_status is False:
|
453
|
+
message += "No changes."
|
444
454
|
logger.info(message)
|
445
455
|
else:
|
446
456
|
message = "Failed to check in!"
|
@@ -448,7 +458,7 @@ class Hardware(BaseAction):
|
|
448
458
|
return result
|
449
459
|
except client_exceptions.ClientConnectorError as exception:
|
450
460
|
message = " [*] Failed to check in! "
|
451
|
-
logger.
|
461
|
+
logger.exception(message)
|
452
462
|
raise exception
|
453
463
|
|
454
464
|
@guard
|
@@ -512,7 +522,8 @@ class Hardware(BaseAction):
|
|
512
522
|
|
513
523
|
def get_own_hardware_details(self):
|
514
524
|
hardware_list_result = self.get_hardware_list(
|
515
|
-
fingerprint=self.primitive.host_config.get("fingerprint")
|
525
|
+
fingerprint=self.primitive.host_config.get("fingerprint"),
|
526
|
+
nested_children=True,
|
516
527
|
)
|
517
528
|
hardware = (
|
518
529
|
hardware_list_result.data.get("hardwareList").get("edges")[0].get("node")
|
@@ -582,4 +593,68 @@ class Hardware(BaseAction):
|
|
582
593
|
# get the latest children from the node
|
583
594
|
# compare the two and update the node with the latest children
|
584
595
|
# remove any children from remote that are not in the latest children
|
585
|
-
|
596
|
+
hardware = self.primitive.hardware.get_own_hardware_details()
|
597
|
+
remote_children = hardware.get("children", [])
|
598
|
+
local_children = self.primitive.hardware._list_local_children()
|
599
|
+
|
600
|
+
new_child_registered = False
|
601
|
+
# need to register new children that were not previously registered
|
602
|
+
if len(remote_children) < len(local_children):
|
603
|
+
logger.info("New children found.")
|
604
|
+
for local_child in local_children:
|
605
|
+
found = False
|
606
|
+
for remote_child in remote_children:
|
607
|
+
if remote_child["slug"] == local_child.slug:
|
608
|
+
found = True
|
609
|
+
break
|
610
|
+
if not found:
|
611
|
+
try:
|
612
|
+
logger.info(f"Registering new child: {local_child.slug}")
|
613
|
+
self.primitive.hardware.register_child(child=local_child)
|
614
|
+
new_child_registered = True
|
615
|
+
except Exception as exception:
|
616
|
+
logger.exception(f"Error registering new children: {exception}")
|
617
|
+
|
618
|
+
# if a new child was registered, get the fresh state of the world
|
619
|
+
if new_child_registered:
|
620
|
+
hardware = self.primitive.hardware.get_own_hardware_details()
|
621
|
+
remote_children = hardware.get("children", [])
|
622
|
+
|
623
|
+
try:
|
624
|
+
# need to check in children that had been previously registered
|
625
|
+
# TODO: this is where, once you've got the local children you run a
|
626
|
+
# predefined health check. online != healthy
|
627
|
+
for remote_child in remote_children:
|
628
|
+
# if the remote_child is not in the local_children, then it is offline
|
629
|
+
found = False
|
630
|
+
for local_child in local_children:
|
631
|
+
if remote_child["slug"] == local_child.slug:
|
632
|
+
is_available = True
|
633
|
+
if remote_child["activeReservation"] is not None:
|
634
|
+
if (
|
635
|
+
remote_child["activeReservation"]["id"]
|
636
|
+
and remote_child["isAvailable"]
|
637
|
+
):
|
638
|
+
is_available = False
|
639
|
+
|
640
|
+
self.primitive.hardware.check_in_http(
|
641
|
+
is_available=is_available,
|
642
|
+
is_healthy=True,
|
643
|
+
is_online=True,
|
644
|
+
fingerprint=remote_child["fingerprint"],
|
645
|
+
)
|
646
|
+
found = True
|
647
|
+
break
|
648
|
+
if not found:
|
649
|
+
logger.info(
|
650
|
+
f"Remote child {remote_child['slug']}, not found in local children. Setting offline."
|
651
|
+
)
|
652
|
+
self.primitive.hardware.check_in_http(
|
653
|
+
is_available=False,
|
654
|
+
is_healthy=False,
|
655
|
+
is_online=False,
|
656
|
+
fingerprint=remote_child["fingerprint"],
|
657
|
+
)
|
658
|
+
|
659
|
+
except Exception as exception:
|
660
|
+
logger.exception(f"Error checking in children: {exception}")
|
primitive/hardware/android.py
CHANGED
@@ -2,9 +2,12 @@ from dataclasses import dataclass, field
|
|
2
2
|
from subprocess import PIPE, Popen
|
3
3
|
from typing import Dict
|
4
4
|
|
5
|
+
from primitive.utils.text import slugify
|
6
|
+
|
5
7
|
|
6
8
|
@dataclass
|
7
9
|
class AndroidDevice:
|
10
|
+
slug: str
|
8
11
|
serial: str
|
9
12
|
usb: str
|
10
13
|
product: str
|
@@ -47,7 +50,9 @@ def list_devices():
|
|
47
50
|
detail for detail in line.split(" ") if detail != ""
|
48
51
|
]
|
49
52
|
|
53
|
+
slug = slugify(device_details_array[0])
|
50
54
|
android_device = AndroidDevice(
|
55
|
+
slug=slug,
|
51
56
|
serial=device_details_array[0],
|
52
57
|
usb=device_details_array[1],
|
53
58
|
product=device_details_array[2],
|
primitive/hardware/commands.py
CHANGED
@@ -87,26 +87,7 @@ def hardware_status_string(hardware):
|
|
87
87
|
return "Available"
|
88
88
|
|
89
89
|
|
90
|
-
|
91
|
-
@click.pass_context
|
92
|
-
def list_command(context):
|
93
|
-
"""List Hardware"""
|
94
|
-
primitive: Primitive = context.obj.get("PRIMITIVE")
|
95
|
-
get_hardware_list_result = primitive.hardware.get_hardware_list(
|
96
|
-
nested_children=True
|
97
|
-
)
|
98
|
-
message = get_hardware_list_result.data
|
99
|
-
|
100
|
-
hardware_list = [
|
101
|
-
hardware.get("node")
|
102
|
-
for hardware in get_hardware_list_result.data.get("hardwareList").get("edges")
|
103
|
-
]
|
104
|
-
|
105
|
-
message = hardware_list
|
106
|
-
if context.obj["JSON"]:
|
107
|
-
print_result(message=message, context=context)
|
108
|
-
return
|
109
|
-
|
90
|
+
def render_hardware_table(hardware_list):
|
110
91
|
console = Console()
|
111
92
|
|
112
93
|
table = Table(show_header=True, header_style="bold magenta")
|
@@ -153,3 +134,45 @@ def list_command(context):
|
|
153
134
|
)
|
154
135
|
|
155
136
|
console.print(table)
|
137
|
+
|
138
|
+
|
139
|
+
@cli.command("list")
|
140
|
+
@click.pass_context
|
141
|
+
def list_command(context):
|
142
|
+
"""List Hardware"""
|
143
|
+
primitive: Primitive = context.obj.get("PRIMITIVE")
|
144
|
+
get_hardware_list_result = primitive.hardware.get_hardware_list(
|
145
|
+
nested_children=True
|
146
|
+
)
|
147
|
+
|
148
|
+
hardware_list = [
|
149
|
+
hardware.get("node")
|
150
|
+
for hardware in get_hardware_list_result.data.get("hardwareList").get("edges")
|
151
|
+
]
|
152
|
+
|
153
|
+
if context.obj["JSON"]:
|
154
|
+
print_result(message=hardware_list, context=context)
|
155
|
+
return
|
156
|
+
else:
|
157
|
+
render_hardware_table(hardware_list)
|
158
|
+
|
159
|
+
|
160
|
+
@cli.command("get")
|
161
|
+
@click.pass_context
|
162
|
+
@click.argument(
|
163
|
+
"hardware_identifier",
|
164
|
+
type=str,
|
165
|
+
required=True,
|
166
|
+
)
|
167
|
+
def get_command(context, hardware_identifier: str) -> None:
|
168
|
+
"""Get Hardware"""
|
169
|
+
primitive: Primitive = context.obj.get("PRIMITIVE")
|
170
|
+
hardware = primitive.hardware.get_hardware_from_slug_or_id(
|
171
|
+
hardware_identifier=hardware_identifier
|
172
|
+
)
|
173
|
+
|
174
|
+
if context.obj["JSON"]:
|
175
|
+
print_result(message=hardware, context=context)
|
176
|
+
return
|
177
|
+
else:
|
178
|
+
render_hardware_table([hardware])
|
primitive/utils/text.py
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
import re
|
2
|
+
import unicodedata
|
3
|
+
|
4
|
+
|
5
|
+
# from Django for consistency
|
6
|
+
# https://github.com/django/django/blob/stable/5.1.x/django/utils/text.py#L452
|
7
|
+
def slugify(value, allow_unicode=False):
|
8
|
+
"""
|
9
|
+
Convert to ASCII if 'allow_unicode' is False. Convert spaces or repeated
|
10
|
+
dashes to single dashes. Remove characters that aren't alphanumerics,
|
11
|
+
underscores, or hyphens. Convert to lowercase. Also strip leading and
|
12
|
+
trailing whitespace, dashes, and underscores.
|
13
|
+
"""
|
14
|
+
value = str(value)
|
15
|
+
if allow_unicode:
|
16
|
+
value = unicodedata.normalize("NFKC", value)
|
17
|
+
else:
|
18
|
+
value = (
|
19
|
+
unicodedata.normalize("NFKD", value)
|
20
|
+
.encode("ascii", "ignore")
|
21
|
+
.decode("ascii")
|
22
|
+
)
|
23
|
+
value = re.sub(r"[^\w\s-]", "", value.lower())
|
24
|
+
return re.sub(r"[-\s]+", "-", value).strip("-_")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: primitive
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.94
|
4
4
|
Project-URL: Documentation, https://github.com//primitivecorp/primitive-cli#readme
|
5
5
|
Project-URL: Issues, https://github.com//primitivecorp/primitive-cli/issues
|
6
6
|
Project-URL: Source, https://github.com//primitivecorp/primitive-cli
|
@@ -1,13 +1,13 @@
|
|
1
|
-
primitive/__about__.py,sha256=
|
1
|
+
primitive/__about__.py,sha256=KXegEIne06p7p51yURPxgSDL9t-28iyLfXrBT-skS_Q,130
|
2
2
|
primitive/__init__.py,sha256=bwKdgggKNVssJFVPfKSxqFMz4IxSr54WWbmiZqTMPNI,106
|
3
3
|
primitive/cli.py,sha256=CiI60bG3UZyNFuLTpchr0KeJRG5SALj455Ob11CegGE,2412
|
4
4
|
primitive/client.py,sha256=PPyIQRvKKSqCF9RRF5mJJ4Vqqolpzy1YXqffNLKIvAA,2390
|
5
5
|
primitive/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
primitive/agent/actions.py,sha256=
|
6
|
+
primitive/agent/actions.py,sha256=s9hOVKsgjwt7iXnpGOpoR5Ctxh9g7g-g1xu5QjtvPbc,7636
|
7
7
|
primitive/agent/commands.py,sha256=-dVDilELfkGfbZB7qfEPs77Dm1oT62qJj4tsIk4KoxI,254
|
8
8
|
primitive/agent/process.py,sha256=32eoj0W1-LG-9xxeHia-jk9jTah1cnmjCYnvczgXYGU,3538
|
9
9
|
primitive/agent/provision.py,sha256=rmwnro1K5F8mwtd45XAq7RVQmpDWnbBCQ8X_qgWhm3M,1546
|
10
|
-
primitive/agent/runner.py,sha256=
|
10
|
+
primitive/agent/runner.py,sha256=gVr-IWizw7UiP-9vgDviGzmrJBi5jLMXMw-0aVusPIs,9487
|
11
11
|
primitive/agent/uploader.py,sha256=OkgwXhWKoECOJnW_ZmpzmUS_cpb-orC_uebNcmf5byw,2948
|
12
12
|
primitive/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
primitive/auth/actions.py,sha256=MPsG9LcKcOPwA7gZ9Ewk0PZJhTQvIrGfODdz4GxSzgA,999
|
@@ -40,13 +40,13 @@ primitive/graphql/relay.py,sha256=bmij2AjdpURQ6GGVCxwWhauF-r_SxuAU2oJ4sDbLxpI,72
|
|
40
40
|
primitive/graphql/sdk.py,sha256=DBFH8vw8FAGvRy8_FZc9WcjnwaQDlXmI8fiYmhCg-b0,1458
|
41
41
|
primitive/graphql/utility_fragments.py,sha256=uIjwILC4QtWNyO5vu77VjQf_p0jvP3A9q_6zRq91zqs,303
|
42
42
|
primitive/hardware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
43
|
-
primitive/hardware/actions.py,sha256=
|
44
|
-
primitive/hardware/android.py,sha256=
|
45
|
-
primitive/hardware/commands.py,sha256=
|
43
|
+
primitive/hardware/actions.py,sha256=tmsr50UPz_xFXPdeSa89e7NgDlw9vMwqWUUXlFGzmQs,25775
|
44
|
+
primitive/hardware/android.py,sha256=tu7pBPxWFrIwb_mm5CEdFFf1_veNDOKjOCQg13i_Lh4,2758
|
45
|
+
primitive/hardware/commands.py,sha256=cWl8j0XtkXQtPHtpO_C6Gh0-dnAEysOFryf3VnDOTOo,5650
|
46
46
|
primitive/hardware/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
47
47
|
primitive/hardware/graphql/fragments.py,sha256=kI6qnTNjaEaUr-C6eD55COphtueVYbYOWZwN5EW_3qw,350
|
48
48
|
primitive/hardware/graphql/mutations.py,sha256=_4Hkbfik9Ron4T-meulu6T-9FR_BZjyPNwn745MPksU,1484
|
49
|
-
primitive/hardware/graphql/queries.py,sha256=
|
49
|
+
primitive/hardware/graphql/queries.py,sha256=I86uLuOSjHSph11Y5MVCYko5Js7hoiEZ-cEoPTc4J-k,1392
|
50
50
|
primitive/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
51
51
|
primitive/jobs/actions.py,sha256=CtyO-Z9614TgIoXJJX1QGsoll0fgpBIjG9PJH5JwCQs,4901
|
52
52
|
primitive/jobs/commands.py,sha256=MxPCkBEYW_eLNqgCRYeyj7ZcLOFAWfpVZlqDR2Y_S0o,830
|
@@ -90,9 +90,10 @@ primitive/utils/git.py,sha256=1qNOu8X-33CavmrD580BmrFhD_WVO9PGWHUUboXJR_g,663
|
|
90
90
|
primitive/utils/memory_size.py,sha256=4xfha21kW82nFvOTtDFx9Jk2ZQoEhkfXii-PGNTpIUk,3058
|
91
91
|
primitive/utils/printer.py,sha256=f1XUpqi5dkTL3GWvYRUGlSwtj2IxU1q745T4Fxo7Tn4,370
|
92
92
|
primitive/utils/shell.py,sha256=vpjr2Y7UQGYOvPGa6_RYXPPjqScfa9k7kT3tugF9h4Y,1837
|
93
|
+
primitive/utils/text.py,sha256=XiESMnlhjQ534xE2hMNf08WehE1SKaYFRNih0MmnK0k,829
|
93
94
|
primitive/utils/verible.py,sha256=Zb5NUISvcaIgEvgCDBWr-GCoceMa79Tcwvr5Wl9lfnA,2252
|
94
|
-
primitive-0.1.
|
95
|
-
primitive-0.1.
|
96
|
-
primitive-0.1.
|
97
|
-
primitive-0.1.
|
98
|
-
primitive-0.1.
|
95
|
+
primitive-0.1.94.dist-info/METADATA,sha256=jF78rkKKUBDKv-30b--nmW4RsQfUIPdzOkWVoD7HUpE,3670
|
96
|
+
primitive-0.1.94.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
97
|
+
primitive-0.1.94.dist-info/entry_points.txt,sha256=p1K8DMCWka5FqLlqP1sPek5Uovy9jq8u51gUsP-z334,48
|
98
|
+
primitive-0.1.94.dist-info/licenses/LICENSE.txt,sha256=B8kmQMJ2sxYygjCLBk770uacaMci4mPSoJJ8WoDBY_c,1098
|
99
|
+
primitive-0.1.94.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|