py-dbms-cli 2.0__tar.gz → 2.1.1__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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py-dbms-cli
3
- Version: 2.0
4
- Summary: A modern, secure, aesthetic and your ultimate DBMS client supporting MySQL and more.
3
+ Version: 2.1.1
4
+ Summary: A modern, secure, aesthetic and your ultimate DBMS client. Implemented as a CLI (Command-Line Interface) tool and written 100% in Python
5
5
  Author-email: Anish Sethi <sethi.dynasty123@gmail.com>
6
6
  License: Copyright 2025 Anish Sethi
7
7
 
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py-dbms-cli
3
- Version: 2.0
4
- Summary: A modern, secure, aesthetic and your ultimate DBMS client supporting MySQL and more.
3
+ Version: 2.1.1
4
+ Summary: A modern, secure, aesthetic and your ultimate DBMS client. Implemented as a CLI (Command-Line Interface) tool and written 100% in Python
5
5
  Author-email: Anish Sethi <sethi.dynasty123@gmail.com>
6
6
  License: Copyright 2025 Anish Sethi
7
7
 
@@ -14,4 +14,5 @@ pydbms/cli.py
14
14
  pydbms/config.py
15
15
  pydbms/core.py
16
16
  pydbms/dependencies.py
17
- pydbms/pydbms_mysql.py
17
+ pydbms/pydbms_mysql.py
18
+ pydbms/pydbms_path.py
@@ -0,0 +1,26 @@
1
+ #Global functions and variables used across all/major files
2
+
3
+ from .dependencies import Console, time
4
+ from .config import load_config
5
+
6
+ console=Console()
7
+ config = load_config()
8
+
9
+ def Print(message: str, color_key="WHITE", style="", type=True) -> None:
10
+ COLOR_MAP = {
11
+ "CYAN": "bright_cyan",
12
+ "YELLOW": "bright_yellow",
13
+ "RED": "bright_red",
14
+ "GREEN": "bright_green",
15
+ "WHITE": "white",
16
+ "MAGENTA": "bright_magenta"
17
+ }
18
+ color = COLOR_MAP.get(color_key, "white")
19
+ delay = 0.02069 if type else 0
20
+ for char in message:
21
+ if char == "\n":
22
+ console.print()
23
+ continue
24
+ console.print(char, style=f"{style} {color}", end="")
25
+ time.sleep(delay)
26
+
@@ -0,0 +1,92 @@
1
+ #config options for pydbms
2
+ #NOTE: If config.json file generated by the program is deleted or currpoted, it will restore to defaults.
3
+
4
+ from .pydbms_path import pydbms_path
5
+ from .dependencies import json, os, copy
6
+
7
+ DEFAULT_CONFIG = {
8
+ "config_version": 1,
9
+ "ui": {
10
+ "show_banner": True,
11
+ },
12
+ "mysql": {
13
+ "host": "localhost",
14
+ "port": 3306,
15
+ "user": "root",
16
+ "database": None,
17
+ }
18
+ }
19
+
20
+ def create_config() -> None:
21
+ path = pydbms_path("config.json")
22
+
23
+ if not os.path.exists(path):
24
+ with open(path, "w") as f:
25
+ json.dump(DEFAULT_CONFIG, f, indent=4)
26
+
27
+ def validate_config_types() -> None:
28
+ cfg = load_config()
29
+ changed=False
30
+
31
+ # validate ui.show_banner
32
+ if not isinstance(cfg.get("ui", {}).get("show_banner"), bool):
33
+ cfg.setdefault("ui", {})["show_banner"] = DEFAULT_CONFIG["ui"]["show_banner"]
34
+ changed=True
35
+
36
+ # validate mysql.port
37
+ if not isinstance(cfg.get("mysql", {}).get("port"), int):
38
+ cfg.setdefault("mysql", {})["port"] = DEFAULT_CONFIG["mysql"]["port"]
39
+ changed=True
40
+
41
+ if changed:
42
+ save_config(cfg)
43
+
44
+ return cfg
45
+
46
+ def load_config() -> dict:
47
+ path = pydbms_path("config.json")
48
+
49
+ try:
50
+ with open(path, "r") as f:
51
+ return json.load(f)
52
+ except (FileNotFoundError, json.JSONDecodeError):
53
+ create_config()
54
+ return copy.deepcopy(DEFAULT_CONFIG)
55
+
56
+ def save_config(config: dict) -> None:
57
+ path = pydbms_path("config.json")
58
+
59
+ with open(path, "w") as f:
60
+ json.dump(config, f, indent=4)
61
+
62
+ def parse_query_config(path: str) -> tuple[str, str] | None:
63
+ if "." not in path:
64
+ return None
65
+ section, key = path.split(".", 1)
66
+ return section, key
67
+
68
+ def coerce_value_config(value: str) -> bool | int | float | None | object:
69
+ v = value.lower()
70
+
71
+ if v in {"true", "yes", "on"}:
72
+ return True
73
+ if v in {"false", "no", "off"}:
74
+ return False
75
+ if v.isdigit():
76
+ return int(v)
77
+
78
+ try:
79
+ return float(v)
80
+ except ValueError:
81
+ pass
82
+
83
+ if v == "null" or v == "none":
84
+ return None
85
+
86
+ return value
87
+
88
+ def get_default_value_config(section: str, key: str) -> bool | int | float | None:
89
+ try:
90
+ return DEFAULT_CONFIG[section][key]
91
+ except KeyError:
92
+ return None
@@ -2,16 +2,16 @@
2
2
  PY DBMS — DB client CLI
