kaqing 1.77.0__py3-none-any.whl → 2.0.171__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.
Files changed (308) hide show
  1. adam/__init__.py +1 -0
  2. adam/app_session.py +182 -0
  3. {walker → adam}/apps.py +8 -24
  4. {walker → adam}/batch.py +54 -97
  5. {walker → adam}/checks/check.py +3 -3
  6. {walker → adam}/checks/check_result.py +1 -1
  7. adam/checks/check_utils.py +65 -0
  8. {walker → adam}/checks/compactionstats.py +6 -6
  9. {walker → adam}/checks/cpu.py +14 -8
  10. adam/checks/cpu_metrics.py +52 -0
  11. {walker → adam}/checks/disk.py +6 -6
  12. {walker → adam}/checks/gossip.py +5 -5
  13. {walker → adam}/checks/memory.py +7 -7
  14. {walker → adam}/checks/status.py +5 -5
  15. {walker → adam}/cli.py +3 -3
  16. {walker → adam}/columns/column.py +1 -1
  17. adam/columns/columns.py +45 -0
  18. {walker → adam}/columns/compactions.py +5 -5
  19. {walker → adam}/columns/cpu.py +6 -4
  20. adam/columns/cpu_metrics.py +22 -0
  21. {walker → adam}/columns/dir_data.py +3 -3
  22. {walker → adam}/columns/dir_snapshots.py +3 -3
  23. {walker → adam}/columns/gossip.py +5 -5
  24. {walker → adam}/columns/host_id.py +3 -3
  25. {walker → adam}/columns/memory.py +3 -3
  26. {walker → adam}/columns/node_address.py +3 -3
  27. {walker → adam}/columns/node_load.py +3 -3
  28. {walker → adam}/columns/node_owns.py +3 -3
  29. {walker → adam}/columns/node_status.py +3 -3
  30. {walker → adam}/columns/node_tokens.py +3 -3
  31. {walker → adam}/columns/node_utils.py +2 -2
  32. {walker → adam}/columns/pod_name.py +2 -2
  33. {walker → adam}/columns/volume_cassandra.py +4 -4
  34. {walker → adam}/columns/volume_root.py +3 -3
  35. adam/commands/__init__.py +15 -0
  36. adam/commands/alter_tables.py +81 -0
  37. adam/commands/app_cmd.py +38 -0
  38. {walker → adam}/commands/app_ping.py +10 -16
  39. adam/commands/audit/audit.py +84 -0
  40. adam/commands/audit/audit_repair_tables.py +74 -0
  41. adam/commands/audit/audit_run.py +50 -0
  42. adam/commands/audit/show_last10.py +48 -0
  43. adam/commands/audit/show_slow10.py +47 -0
  44. adam/commands/audit/show_top10.py +45 -0
  45. adam/commands/audit/utils_show_top10.py +59 -0
  46. adam/commands/bash/__init__.py +5 -0
  47. adam/commands/bash/bash.py +36 -0
  48. adam/commands/bash/bash_completer.py +93 -0
  49. adam/commands/bash/utils_bash.py +16 -0
  50. adam/commands/cat.py +50 -0
  51. adam/commands/cd.py +43 -0
  52. adam/commands/check.py +73 -0
  53. {walker → adam}/commands/cli_commands.py +7 -8
  54. adam/commands/code.py +57 -0
  55. adam/commands/command.py +190 -0
  56. {walker → adam}/commands/command_helpers.py +1 -1
  57. {walker → adam}/commands/commands_utils.py +15 -25
  58. adam/commands/cp.py +89 -0
  59. adam/commands/cql/cql_completions.py +33 -0
  60. {walker/commands → adam/commands/cql}/cqlsh.py +20 -35
  61. adam/commands/cql/utils_cql.py +343 -0
  62. {walker/commands/frontend → adam/commands/deploy}/code_start.py +11 -14
  63. adam/commands/deploy/code_stop.py +40 -0
  64. {walker/commands/frontend → adam/commands/deploy}/code_utils.py +7 -9
  65. adam/commands/deploy/deploy.py +25 -0
  66. adam/commands/deploy/deploy_frontend.py +49 -0
  67. adam/commands/deploy/deploy_pg_agent.py +35 -0
  68. adam/commands/deploy/deploy_pod.py +108 -0
  69. adam/commands/deploy/deploy_utils.py +29 -0
  70. adam/commands/deploy/undeploy.py +25 -0
  71. adam/commands/deploy/undeploy_frontend.py +38 -0
  72. adam/commands/deploy/undeploy_pg_agent.py +39 -0
  73. adam/commands/deploy/undeploy_pod.py +48 -0
  74. adam/commands/devices/device.py +118 -0
  75. adam/commands/devices/device_app.py +173 -0
  76. adam/commands/devices/device_auit_log.py +49 -0
  77. adam/commands/devices/device_cass.py +185 -0
  78. adam/commands/devices/device_export.py +86 -0
  79. adam/commands/devices/device_postgres.py +144 -0
  80. adam/commands/devices/devices.py +25 -0
  81. {walker → adam}/commands/exit.py +3 -6
  82. adam/commands/export/clean_up_all_export_sessions.py +37 -0
  83. adam/commands/export/clean_up_export_sessions.py +51 -0
  84. adam/commands/export/drop_export_database.py +55 -0
  85. adam/commands/export/drop_export_databases.py +43 -0
  86. adam/commands/export/export.py +53 -0
  87. adam/commands/export/export_databases.py +170 -0
  88. adam/commands/export/export_handlers.py +71 -0
  89. adam/commands/export/export_select.py +81 -0
  90. adam/commands/export/export_select_x.py +54 -0
  91. adam/commands/export/export_use.py +52 -0
  92. adam/commands/export/exporter.py +352 -0
  93. adam/commands/export/import_session.py +40 -0
  94. adam/commands/export/importer.py +67 -0
  95. adam/commands/export/importer_athena.py +80 -0
  96. adam/commands/export/importer_sqlite.py +47 -0
  97. adam/commands/export/show_column_counts.py +54 -0
  98. adam/commands/export/show_export_databases.py +36 -0
  99. adam/commands/export/show_export_session.py +48 -0
  100. adam/commands/export/show_export_sessions.py +44 -0
  101. adam/commands/export/utils_export.py +314 -0
  102. {walker → adam}/commands/help.py +17 -12
  103. adam/commands/intermediate_command.py +49 -0
  104. adam/commands/issues.py +43 -0
  105. adam/commands/kubectl.py +38 -0
  106. adam/commands/login.py +70 -0
  107. {walker → adam}/commands/logs.py +8 -10
  108. adam/commands/ls.py +41 -0
  109. adam/commands/medusa/medusa.py +27 -0
  110. adam/commands/medusa/medusa_backup.py +57 -0
  111. adam/commands/medusa/medusa_restore.py +83 -0
  112. adam/commands/medusa/medusa_show_backupjobs.py +51 -0
  113. adam/commands/medusa/medusa_show_restorejobs.py +47 -0
  114. {walker → adam}/commands/nodetool.py +17 -21
  115. {walker → adam}/commands/param_get.py +15 -16
  116. adam/commands/param_set.py +43 -0
  117. adam/commands/postgres/postgres.py +104 -0
  118. adam/commands/postgres/postgres_context.py +274 -0
  119. {walker → adam}/commands/postgres/postgres_ls.py +7 -11
  120. {walker → adam}/commands/postgres/postgres_preview.py +8 -13
  121. adam/commands/postgres/psql_completions.py +10 -0
  122. adam/commands/postgres/utils_postgres.py +66 -0
  123. adam/commands/preview_table.py +37 -0
  124. adam/commands/pwd.py +47 -0
  125. adam/commands/reaper/reaper.py +35 -0
  126. adam/commands/reaper/reaper_forward.py +93 -0
  127. adam/commands/reaper/reaper_forward_session.py +6 -0
  128. {walker → adam}/commands/reaper/reaper_forward_stop.py +13 -19
  129. {walker → adam}/commands/reaper/reaper_restart.py +10 -17
  130. adam/commands/reaper/reaper_run_abort.py +46 -0
  131. adam/commands/reaper/reaper_runs.py +82 -0
  132. adam/commands/reaper/reaper_runs_abort.py +63 -0
  133. adam/commands/reaper/reaper_schedule_activate.py +45 -0
  134. adam/commands/reaper/reaper_schedule_start.py +45 -0
  135. adam/commands/reaper/reaper_schedule_stop.py +45 -0
  136. {walker → adam}/commands/reaper/reaper_schedules.py +6 -16
  137. {walker → adam}/commands/reaper/reaper_status.py +11 -19
  138. adam/commands/reaper/utils_reaper.py +196 -0
  139. adam/commands/repair/repair.py +26 -0
  140. {walker → adam}/commands/repair/repair_log.py +7 -10
  141. adam/commands/repair/repair_run.py +70 -0
  142. adam/commands/repair/repair_scan.py +71 -0
  143. {walker → adam}/commands/repair/repair_stop.py +8 -11
  144. adam/commands/report.py +61 -0
  145. adam/commands/restart.py +60 -0
  146. {walker → adam}/commands/rollout.py +25 -30
  147. adam/commands/shell.py +34 -0
  148. adam/commands/show/show.py +39 -0
  149. walker/commands/show/show_version.py → adam/commands/show/show_adam.py +14 -10
  150. adam/commands/show/show_app_actions.py +57 -0
  151. {walker → adam}/commands/show/show_app_id.py +12 -15
  152. {walker → adam}/commands/show/show_app_queues.py +9 -12
  153. adam/commands/show/show_cassandra_repairs.py +38 -0
  154. adam/commands/show/show_cassandra_status.py +124 -0
  155. {walker → adam}/commands/show/show_cassandra_version.py +6 -16
  156. adam/commands/show/show_commands.py +59 -0
  157. walker/commands/show/show_storage.py → adam/commands/show/show_host.py +11 -13
  158. adam/commands/show/show_login.py +62 -0
  159. {walker → adam}/commands/show/show_params.py +4 -4
  160. adam/commands/show/show_processes.py +51 -0
  161. adam/commands/show/show_storage.py +42 -0
  162. adam/commands/watch.py +82 -0
  163. {walker → adam}/config.py +10 -22
  164. {walker → adam}/embedded_apps.py +1 -1
  165. adam/embedded_params.py +2 -0
  166. adam/log.py +47 -0
  167. {walker → adam}/pod_exec_result.py +10 -2
  168. adam/repl.py +182 -0
  169. adam/repl_commands.py +124 -0
  170. adam/repl_state.py +458 -0
  171. adam/sql/__init__.py +0 -0
  172. adam/sql/sql_completer.py +120 -0
  173. adam/sql/sql_state_machine.py +618 -0
  174. adam/sql/term_completer.py +76 -0
  175. adam/sso/__init__.py +0 -0
  176. {walker → adam}/sso/authenticator.py +5 -1
  177. adam/sso/authn_ad.py +170 -0
  178. {walker → adam}/sso/authn_okta.py +39 -22
  179. adam/sso/cred_cache.py +60 -0
  180. adam/sso/id_token.py +23 -0
  181. adam/sso/idp.py +143 -0
  182. adam/sso/idp_login.py +50 -0
  183. adam/sso/idp_session.py +55 -0
  184. adam/sso/sso_config.py +63 -0
  185. adam/utils.py +679 -0
  186. adam/utils_app.py +98 -0
  187. adam/utils_athena.py +145 -0
  188. adam/utils_audits.py +106 -0
  189. adam/utils_issues.py +32 -0
  190. adam/utils_k8s/__init__.py +0 -0
  191. adam/utils_k8s/app_clusters.py +28 -0
  192. adam/utils_k8s/app_pods.py +33 -0
  193. adam/utils_k8s/cassandra_clusters.py +36 -0
  194. adam/utils_k8s/cassandra_nodes.py +33 -0
  195. adam/utils_k8s/config_maps.py +34 -0
  196. {walker/k8s_utils → adam/utils_k8s}/custom_resources.py +7 -2
  197. adam/utils_k8s/deployment.py +56 -0
  198. {walker/k8s_utils → adam/utils_k8s}/ingresses.py +3 -4
  199. {walker/k8s_utils → adam/utils_k8s}/jobs.py +3 -3
  200. adam/utils_k8s/k8s.py +87 -0
  201. {walker/k8s_utils → adam/utils_k8s}/kube_context.py +4 -4
  202. adam/utils_k8s/pods.py +290 -0
  203. {walker/k8s_utils → adam/utils_k8s}/secrets.py +8 -4
  204. adam/utils_k8s/service_accounts.py +170 -0
  205. {walker/k8s_utils → adam/utils_k8s}/services.py +3 -4
  206. {walker/k8s_utils → adam/utils_k8s}/statefulsets.py +6 -16
  207. {walker/k8s_utils → adam/utils_k8s}/volumes.py +10 -1
  208. adam/utils_net.py +24 -0
  209. adam/utils_repl/__init__.py +0 -0
  210. adam/utils_repl/automata_completer.py +48 -0
  211. adam/utils_repl/repl_completer.py +46 -0
  212. adam/utils_repl/state_machine.py +173 -0
  213. adam/utils_sqlite.py +109 -0
  214. adam/version.py +5 -0
  215. {kaqing-1.77.0.dist-info → kaqing-2.0.171.dist-info}/METADATA +1 -1
  216. kaqing-2.0.171.dist-info/RECORD +236 -0
  217. kaqing-2.0.171.dist-info/entry_points.txt +3 -0
  218. kaqing-2.0.171.dist-info/top_level.txt +1 -0
  219. kaqing-1.77.0.dist-info/RECORD +0 -159
  220. kaqing-1.77.0.dist-info/entry_points.txt +0 -3
  221. kaqing-1.77.0.dist-info/top_level.txt +0 -1
  222. walker/__init__.py +0 -3
  223. walker/app_session.py +0 -168
  224. walker/checks/check_utils.py +0 -97
  225. walker/columns/columns.py +0 -43
  226. walker/commands/add_user.py +0 -68
  227. walker/commands/app.py +0 -67
  228. walker/commands/bash.py +0 -87
  229. walker/commands/cd.py +0 -115
  230. walker/commands/check.py +0 -68
  231. walker/commands/command.py +0 -104
  232. walker/commands/cp.py +0 -95
  233. walker/commands/cql_utils.py +0 -53
  234. walker/commands/devices.py +0 -89
  235. walker/commands/frontend/code_stop.py +0 -57
  236. walker/commands/frontend/setup.py +0 -60
  237. walker/commands/frontend/setup_frontend.py +0 -58
  238. walker/commands/frontend/teardown.py +0 -61
  239. walker/commands/frontend/teardown_frontend.py +0 -42
  240. walker/commands/issues.py +0 -69
  241. walker/commands/login.py +0 -72
  242. walker/commands/ls.py +0 -145
  243. walker/commands/medusa/medusa.py +0 -69
  244. walker/commands/medusa/medusa_backup.py +0 -61
  245. walker/commands/medusa/medusa_restore.py +0 -86
  246. walker/commands/medusa/medusa_show_backupjobs.py +0 -52
  247. walker/commands/medusa/medusa_show_restorejobs.py +0 -52
  248. walker/commands/param_set.py +0 -44
  249. walker/commands/postgres/postgres.py +0 -113
  250. walker/commands/postgres/postgres_session.py +0 -225
  251. walker/commands/preview_table.py +0 -98
  252. walker/commands/processes.py +0 -53
  253. walker/commands/pwd.py +0 -64
  254. walker/commands/reaper/reaper.py +0 -78
  255. walker/commands/reaper/reaper_forward.py +0 -100
  256. walker/commands/reaper/reaper_run_abort.py +0 -65
  257. walker/commands/reaper/reaper_runs.py +0 -97
  258. walker/commands/reaper/reaper_runs_abort.py +0 -83
  259. walker/commands/reaper/reaper_schedule_activate.py +0 -64
  260. walker/commands/reaper/reaper_schedule_start.py +0 -64
  261. walker/commands/reaper/reaper_schedule_stop.py +0 -64
  262. walker/commands/reaper/reaper_session.py +0 -159
  263. walker/commands/repair/repair.py +0 -68
  264. walker/commands/repair/repair_run.py +0 -72
  265. walker/commands/repair/repair_scan.py +0 -79
  266. walker/commands/report.py +0 -57
  267. walker/commands/restart.py +0 -61
  268. walker/commands/show/show.py +0 -72
  269. walker/commands/show/show_app_actions.py +0 -53
  270. walker/commands/show/show_cassandra_status.py +0 -35
  271. walker/commands/show/show_commands.py +0 -58
  272. walker/commands/show/show_processes.py +0 -35
  273. walker/commands/show/show_repairs.py +0 -47
  274. walker/commands/status.py +0 -128
  275. walker/commands/storage.py +0 -52
  276. walker/commands/user_entry.py +0 -69
  277. walker/commands/watch.py +0 -85
  278. walker/embedded_params.py +0 -2
  279. walker/k8s_utils/cassandra_clusters.py +0 -48
  280. walker/k8s_utils/cassandra_nodes.py +0 -26
  281. walker/k8s_utils/pods.py +0 -211
  282. walker/repl.py +0 -165
  283. walker/repl_commands.py +0 -58
  284. walker/repl_state.py +0 -211
  285. walker/sso/authn_ad.py +0 -94
  286. walker/sso/idp.py +0 -150
  287. walker/sso/idp_login.py +0 -29
  288. walker/sso/sso_config.py +0 -45
  289. walker/utils.py +0 -194
  290. walker/version.py +0 -5
  291. {walker → adam}/checks/__init__.py +0 -0
  292. {walker → adam}/checks/check_context.py +0 -0
  293. {walker → adam}/checks/issue.py +0 -0
  294. {walker → adam}/cli_group.py +0 -0
  295. {walker → adam}/columns/__init__.py +0 -0
  296. {walker/commands → adam/commands/audit}/__init__.py +0 -0
  297. {walker/commands/frontend → adam/commands/cql}/__init__.py +0 -0
  298. {walker/commands/medusa → adam/commands/deploy}/__init__.py +0 -0
  299. {walker/commands/postgres → adam/commands/devices}/__init__.py +0 -0
  300. {walker/commands/reaper → adam/commands/export}/__init__.py +0 -0
  301. {walker/commands/repair → adam/commands/medusa}/__init__.py +0 -0
  302. {walker → adam}/commands/nodetool_commands.py +0 -0
  303. {walker/commands/show → adam/commands/postgres}/__init__.py +0 -0
  304. {walker/k8s_utils → adam/commands/reaper}/__init__.py +0 -0
  305. {walker/sso → adam/commands/repair}/__init__.py +0 -0
  306. /walker/medusa_show_restorejobs.py → /adam/commands/show/__init__.py +0 -0
  307. {walker → adam}/repl_session.py +0 -0
  308. {kaqing-1.77.0.dist-info → kaqing-2.0.171.dist-info}/WHEEL +0 -0
