chemql-python 1.0.0__tar.gz → 1.0.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.
Files changed (24) hide show
  1. {chemql_python-1.0.0 → chemql_python-1.0.1}/PKG-INFO +71 -1
  2. {chemql_python-1.0.0 → chemql_python-1.0.1}/README.md +70 -0
  3. {chemql_python-1.0.0 → chemql_python-1.0.1}/pyproject.toml +1 -1
  4. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql/__init__.py +151 -13
  5. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql_python.egg-info/PKG-INFO +71 -1
  6. {chemql_python-1.0.0 → chemql_python-1.0.1}/LICENSE +0 -0
  7. {chemql_python-1.0.0 → chemql_python-1.0.1}/setup.cfg +0 -0
  8. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql/__main__.py +0 -0
  9. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql/data/BondEnergies.json +0 -0
  10. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql/data/MoleculeBonds.json +0 -0
  11. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql/data/Molecules.json +0 -0
  12. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql/data/PeriodicTableJSON.json +0 -0
  13. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql/data/Reactions.json +0 -0
  14. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql/data/THIRD_PARTY_LICENSES/PeriodicTableJSON.txt +0 -0
  15. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql/data/THIRD_PARTY_LICENSES/RHEA.txt +0 -0
  16. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql/html/periodic_table.html +0 -0
  17. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql_python.egg-info/SOURCES.txt +0 -0
  18. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql_python.egg-info/dependency_links.txt +0 -0
  19. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql_python.egg-info/entry_points.txt +0 -0
  20. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql_python.egg-info/requires.txt +0 -0
  21. {chemql_python-1.0.0 → chemql_python-1.0.1}/src/chemql_python.egg-info/top_level.txt +0 -0
  22. {chemql_python-1.0.0 → chemql_python-1.0.1}/tests/test_external_molecule_lookup.py +0 -0
  23. {chemql_python-1.0.0 → chemql_python-1.0.1}/tests/test_public_api.py +0 -0
  24. {chemql_python-1.0.0 → chemql_python-1.0.1}/tests/test_reactions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chemql-python
3
- Version: 1.0.0
3
+ Version: 1.0.1
4
4
  Summary: A chemistry-focused query language and REPL
5
5
  Author-email: Mohammad Rakibul Islam <rakibulofficial1017@gmail.com>
6
6
  Requires-Python: >=3.10
@@ -48,6 +48,25 @@ Install the Python package from PyPI:
48
48
  pip install chemql-python
49
49
  ```
50
50
 
51
+ ## Upgrading the package or switching versions
52
+
53
+ If your chemql-python version is >=1.0.1, you can simply run
54
+ ```bash
55
+ chemql --upgrade
56
+ ```
57
+ Or to switch versions to for example 0.2.2
58
+ ```bash
59
+ chemql --upgrade 0.2.2
60
+ ```
61
+ However if you do not have chemql-python version >=1.0.1
62
+ ```bash
63
+ pip install --upgrade chemql-python
64
+ ```
65
+ Or to switch versions to for example 0.2.2
66
+ ```bash
67
+ pip install --force-reinstall chemql-python==0.2.2
68
+ ```
69
+
51
70
  ## Quick start
52
71
 
53
72
  Start the interactive terminal:
@@ -337,6 +356,57 @@ Python:
337
356
 
338
357
  Only run Python code and shell commands from sources you trust.
339
358
 
359
+ ## Shell Commands
360
+
361
+ ChemQL supports executing system shell commands by enclosing them in backticks (`` ` ``). Commands execute in a **persistent shell session**, allowing shell state to be preserved between commands.
362
+
363
+ **Syntax**
364
+
365
+ ```chemql
366
+ `command`
367
+ ```
368
+
369
+ **Examples**
370
+
371
+ Execute system commands:
372
+
373
+ ```chemql
374
+ `whoami`
375
+ `dir`
376
+ `echo Hello`
377
+ ```
378
+
379
+ Change the working directory:
380
+
381
+ ```chemql
382
+ `cd ..`
383
+ `cd ~`
384
+ `dir`
385
+ ```
386
+
387
+ The working directory persists between commands.
388
+
389
+ Environment variables and other shell state can also persist between commands, depending on the shell being used.
390
+
391
+ **Platform support**
392
+
393
+ - **Linux:** Bash
394
+ - **macOS:** Bash
395
+ - **Windows:** Command Prompt (`cmd.exe`)
396
+
397
+ PowerShell is not supported by the current implementation.
398
+
399
+ **How it works**
400
+
401
+ ChemQL maintains a persistent shell process and sends commands to it sequentially. Command output is captured and displayed in the ChemQL interface, allowing shell state to persist throughout the session.
402
+
403
+ **Notes**
404
+
405
+ - Commands must be enclosed in backticks to be interpreted as shell commands rather than ChemQL statements.
406
+ - Shell syntax differs between operating systems. Use commands appropriate for your platform.
407
+ - Commands run with the permissions of the process running ChemQL and may modify files or affect your system.
408
+ - Interactive terminal programs and commands requiring direct terminal input may not work correctly because the shell uses pipes rather than a real terminal.
409
+
340
410
  ## Data and external services
