dmart 1.4.39__py3-none-any.whl → 1.4.40__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.
- dmart/cli.py +1103 -0
- dmart/config.ini.sample +7 -0
- dmart/dmart.py +9 -14
- {dmart-1.4.39.dist-info → dmart-1.4.40.dist-info}/METADATA +1 -1
- {dmart-1.4.39.dist-info → dmart-1.4.40.dist-info}/RECORD +8 -6
- {dmart-1.4.39.dist-info → dmart-1.4.40.dist-info}/WHEEL +0 -0
- {dmart-1.4.39.dist-info → dmart-1.4.40.dist-info}/entry_points.txt +0 -0
- {dmart-1.4.39.dist-info → dmart-1.4.40.dist-info}/top_level.txt +0 -0
dmart/cli.py
ADDED
|
@@ -0,0 +1,1103 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from prompt_toolkit import PromptSession
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
from prompt_toolkit.filters import has_completions, completion_is_selected
|
|
8
|
+
from prompt_toolkit.key_binding import KeyBindings
|
|
9
|
+
from rich import pretty
|
|
10
|
+
from rich import print
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
13
|
+
import requests
|
|
14
|
+
import re
|
|
15
|
+
|
|
16
|
+
# from rich.tree import Tree
|
|
17
|
+
from rich.table import Table
|
|
18
|
+
from dataclasses import dataclass
|
|
19
|
+
from prompt_toolkit.styles import Style
|
|
20
|
+
from prompt_toolkit.formatted_text import HTML
|
|
21
|
+
from prompt_toolkit.completion import Completer, Completion # , FuzzyCompleter
|
|
22
|
+
from prompt_toolkit.history import FileHistory
|
|
23
|
+
from prompt_toolkit.cursor_shapes import CursorShape
|
|
24
|
+
from rich.traceback import install
|
|
25
|
+
import json
|
|
26
|
+
import pathlib
|
|
27
|
+
from enum import Enum
|
|
28
|
+
import termios
|
|
29
|
+
import tty
|
|
30
|
+
from dataclasses import field
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
|
|
33
|
+
install(show_locals=False)
|
|
34
|
+
|
|
35
|
+
KEYWORDS = [
|
|
36
|
+
"ls",
|
|
37
|
+
"switch",
|
|
38
|
+
"mv",
|
|
39
|
+
"cat",
|
|
40
|
+
"cd",
|
|
41
|
+
"rm",
|
|
42
|
+
"print",
|
|
43
|
+
"pwd",
|
|
44
|
+
"help",
|
|
45
|
+
"mkdir",
|
|
46
|
+
"schema",
|
|
47
|
+
"create",
|
|
48
|
+
"attach",
|
|
49
|
+
"request",
|
|
50
|
+
"csv",
|
|
51
|
+
"progress",
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
style = Style.from_dict(
|
|
55
|
+
{
|
|
56
|
+
"completion-menu.completion": "bg:#008888 #ffffff",
|
|
57
|
+
"completion-menu.completion.current": "bg:#00aaaa #000000",
|
|
58
|
+
"scrollbar.background": "bg:#88aaaa",
|
|
59
|
+
"scrollbar.button": "bg:#222222",
|
|
60
|
+
"prompt": "#dddd22 bold",
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
console = Console()
|
|
65
|
+
pretty.install()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class Settings(BaseSettings):
|
|
69
|
+
url: str = "http://localhost:8282"
|
|
70
|
+
shortname: str = "dmart"
|
|
71
|
+
password: str = "password"
|
|
72
|
+
query_limit: int = 100
|
|
73
|
+
retrieve_json_payload: bool = True
|
|
74
|
+
default_space: str = "management"
|
|
75
|
+
pagination: int = 5
|
|
76
|
+
|
|
77
|
+
model_config = SettingsConfigDict(env_file = os.getenv("BACKEND_ENV", os.path.dirname(os.path.realpath(__file__)) + "/config.ini"), env_file_encoding = "utf-8")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
settings = Settings()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class CLI_MODE(str, Enum):
|
|
84
|
+
REPL = "REPL"
|
|
85
|
+
CMD = "CMD"
|
|
86
|
+
SCRIPT = "SCRIPT"
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
mode = CLI_MODE.REPL
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class SpaceManagmentType(str, Enum):
|
|
93
|
+
CREATE = "create"
|
|
94
|
+
UPDATE = "update"
|
|
95
|
+
DELETE = "delete"
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@dataclass
|
|
99
|
+
class DMart:
|
|
100
|
+
session = requests.Session()
|
|
101
|
+
headers = {"Content-Type": "application/json"}
|
|
102
|
+
dmart_spaces : list = field(default_factory=lambda: [])
|
|
103
|
+
space_names : list[str] = field(default_factory=list[str])
|
|
104
|
+
current_space: str = settings.default_space
|
|
105
|
+
current_subpath: str = "/"
|
|
106
|
+
current_subpath_entries : list = field(default_factory=list)
|
|
107
|
+
|
|
108
|
+
def __dmart_api(self, endpoint, json=None):
|
|
109
|
+
url = f"{settings.url}{endpoint}"
|
|
110
|
+
|
|
111
|
+
if json:
|
|
112
|
+
response = self.session.post(url, headers=self.headers, json=json)
|
|
113
|
+
else:
|
|
114
|
+
response = self.session.get(url)
|
|
115
|
+
|
|
116
|
+
response_body = response.json()
|
|
117
|
+
if response.status_code != 200:
|
|
118
|
+
print(f"[red]{endpoint}", end="\r")
|
|
119
|
+
return response_body
|
|
120
|
+
|
|
121
|
+
def create_content(self, endpoint, json):
|
|
122
|
+
url = f"{settings.url}{endpoint}"
|
|
123
|
+
|
|
124
|
+
response = self.session.post(url, headers=self.headers, json=json)
|
|
125
|
+
|
|
126
|
+
if response.status_code != 200:
|
|
127
|
+
print(endpoint, response.json())
|
|
128
|
+
return response.json().get('status', None)
|
|
129
|
+
|
|
130
|
+
def delete(self, spacename, subpath, shortname, resource_type):
|
|
131
|
+
endpoint = "/managed/request"
|
|
132
|
+
json = {
|
|
133
|
+
"space_name": spacename,
|
|
134
|
+
"request_type": "delete",
|
|
135
|
+
"records": [
|
|
136
|
+
{
|
|
137
|
+
"resource_type": resource_type,
|
|
138
|
+
"subpath": subpath,
|
|
139
|
+
"shortname": shortname,
|
|
140
|
+
"attributes": {},
|
|
141
|
+
}
|
|
142
|
+
],
|
|
143
|
+
}
|
|
144
|
+
return self.__dmart_api(endpoint, json)
|
|
145
|
+
|
|
146
|
+
def register(self, invitation):
|
|
147
|
+
json = {
|
|
148
|
+
"resource_type": "user",
|
|
149
|
+
"spacename": "management",
|
|
150
|
+
"subpath": "/users",
|
|
151
|
+
"shortname": settings.shortname,
|
|
152
|
+
"attributes": {"invitation": invitation, "password": settings.password},
|
|
153
|
+
}
|
|
154
|
+
self.__dmart_api("/user/create", json)
|
|
155
|
+
|
|
156
|
+
def login(self):
|
|
157
|
+
json = {"shortname": settings.shortname, "password": settings.password}
|
|
158
|
+
response = self.__dmart_api("/user/login", json)
|
|
159
|
+
if response["status"] == "success":
|
|
160
|
+
self.headers = {
|
|
161
|
+
**self.headers,
|
|
162
|
+
"Authorization": f'Bearer {response["records"][0]["attributes"]["access_token"]}',
|
|
163
|
+
}
|
|
164
|
+
return response
|
|
165
|
+
|
|
166
|
+
def profile(self):
|
|
167
|
+
self.__dmart_api("/user/profile")
|
|
168
|
+
|
|
169
|
+
def spaces(self, force: bool = False):
|
|
170
|
+
if force or not self.dmart_spaces:
|
|
171
|
+
json = {
|
|
172
|
+
"type": "spaces",
|
|
173
|
+
"space_name": "management",
|
|
174
|
+
"subpath": "/",
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
response = self.__dmart_api("/managed/query", json)
|
|
178
|
+
self.dmart_spaces = response["records"]
|
|
179
|
+
self.space_names = [one["shortname"] for one in self.dmart_spaces]
|
|
180
|
+
return self.dmart_spaces
|
|
181
|
+
|
|
182
|
+
def query(self, json):
|
|
183
|
+
json["limit"] = settings.query_limit
|
|
184
|
+
json["retrieve_json_payload"] = settings.retrieve_json_payload
|
|
185
|
+
return self.__dmart_api("/managed/query", json)
|
|
186
|
+
|
|
187
|
+
def meta(self, resource_type, space_name, subpath, shortname):
|
|
188
|
+
endpoint = "managed/meta"
|
|
189
|
+
url = f"{settings.url}/{endpoint}/{resource_type}/{space_name}/{subpath}/{shortname}"
|
|
190
|
+
response = self.session.get(url)
|
|
191
|
+
|
|
192
|
+
if response.status_code != 200:
|
|
193
|
+
print(endpoint, response.json())
|
|
194
|
+
return response.json()
|
|
195
|
+
|
|
196
|
+
def payload(self, resource_type, space_name, subpath, shortname):
|
|
197
|
+
endpoint = "managed/payload"
|
|
198
|
+
url = f"{settings.url}/{endpoint}/{resource_type}/{space_name}/{subpath}/{shortname}.json"
|
|
199
|
+
response = self.session.get(url)
|
|
200
|
+
|
|
201
|
+
# if response.status_code != 200:
|
|
202
|
+
# print(endpoint, response.json())
|
|
203
|
+
return response.status_code, response.json()
|
|
204
|
+
|
|
205
|
+
def print_spaces(self):
|
|
206
|
+
print_spaces = "Available spaces: "
|
|
207
|
+
for one in self.space_names:
|
|
208
|
+
if self.current_space == one:
|
|
209
|
+
one = f" [bold yellow]{one}[/] "
|
|
210
|
+
else:
|
|
211
|
+
one = f" [blue]{one}[/] "
|
|
212
|
+
print_spaces += one
|
|
213
|
+
print(print_spaces)
|
|
214
|
+
|
|
215
|
+
def list(self):
|
|
216
|
+
json = {
|
|
217
|
+
"space_name": dmart.current_space,
|
|
218
|
+
"type": "subpath",
|
|
219
|
+
"subpath": dmart.current_subpath.replace("//", "/"),
|
|
220
|
+
"retrieve_json_payload": True,
|
|
221
|
+
"limit": 100,
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
ret = self.query(json)
|
|
225
|
+
self.current_subpath_entries.clear()
|
|
226
|
+
if "records" in ret:
|
|
227
|
+
for one in ret["records"]:
|
|
228
|
+
self.current_subpath_entries.append(one)
|
|
229
|
+
|
|
230
|
+
def get_mime_type(self, ext):
|
|
231
|
+
match ext:
|
|
232
|
+
case ".jfif" | ".jfif-tbnl" | ".jpe" | ".jpeg" | ".jpg":
|
|
233
|
+
return "image/jpeg"
|
|
234
|
+
case ".png":
|
|
235
|
+
return "image/png"
|
|
236
|
+
case ".json":
|
|
237
|
+
return "application/json"
|
|
238
|
+
|
|
239
|
+
def create_folder(self, shortname):
|
|
240
|
+
json = {
|
|
241
|
+
"space_name": self.current_space,
|
|
242
|
+
"request_type": "create",
|
|
243
|
+
"records": [
|
|
244
|
+
{
|
|
245
|
+
"resource_type": "folder",
|
|
246
|
+
"subpath": self.current_subpath,
|
|
247
|
+
"shortname": shortname,
|
|
248
|
+
"attributes": {"is_active": True},
|
|
249
|
+
}
|
|
250
|
+
],
|
|
251
|
+
}
|
|
252
|
+
endpoint = "/managed/request"
|
|
253
|
+
return self.__dmart_api(endpoint, json)
|
|
254
|
+
|
|
255
|
+
def manage_space(self, spacename, mode: SpaceManagmentType):
|
|
256
|
+
endpoint = "/managed/space"
|
|
257
|
+
json = {
|
|
258
|
+
"space_name": spacename,
|
|
259
|
+
"request_type": mode.value,
|
|
260
|
+
"records": [
|
|
261
|
+
{
|
|
262
|
+
"resource_type": "space",
|
|
263
|
+
"subpath": "/",
|
|
264
|
+
"shortname": spacename,
|
|
265
|
+
"attributes": {},
|
|
266
|
+
}
|
|
267
|
+
],
|
|
268
|
+
}
|
|
269
|
+
result = self.__dmart_api(endpoint, json)
|
|
270
|
+
self.spaces(force=True)
|
|
271
|
+
return result
|
|
272
|
+
|
|
273
|
+
def create_entry(self, shortname, resource_type):
|
|
274
|
+
endpoint = "/managed/request"
|
|
275
|
+
json = {
|
|
276
|
+
"space_name": self.current_space,
|
|
277
|
+
"request_type": "create",
|
|
278
|
+
"records": [
|
|
279
|
+
{
|
|
280
|
+
"resource_type": resource_type,
|
|
281
|
+
"subpath": self.current_subpath,
|
|
282
|
+
"shortname": shortname,
|
|
283
|
+
"attributes": {"is_active": True},
|
|
284
|
+
}
|
|
285
|
+
],
|
|
286
|
+
}
|
|
287
|
+
return self.__dmart_api(endpoint, json)
|
|
288
|
+
|
|
289
|
+
def create_attachments(self, request_record: dict, payload_file):
|
|
290
|
+
endpoint = f"{settings.url}/managed/resource_with_payload"
|
|
291
|
+
with open("temp.json", "w") as request_record_file:
|
|
292
|
+
json.dump(request_record, request_record_file)
|
|
293
|
+
|
|
294
|
+
with open("temp.json", "rb") as request_file:
|
|
295
|
+
with open(payload_file, "rb") as media_file:
|
|
296
|
+
request_file.seek(0)
|
|
297
|
+
data = [
|
|
298
|
+
(
|
|
299
|
+
"request_record",
|
|
300
|
+
("record.json", request_file, "application/json"),
|
|
301
|
+
),
|
|
302
|
+
(
|
|
303
|
+
"payload_file",
|
|
304
|
+
(
|
|
305
|
+
media_file.name.split("/")[-1],
|
|
306
|
+
media_file,
|
|
307
|
+
self.get_mime_type(pathlib.Path(payload_file).suffix),
|
|
308
|
+
),
|
|
309
|
+
),
|
|
310
|
+
]
|
|
311
|
+
response = self.session.post(
|
|
312
|
+
endpoint,
|
|
313
|
+
data={"space_name": self.current_space},
|
|
314
|
+
files=data,
|
|
315
|
+
headers=self.headers,
|
|
316
|
+
)
|
|
317
|
+
if response.status_code != 200:
|
|
318
|
+
print(endpoint, response.json())
|
|
319
|
+
|
|
320
|
+
os.remove("temp.json")
|
|
321
|
+
return response.json()
|
|
322
|
+
|
|
323
|
+
def upload_csv(self, resource_type, subpath, schema_shortname, payload_file):
|
|
324
|
+
with open(payload_file, "rb") as media_file:
|
|
325
|
+
endpoint = f"{settings.url}/managed/resources_from_csv/{resource_type}/{dmart.current_space}/{subpath}/{schema_shortname}"
|
|
326
|
+
headers = {**self.headers}
|
|
327
|
+
del headers["Content-Type"]
|
|
328
|
+
response = self.session.post(
|
|
329
|
+
endpoint,
|
|
330
|
+
files=[
|
|
331
|
+
('resources_file', ('file', media_file, 'text/csv'))
|
|
332
|
+
],
|
|
333
|
+
headers=headers,
|
|
334
|
+
)
|
|
335
|
+
if response.status_code != 200:
|
|
336
|
+
print(endpoint, response.json())
|
|
337
|
+
|
|
338
|
+
return response.json()
|
|
339
|
+
|
|
340
|
+
def upload_schema(self, shortname, payload_file_path):
|
|
341
|
+
data = {
|
|
342
|
+
"resource_type": "schema",
|
|
343
|
+
"subpath": "schema",
|
|
344
|
+
"shortname": shortname,
|
|
345
|
+
"attributes": {"schema_shortname": "meta_schema", "is_active": True},
|
|
346
|
+
}
|
|
347
|
+
endpoint = f"{settings.url}/managed/resource_with_payload"
|
|
348
|
+
|
|
349
|
+
with open("temp.json", "w") as request_record_file:
|
|
350
|
+
json.dump(data, request_record_file)
|
|
351
|
+
|
|
352
|
+
with open("temp.json", "rb") as request_record:
|
|
353
|
+
with open(payload_file_path, "rb") as payload_file:
|
|
354
|
+
files = {
|
|
355
|
+
"space_name": (None, self.current_space),
|
|
356
|
+
"request_record": request_record,
|
|
357
|
+
"payload_file": payload_file,
|
|
358
|
+
}
|
|
359
|
+
headers = {**self.headers}
|
|
360
|
+
del headers["Content-Type"]
|
|
361
|
+
response = self.session.post(
|
|
362
|
+
endpoint,
|
|
363
|
+
files=files,
|
|
364
|
+
headers=headers,
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
if response.status_code != 200:
|
|
368
|
+
print(endpoint, response.json())
|
|
369
|
+
|
|
370
|
+
return response.json()
|
|
371
|
+
|
|
372
|
+
def upload_folder(self, folder_schema_path):
|
|
373
|
+
endpoint = f"{settings.url}/managed/request"
|
|
374
|
+
with open(folder_schema_path, "r") as folder_schema:
|
|
375
|
+
response = self.session.post(
|
|
376
|
+
url=endpoint,
|
|
377
|
+
data=folder_schema,
|
|
378
|
+
headers=self.headers,
|
|
379
|
+
)
|
|
380
|
+
if response.status_code != 200:
|
|
381
|
+
print(endpoint, response.json())
|
|
382
|
+
else:
|
|
383
|
+
print(response.json())
|
|
384
|
+
return response.json()
|
|
385
|
+
|
|
386
|
+
def move(
|
|
387
|
+
self,
|
|
388
|
+
resource_type,
|
|
389
|
+
source_path,
|
|
390
|
+
source_shortname,
|
|
391
|
+
destination_path,
|
|
392
|
+
destination_shortname,
|
|
393
|
+
):
|
|
394
|
+
endpoint = "/managed/request"
|
|
395
|
+
data = {
|
|
396
|
+
"space_name": self.current_space,
|
|
397
|
+
"request_type": "move",
|
|
398
|
+
"records": [
|
|
399
|
+
{
|
|
400
|
+
"resource_type": resource_type,
|
|
401
|
+
"subpath": self.current_subpath,
|
|
402
|
+
"shortname": source_shortname,
|
|
403
|
+
"attributes": {
|
|
404
|
+
"src_subpath": source_path,
|
|
405
|
+
"src_shortname": source_shortname,
|
|
406
|
+
"dest_subpath": destination_path,
|
|
407
|
+
"dest_shortname": destination_shortname,
|
|
408
|
+
},
|
|
409
|
+
}
|
|
410
|
+
],
|
|
411
|
+
}
|
|
412
|
+
return self.__dmart_api(endpoint, data)
|
|
413
|
+
|
|
414
|
+
def import_zip(self, zip_file_path):
|
|
415
|
+
endpoint = f"{settings.url}/managed/import"
|
|
416
|
+
with open(zip_file_path, "rb") as zip_file:
|
|
417
|
+
headers = {**self.headers}
|
|
418
|
+
del headers["Content-Type"]
|
|
419
|
+
response = self.session.post(
|
|
420
|
+
endpoint,
|
|
421
|
+
files={"zip_file": zip_file},
|
|
422
|
+
headers=headers,
|
|
423
|
+
)
|
|
424
|
+
if response.status_code != 200:
|
|
425
|
+
print(endpoint, response.json())
|
|
426
|
+
return response.json()
|
|
427
|
+
|
|
428
|
+
def export_json(self, query_json_file):
|
|
429
|
+
output_file_name = "/export.zip"
|
|
430
|
+
os_downloads_path = str(Path.home()/"Downloads")
|
|
431
|
+
output_file_path = os_downloads_path + output_file_name
|
|
432
|
+
with open(query_json_file, "r") as f:
|
|
433
|
+
data = json.load(f)
|
|
434
|
+
endpoint = f"{settings.url}/managed/export"
|
|
435
|
+
response = self.session.post(endpoint, headers=self.headers, json=data, stream=True)
|
|
436
|
+
if response.status_code != 200:
|
|
437
|
+
print(endpoint, response.json())
|
|
438
|
+
return response.json()
|
|
439
|
+
with open(output_file_path, "wb") as out_file:
|
|
440
|
+
for chunk in response.iter_content(chunk_size=8192):
|
|
441
|
+
if chunk:
|
|
442
|
+
out_file.write(chunk)
|
|
443
|
+
print(f"Exported to {os_downloads_path}")
|
|
444
|
+
return {"status": "success", "file": output_file_path}
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
dmart = DMart()
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
class CustomCompleter(Completer):
|
|
451
|
+
def get_completions(self, document, complete_event):
|
|
452
|
+
cmd = document.text
|
|
453
|
+
arg = document.get_word_under_cursor()
|
|
454
|
+
if len(cmd) < 2 or re.match(r"^\s*$", cmd):
|
|
455
|
+
for one in KEYWORDS:
|
|
456
|
+
if one.startswith(arg):
|
|
457
|
+
yield Completion(one, start_position=-len(arg))
|
|
458
|
+
elif re.match(r"^\s*\w+\s+", cmd):
|
|
459
|
+
if cmd.startswith("s"):
|
|
460
|
+
for one in dmart.space_names:
|
|
461
|
+
if one.startswith(arg):
|
|
462
|
+
yield Completion(one, start_position=-len(arg))
|
|
463
|
+
else:
|
|
464
|
+
for one in dmart.current_subpath_entries:
|
|
465
|
+
if one[ "shortname" ].startswith(
|
|
466
|
+
arg
|
|
467
|
+
):
|
|
468
|
+
if "cd" in cmd and one["resource_type"] == "folder":
|
|
469
|
+
yield Completion(
|
|
470
|
+
one["shortname"],
|
|
471
|
+
start_position=-len(arg),
|
|
472
|
+
display_meta=one["resource_type"],
|
|
473
|
+
)
|
|
474
|
+
elif "cd" not in cmd:
|
|
475
|
+
yield Completion(
|
|
476
|
+
one["shortname"],
|
|
477
|
+
start_position=-len(arg),
|
|
478
|
+
display_meta=one["resource_type"],
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
def bottom_toolbar():
|
|
484
|
+
return HTML(
|
|
485
|
+
f'<b>{dmart.current_space}</b> : <b><style bg="ansired">{dmart.current_subpath}</style></b>'
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def check_update_space(space, subpath=None):
|
|
490
|
+
for one in dmart.space_names:
|
|
491
|
+
if one.startswith(space) and not one.startswith(dmart.current_space):
|
|
492
|
+
dmart.current_space = one
|
|
493
|
+
print("Current space switched to:", dmart.current_space)
|
|
494
|
+
if subpath is not None:
|
|
495
|
+
dmart.current_subpath = subpath
|
|
496
|
+
dmart.list()
|
|
497
|
+
dmart.print_spaces()
|
|
498
|
+
break
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
def action(text: str):
|
|
502
|
+
old_space, old_subpath = dmart.current_space, dmart.current_subpath
|
|
503
|
+
match text.split():
|
|
504
|
+
case ["h" | "help" | "?"]:
|
|
505
|
+
table = Table(title="Help")
|
|
506
|
+
table.add_column("Command")
|
|
507
|
+
table.add_column("Description")
|
|
508
|
+
table.add_row(
|
|
509
|
+
r"[blue]s[paces][/] [green]\[space_name][/]",
|
|
510
|
+
"List availble spaces or switch to space",
|
|
511
|
+
)
|
|
512
|
+
table.add_row(
|
|
513
|
+
r"[blue]ls[/] [green]\[folder_name][/]",
|
|
514
|
+
"List entries under current subpath",
|
|
515
|
+
)
|
|
516
|
+
table.add_row("[blue]pwd[/]", "Print current subpath")
|
|
517
|
+
table.add_row("[blue]cd[/] [green]folder_name[/]", "Enter the folder")
|
|
518
|
+
table.add_row("[blue]cd ..[/]", "Go one-level up with the subpath")
|
|
519
|
+
table.add_row(
|
|
520
|
+
r"[blue]p\[rint][/blue] [green]shortname[/]",
|
|
521
|
+
"Print meta data for the entry shortname under current subpath",
|
|
522
|
+
)
|
|
523
|
+
table.add_row(
|
|
524
|
+
r"[blue]c\[at][/] [green]shortname[/]",
|
|
525
|
+
"Print the json payload (only) for th entry shortnae under current subpath",
|
|
526
|
+
)
|
|
527
|
+
table.add_row(
|
|
528
|
+
"[blue]rm[/] [green]shortname|*[/]",
|
|
529
|
+
"Delete the shortname (entry or attachment)",
|
|
530
|
+
)
|
|
531
|
+
table.add_row(
|
|
532
|
+
"[blue]create [space|folder] <shortname>[/]", "Create space/folder for current space"
|
|
533
|
+
)
|
|
534
|
+
table.add_row(
|
|
535
|
+
"[blue]upload csv <resource_type> <shortname> <schema_shortname> <csv_file>[/]",
|
|
536
|
+
"Upload data to the current space with schema validation",
|
|
537
|
+
)
|
|
538
|
+
table.add_row(
|
|
539
|
+
"[blue]upload schema <shortname> <json_file>[/]",
|
|
540
|
+
"Upload schema to the current space",
|
|
541
|
+
)
|
|
542
|
+
table.add_row(
|
|
543
|
+
"[blue]request <resource_type> <json_file>[/]",
|
|
544
|
+
"Add/Manage a resource to/in the space",
|
|
545
|
+
)
|
|
546
|
+
table.add_row(
|
|
547
|
+
"[blue]progress <subpath> <shortname> <action>[/]",
|
|
548
|
+
"Progress a ticket into a new state using an action",
|
|
549
|
+
)
|
|
550
|
+
table.add_row(
|
|
551
|
+
"[blue]move <resource_type> <source> <destination>[/]", "Move resource"
|
|
552
|
+
)
|
|
553
|
+
table.add_row("[blue]import <zip_file>[/]", "Import a ZIP file")
|
|
554
|
+
table.add_row("[blue]export <query_json> [/]", "Export a ZIP file")
|
|
555
|
+
table.add_row("[blue]exit|Ctrl+d[/]", "Exit the app")
|
|
556
|
+
table.add_row("[blue]help|h|?[/]", "Show this help")
|
|
557
|
+
print(table)
|
|
558
|
+
return None
|
|
559
|
+
case ["mkdir", dir_shortname]:
|
|
560
|
+
print(dmart.create_folder(dir_shortname))
|
|
561
|
+
return None
|
|
562
|
+
case ["attach", *args]:
|
|
563
|
+
shortname = None
|
|
564
|
+
entry_shortname = None
|
|
565
|
+
payload_file = None
|
|
566
|
+
payload_type = None
|
|
567
|
+
|
|
568
|
+
shortname = args[0]
|
|
569
|
+
entry_shortname = args[1]
|
|
570
|
+
payload_type = args[2]
|
|
571
|
+
payload_file = args[3]
|
|
572
|
+
|
|
573
|
+
print(
|
|
574
|
+
dmart.create_attachments(
|
|
575
|
+
{
|
|
576
|
+
"shortname": shortname,
|
|
577
|
+
"resource_type": payload_type,
|
|
578
|
+
"subpath": f"{dmart.current_subpath}/{entry_shortname}",
|
|
579
|
+
"attributes": {"is_active": True},
|
|
580
|
+
},
|
|
581
|
+
payload_file,
|
|
582
|
+
)
|
|
583
|
+
)
|
|
584
|
+
return None
|
|
585
|
+
case ["upload", "schema", *args]:
|
|
586
|
+
shortname = None
|
|
587
|
+
payload_file = None
|
|
588
|
+
|
|
589
|
+
if len(args) == 3:
|
|
590
|
+
search = re.search(r"@\w+", args[2])
|
|
591
|
+
if not search:
|
|
592
|
+
print("[red]Malformated Command")
|
|
593
|
+
return None
|
|
594
|
+
space = search.group()
|
|
595
|
+
space = space.replace("@", "")
|
|
596
|
+
check_update_space(space)
|
|
597
|
+
dmart.current_subpath = args[2].replace(f"@{space}/", "")
|
|
598
|
+
dmart.list()
|
|
599
|
+
shortname = args[0]
|
|
600
|
+
payload_file = args[1]
|
|
601
|
+
|
|
602
|
+
dmart.upload_schema(shortname, payload_file)
|
|
603
|
+
check_update_space(old_space)
|
|
604
|
+
dmart.current_subpath = old_subpath
|
|
605
|
+
dmart.list()
|
|
606
|
+
return None
|
|
607
|
+
case ["create", *args]:
|
|
608
|
+
shortname = None
|
|
609
|
+
resource_type = None
|
|
610
|
+
if len(args) == 3:
|
|
611
|
+
search = re.search(r"@\w+", args[2])
|
|
612
|
+
if not search:
|
|
613
|
+
print("[red]Malformated Command")
|
|
614
|
+
return None
|
|
615
|
+
space = search.group()
|
|
616
|
+
space = space.replace("@", "")
|
|
617
|
+
check_update_space(space)
|
|
618
|
+
dmart.current_subpath = args[2].replace(f"@{space}", "")
|
|
619
|
+
dmart.list()
|
|
620
|
+
shortname = args[0]
|
|
621
|
+
resource_type = args[1]
|
|
622
|
+
|
|
623
|
+
if args[0] == "space":
|
|
624
|
+
print(dmart.manage_space(args[1], SpaceManagmentType.CREATE))
|
|
625
|
+
else:
|
|
626
|
+
print(dmart.create_entry(resource_type, shortname))
|
|
627
|
+
|
|
628
|
+
check_update_space(old_space)
|
|
629
|
+
dmart.current_subpath = old_subpath
|
|
630
|
+
dmart.list()
|
|
631
|
+
return None
|
|
632
|
+
case ["move", type, source, destination]:
|
|
633
|
+
if not source.startswith("/"):
|
|
634
|
+
source += f"{dmart.current_subpath}/{source}"
|
|
635
|
+
if not destination.startswith("/"):
|
|
636
|
+
destination += f"{dmart.current_subpath}/{destination}"
|
|
637
|
+
source_path = "/".join(source.split("/")[:-1])
|
|
638
|
+
source_shortname = source.split("/")[-1]
|
|
639
|
+
destination_path = "/".join(destination.split("/")[:-1])
|
|
640
|
+
destination_shortname = destination.split("/")[-1]
|
|
641
|
+
print(
|
|
642
|
+
dmart.move(
|
|
643
|
+
type,
|
|
644
|
+
source_path,
|
|
645
|
+
source_shortname,
|
|
646
|
+
destination_path,
|
|
647
|
+
destination_shortname,
|
|
648
|
+
)
|
|
649
|
+
)
|
|
650
|
+
return None
|
|
651
|
+
|
|
652
|
+
case ["progress", ticket_subpath, ticket_shortname, new_state]:
|
|
653
|
+
endpoint = f"{settings.url}/managed/progress-ticket/{dmart.current_space}/{ticket_subpath}/{ticket_shortname}/{new_state}"
|
|
654
|
+
response = dmart.session.put(
|
|
655
|
+
url=endpoint,
|
|
656
|
+
data={},
|
|
657
|
+
headers=dmart.headers,
|
|
658
|
+
)
|
|
659
|
+
print(response.json())
|
|
660
|
+
return None
|
|
661
|
+
case ["request", *args]:
|
|
662
|
+
if len(args) != 1:
|
|
663
|
+
print("[red]Malformated Command")
|
|
664
|
+
return None
|
|
665
|
+
|
|
666
|
+
with open(args[0]) as f:
|
|
667
|
+
return print(
|
|
668
|
+
dmart.create_content("/managed/request", json.load(f)), end="\r"
|
|
669
|
+
)
|
|
670
|
+
|
|
671
|
+
check_update_space(old_space)
|
|
672
|
+
dmart.current_subpath = old_subpath
|
|
673
|
+
dmart.list()
|
|
674
|
+
return None
|
|
675
|
+
case ["query", shortname]:
|
|
676
|
+
action(f"query {shortname}")
|
|
677
|
+
action("ls")
|
|
678
|
+
action("cd ..")
|
|
679
|
+
return None
|
|
680
|
+
case ["upload", "csv", *args]:
|
|
681
|
+
if len(args) == 4:
|
|
682
|
+
print(dmart.upload_csv(args[0], args[1], args[2], args[3]))
|
|
683
|
+
elif len(args) == 3:
|
|
684
|
+
print("[red]Malformated Command")
|
|
685
|
+
return None
|
|
686
|
+
check_update_space(old_space)
|
|
687
|
+
dmart.current_subpath = old_subpath
|
|
688
|
+
dmart.list()
|
|
689
|
+
return None
|
|
690
|
+
case ["rm", "*"]:
|
|
691
|
+
dmart.list()
|
|
692
|
+
for one in dmart.current_subpath_entries:
|
|
693
|
+
shortname = one["shortname"]
|
|
694
|
+
resource_type = one["resource_type"]
|
|
695
|
+
if shortname and resource_type:
|
|
696
|
+
print(
|
|
697
|
+
shortname,
|
|
698
|
+
dmart.delete(
|
|
699
|
+
dmart.current_space,
|
|
700
|
+
dmart.current_subpath,
|
|
701
|
+
shortname,
|
|
702
|
+
resource_type,
|
|
703
|
+
),
|
|
704
|
+
)
|
|
705
|
+
return None
|
|
706
|
+
case ["rm", *content]:
|
|
707
|
+
if content[0] == "space":
|
|
708
|
+
print(dmart.manage_space(content[1], SpaceManagmentType.DELETE))
|
|
709
|
+
else:
|
|
710
|
+
content = content[0]
|
|
711
|
+
if content.startswith("@"):
|
|
712
|
+
path = content[1]
|
|
713
|
+
search = re.search(r"@\w+", content)
|
|
714
|
+
if not search:
|
|
715
|
+
print("[red]Malformated Command")
|
|
716
|
+
return None
|
|
717
|
+
space = search.group()
|
|
718
|
+
space = space.replace("@", "")
|
|
719
|
+
check_update_space(space)
|
|
720
|
+
dmart.list()
|
|
721
|
+
content = content.replace(f"@{space}/", "")
|
|
722
|
+
# print(dmart.current_subpath_entries)
|
|
723
|
+
shortname = ""
|
|
724
|
+
resource_type = ""
|
|
725
|
+
for one in dmart.current_subpath_entries:
|
|
726
|
+
if one["shortname"] == content:
|
|
727
|
+
shortname = one["shortname"]
|
|
728
|
+
resource_type = one["resource_type"]
|
|
729
|
+
if shortname and resource_type:
|
|
730
|
+
print(
|
|
731
|
+
dmart.delete(
|
|
732
|
+
dmart.current_space,
|
|
733
|
+
dmart.current_subpath,
|
|
734
|
+
shortname,
|
|
735
|
+
resource_type,
|
|
736
|
+
)
|
|
737
|
+
)
|
|
738
|
+
else:
|
|
739
|
+
print("item not found")
|
|
740
|
+
check_update_space(old_space)
|
|
741
|
+
dmart.list()
|
|
742
|
+
case ["pwd"]:
|
|
743
|
+
print(f"{dmart.current_space}:{dmart.current_subpath}")
|
|
744
|
+
return None
|
|
745
|
+
case ["cd"]:
|
|
746
|
+
dmart.current_subpath = "/"
|
|
747
|
+
dmart.list()
|
|
748
|
+
print(f"[yellow]Switched subpath to:[/] [green]{dmart.current_subpath}[/]")
|
|
749
|
+
return None
|
|
750
|
+
case ["cd", ".."]:
|
|
751
|
+
if dmart.current_subpath != "/":
|
|
752
|
+
dmart.current_subpath = "/".join(dmart.current_subpath.split("/")[:-1])
|
|
753
|
+
if not dmart.current_subpath:
|
|
754
|
+
dmart.current_subpath = "/"
|
|
755
|
+
dmart.list()
|
|
756
|
+
print(f"[yellow]Switched subpath to:[/] [green]{dmart.current_subpath}[/]")
|
|
757
|
+
return None
|
|
758
|
+
case ["p" | "print", content]:
|
|
759
|
+
shortname = ""
|
|
760
|
+
resource_type = ""
|
|
761
|
+
shortname = content
|
|
762
|
+
for one in dmart.current_subpath_entries:
|
|
763
|
+
if one["shortname"].startswith(shortname):
|
|
764
|
+
shortname = one["shortname"]
|
|
765
|
+
resource_type = one["resource_type"]
|
|
766
|
+
if shortname and resource_type:
|
|
767
|
+
print(
|
|
768
|
+
dmart.meta(
|
|
769
|
+
resource_type,
|
|
770
|
+
dmart.current_space,
|
|
771
|
+
dmart.current_subpath,
|
|
772
|
+
shortname,
|
|
773
|
+
)
|
|
774
|
+
)
|
|
775
|
+
else:
|
|
776
|
+
print("item not found")
|
|
777
|
+
case ["cd", directory]:
|
|
778
|
+
if directory.startswith("@"):
|
|
779
|
+
search = re.search(r"@\w+", directory)
|
|
780
|
+
if not search:
|
|
781
|
+
print("[red]Malformated Command")
|
|
782
|
+
return None
|
|
783
|
+
space = search.group()
|
|
784
|
+
space = space.replace("@", "")
|
|
785
|
+
check_update_space(space)
|
|
786
|
+
dmart.current_subpath = directory.replace(f"@{space}/", "")
|
|
787
|
+
dmart.list()
|
|
788
|
+
directory = dmart.current_subpath
|
|
789
|
+
new_subpath = ""
|
|
790
|
+
for one in dmart.current_subpath_entries:
|
|
791
|
+
if (
|
|
792
|
+
one["shortname"].startswith(directory)
|
|
793
|
+
and one["resource_type"] == "folder"
|
|
794
|
+
):
|
|
795
|
+
new_subpath = (
|
|
796
|
+
""
|
|
797
|
+
if dmart.current_subpath == "/" or dmart.current_subpath == ""
|
|
798
|
+
else dmart.current_subpath
|
|
799
|
+
)
|
|
800
|
+
if new_subpath != "":
|
|
801
|
+
new_subpath += "/"
|
|
802
|
+
new_subpath += one["shortname"]
|
|
803
|
+
dmart.current_subpath = new_subpath
|
|
804
|
+
dmart.list()
|
|
805
|
+
print(
|
|
806
|
+
f"[yellow]Switched subpath to:[/] [green]{dmart.current_subpath}[/]"
|
|
807
|
+
)
|
|
808
|
+
break
|
|
809
|
+
return None
|
|
810
|
+
return None
|
|
811
|
+
case ["c" | "cat", *extra_shortname]:
|
|
812
|
+
old_path = dmart.current_subpath
|
|
813
|
+
if "/" in extra_shortname[0]:
|
|
814
|
+
dmart.current_subpath = "/".join(extra_shortname[0].split("/")[:-1])
|
|
815
|
+
extra_shortname[0] = "".join(extra_shortname[0].split("/")[-1])
|
|
816
|
+
dmart.list()
|
|
817
|
+
dmart.current_subpath = old_path
|
|
818
|
+
|
|
819
|
+
record = {}
|
|
820
|
+
if extra_shortname[0] == "*":
|
|
821
|
+
for one in dmart.current_subpath_entries:
|
|
822
|
+
print(one)
|
|
823
|
+
elif len(extra_shortname) > 0:
|
|
824
|
+
shortname = extra_shortname[0]
|
|
825
|
+
for one in dmart.current_subpath_entries:
|
|
826
|
+
if one["shortname"].startswith(shortname):
|
|
827
|
+
record = one
|
|
828
|
+
if record is not None:
|
|
829
|
+
print(record)
|
|
830
|
+
else:
|
|
831
|
+
print("[yellow]Item is not found[/]")
|
|
832
|
+
case ["ls", *_extra_subpath]:
|
|
833
|
+
if len(_extra_subpath) >= 2:
|
|
834
|
+
print("Too many args passed !")
|
|
835
|
+
return None
|
|
836
|
+
|
|
837
|
+
extra_subpath = ""
|
|
838
|
+
if len(_extra_subpath) == 1 and not _extra_subpath[0].isnumeric():
|
|
839
|
+
if _extra_subpath[0].startswith("/"):
|
|
840
|
+
_extra_subpath[0] = _extra_subpath[0][1:]
|
|
841
|
+
if _extra_subpath[0].endswith("/"):
|
|
842
|
+
_extra_subpath[0] = _extra_subpath[0][:-1]
|
|
843
|
+
|
|
844
|
+
if _extra_subpath[0].startswith("@"):
|
|
845
|
+
search = re.search(r"@\w+", _extra_subpath[0])
|
|
846
|
+
if not search:
|
|
847
|
+
print("[red]Malformated Command")
|
|
848
|
+
return None
|
|
849
|
+
space = search.group()
|
|
850
|
+
space = space.replace("@", "")
|
|
851
|
+
check_update_space(space)
|
|
852
|
+
dmart.current_subpath = _extra_subpath[0].replace(f"@{space}/", "")
|
|
853
|
+
dmart.list()
|
|
854
|
+
else:
|
|
855
|
+
dmart.current_subpath = _extra_subpath[0]
|
|
856
|
+
dmart.list()
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
if extra_subpath == "":
|
|
860
|
+
for one in dmart.current_subpath_entries:
|
|
861
|
+
if one["shortname"].startswith(extra_subpath):
|
|
862
|
+
extra_subpath = one["shortname"]
|
|
863
|
+
|
|
864
|
+
path = f"[yellow]{dmart.current_space}[/]:[blue]{dmart.current_subpath}"
|
|
865
|
+
if dmart.current_subpath != "/":
|
|
866
|
+
path = f"{path}/{extra_subpath}"
|
|
867
|
+
else:
|
|
868
|
+
path = f"{path}{extra_subpath}"
|
|
869
|
+
# tree = Tree(path)
|
|
870
|
+
|
|
871
|
+
pagination_length = 0
|
|
872
|
+
if len(_extra_subpath) >= 1 and _extra_subpath[-1].isnumeric():
|
|
873
|
+
pagination_length = int(_extra_subpath[-1])
|
|
874
|
+
else:
|
|
875
|
+
pagination_length = settings.pagination
|
|
876
|
+
|
|
877
|
+
pagination_bucket : list[list] = []
|
|
878
|
+
bucket = []
|
|
879
|
+
idx = 0
|
|
880
|
+
for one in dmart.current_subpath_entries:
|
|
881
|
+
icon = ":page_facing_up:"
|
|
882
|
+
extra = ""
|
|
883
|
+
if one["resource_type"] == "folder":
|
|
884
|
+
icon = ":file_folder:"
|
|
885
|
+
if (
|
|
886
|
+
isinstance(one, dict)
|
|
887
|
+
and "attributes" in one
|
|
888
|
+
and isinstance(one["attributes"], dict)
|
|
889
|
+
and "payload" in one["attributes"]
|
|
890
|
+
and isinstance(one["attributes"]["payload"], dict)
|
|
891
|
+
and "content_type" in one["attributes"]["payload"]
|
|
892
|
+
):
|
|
893
|
+
if "schema_shortname" in one["attributes"]["payload"]:
|
|
894
|
+
schema = f",schema= {one["attributes"]["payload"].get("schema_shortname", "N/A")}"
|
|
895
|
+
extra = f"[yellow](payload:type={one['attributes']['payload']['content_type']}{schema})[/]"
|
|
896
|
+
|
|
897
|
+
idx += 1
|
|
898
|
+
bucket.append(f"{icon} [green]{one['shortname']}[/] {extra}")
|
|
899
|
+
if idx == pagination_length:
|
|
900
|
+
idx = 0
|
|
901
|
+
pagination_bucket.append(bucket)
|
|
902
|
+
bucket = []
|
|
903
|
+
|
|
904
|
+
if len(bucket) != 0:
|
|
905
|
+
pagination_bucket.append(bucket)
|
|
906
|
+
idx = 0
|
|
907
|
+
c = ""
|
|
908
|
+
if len(pagination_bucket) == 1:
|
|
909
|
+
for bucket in pagination_bucket[0]:
|
|
910
|
+
print(bucket)
|
|
911
|
+
else:
|
|
912
|
+
while True:
|
|
913
|
+
if len(pagination_bucket) == 0:
|
|
914
|
+
break
|
|
915
|
+
|
|
916
|
+
for bucket in pagination_bucket[idx]:
|
|
917
|
+
print(bucket)
|
|
918
|
+
|
|
919
|
+
if idx >= len(pagination_bucket) - 1:
|
|
920
|
+
break
|
|
921
|
+
|
|
922
|
+
print("q: quite, n: next")
|
|
923
|
+
fd = sys.stdin.fileno()
|
|
924
|
+
old_settings = termios.tcgetattr(fd)
|
|
925
|
+
try:
|
|
926
|
+
tty.setraw(fd)
|
|
927
|
+
c = sys.stdin.readline(1)
|
|
928
|
+
|
|
929
|
+
if c == "q":
|
|
930
|
+
break
|
|
931
|
+
if c == "n" or c == "\r":
|
|
932
|
+
idx += 1
|
|
933
|
+
finally:
|
|
934
|
+
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
|
935
|
+
return None
|
|
936
|
+
# c = input("q: quite, b: previous, n: next = ")
|
|
937
|
+
# print(tree)
|
|
938
|
+
dmart.current_space, dmart.current_subpath = old_space, old_subpath
|
|
939
|
+
dmart.list()
|
|
940
|
+
return None
|
|
941
|
+
case ["s" | "switch", *space]:
|
|
942
|
+
if len(space) == 0:
|
|
943
|
+
dmart.print_spaces()
|
|
944
|
+
return None
|
|
945
|
+
match = False
|
|
946
|
+
for one in dmart.space_names:
|
|
947
|
+
if space and one.startswith(space[0]):
|
|
948
|
+
print(
|
|
949
|
+
f"Switching current space from {dmart.current_space} to {one} / {space}"
|
|
950
|
+
)
|
|
951
|
+
dmart.current_space = one
|
|
952
|
+
dmart.list()
|
|
953
|
+
match = True
|
|
954
|
+
dmart.print_spaces()
|
|
955
|
+
break
|
|
956
|
+
if not match:
|
|
957
|
+
print(f"Requested space {space} not found")
|
|
958
|
+
return None
|
|
959
|
+
return None
|
|
960
|
+
case ["import", zip_file]:
|
|
961
|
+
print(dmart.import_zip(zip_file))
|
|
962
|
+
return None
|
|
963
|
+
case ["export", query_json_file]:
|
|
964
|
+
print(dmart.export_json(query_json_file))
|
|
965
|
+
return None
|
|
966
|
+
case _:
|
|
967
|
+
print(f"[red]Command[/] [yello]{text}[/] [red]unknown[/]")
|
|
968
|
+
return None
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
var : dict = {}
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
def parsing_variables(sliced_command):
|
|
975
|
+
for i in range(len(sliced_command)):
|
|
976
|
+
search = re.search(r"\$\w*", sliced_command[i])
|
|
977
|
+
if search is not None:
|
|
978
|
+
if v := search[0]:
|
|
979
|
+
sliced_command[i] = sliced_command[i].replace(v, var.get(v, ""))
|
|
980
|
+
return sliced_command
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
key_bindings = KeyBindings()
|
|
984
|
+
filter = has_completions & ~completion_is_selected
|
|
985
|
+
@key_bindings.add("enter", filter=filter)
|
|
986
|
+
def _(event):
|
|
987
|
+
event.current_buffer.go_to_completion(0)
|
|
988
|
+
event.current_buffer.validate_and_handle()
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
if __name__ == "__main__":
|
|
992
|
+
try :
|
|
993
|
+
# print(Panel.fit("For help, type : [bold]?[/]", title="DMart Cli"))
|
|
994
|
+
print("[bold][green]DMART[/] [yellow]Command line interface[/][/]")
|
|
995
|
+
print(
|
|
996
|
+
f"Connecting to [yellow]{settings.url}[/] user: [yellow]{settings.shortname}[/]"
|
|
997
|
+
)
|
|
998
|
+
|
|
999
|
+
ret = dmart.login()
|
|
1000
|
+
if ret["status"] == "failed":
|
|
1001
|
+
print("Login failed")
|
|
1002
|
+
exit(1)
|
|
1003
|
+
dmart.profile()
|
|
1004
|
+
spaces = dmart.spaces()
|
|
1005
|
+
dmart.current_space = settings.default_space # dmart.space_names[0]
|
|
1006
|
+
|
|
1007
|
+
dmart.list()
|
|
1008
|
+
# print("Available spaces:", space_names)
|
|
1009
|
+
# print("Current space:", current_space)
|
|
1010
|
+
dmart.print_spaces()
|
|
1011
|
+
print("[red]Type [bold]?[/] for help[/]")
|
|
1012
|
+
# current_subpath = "/"
|
|
1013
|
+
# session = PromptSession(lexer=PygmentsLexer(DmartLexer), completer=dmart_completer, style=style)
|
|
1014
|
+
|
|
1015
|
+
session = PromptSession(
|
|
1016
|
+
style=style,
|
|
1017
|
+
completer=CustomCompleter(),
|
|
1018
|
+
history=FileHistory(".cli_history"),
|
|
1019
|
+
key_bindings=key_bindings
|
|
1020
|
+
)
|
|
1021
|
+
|
|
1022
|
+
if len(sys.argv) >= 2:
|
|
1023
|
+
if sys.argv[1] == "s":
|
|
1024
|
+
mode = CLI_MODE.SCRIPT
|
|
1025
|
+
elif sys.argv[1] == "c":
|
|
1026
|
+
mode = CLI_MODE.CMD
|
|
1027
|
+
if sys.argv[3].startswith("/"):
|
|
1028
|
+
check_update_space(sys.argv[2], sys.argv[3])
|
|
1029
|
+
del sys.argv[2]
|
|
1030
|
+
del sys.argv[2]
|
|
1031
|
+
else:
|
|
1032
|
+
check_update_space(sys.argv[2])
|
|
1033
|
+
del sys.argv[2]
|
|
1034
|
+
del sys.argv[0]
|
|
1035
|
+
del sys.argv[0]
|
|
1036
|
+
|
|
1037
|
+
if mode == CLI_MODE.CMD:
|
|
1038
|
+
print(sys.argv)
|
|
1039
|
+
action(" ".join(sys.argv))
|
|
1040
|
+
elif mode == CLI_MODE.SCRIPT:
|
|
1041
|
+
with open(sys.argv[0], "r") as commands:
|
|
1042
|
+
is_comment_block = False
|
|
1043
|
+
for command in commands:
|
|
1044
|
+
if (
|
|
1045
|
+
command.startswith("#")
|
|
1046
|
+
or command.startswith("//")
|
|
1047
|
+
or command == "\n"
|
|
1048
|
+
):
|
|
1049
|
+
continue
|
|
1050
|
+
elif command.startswith("/*"):
|
|
1051
|
+
is_comment_block = True
|
|
1052
|
+
continue
|
|
1053
|
+
elif command.startswith("*/"):
|
|
1054
|
+
is_comment_block = False
|
|
1055
|
+
continue
|
|
1056
|
+
elif is_comment_block:
|
|
1057
|
+
continue
|
|
1058
|
+
|
|
1059
|
+
print("[green]> ", command)
|
|
1060
|
+
sliced_command = command.split()
|
|
1061
|
+
|
|
1062
|
+
if sliced_command[0] == "VAR":
|
|
1063
|
+
var[sliced_command[1]] = sliced_command[2]
|
|
1064
|
+
continue
|
|
1065
|
+
|
|
1066
|
+
sliced_command = parsing_variables(sliced_command)
|
|
1067
|
+
|
|
1068
|
+
action(" ".join(sliced_command))
|
|
1069
|
+
elif mode == CLI_MODE.REPL:
|
|
1070
|
+
while True:
|
|
1071
|
+
try:
|
|
1072
|
+
text = session.prompt(
|
|
1073
|
+
[("class:prompt", "❯ ")], # ≻≻
|
|
1074
|
+
# cursor=CursorShape.BLINKING_BLOCK,
|
|
1075
|
+
# cursor=CursorShape.BLINKING_BEAM,
|
|
1076
|
+
cursor=CursorShape.BLINKING_UNDERLINE,
|
|
1077
|
+
bottom_toolbar=bottom_toolbar,
|
|
1078
|
+
complete_in_thread=True,
|
|
1079
|
+
complete_while_typing=True,
|
|
1080
|
+
)
|
|
1081
|
+
# remove whitespaces
|
|
1082
|
+
text = re.sub(r"^\s+", "", text) # leading
|
|
1083
|
+
text = re.sub(r"\s+$", "", text) # trailing
|
|
1084
|
+
text = re.sub(
|
|
1085
|
+
r"\s+", " ", text
|
|
1086
|
+
) # replace multiple inline whitespaces with one
|
|
1087
|
+
if text in ["exit", "q", "quit"]:
|
|
1088
|
+
break
|
|
1089
|
+
else:
|
|
1090
|
+
if text == "":
|
|
1091
|
+
continue
|
|
1092
|
+
action(text)
|
|
1093
|
+
except KeyboardInterrupt as ex:
|
|
1094
|
+
print(repr(ex))
|
|
1095
|
+
continue
|
|
1096
|
+
except EOFError as _:
|
|
1097
|
+
print("[green]Exiting ...[/]")
|
|
1098
|
+
break
|
|
1099
|
+
# else:
|
|
1100
|
+
# print('You entered:', repr(text))
|
|
1101
|
+
print("[yellow]Good bye![/]")
|
|
1102
|
+
except requests.exceptions.ConnectionError as _ :
|
|
1103
|
+
print("[yellow]Connection error[/]")
|
dmart/config.ini.sample
ADDED
dmart/dmart.py
CHANGED
|
@@ -441,27 +441,22 @@ def main():
|
|
|
441
441
|
|
|
442
442
|
# Try to find cli.py in the package or nearby
|
|
443
443
|
try:
|
|
444
|
+
# When installed as a package, cli.py is in the same directory as dmart.py
|
|
445
|
+
dmart_dir = Path(__file__).resolve().parent
|
|
446
|
+
if str(dmart_dir) not in sys.path:
|
|
447
|
+
sys.path.append(str(dmart_dir))
|
|
444
448
|
import cli
|
|
445
449
|
cli.main()
|
|
446
450
|
except ImportError:
|
|
447
|
-
#
|
|
448
|
-
|
|
449
|
-
cli_path = dmart_dir / "cli.py"
|
|
451
|
+
# Fallback for local development
|
|
452
|
+
cli_path = Path(__file__).resolve().parent.parent / "cli"
|
|
450
453
|
if cli_path.exists():
|
|
451
|
-
|
|
452
|
-
sys.path.append(str(dmart_dir))
|
|
454
|
+
sys.path.append(str(cli_path))
|
|
453
455
|
import cli
|
|
454
456
|
cli.main()
|
|
455
457
|
else:
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
if cli_path.exists():
|
|
459
|
-
sys.path.append(str(cli_path))
|
|
460
|
-
import cli
|
|
461
|
-
cli.main()
|
|
462
|
-
else:
|
|
463
|
-
print("Error: cli.py not found.")
|
|
464
|
-
sys.exit(1)
|
|
458
|
+
print("Error: cli.py not found.")
|
|
459
|
+
sys.exit(1)
|
|
465
460
|
case "serve":
|
|
466
461
|
open_cxb = False
|
|
467
462
|
if "--open-cxb" in sys.argv:
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
dmart/__init__.py,sha256=xHodcATn-JYaoi3_TVDimR_UWG_ux9uLePUNQDzHhsY,122
|
|
2
2
|
dmart/alembic.ini,sha256=wQweByyHQm-EI8BQkE0SHNRjULJ6Xn5jqgvv88IT5Sg,3738
|
|
3
3
|
dmart/bundler.py,sha256=so8ZJResb1PcOH5vboa_mpFAdYr_T8u8DbbFXd570Lg,1704
|
|
4
|
+
dmart/cli.py,sha256=aE3_2uHcEiQJA_f6viGRwUmGPB-OaNfzSgDgLR5gf40,40447
|
|
4
5
|
dmart/config.env.sample,sha256=CKd4KIBeUatoFcO2IefmrVNBohpaVMQMFcoPkNBvCeI,696
|
|
6
|
+
dmart/config.ini.sample,sha256=AADMdwG07zRV_cAGMoOorHQaqzTTL2WEIC_mPWjIslE,159
|
|
5
7
|
dmart/conftest.py,sha256=0ry_zeCmdBNLbm5q115b-pkOrUFYxdsOUXbIMkr7E5Y,362
|
|
6
8
|
dmart/curl.sh,sha256=lmHSFVr5ft-lc5Aq9LfvKyWfntrfYbnirhzx1EGjp_A,15743
|
|
7
9
|
dmart/data_generator.py,sha256=CnE-VHEeX7-lAXtqCgbRqR9WHjTuOgeiZcviYrHAmho,2287
|
|
8
|
-
dmart/dmart.py,sha256=
|
|
10
|
+
dmart/dmart.py,sha256=KR4FYOc5yqIkK2oR3F4NuINE4kju8wsEjSRcEiSkwp8,24182
|
|
9
11
|
dmart/get_settings.py,sha256=Sbe2WCoiK398E7HY4SNLfDN_GmE8knR4M-YJWF31jcg,153
|
|
10
12
|
dmart/hypercorn_config.toml,sha256=-eryppEG8HBOM_KbFc4dTQePnpyfoW9ZG5aUATU_6yM,50
|
|
11
13
|
dmart/info.json,sha256=5Yz4tc5dEt5eVrM2LzLhXgN8vGvE0aDbbbEEaGDsD5k,123
|
|
@@ -278,8 +280,8 @@ dmart/utils/ticket_sys_utils.py,sha256=9QAlW2iiy8KyxQRBDj_WmzS5kKb0aYJmGwd4qzmGV
|
|
|
278
280
|
dmart/utils/web_notifier.py,sha256=QM87VVid2grC5lK3NdS1yzz0z1wXljr4GChJOeK86W4,843
|
|
279
281
|
dmart/utils/templates/activation.html.j2,sha256=XAMKCdoqONoc4ZQucD0yV-Pg5DlHHASZrTVItNS-iBE,640
|
|
280
282
|
dmart/utils/templates/reminder.html.j2,sha256=aoS8bTs56q4hjAZKsb0jV9c-PIURBELuBOpT_qPZNVU,639
|
|
281
|
-
dmart-1.4.
|
|
282
|
-
dmart-1.4.
|
|
283
|
-
dmart-1.4.
|
|
284
|
-
dmart-1.4.
|
|
285
|
-
dmart-1.4.
|
|
283
|
+
dmart-1.4.40.dist-info/METADATA,sha256=y57VLJSX2_m7tL7bd_1IqrRHk9AWro9WgG17tfNM_jU,2571
|
|
284
|
+
dmart-1.4.40.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
285
|
+
dmart-1.4.40.dist-info/entry_points.txt,sha256=N832M4wG8d2GDw1xztKRVM3TnxpY2QDzvdFE8XaWaG8,43
|
|
286
|
+
dmart-1.4.40.dist-info/top_level.txt,sha256=zJo4qk9fUW0BGIR9f4DCfpxaXbvQXH9izIOom6JsyAo,6
|
|
287
|
+
dmart-1.4.40.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|