@@ -1,14 +1,11 @@
1
- from collections.abc import Callable
2
- from concurrent.futures import ThreadPoolExecutor
3
1
  from datetime import datetime
4
2
  import functools
5
3
  import re
6
4
  from typing import List, TypeVar, cast
7
5
  from kubernetes import client
8
6
 
9
- from .pods import Pods
10
7
  from .kube_context import KubeContext
11
- from walker.utils import log2
8
+ from adam.utils import log2
12
9
 
13
10
 
14
11
  T = TypeVar('T')
@@ -24,11 +21,12 @@ class StatefulSets:
24
21
 
25
22
  return statefulsets.items
26
23
 
24
+ @functools.lru_cache()
27
25
  def list_sts_name_and_ns():
28
26
  return [(statefulset.metadata.name, statefulset.metadata.namespace) for statefulset in StatefulSets.list_sts()]
29
27
 
30
- def list_sts_names(show_namespace = True):
31
- if show_namespace:
28
+ def list_sts_names():
29
+ if not KubeContext.in_cluster_namespace():
32
30
  return [f"{sts}@{ns}" for sts, ns in StatefulSets.list_sts_name_and_ns()]
33
31
  else:
34
32
  return [f"{sts}" for sts, _ in StatefulSets.list_sts_name_and_ns()]