341
411
 
342
412
  ChemQL loads bundled JSON datasets for elements, molecules, reactions,
@@ -35,6 +35,25 @@ Install the Python package from PyPI:
35
35
  pip install chemql-python
36
36
  ```
37
37
 
38
+ ## Upgrading the package or switching versions
39
+
40
+ If your chemql-python version is >=1.0.1, you can simply run
41
+ ```bash
42
+ chemql --upgrade
43
+ ```
44
+ Or to switch versions to for example 0.2.2
45
+ ```bash
46
+ chemql --upgrade 0.2.2
47
+ ```
48
+ However if you do not have chemql-python version >=1.0.1
49
+ ```bash
50
+ pip install --upgrade chemql-python
51
+ ```
52
+ Or to switch versions to for example 0.2.2
53
+ ```bash
54
+ pip install --force-reinstall chemql-python==0.2.2
55
+ ```
56
+
38
57
  ## Quick start
39
58
 
40
59
  Start the interactive terminal:
@@ -324,6 +343,57 @@ Python:
324
343
 
325
344
  Only run Python code and shell commands from sources you trust.
326
345
 
346
+ ## Shell Commands
347
+
348
+ ChemQL supports executing system shell commands by enclosing them in backticks (`` ` ``). Commands execute in a **persistent shell session**, allowing shell state to be preserved between commands.
349
+
350
+ **Syntax**
351
+
352
+ ```chemql
353
+ `command`
354
+ ```
355
+
356
+ **Examples**
357
+
358
+ Execute system commands:
359
+
360
+ ```chemql
361
+ `whoami`
362
+ `dir`
363
+ `echo Hello`
364
+ ```
365
+
366
+ Change the working directory:
367
+
368
+ ```chemql
369
+ `cd ..`
370
+ `cd ~`
371
+ `dir`
372
+ ```
373
+
374
+ The working directory persists between commands.
375
+
376
+ Environment variables and other shell state can also persist between commands, depending on the shell being used.
377
+
378
+ **Platform support**
379
+
380
+ - **Linux:** Bash
381
+ - **macOS:** Bash
382
+ - **Windows:** Command Prompt (`cmd.exe`)
383
+
384
+ PowerShell is not supported by the current implementation.
385
+
386
+ **How it works**
387
+
388
+ ChemQL maintains a persistent shell process and sends commands to it sequentially. Command output is captured and displayed in the ChemQL interface, allowing shell state to persist throughout the session.
389
+
390
+ **Notes**
391
+
392
+ - Commands must be enclosed in backticks to be interpreted as shell commands rather than ChemQL statements.
393
+ - Shell syntax differs between operating systems. Use commands appropriate for your platform.
394
+ - Commands run with the permissions of the process running ChemQL and may modify files or affect your system.
395
+ - Interactive terminal programs and commands requiring direct terminal input may not work correctly because the shell uses pipes rather than a real terminal.
396
+
327
397
  ## Data and external services
