vortex-cli 4.13.1__tar.gz → 4.14.0__tar.gz
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.
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/PKG-INFO +1 -2
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/setup.cfg +2 -2
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/cli.py +31 -14
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/clone.py +8 -1
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/db.py +53 -21
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/list.py +9 -2
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/main.py +4 -3
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/models.py +5 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex_cli.egg-info/PKG-INFO +1 -2
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/LICENSE +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/README.md +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/setup.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/__init__.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/__main__.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/colour.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/__init__.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/clean.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/code.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/config.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/copy.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/delete.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/docs.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/execute.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/find.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/grep.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/log.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/new.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/commands/watch.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/constants.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/docs/Blackbook.pdf +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/lib/puakma.jar +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/logging.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/soap.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/spinner.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/util.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex/workspace.py +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex_cli.egg-info/SOURCES.txt +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex_cli.egg-info/dependency_links.txt +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex_cli.egg-info/entry_points.txt +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex_cli.egg-info/requires.txt +0 -0
- {vortex_cli-4.13.1 → vortex_cli-4.14.0}/vortex_cli.egg-info/top_level.txt +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
[metadata]
|
|
2
2
|
name = vortex_cli
|
|
3
|
-
version = 4.
|
|
4
|
-
description = Vortex CLI
|
|
3
|
+
version = 4.14.0
|
|
5
4
|
long_description = file: README.md
|
|
6
5
|
long_description_content_type = text/markdown
|
|
7
6
|
url = https://github.com/jordanamos/vortex-cli
|
|
@@ -18,6 +17,7 @@ classifiers =
|
|
|
18
17
|
Programming Language :: Python :: 3
|
|
19
18
|
Programming Language :: Python :: 3 :: Only
|
|
20
19
|
keywords = vortex cli
|
|
20
|
+
vdescription = Vortex CLI
|
|
21
21
|
|
|
22
22
|
[options]
|
|
23
23
|
packages = find:
|
|
@@ -71,6 +71,7 @@ def validate_args(
|
|
|
71
71
|
args: Namespace,
|
|
72
72
|
new_parser: ArgumentParser,
|
|
73
73
|
clone_parser: ArgumentParser,
|
|
74
|
+
db_parser: ArgumentParser,
|
|
74
75
|
) -> None:
|
|
75
76
|
if args.command == "new" and args.subcommand == "object":
|
|
76
77
|
missing_required_fields = not args.update_id and not (
|
|
@@ -103,13 +104,18 @@ def validate_args(
|
|
|
103
104
|
elif update_arg_contains_app_id:
|
|
104
105
|
msg = "Can't use --app-id with --update"
|
|
105
106
|
elif update_is_missing_args:
|
|
106
|
-
msg = "Please
|
|
107
|
+
msg = "Please specify an option to update"
|
|
107
108
|
|
|
108
109
|
if msg:
|
|
109
110
|
new_parser.error(msg)
|
|
110
111
|
|
|
111
112
|
elif args.command == "clone" and not (args.app_ids or args.reclone):
|
|
112
|
-
clone_parser.error("Please specifiy the APP_ID[s] to clone or use --reclone")
|
|
113
|
+
clone_parser.error("Please specifiy the APP_ID[s] to clone or use '--reclone'")
|
|
114
|
+
elif args.command == "db":
|
|
115
|
+
if args.sql and not args.conn_id:
|
|
116
|
+
db_parser.error("The '--sql' option requires '--connection-id'")
|
|
117
|
+
if (args.schema or args.list) and not args.db_name:
|
|
118
|
+
db_parser.error("Options '--schema' and '--list' require '--db-name'")
|
|
113
119
|
|
|
114
120
|
|
|
115
121
|
def add_code_parser(
|
|
@@ -198,9 +204,10 @@ def add_list_parser(command_parser: _SubParsersAction[ArgumentParser]) -> None:
|
|
|
198
204
|
action="store_true",
|
|
199
205
|
)
|
|
200
206
|
list_parser.add_argument(
|
|
201
|
-
"--
|
|
207
|
+
"--connections",
|
|
202
208
|
help="List the Database Connections of locally cloned apps",
|
|
203
209
|
action="store_true",
|
|
210
|
+
dest="show_connections",
|
|
204
211
|
)
|
|
205
212
|
_add_server_option(list_parser)
|
|
206
213
|
|
|
@@ -514,16 +521,9 @@ def add_delete_parser(command_parser: _SubParsersAction[ArgumentParser]) -> None
|
|
|
514
521
|
_add_server_option(delete_parser)
|
|
515
522
|
|
|
516
523
|
|
|
517
|
-
def add_db_parser(command_parser: _SubParsersAction[ArgumentParser]) ->
|
|
518
|
-
db_parser = command_parser.add_parser(
|
|
519
|
-
|
|
520
|
-
)
|
|
521
|
-
db_parser.add_argument(
|
|
522
|
-
"connection_id",
|
|
523
|
-
metavar="CONNECTION_ID",
|
|
524
|
-
type=int,
|
|
525
|
-
help="The Database Connection ID",
|
|
526
|
-
)
|
|
524
|
+
def add_db_parser(command_parser: _SubParsersAction[ArgumentParser]) -> ArgumentParser:
|
|
525
|
+
db_parser = command_parser.add_parser("db", help="Interact with Databases")
|
|
526
|
+
|
|
527
527
|
db_mutex = db_parser.add_mutually_exclusive_group(required=True)
|
|
528
528
|
db_mutex.add_argument("--sql", help="Execute a given SQL query")
|
|
529
529
|
db_mutex.add_argument(
|
|
@@ -537,7 +537,24 @@ def add_db_parser(command_parser: _SubParsersAction[ArgumentParser]) -> None:
|
|
|
537
537
|
action="store_true",
|
|
538
538
|
help="List the tables in the Database",
|
|
539
539
|
)
|
|
540
|
+
list_schema_group = db_parser.add_argument_group("List/Schema Options")
|
|
541
|
+
list_schema_group.add_argument(
|
|
542
|
+
"--db-name",
|
|
543
|
+
"--name",
|
|
544
|
+
"-n",
|
|
545
|
+
metavar="DB_NAME",
|
|
546
|
+
dest="db_name",
|
|
547
|
+
help="The Database Name.",
|
|
548
|
+
)
|
|
540
549
|
sql_group = db_parser.add_argument_group("SQL Options")
|
|
550
|
+
sql_group.add_argument(
|
|
551
|
+
"--connection-id",
|
|
552
|
+
"--id",
|
|
553
|
+
metavar="INT",
|
|
554
|
+
dest="conn_id",
|
|
555
|
+
type=int,
|
|
556
|
+
help="The Database Connection ID to query. (Required for SQL)",
|
|
557
|
+
)
|
|
541
558
|
sql_group.add_argument(
|
|
542
559
|
"--update",
|
|
543
560
|
"-u",
|
|
@@ -552,7 +569,6 @@ def add_db_parser(command_parser: _SubParsersAction[ArgumentParser]) -> None:
|
|
|
552
569
|
)
|
|
553
570
|
sql_group.add_argument(
|
|
554
571
|
"--limit",
|
|
555
|
-
"-n",
|
|
556
572
|
metavar="INT",
|
|
557
573
|
type=_check_int_in_range,
|
|
558
574
|
help=(
|
|
@@ -563,6 +579,7 @@ def add_db_parser(command_parser: _SubParsersAction[ArgumentParser]) -> None:
|
|
|
563
579
|
),
|
|
564
580
|
default=5,
|
|
565
581
|
)
|
|
582
|
+
return db_parser
|
|
566
583
|
|
|
567
584
|
|
|
568
585
|
def add_docs_parser(command_parser: _SubParsersAction[ArgumentParser]) -> None:
|
|
@@ -122,8 +122,15 @@ def _parse_app_xml(
|
|
|
122
122
|
db_connections: list[DatabaseConnection] = []
|
|
123
123
|
for db_ele in app_xml.findall(".//database"):
|
|
124
124
|
db_conn = DatabaseConnection(
|
|
125
|
-
int(db_ele.attrib["id"]),
|
|
125
|
+
int(db_ele.attrib["id"]),
|
|
126
|
+
db_ele.attrib["name"],
|
|
127
|
+
db_ele.attrib["dbName"],
|
|
128
|
+
db_ele.attrib["driver"],
|
|
129
|
+
db_ele.attrib["url"],
|
|
130
|
+
db_ele.attrib["userName"],
|
|
131
|
+
db_ele.attrib["pwd"],
|
|
126
132
|
)
|
|
133
|
+
# print(db_ele.attrib)
|
|
127
134
|
db_connections.append(db_conn)
|
|
128
135
|
|
|
129
136
|
java_version_ele = app_xml.find('.//sysProp[@name="java.class.version"]')
|
|
@@ -38,9 +38,14 @@ def _output_result(
|
|
|
38
38
|
sql: str,
|
|
39
39
|
update: bool,
|
|
40
40
|
truncate_cols: bool = False,
|
|
41
|
-
|
|
41
|
+
db_name: str | None = None,
|
|
42
|
+
schema_table: str | None = None,
|
|
43
|
+
) -> int:
|
|
42
44
|
with server:
|
|
43
45
|
result = tuple(server.database_designer.execute_query(conn_id, sql, update))
|
|
46
|
+
if schema_table and not result:
|
|
47
|
+
logger.error(f"Table '{schema_table}' not found in database '{db_name}'")
|
|
48
|
+
return 1
|
|
44
49
|
if result:
|
|
45
50
|
if truncate_cols:
|
|
46
51
|
result = _truncate_cols(result)
|
|
@@ -55,9 +60,10 @@ def _output_result(
|
|
|
55
60
|
)
|
|
56
61
|
else:
|
|
57
62
|
logger.info("Query returned nil results.")
|
|
63
|
+
return 0
|
|
58
64
|
|
|
59
65
|
|
|
60
|
-
def
|
|
66
|
+
def _is_connection_cloned(workspace: Workspace, conn_id: int) -> bool:
|
|
61
67
|
"""Returns True if the given conn_id exists in a locally cloned Application."""
|
|
62
68
|
conns: list[DatabaseConnection] = []
|
|
63
69
|
for app in workspace.listapps():
|
|
@@ -69,7 +75,8 @@ def _check_connection_is_cloned(workspace: Workspace, conn_id: int) -> bool:
|
|
|
69
75
|
def db(
|
|
70
76
|
workspace: Workspace,
|
|
71
77
|
server: PuakmaServer,
|
|
72
|
-
conn_id: int,
|
|
78
|
+
conn_id: int | None,
|
|
79
|
+
db_name: str | None,
|
|
73
80
|
sql: str | None,
|
|
74
81
|
update: bool = False,
|
|
75
82
|
limit_n_results: int = 5,
|
|
@@ -77,21 +84,45 @@ def db(
|
|
|
77
84
|
list_tables: bool = False,
|
|
78
85
|
truncate_cols: bool = False,
|
|
79
86
|
) -> int:
|
|
80
|
-
|
|
87
|
+
do_schema = schema_table is not None
|
|
88
|
+
db_name = db_name or ""
|
|
89
|
+
conn_id = conn_id or -1
|
|
90
|
+
if do_schema:
|
|
81
91
|
sql = f"""\
|
|
82
|
-
SELECT
|
|
83
|
-
|
|
84
|
-
|
|
92
|
+
SELECT DISTINCT
|
|
93
|
+
CASE
|
|
94
|
+
WHEN isprimarykey = '1'
|
|
95
|
+
THEN 'PK'
|
|
96
|
+
ELSE ''
|
|
97
|
+
END AS "PK"
|
|
98
|
+
, attributename AS "Attribute"
|
|
99
|
+
, CASE WHEN ref.tableid > 0
|
|
100
|
+
THEN UPPER(ref.tablename)
|
|
101
|
+
ELSE ''
|
|
102
|
+
END AS "References"
|
|
103
|
+
, CASE WHEN type IN ('VARCHAR', 'CHAR')
|
|
104
|
+
THEN CONCAT(type, ' (', typesize, ')')
|
|
105
|
+
ELSE type
|
|
106
|
+
END AS "Type"
|
|
107
|
+
, CASE
|
|
108
|
+
WHEN isunique = '1'
|
|
109
|
+
THEN 'Yes'
|
|
110
|
+
ELSE 'No'
|
|
111
|
+
END AS "Unique"
|
|
85
112
|
, CASE
|
|
86
113
|
WHEN allownull = '1'
|
|
87
|
-
THEN '
|
|
88
|
-
ELSE '
|
|
89
|
-
END AS
|
|
114
|
+
THEN 'Yes'
|
|
115
|
+
ELSE 'No'
|
|
116
|
+
END AS "Allow Null"
|
|
90
117
|
FROM attribute a
|
|
91
118
|
INNER JOIN pmatable t
|
|
92
119
|
ON t.tableid = a.tableid
|
|
93
|
-
|
|
94
|
-
|
|
120
|
+
INNER JOIN dbconnection db
|
|
121
|
+
ON db.dbconnectionid = t.dbconnectionid
|
|
122
|
+
LEFT JOIN pmatable ref
|
|
123
|
+
ON ref.tableid::VARCHAR = a.reftable
|
|
124
|
+
WHERE LOWER(db.dbname) = '{db_name.lower()}'
|
|
125
|
+
AND LOWER(t.tablename) = '{schema_table}'
|
|
95
126
|
ORDER BY attributename
|
|
96
127
|
"""
|
|
97
128
|
update = False
|
|
@@ -99,11 +130,12 @@ def db(
|
|
|
99
130
|
conn_id = server.puakma_db_conn_id
|
|
100
131
|
elif list_tables:
|
|
101
132
|
sql = f"""\
|
|
102
|
-
SELECT tablename
|
|
133
|
+
SELECT DISTINCT tablename
|
|
103
134
|
, description
|
|
104
|
-
FROM
|
|
105
|
-
|
|
106
|
-
|
|
135
|
+
FROM dbconnection db
|
|
136
|
+
INNER JOIN pmatable t
|
|
137
|
+
ON db.dbconnectionid = t.dbconnectionid
|
|
138
|
+
WHERE LOWER(db.dbname)='{db_name.lower()}'
|
|
107
139
|
"""
|
|
108
140
|
update = False
|
|
109
141
|
truncate_cols = False
|
|
@@ -111,8 +143,8 @@ def db(
|
|
|
111
143
|
elif sql is not None:
|
|
112
144
|
# If we're modifying a database, lets check that its locally
|
|
113
145
|
# cloned to ensure intent
|
|
114
|
-
if
|
|
115
|
-
logger.error(f"No cloned applications with DB Connection '{conn_id}'")
|
|
146
|
+
if not _is_connection_cloned(workspace, conn_id):
|
|
147
|
+
logger.error(f"No cloned applications with DB Connection ID '{conn_id}'")
|
|
116
148
|
return 1
|
|
117
149
|
if not update:
|
|
118
150
|
sql = sql + f" LIMIT {limit_n_results}"
|
|
@@ -120,6 +152,6 @@ def db(
|
|
|
120
152
|
if sql is None:
|
|
121
153
|
raise ValueError("No Query to execute.")
|
|
122
154
|
|
|
123
|
-
_output_result(
|
|
124
|
-
|
|
125
|
-
|
|
155
|
+
return _output_result(
|
|
156
|
+
server, conn_id, sql, update, truncate_cols, db_name, schema_table
|
|
157
|
+
)
|
|
@@ -63,12 +63,19 @@ def list_(
|
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
def _render_db_connections(apps: list[PuakmaApplication]) -> None:
|
|
66
|
-
row_headers = ["ID", "
|
|
66
|
+
row_headers = ["ID", "Name", "DB Name", "Driver", "URL", "Application"]
|
|
67
67
|
row_data = []
|
|
68
68
|
for app in sorted(apps, key=lambda x: (x.group.casefold(), x.name.casefold())):
|
|
69
69
|
if app.db_connections:
|
|
70
70
|
for conn in app.db_connections:
|
|
71
|
-
row = (
|
|
71
|
+
row = (
|
|
72
|
+
conn.id,
|
|
73
|
+
conn.name,
|
|
74
|
+
conn.db_name,
|
|
75
|
+
conn.driver,
|
|
76
|
+
conn.url,
|
|
77
|
+
str(app),
|
|
78
|
+
)
|
|
72
79
|
row_data.append(row)
|
|
73
80
|
print(tabulate.tabulate(row_data, headers=row_headers))
|
|
74
81
|
|
|
@@ -92,11 +92,11 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
92
92
|
cli.add_grep_parser(command_parser)
|
|
93
93
|
cli.add_log_parser(command_parser)
|
|
94
94
|
cli.add_watch_parser(command_parser)
|
|
95
|
-
cli.add_db_parser(command_parser)
|
|
96
95
|
cli.add_docs_parser(command_parser)
|
|
97
96
|
cli.add_execute_parser(command_parser)
|
|
98
97
|
clone_parser = cli.add_clone_parser(command_parser)
|
|
99
98
|
code_parser = cli.add_code_parser(command_parser)
|
|
99
|
+
db_parser = cli.add_db_parser(command_parser)
|
|
100
100
|
new_parser = cli.add_new_parser(command_parser)
|
|
101
101
|
|
|
102
102
|
args, remaining_args = parser.parse_known_args(argv)
|
|
@@ -104,7 +104,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
104
104
|
if args.command != "code":
|
|
105
105
|
parser.parse_args(argv)
|
|
106
106
|
|
|
107
|
-
cli.validate_args(args, new_parser, clone_parser)
|
|
107
|
+
cli.validate_args(args, new_parser, clone_parser, db_parser)
|
|
108
108
|
|
|
109
109
|
if args.no_colour:
|
|
110
110
|
Colour.disable()
|
|
@@ -230,7 +230,8 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
230
230
|
return db(
|
|
231
231
|
workspace,
|
|
232
232
|
server,
|
|
233
|
-
args.
|
|
233
|
+
args.conn_id,
|
|
234
|
+
args.db_name,
|
|
234
235
|
args.sql,
|
|
235
236
|
update=args.update,
|
|
236
237
|
limit_n_results=args.limit,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|