@@ -57,15 +55,6 @@ class StatefulSets:
57
55
 
58
56
  return statefulset_pods
59
57
 
60
- def on_cluster(statefulset: str,
61
- namespace: str,
62
- body: Callable[[ThreadPoolExecutor, str, str, bool], T],
63
- post: Callable[[T], T] = None,
64
- action: str = 'action', max_workers=0, show_out=True) -> list[T]:
65
- pods = StatefulSets.pod_names(statefulset, namespace)
66
-
67
- return Pods.on_pods(pods, namespace, body, post=post, action=action, max_workers=max_workers, show_out=show_out)
68
-
69
58
  @functools.lru_cache()
70
59
  def pod_names(ss: str, ns: str):
71
60
  return [pod.metadata.name for pod in StatefulSets.pods(ss, ns)]
@@ -90,7 +79,8 @@ class StatefulSets:
90
79
  return restarted, True
91
80
 
92
81
  return restarted, False
93
-
82
+
83
+ @functools.lru_cache()
94
84
  def get_datacenter(sts: str, ns: str) -> str:
95
85
  v1 = client.AppsV1Api()
96
86
  namespace = ns
@@ -1,5 +1,14 @@
1
1
  from kubernetes import client
2
- from walker.utils import log2
2
+ from adam.utils import log2
3
+
4
+ class ConfigMapMount:
5
+ def __init__(self, config_map_name: str, sub_path: str, mount_path: str):
6
+ self.config_map_name = config_map_name
7
+ self.sub_path = sub_path
8
+ self.mount_path = mount_path
9
+
10
+ def name(self) -> str:
11
+ return f"{self.config_map_name}-volume"
3
12
 