328
398
 
329
399
  ChemQL loads bundled JSON datasets for elements, molecules, reactions,
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "chemql-python"
7
- version = "1.0.0"
7
+ version = "1.0.1"
8
8
  authors = [
9
9
  { name = "Mohammad Rakibul Islam", email = "rakibulofficial1017@gmail.com" }
10
10
  ]
@@ -10,6 +10,8 @@ import sys
10
10
  from pathlib import Path
11
11
  from prompt_toolkit import PromptSession
12
12
  from prompt_toolkit.lexers import Lexer
13
+ import atexit
14
+ import uuid
13
15
  from prompt_toolkit.styles import Style
14
16
  from prompt_toolkit.completion import Completer, Completion
15
17
  import urllib.parse
@@ -37,6 +39,84 @@ __all__ = [
37
39
  ]
38
40
 
39
41
 
42
+
43
+ _shell_process = None
44
+
45
+
46
+ def get_shell():
47
+ """Start Bash once and reuse the same session."""
48
+ global _shell_process
49
+
50
+ if _shell_process is None or _shell_process.poll() is not None:
51
+ _shell_process = subprocess.Popen(
52
+ ["bash", "--noprofile", "--norc"],
53
+ stdin=subprocess.PIPE,
54
+ stdout=subprocess.PIPE,
55
+ stderr=subprocess.STDOUT,
56
+ text=True,
57
+ bufsize=1,
58
+ )
59
+
60
+ return _shell_process
61
+
62
+
63
+ def run_shell_command(command):
64
+ """Run a command in the persistent Bash session."""
65
+ shell = get_shell()
66
+ marker = f"__CHEMQL_END_{uuid.uuid4().hex}__"
67
+
68
+ try:
69
+ shell.stdin.write(command + "\n") #type:ignore
70
+ shell.stdin.write( #type:ignore
71
+ f"printf '\\n%s:%s\\n' '{marker}' \"$?\"\n"
72
+ )
73
+ shell.stdin.flush() #type:ignore
74
+
75
+ output = []
76
+ exit_code = None
77
+
78
+ while True:
79
+ line = shell.stdout.readline() #type:ignore
80
+
81
+ if not line:
82
+ break
83
+
84
+ line = line.rstrip("\n")
85
+
86
+ if line.startswith(marker + ":"):
87
+ exit_code = int(line[len(marker) + 1:])
88
+ break
89
+
90
+ output.append(line)
91
+
92
+ result = "\n".join(output)
93
+
94
+ if exit_code is None:
95
+ return result or "Shell session terminated."
96
+
97
+ if exit_code != 0 and not result:
98
+ return f"Command exited with status {exit_code}"
99
+
100
+ return result
101
+
102
+ except (BrokenPipeError, OSError) as exc:
103
+ return f"Shell error: {exc}"
104
+
105
+
106
+ def close_shell():
107
+ """Clean up the persistent shell on exit."""
108
+ global _shell_process
109
+
110
+ if _shell_process is not None:
111
+ if _shell_process.poll() is None:
112
+ _shell_process.terminate()
113
+ _shell_process.wait(timeout=2)
114
+
115
+ _shell_process = None
116
+
117
+
118
+ atexit.register(close_shell)
119
+
40
120
  class Unknown:
41
121
  """Represents a Chemql query result that cannot be resolved to a known object."""
42
122
 
@@ -1623,7 +1703,7 @@ def _space_query_operators(text):
1623
1703
  out.append(ch)
1624
1704
  if escaped:
1625
1705
  escaped = False
1626
- elif ch == "\\\\":
1706
+ elif ch == "\\":
1627
1707
  escaped = True
1628
1708
  elif ch == quote:
1629
1709
  quote = None
@@ -1666,7 +1746,7 @@ def _split_set_operations(text):
1666
1746
  ch = text[j]