3
3
  Copyright (C) 2025 Anish Sethi
4
4
  Licensed under - BSD-3-Clause License
5
- Version - 2.0
6
- Release - Experimental
5
+ Version - 2.1.1 #NOTE: v2.1.0 had a bug while uploading to PyPI, hence v2.1.1 has been taken for stable release.
6
+ Release - Stable
7
7
  '''
8
8
 
9
- from .Global import Print, console
10
- from .dependencies import pyfiglet, Text, Table, Align, Rule, Panel, mysql, sys, os
9
+ from .Global import Print, console, config
10
+ from .dependencies import pyfiglet, Text, Table, Align, Rule, Panel, mysql, sys
11
11
  from .pydbms_mysql import execute, execute_change, execute_select, connect, get_query_mysql
12
- from .config import load_config
12
+ from .config import parse_query_config, coerce_value_config, save_config, get_default_value_config, validate_config_types
13
13
 
14
- def print_banner():
14
+ def print_banner() -> None:
15
15
  ascii_art = pyfiglet.figlet_format("PY DBMS", font="slant").rstrip()
16
16
 
17
17
  logo = Text(ascii_art, style="bold color(57)")
@@ -22,7 +22,7 @@ def print_banner():
22
22
  stats_table.add_column("3", justify="center", ratio=1)
23
23
 
24
24
  stats_table.add_row(
25
- "[bold cyan]v2.0[/]\n [bold white]Version[/]",
25
+ "[bold cyan]v2.1.1[/]\n[bold white]Version[/]",
26
26
  "[bold yellow]MySQL[/]\n[bold white]Currently Supported[/]",
27
27
  "[bold green]Online since 2025[/]\n[bold white]Status[/]"
28
28
  )
@@ -56,8 +56,17 @@ def print_banner():
56
56
  )
57
57
  )
58
58
  print('\n\n')
59
+
60
+ def build_section_table(section: dict) -> Table:
61
+ table = Table(show_header=False, box=None)
62
+ table.add_column("", style="white", no_wrap=True)
63
+ table.add_column("", style="dim white")
64
+ for key, value in section.items():
65
+ table.add_row(key, str(value))
59
66
 
60
- def meta(cmd, cur):
67
+ return table
68
+
69
+ def meta(cmd: str, cur: object, con=None) -> None:
61
70
  cmd = cmd.strip()
62
71
 
63
72
  # .help
@@ -71,6 +80,9 @@ def meta(cmd, cur):
71
80
  help_table.add_row(".schema <table>", "Show CREATE TABLE statement for table <table>")
72
81
  help_table.add_row(".clear", "Clear the terminal screen")
73
82
  help_table.add_row(".version", "Show pydbms build information")
83
+ help_table.add_row(".config", "Show config settings for pydbms")
84
+ help_table.add_row(".config set <section>.<key> <value>", "Set config to a new value")
85
+ help_table.add_row(".config reset <section>.<key>", "Reset config to a default value")
74
86
  help_table.add_row(".exit", "Exit pydbms")
75
87
  console.print(help_table)
76
88
  console.print()
@@ -126,9 +138,10 @@ def meta(cmd, cur):
126
138
  info.add_column("", style="dim white")
127
139
 
128
140
  info.add_row("Name", "[link=https://github.com/Anish-Sethi-12122/py-dbms-cli]pydbms Terminal[/link]")
129
- info.add_row("Version", "v2.0")
130
- info.add_row("Build", "Experimental Release")
141
+ info.add_row("Version", "v2.1.1")
142
+ info.add_row("Build", "Stable Release")
131
143
  info.add_row("Python", f"[link=https://www.python.org/]{sys.version.split()[0]}[/link]")
144
+ info.add_row("MySQL", f"[link=https://www.mysql.com/]{con.get_server_info()}[/link]")
132
145
  info.add_row("Author", "[link=https://www.linkedin.com/in/anish-sethi-dtu-cse/]Anish Sethi[/link]")
133
146
  info.add_row("Institution", "B.Tech Computer Science and Engineering @ Delhi Technological University")
134
147
  info.add_row("Licensed under", "[link=https://opensource.org/license/bsd-3-clause]BSD-3-Clause License[/link]")
@@ -143,6 +156,92 @@ def meta(cmd, cur):
143
156
  )
144
157
  console.print()
145
158
  console.print("Run `pip install -U py-dbms-cli` in terminal to check for updates.",style="dim white")
159
+ console.print()
160
+ return
161
+
162
+ # .config
163
+ if cmd == ".config":
164
+ outer = Table(show_header=False, box=None)
165
+ outer.add_column("", style="bold white", no_wrap=True)
166
+ outer.add_column("", style="white")
167
+
168
+ # UI section
169
+ ui_cfg = config.get("ui", {})
170
+ outer.add_row("UI", build_section_table(ui_cfg))
171
+
172
+ outer.add_row("", "")
173
+
174
+ # MySQL section
175
+ mysql_cfg = config.get("mysql", {})
176
+ outer.add_row("MySQL",build_section_table(mysql_cfg))
177
+
178
+ console.print(
179
+ Panel(
180
+ outer,
181
+ title="[bold white]PYSQL Terminal — config settings[/]",
182
+ border_style="bright_magenta",
183
+ padding=(1, 2),
184
+ )
185
+ )
186
+
187
+ console.print()
188
+ return
189
+
190
+ # .config set
191
+ if cmd.startswith(".config set"):
192
+ parts = cmd.split(maxsplit=3)
193
+
194
+ if len(parts) != 4:
195
+ Print("Usage: .config set <section>.<key> <value>", "YELLOW")
196
+ return
197
+
198
+ _, _, path, raw_value = parts
199
+
200
+ parsed = parse_query_config(path)
201
+
202
+ if not parsed:
203
+ Print("Invalid input format. Use <section>.<key>", "RED")
204
+ return
205
+
206
+ section, key = parsed
207
+
208
+ if section not in config or key not in config[section]:
209
+ Print(f"Unknown config key: {path}", "RED")
210
+ return
211
+
212
+ value = coerce_value_config(raw_value)
213
+ config[section][key] = value
214
+ save_config(config)
215
+
216
+ Print(f"Updated {path} → {value}", "GREEN")
217
+ return
218
+
219
+ # .config reset or .config -d or .config --default
220
+ if cmd.startswith(".config reset"):
221
+ parts = cmd.split(maxsplit=2)
222
+
223
+ if len(parts) != 3:
224
+ Print("Usage: .config reset <section>.<key>", "YELLOW")
225
+ return
226
+
227
+ path = parts[2]
228
+ parsed = parse_query_config(path)
229
+
230
+ if not parsed:
231
+ Print("Invalid config key format. Use <section>.<key>", "RED")
232
+ return
233
+
234
+ section, key = parsed
235
+ default = get_default_value_config(section, key)
236
+
237
+ if default is None:
238
+ Print(f"No default value for {path}.", "RED")
239
+ return
240
+
241
+ config[section][key] = default
242
+ save_config(config)
243
+
244
+ Print(f"Reset {path} → {default}", "GREEN")
146
245
  return
147
246
 
148
247
  # .exit
@@ -150,11 +249,12 @@ def meta(cmd, cur):
150
249
  Print("Session Terminated.", "RED", "bold")
151
250
  sys.exit()
152
251
 
153
- print(f"Unknown command: {cmd}\nCheck your manual that corresponds to helper commands.")
154
-
252
+ Print(f"Unknown command: {cmd}\nRefer to `.help` for list of commands", "YELLOW")
253
+
155
254
  def main():
156
- config = load_config()
157
- if config.get("show_banner", True):
255
+ global config
256
+ config = validate_config_types()
257
+ if config["ui"].get("show_banner", True):
158
258
  print_banner()
159
259
 
160
260
  con, cur = connect()
@@ -167,7 +267,7 @@ def main():
167
267
  query=get_query_mysql()
168
268
 
169
269
  if query.strip().startswith("."):
170
- meta(query.strip(), cur)
270
+ meta(query.strip(), cur, con)
171
271
  continue
172
272
 
173
273
  if query.lower().strip()=="exit;":
@@ -15,4 +15,5 @@ from rich.align import Align
15
15
  from rich.rule import Rule
16
16
  import re
17
17
  import os
18
- import json
18
+ import json
19
+ import copy
@@ -1,12 +1,12 @@
1
1
  #Instance MySQL
2
2
 
3
3
  from .dependencies import mysql, pwinput, sys, time, sqlparse, Panel, Table, re, box
4
- from .Global import Print, console
4
+ from .Global import Print, console, config
5
5
 
6
- def connect():
6
+ def connect() -> tuple[object,object] | int:
7
7
  try:
8
- host="localhost"
9
- user="root"
8
+ host=config["mysql"].get("host", "localhost")
9
+ user=config["mysql"].get("user", "root")
10
10
  Print(f"pydbms> Enter host name for MySQL (default value -> {host}):", "YELLOW")
11
11
  host=input()
12
12
  if not host:
@@ -30,7 +30,7 @@ def connect():
30
30
  sys.exit()
31
31
  return -1
32
32
 
33
- def print_warnings(cur):
33
+ def print_warnings(cur: object) -> bool:
34
34
  warnings = cur.fetchwarnings()
35
35
  if warnings:
36
36
  for level, warning_code, warning_msg in warnings:
@@ -39,7 +39,7 @@ def print_warnings(cur):
39
39
  return True
40
40
  return False
41
41
 
42
- def execute_select(query,cur):
42
+ def execute_select(query: str,cur: object) -> None:
43
43
  start = time.time()
44
44
  cur.execute(query)
45
45
  end = time.time()
@@ -85,7 +85,7 @@ def execute_select(query,cur):
85
85
  Print(msg, "YELLOW" if has_warning else "GREEN")
86
86
  console.print()
87
87
 
88
- def execute_change(query,con,cur):
88
+ def execute_change(query: str,con: object,cur: object) -> None:
89
89
  cur.execute(query)
90
90
  affected_row_num=cur.rowcount
91
91
  con.commit()
@@ -100,7 +100,7 @@ def execute_change(query,con,cur):
100
100
  Print(msg, "YELLOW" if has_warning else "GREEN")
101
101
  console.print()
102
102
 
103
- def execute(query,cur):
103
+ def execute(query: str,cur: object) -> None:
104
104
  cur.execute(query)
105
105
 
106
106
  has_warning=print_warnings(cur)
@@ -113,7 +113,7 @@ def execute(query,cur):
113
113
  Print(msg, "YELLOW" if has_warning else "GREEN")
114
114
  console.print()
115
115
 
116
- def get_query_mysql():
116
+ def get_query_mysql() -> object:
117
117
  try:
118
118
  buffer = ""
119
119
  while True:
@@ -132,7 +132,7 @@ def get_query_mysql():
132
132
  console.print()
133
133
  return query
134
134
 
135
- def get_query_title(query):
135
+ def get_query_title(query: str) -> str:
136
136
  q = query.strip().lower()
137
137
 
138
138
  # === Simple SELECT ===
@@ -0,0 +1,16 @@
1
+ from .dependencies import sys, os
2
+
3
+ def pydbms_dir() -> str:
4
+ if sys.platform.startswith("win"):
5
+ base = os.getenv("APPDATA")
6
+ elif sys.platform == "darwin":
7
+ base = os.path.expanduser("~/Library/Application Support")
8
+ else:
9
+ base = os.path.expanduser("~/.local/share")
10
+
11
+ path = os.path.join(base, "pydbms")
12
+ os.makedirs(path, exist_ok=True)
13
+ return path
14
+
15
+ def pydbms_path(*parts) -> str:
16
+ return os.path.join(pydbms_dir(), *parts)
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "py-dbms-cli"
7
- version = "2.0"
8
- description = "A modern, secure, aesthetic and your ultimate DBMS client supporting MySQL and more."
7
+ version = "2.1.1"
8
+ description = "A modern, secure, aesthetic and your ultimate DBMS client. Implemented as a CLI (Command-Line Interface) tool and written 100% in Python"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
11
11
  authors = [
@@ -1,38 +0,0 @@
1
- #Global functions and variables used across all/major files
2
-
3
- from .dependencies import Console, time, sys, os
4
-
5
- console=Console()
6
-
7
- def Print(message, color_key="WHITE", style="", type=True):
8
- COLOR_MAP = {
9
- "CYAN": "bright_cyan",
10
- "YELLOW": "bright_yellow",
11
- "RED": "bright_red",
12
- "GREEN": "bright_green",
13
- "WHITE": "white",
14
- "MAGENTA": "bright_magenta"
15
- }
16
- color = COLOR_MAP.get(color_key, "white")
17
- delay = 0.02069 if type else 0
18
- for char in message:
19
- if char == "\n":
20
- console.print()
21
- continue
22
- console.print(char, style=f"{style} {color}", end="")
23
- time.sleep(delay)
24
-
25
- def pydbms_dir():
26
- if sys.platform.startswith("win"):
27
- base = os.getenv("APPDATA")
28
- elif sys.platform == "darwin":
29
- base = os.path.expanduser("~/Library/Application Support")
30
- else:
31
- base = os.path.expanduser("~/.local/share")
32
-
33
- path = os.path.join(base, "pydbms")
34
- os.makedirs(path, exist_ok=True)
35
- return path
36
-
37
- def pydbms_path(*parts):
38
- return os.path.join(pydbms_dir(), *parts)
@@ -1,31 +0,0 @@
1
- #config options for pydbms
2
-
3
- from .Global import pydbms_path
4
- from .dependencies import json, os
5
-
6
- DEFAULT_CONFIG = {
7
- "show_banner": True
8
- }
9
-
10
- def create_config():
11
- path = pydbms_path("config.json")
12
-
13
- if not os.path.exists(path):
14
- with open(path, "w") as f:
15
- json.dump(DEFAULT_CONFIG, f, indent=4)
16
-
17
- def load_config():
18
- path = pydbms_path("config.json")
19
-
20
- try:
21
- with open(path, "r") as f:
22
- return json.load(f)
23
- except (FileNotFoundError, json.JSONDecodeError):
24
- create_config()
25
- return DEFAULT_CONFIG.copy()
26
-
27
- def save_config(config):
28
- path = pydbms_path("config.json")
29
-
30
- with open(path, "w") as f:
31
- json.dump(config, f, indent=4)
File without changes
File without changes
File without changes
File without changes
File without changes