4
13
  # utility collection on volumes; methods are all static
5
14
  class Volumes:
adam/utils_net.py ADDED
@@ -0,0 +1,24 @@
1
+ import socket
2
+
3
+ MY_HOST = None
4
+
5
+ def get_my_host():
6
+ global MY_HOST
7
+
8
+ if MY_HOST:
9
+ return MY_HOST
10
+
11
+ MY_HOST = get_ip_from_hostname('host.docker.internal')
12
+ if not MY_HOST:
13
+ MY_HOST = socket.gethostname()
14
+
15
+ if not MY_HOST:
16
+ MY_HOST = 'NA'
17
+
18
+ return MY_HOST
19
+
20
+ def get_ip_from_hostname(hostname):
21
+ try:
22
+ return socket.gethostbyname(hostname)
23
+ except socket.gaierror:
24
+ return None
File without changes
@@ -0,0 +1,48 @@
1
+ from typing import Generic, Iterable, TypeVar
2
+ from prompt_toolkit.completion import CompleteEvent, Completer, Completion, WordCompleter
3
+ from prompt_toolkit.document import Document
4
+
5
+ from adam.utils_repl.state_machine import StateMachine, State
6
+
7
+ __all__ = [
8
+ "AutomataCompleter",
9
+ ]
10
+
11
+ T = TypeVar('T')
12
+
13
+ class AutomataCompleter(Completer, Generic[T]):
14
+ def __init__(self,
15
+ state_machine: StateMachine,
16
+ first_term: str = '',
17
+ debug = False):
18
+ super().__init__()
19
+ self.machine = state_machine
20
+ self.first_term = first_term
21
+ self.debug = debug
22
+
23
+ def get_completions(
24
+ self, document: Document, complete_event: CompleteEvent
25
+ ) -> Iterable[Completion]:
26
+ text = document.text_before_cursor.lstrip()
27
+ state = ''
28
+ if self.first_term:
29
+ text = f'{self.first_term} {text}'
30
+
31
+ completer: Completer = None
32
+ state: State = self.machine.traverse_tokens(self.tokens(text), State(state))
33
+ if self.debug:
34
+ print('\n =>', state.state if isinstance(state, State) else '')
35
+
36
+ if state.state in self.machine.suggestions:
37
+ if completer := self.suggestions_completer(state, self.machine.suggestions[state.state].strip(' ')):
38
+ for c in completer.get_completions(document, complete_event):
39
+ yield c
40
+
41
+ def tokens(self, text: str) -> list[T]:
42
+ return text.split(' ')
43
+
44
+ def suggestions_completer(self, _: State, suggestions: str) -> list[str]:
45
+ if not suggestions:
46
+ return None
47
+
48
+ return WordCompleter(suggestions.split(','))
@@ -0,0 +1,46 @@
1
+ import re
2
+ from typing import Iterable, TypeVar
3
+ from prompt_toolkit.completion import CompleteEvent, Completion, NestedCompleter, WordCompleter
4
+ from prompt_toolkit.document import Document
5
+
6
+ __all__ = [
7
+ "ReplCompleter",
8
+ ]
9
+
10
+ T = TypeVar('T')
11
+
12
+ class ReplCompleter(NestedCompleter):
13
+ def get_completions(
14
+ self, document: Document, complete_event: CompleteEvent
15
+ ) -> Iterable[Completion]:
16
+ # Split document.
17
+ text = document.text_before_cursor.lstrip()
18
+ stripped_len = len(document.text_before_cursor) - len(text)
19
+
20
+ # If there is a space, check for the first term, and use a
21
+ # subcompleter.
22
+ if " " in text:
23
+ first_term = text.split()[0]
24
+ completer = self.options.get(first_term)
25
+
26
+ # If we have a sub completer, use this for the completions.
27
+ if completer is not None:
28
+ remaining_text = text[len(first_term) :].lstrip()
29
+ move_cursor = len(text) - len(remaining_text) + stripped_len
30
+
31
+ new_document = Document(
32
+ remaining_text,
33
+ cursor_position=document.cursor_position - move_cursor,
34
+ )
35
+
36
+ for c in completer.get_completions(new_document, complete_event):
37
+ yield c
38
+
39
+ # No space in the input: behave exactly like `WordCompleter`.
40
+ else:
41
+ completer = WordCompleter(
42
+ # Allow dot in the middle or a word
43
+ list(self.options.keys()), ignore_case=self.ignore_case, pattern=re.compile(r"([a-zA-Z0-9_\.\@\&]+|[^a-zA-Z0-9_\.\@\&\s]+)")
44
+ )
45
+ for c in completer.get_completions(document, complete_event):
46
+ yield c
@@ -0,0 +1,173 @@
1
+ from abc import abstractmethod
2
+ from typing import Generic, TypeVar
3
+
4
+ __all__ = [
5
+ 'State',
6
+ 'StateMachine',
7
+ ]
8
+
9
+ T = TypeVar('T')
10
+
11
+ class State:
12
+ def __init__(self, state: str, comeback_token: str = None, comeback_state: str = None):
13
+ self.state = state
14
+ self.comeback_token = comeback_token
15
+ self.comeback_state = comeback_state
16
+ self.context: dict[str, str] = {}
17
+
18
+ def __str__(self):
19
+ return f'{self.state if self.state else None} comeback[{self.comeback_token} {self.comeback_state}]'
20
+
21
+ class StateMachine(Generic[T]):
22
+ @abstractmethod
23
+ def spec(self) -> str:
24
+ return None
25
+
26
+ @abstractmethod
27
+ def keywords(self) -> list[str]:
28
+ return None
29
+
30
+ def expandable_names(self):
31
+ return []
32
+
33
+ def incomplete_name_transition_condition(self, from_s: str, token: str, to_s: str, suggestions: str) -> list[str]:
34
+ if not suggestions:
35
+ return None
36
+
37
+ tokens = [token]
38
+ if '|' in token:
39
+ tokens = token.split('|')
40
+
41
+ if 'name' not in tokens:
42
+ return None
43
+
44
+ return tokens
45
+
46
+ def __init__(self, indent=0, push_level = 0, debug = False):
47
+ self.states: dict[str, State] = {}
48
+ self.suggestions: dict[str, str] = {}
49
+
50
+ self.indent = indent
51
+ self.push_level = push_level
52
+ self.comebacks: dict[int, str] = {}
53
+ self.debug = debug
54
+
55
+ from_ss_to_add = []
56
+ from_ss = ['']
57
+ words: str = None
58
+ for l in self.spec():
59
+ t_and_w = l.split('^')
60
+ if len(t_and_w) > 1:
61
+ words = t_and_w[1].strip()
62
+ else:
63
+ words = None
64
+
65
+ tks = t_and_w[0].strip(' ').split('>')
66
+ if not l.startswith('-'):
67
+ if words:
68
+ self.suggestions[tks[0].strip(' ')] = words
69
+
70
+ if len(tks) == 1:
71
+ from_ss_to_add.append(tks[0].strip(' '))
72
+ continue
73
+
74
+ from_ss = []
75
+ from_ss.extend(from_ss_to_add)
76
+ from_ss_to_add = []
77
+ from_ss.append(tks[0].strip(' '))
78
+
79
+ self.add_transitions(from_ss, tks, words)
80
+
81
+ def add_transitions(self, from_ss: list[str], tks: list[str], words: str):
82
+ token = tks[1].strip(' ')
83
+ if len(tks) > 2:
84
+ to_s = tks[2].strip(' ')
85
+ for from_s in from_ss:
86
+ self.add_whitespace_transition(from_s, to_s)
87
+ self.add_transition(from_s, token, to_s)
88
+ self.add_incomplete_name_transition(from_s, token, to_s, words)
89
+ elif '<' in tks[0]:
90
+ from_and_token = tks[0].split('<')
91
+ if len(from_and_token) > 1:
92
+ for from_s in from_ss:
93
+ self.add_comeback_transition(from_s, from_and_token[1], tks[1].strip(' '))
94
+
95
+ def add_whitespace_transition(self, from_s: str, to_s: str):
96
+ if self.witespace_transition_condition(from_s, to_s):
97
+ if self.debug:
98
+ print(f'{from_s[:-1]} > _ = {to_s}')
99
+ self.states[f'{from_s[:-1]} > _'] = State(from_s)
100
+
101
+ def witespace_transition_condition(self, from_s: str, to_s: str):
102
+ return from_s.endswith('_')
103
+
104
+ def add_incomplete_name_transition(self, from_s: str, token: str, to_s: str, words: str):
105
+ if tokens := self.incomplete_name_transition_condition(from_s, token, to_s, words):
106
+ self.suggestions[to_s] = words
107
+ for token in tokens:
108
+ if self.debug:
109
+ print(f'{to_s} > {token} = {to_s}')
110
+ self.states[f'{to_s} > {token}'] = State(to_s)
111
+
112
+ def add_transition(self, from_s: str, token: str, to_s: str):
113
+ tokens = [token]
114
+ if '|' in token:
115
+ tokens = token.split('|')
116
+
117
+ for t in tokens:
118
+ if t == '_or_':
119
+ t = '||'
120
+ elif t == 'pipe':
121
+ t = '|'
122
+ elif t == '_rdr0_':
123
+ t = '<'
124
+ elif t == '_rdr1_':
125
+ t = '>'
126
+ elif t == '_rdr2_':
127
+ t = '2>'
128
+
129
+ if self.debug:
130
+ print(f'{from_s} > {t} = {to_s}')
131
+ self.states[f'{from_s} > {t}'] = State(to_s)
132
+
133
+ def add_comeback_transition(self, from_s: str, token: str, to_s: str):
134
+ key = f'{from_s} > ('
135
+ orig = self.states[key]
136
+ if not orig:
137
+ raise Exception(f'from state not found for {key}')
138
+
139
+ orig.comeback_token = token
140
+ orig.comeback_state = to_s
141
+ if self.debug:
142
+ print(f'{from_s} > ) = {to_s}')
143
+ self.states[key] = orig
144
+
145
+ def traverse_tokens(self, tokens: list[str], state: State = State('')):
146
+ for token in tokens[:-1]:
147
+ if not token:
148
+ continue
149
+
150
+ if self.debug:
151
+ print(f'{token} ', end='')
152
+
153
+ last_name = None
154
+
155
+ if (t := token.lower()) in self.keywords():
156
+ token = t
157
+ elif token in ['*', ',', '.']:
158
+ pass
159
+ else:
160
+ last_name = token
161
+ token = 'word'
162
+
163
+ try:
164
+ context = state.context
165
+ state = self.states[f'{state.state} > {token}']
166
+ state.context = context
167
+
168
+ if last_name:
169
+ state.context['last_name'] = last_name
170
+ except:
171
+ pass
172
+
173
+ return state
adam/utils_sqlite.py ADDED
@@ -0,0 +1,109 @@
1
+ import functools
2
+ import glob
3
+ import os
4
+ import sqlite3
5
+ import pandas
6
+
7
+ from adam.config import Config
8
+ from adam.utils import lines_to_tabular, log, wait_log
9
+
10
+ class CursorHandler:
11
+ def __init__(self, conn: sqlite3.Connection):
12
+ self.conn = conn
13
+
14
+ def __enter__(self):
15
+ self.cursor = self.conn.cursor()
16
+
17
+ return self.cursor
18
+
19
+ def __exit__(self, exc_type, exc_val, exc_tb):
20
+ if self.cursor:
21
+ self.cursor.close()
22
+
23
+ return False
24
+
25
+ # no state utility class
26
+ class SQLite:
27
+ def cursor(conn: sqlite3.Connection):
28
+ return CursorHandler(conn)
29
+
30
+ def local_db_dir():
31
+ return Config().get('export.sqlite.local-db-dir', '/tmp/qing-db')
32
+
33
+ def keyspace(database: str):
34
+ return '_'.join(database.replace(".db", "").split('_')[1:])
35
+
36
+ def connect(session: str):
37
+ os.makedirs(SQLite.local_db_dir(), exist_ok=True)
38
+
39
+ conn = None
40
+
41
+ try:
42
+ conn = sqlite3.connect(f'{SQLite.local_db_dir()}/{session}_root.db')
43
+ with SQLite.cursor(conn) as cursor:
44
+ for d in SQLite.database_names(session):
45
+ if d != f'{session}_root.db':
46
+ q = f"ATTACH DATABASE '{SQLite.local_db_dir()}/{d}' AS {SQLite.keyspace(d)};"
47
+ cursor.execute(q)
48
+ finally:
49
+ pass
50
+
51
+ return conn
52
+
53
+ @functools.lru_cache()
54
+ def database_names(prefix: str = None):
55
+ wait_log('Inspecting export databases...')
56
+
57
+ pattern = f'{SQLite.local_db_dir()}/s*.db'
58
+ if prefix:
59
+ pattern = f'{SQLite.local_db_dir()}/{prefix}*'
60
+ return [os.path.basename(f) for f in glob.glob(pattern)]
61
+
62
+ def clear_cache(cache: str = None):
63
+ SQLite.database_names.cache_clear()
64
+ SQLite.table_names.cache_clear()
65
+
66
+ @functools.lru_cache()
67
+ def table_names(database: str):
68
+ tokens = database.replace('.db', '').split('_')
69
+ ts_prefix = tokens[0]
70
+ keyspace = '_'.join(tokens[1:])
71
+
72
+ conn = None
73
+ tables = []
74
+ try:
75
+ conn = sqlite3.connect(f'{SQLite.local_db_dir()}/{ts_prefix}_{keyspace}.db')
76
+ with SQLite.cursor(conn) as cursor:
77
+ cursor.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;")
78
+
79
+ tables = [row[0] for row in cursor.fetchall() if row[0] != "sqlite_sequence"]
80
+
81
+ return tables
82
+ except sqlite3.Error as e:
83
+ print(f"Error connecting to or querying the database: {e}")
84
+ return []
85
+ finally:
86
+ if conn:
87
+ conn.close()
88
+
89
+ @functools.lru_cache()
90
+ def column_names(tables: list[str] = [], database: str = None, function: str = 'audit', partition_cols_only = False):
91
+ pass
92
+
93
+ def run_query(query: str, database: str = None, conn_passed = None):
94
+ conn = None
95
+ try:
96
+ if not conn_passed:
97
+ conn = SQLite.connect(database)
98
+
99
+ df = SQLite.query(conn_passed if conn_passed else conn, query)
100
+ lines = ['\t'.join(map(str, line)) for line in df.values.tolist()]
101
+ log(lines_to_tabular(lines, header='\t'.join(df.columns.tolist()), separator='\t'))
102
+
103
+ return len(lines)
104
+ finally:
105
+ if conn:
106
+ conn.close()
107
+
108
+ def query(conn, sql: str) -> tuple[str, str, list]:
109
+ return pandas.read_sql_query(sql, conn)
adam/version.py ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ __version__ = "2.0.171" #: the working version
5
+ __release__ = "1.0.0" #: the release version
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kaqing
3
- Version: 1.77.0
3
+ Version: 2.0.171
4
4
  Summary: UNKNOWN
5
5
  Home-page: UNKNOWN
6
6
  License: UNKNOWN