1667
1747
  if quote:
1668
1748
  if escaped: escaped = False
1669
- elif ch == "\\\\": escaped = True
1749
+ elif ch == "\\": escaped = True
1670
1750
  elif ch == quote: quote = None
1671
1751
  elif ch in ("'", '"'): quote = ch
1672
1752
  elif ch == "(": depth += 1
@@ -2097,16 +2177,11 @@ def process_inline(text):
2097
2177
  if not stripped[end + 2:].strip():
2098
2178
  return execute_query_block(stripped[2:end].strip())
2099
2179
 
2100
- # Backtick-wrapped commands execute through subprocess (not deprecated os.system).
2180
+ # Backtick-wrapped commands use the persistent Bash session.
2101
2181
  if len(stripped) >= 2 and stripped.startswith("`") and stripped.endswith("`"):
2102
2182
  command = stripped[1:-1]
2103
- completed = subprocess.run(command, shell=True, text=True, capture_output=True)
2104
- output = completed.stdout
2105
- if completed.stderr:
2106
- output += completed.stderr
2107
- if completed.returncode and not output:
2108
- output = f"Command exited with status {completed.returncode}"
2109
- return output.rstrip("\\n")
2183
+ return run_shell_command(command)
2184
+
2110
2185
 
2111
2186
  # Everything else is query language.
2112
2187
  return execute_query_text(stripped)
@@ -3433,6 +3508,54 @@ def intersection(x, y):
3433
3508
  raise TypeError("intersection() expects two ChemQLQuery objects")
3434
3509
  return x & y
3435
3510
 
3511
+ PACKAGE_NAME = "chemql-python"
3512
+
3513
+ def upgrade_package(version=None):
3514
+ """Upgrade ChemQL, optionally to a specific version."""
3515
+
3516
+ if version is not None:
3517
+ # Accept ordinary numeric release versions, optionally with
3518
+ # prerelease or post-release suffixes.
3519
+ if not re.fullmatch(
3520
+ r"\d+(?:\.\d+)*(?:(?:a|b|rc)\d+)?(?:\.post\d+)?(?:\.dev\d+)?",
3521
+ version,
3522
+ re.IGNORECASE,
3523
+ ):
3524
+ print(f"Invalid version: {version}", file=sys.stderr)
3525
+ return 2
3526
+
3527
+ target = f"{PACKAGE_NAME}=={version}"
3528
+ print(f"Installing {target}...")
3529
+ cmd = [
3530
+ sys.executable, "-m", "pip", "install",
3531
+ "--force-reinstall", target,
3532
+ ]
3533
+ else:
3534
+ print(f"Upgrading {PACKAGE_NAME} to the latest version...")
3535
+ cmd = [
3536
+ sys.executable, "-m", "pip", "install",
3537
+ "--upgrade", PACKAGE_NAME,
3538
+ ]
3539
+
3540
+ try:
3541
+ result = subprocess.run(cmd, check=False)
3542
+ if result.returncode != 0:
3543
+ print(
3544
+ f"Installation failed (exit code {result.returncode}).",
3545
+ file=sys.stderr,
3546
+ )
3547
+ return result.returncode
3548
+
3549
+ except KeyboardInterrupt:
3550
+ print("\nUpgrade cancelled.", file=sys.stderr)
3551
+ return 130
3552
+ except OSError as exc:
3553
+ print(f"Could not run pip: {exc}", file=sys.stderr)
3554
+ return 1
3555
+
3556
+ print("ChemQL installation completed.")
3557
+ return 0
3558
+
3436
3559
 
3437
3560
  ChemQLQuery.__name__ = "ChemQLQuery"
3438
3561
  ChemQLQuery.__qualname__ = "ChemQLQuery"
@@ -3459,13 +3582,28 @@ def main():
3459
3582
  "-v",
3460
3583
  "--version",
3461
3584
  action="version",
3462
- version="1.0.0",
3585
+ version="1.0.1",
3463
3586
  )
3464
3587
 
3588
+
3589
+ parser.add_argument(
3590
+ "--upgrade",
3591
+ nargs="?",
3592
+ const="latest",
3593
+ default=None,
3594
+ metavar="VERSION",
3595
+ help="Upgrade ChemQL, optionally to a specific version.",
3596
+ )
3597
+
3598
+
3465
3599
  args = parser.parse_args()
3466
3600
 
3467
- if args.command:
3468
- process_lines(args.command.splitlines())
3601
+ if args.upgrade is not None:
3602
+ version_target = (
3603
+ None if args.upgrade == "latest" else args.upgrade
3604
+ )
3605
+ sys.exit(upgrade_package(version_target))
3606
+
3469
3607
 
3470
3608
  elif args.file:
3471
3609
  with open(args.file) as f:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chemql-python
3
- Version: 1.0.0
3
+ Version: 1.0.1
4
4
  Summary: A chemistry-focused query language and REPL
5
5
  Author-email: Mohammad Rakibul Islam <rakibulofficial1017@gmail.com>
6
6
  Requires-Python: >=3.10
@@ -48,6 +48,25 @@ Install the Python package from PyPI:
48
48
  pip install chemql-python
49
49
  ```
50
50
 
51
+ ## Upgrading the package or switching versions
52
+
53
+ If your chemql-python version is >=1.0.1, you can simply run
54
+ ```bash
55
+ chemql --upgrade
56
+ ```
57
+ Or to switch versions to for example 0.2.2
58
+ ```bash
59
+ chemql --upgrade 0.2.2
60
+ ```
61
+ However if you do not have chemql-python version >=1.0.1
62
+ ```bash
63
+ pip install --upgrade chemql-python
64
+ ```
65
+ Or to switch versions to for example 0.2.2
66
+ ```bash
67
+ pip install --force-reinstall chemql-python==0.2.2
68
+ ```
69
+
51
70
  ## Quick start
52
71
 
53
72
  Start the interactive terminal:
@@ -337,6 +356,57 @@ Python:
337
356
 
338
357
  Only run Python code and shell commands from sources you trust.
339
358
 
359
+ ## Shell Commands
360
+
361
+ ChemQL supports executing system shell commands by enclosing them in backticks (`` ` ``). Commands execute in a **persistent shell session**, allowing shell state to be preserved between commands.
362
+
363
+ **Syntax**
364
+
365
+ ```chemql
366
+ `command`
367
+ ```
368
+
369
+ **Examples**
370
+
371
+ Execute system commands:
372
+
373
+ ```chemql
374
+ `whoami`
375
+ `dir`
376
+ `echo Hello`
377
+ ```
378
+
379
+ Change the working directory:
380
+
381
+ ```chemql
382
+ `cd ..`
383
+ `cd ~`
384
+ `dir`
385
+ ```
386
+
387
+ The working directory persists between commands.
388
+
389
+ Environment variables and other shell state can also persist between commands, depending on the shell being used.
390
+
391
+ **Platform support**
392
+
393
+ - **Linux:** Bash
394
+ - **macOS:** Bash
395
+ - **Windows:** Command Prompt (`cmd.exe`)
396
+
397
+ PowerShell is not supported by the current implementation.
398
+
399
+ **How it works**
400
+
401
+ ChemQL maintains a persistent shell process and sends commands to it sequentially. Command output is captured and displayed in the ChemQL interface, allowing shell state to persist throughout the session.
402
+
403
+ **Notes**
404
+
405
+ - Commands must be enclosed in backticks to be interpreted as shell commands rather than ChemQL statements.
406
+ - Shell syntax differs between operating systems. Use commands appropriate for your platform.
407
+ - Commands run with the permissions of the process running ChemQL and may modify files or affect your system.
408
+ - Interactive terminal programs and commands requiring direct terminal input may not work correctly because the shell uses pipes rather than a real terminal.
409
+
340
410
  ## Data and external services
341
411
 
342
412
  ChemQL loads bundled JSON datasets for elements, molecules, reactions,
File without changes
File without changes