chemql-python 1.0.3__tar.gz → 1.2.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.
Files changed (27) hide show
  1. chemql_python-1.2.0/PKG-INFO +1067 -0
  2. chemql_python-1.2.0/README.md +1054 -0
  3. {chemql_python-1.0.3 → chemql_python-1.2.0}/pyproject.toml +1 -1
  4. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql/__init__.py +1169 -619
  5. chemql_python-1.2.0/src/chemql_python.egg-info/PKG-INFO +1067 -0
  6. chemql_python-1.0.3/PKG-INFO +0 -443
  7. chemql_python-1.0.3/README.md +0 -430
  8. chemql_python-1.0.3/src/chemql_python.egg-info/PKG-INFO +0 -443
  9. {chemql_python-1.0.3 → chemql_python-1.2.0}/LICENSE +0 -0
  10. {chemql_python-1.0.3 → chemql_python-1.2.0}/setup.cfg +0 -0
  11. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql/__main__.py +0 -0
  12. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql/data/BondEnergies.json +0 -0
  13. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql/data/MoleculeBonds.json +0 -0
  14. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql/data/Molecules.json +0 -0
  15. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql/data/PeriodicTableJSON.json +0 -0
  16. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql/data/Reactions.json +0 -0
  17. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql/data/THIRD_PARTY_LICENSES/PeriodicTableJSON.txt +0 -0
  18. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql/data/THIRD_PARTY_LICENSES/RHEA.txt +0 -0
  19. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql/html/periodic_table.html +0 -0
  20. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql_python.egg-info/SOURCES.txt +0 -0
  21. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql_python.egg-info/dependency_links.txt +0 -0
  22. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql_python.egg-info/entry_points.txt +0 -0
  23. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql_python.egg-info/requires.txt +0 -0
  24. {chemql_python-1.0.3 → chemql_python-1.2.0}/src/chemql_python.egg-info/top_level.txt +0 -0
  25. {chemql_python-1.0.3 → chemql_python-1.2.0}/tests/test_external_molecule_lookup.py +0 -0
  26. {chemql_python-1.0.3 → chemql_python-1.2.0}/tests/test_public_api.py +0 -0
  27. {chemql_python-1.0.3 → chemql_python-1.2.0}/tests/test_reactions.py +0 -0
@@ -0,0 +1,1067 @@
1
+ Metadata-Version: 2.4
2
+ Name: chemql-python
3
+ Version: 1.2.0
4
+ Summary: A chemistry-focused query language and REPL
5
+ Author-email: Mohammad Rakibul Islam <rakibulofficial1017@gmail.com>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: prompt_toolkit>=3.0
10
+ Provides-Extra: test
11
+ Requires-Dist: pytest>=8.0; extra == "test"
12
+ Dynamic: license-file
13
+
14
+ # ChemQL --- Chemistry Query Language
15
+
16
+ **Query chemistry like a database. Mix chemistry queries, Python, and
17
+ shell commands in one interactive environment.**
18
+
19
+ ChemQL is a command-line chemistry query language for exploring chemical
20
+ elements, molecules, and reactions. Version 1.2.0 combines database-style
21
+ chemistry queries, reaction tools, Python interoperability, reusable functions
22
+ and macros, and a persistent shell in one scriptable environment. It combines a small SQL-inspired
23
+ query syntax with a persistent Python environment, reaction utilities,
24
+ optional external molecule lookup, and tools for running repeatable
25
+ scripts.
26
+
27
+ > **Version covered by this README:** 1.2.0\
28
+ > The examples below describe the ChemQL 1.2.0 source. Dataset
29
+ > contents and external-service availability can affect individual
30
+ > lookup results.
31
+
32
+ ## Contents
33
+
34
+ - [Highlights](#highlights)
35
+ - [Installation](#installation)
36
+ - [Starting ChemQL](#starting-chemql)
37
+ - [Your first queries](#your-first-queries)
38
+ - [Sources and data fields](#sources-and-data-fields)
39
+ - [Filtering and query logic](#filtering-and-query-logic)
40
+ - [Sorting, limiting, counting, and returning
41
+ fields](#sorting-limiting-counting-and-returning-fields)
42
+ - [Quick lookup commands](#quick-lookup-commands)
43
+ - [Molecules from external chemistry
44
+ sources](#molecules-from-external-chemistry-sources)
45
+ - [Chemical reactions](#chemical-reactions)
46
+ - [Balancing equations](#balancing-equations)
47
+ - [Preprocessor, functions, and macros](#preprocessor-functions-and-macros)
48
+ - [Mixing ChemQL with Python](#mixing-chemql-with-python)
49
+ - [Multiline Python blocks](#multiline-python-blocks)
50
+ - [Running shell commands](#running-shell-commands)
51
+ - [Comments, semicolons, and line
52
+ continuation](#comments-semicolons-and-line-continuation)
53
+ - [Scripts, pipes, and output files](#scripts-pipes-and-output-files)
54
+ - [Session history and exports](#session-history-and-exports)
55
+ - [Terminal experience](#terminal-experience)
56
+ - [Python API](#python-api)
57
+ - [Query syntax reference](#query-syntax-reference)
58
+ - [Examples](#examples)
59
+ - [Troubleshooting](#troubleshooting)
60
+
61
+ ## Highlights
62
+
63
+ - **Three queryable chemistry sources:** `elements`, `molecules`, and
64
+ `reactions`.
65
+ - **Database-style filtering:** equality, inequality, numeric
66
+ comparisons, pattern matching, containment, and grouped Boolean
67
+ logic.
68
+ - **Useful result operations:** choose the first or last match, sort
69
+ ascending or descending, limit results, count matches, and project
70
+ selected fields.
71
+ - **Readable results:** one selected field returns a list; multiple
72
+ fields are formatted as a column-aligned table.
73
+ - **Quick lookups:** find elements by name or symbol, molecules by
74
+ name or formula, and reactions by name, identifier, or equation.
75
+ - **External molecule lookup:** ChemQL can try local data first and
76
+ then use online chemistry services, including PubChem and the NIST
77
+ Chemistry WebBook, when available.
78
+ - **Reaction exploration:** search reaction records and match
79
+ reactants against the current reaction conditions and catalysts.
80
+ - **Equation balancing:** balance reaction equations with smallest
81
+ positive integer coefficients.
82
+ - **Reaction conditions:** configure temperature, pressure, and
83
+ catalysts before running reaction matching.
84
+ - **Hybrid Python:** execute Python expressions and statements, retain
85
+ variables between commands, and embed ChemQL query results directly
86
+ inside Python.
87
+ - **Preprocessor definitions:** define reusable literal values with `define`
88
+ and `@NAME` references.
89
+ - **User-defined functions:** define reusable Python-backed functions with
90
+ positional arguments and return values.
91
+ - **Source-generating macros:** define reusable ChemQL command sequences
92
+ and expand them with arguments.
93
+ - **Python control flow:** use `if`/`elif`/`else`, `for`, `while`,
94
+ `break`, and `continue` blocks.
95
+ - **Multiline Python:** use `[[[` ... `]]]` for a single multiline
96
+ Python block.
97
+ - **Integrated shell:** execute commands in a persistent Bash or
98
+ Windows Command Prompt session using backticks or fenced terminal
99
+ blocks.
100
+ - **Comments and convenient command composition:** use `//` comments,
101
+ `///` multiline comments, semicolon-separated commands, and
102
+ backslash line continuation.
103
+ - **Interactive assistance:** syntax highlighting, command completion,
104
+ built-in help, and a browser-based periodic-table viewer.
105
+ - **Scriptable CLI:** run a command, run a file, pipe input through
106
+ standard input, disable ANSI escape sequences, or save clean output
107
+ to a file.
108
+ - **Execution-history exports:** save all, successful, or failed
109
+ queries and results.
110
+ - **Python integration:** import the query API and build queries
111
+ programmatically.
112
+ - **Upgrade helper:** request the latest release or a particular
113
+ version from the CLI.
114
+
115
+ ## Installation
116
+
117
+ Install the Python package from PyPI:
118
+
119
+ ``` bash
120
+ pip install chemql-python
121
+ ```
122
+
123
+ ## Upgrading the package or switching versions
124
+
125
+ If your chemql-python version is >=1.0.1, you can simply run
126
+ ```bash
127
+ chemql --upgrade
128
+ ```
129
+ Or to switch versions to for example 0.2.2
130
+ ```bash
131
+ chemql --upgrade 0.2.2
132
+ ```
133
+ However if you do not have chemql-python version >=1.0.1
134
+ ```bash
135
+ pip install --upgrade chemql-python
136
+ ```
137
+ Or to switch versions to for example 0.2.2
138
+ ```bash
139
+ pip install --force-reinstall chemql-python==0.2.2
140
+ ```
141
+ If your chemql-python version is >=1.1.0, and the terminal respond with something like "This environment is externally managed" then you can run
142
+ ```bash
143
+ chemql --upgrade --force
144
+ ```
145
+ OR
146
+ ```bash
147
+ chemql --upgrade --dangerously
148
+ ```
149
+ Else
150
+ ```bash
151
+ pip install --upgrade chemql-python --break-system-packages
152
+ ```
153
+
154
+ However, this is highly discouraged and creating a venv using `python -m venv .` and activating it with `source .venv/bin/activate` on MacOS/Linux or `.\.venv\Scripts\Activate.ps1`
155
+
156
+ ## Starting ChemQL
157
+
158
+ Start the interactive prompt:
159
+
160
+ ``` bash
161
+ chemql
162
+ ```
163
+
164
+ At the prompt, type `help` or `?` to see the built-in command reference.
165
+ Type `exit` or press `Ctrl+C` to leave.
166
+
167
+ Check the installed version:
168
+
169
+ ``` bash
170
+ chemql --version
171
+ ```
172
+
173
+ You can also use the language as a one-off command:
174
+
175
+ ``` bash
176
+ chemql -c 'search elements name = "Hydrogen"'
177
+ ```
178
+
179
+ ## Your first queries
180
+
181
+ ChemQL has three main sources. Specify the source in a query:
182
+
183
+ ``` text
184
+ search elements
185
+ search molecules
186
+ search reactions
187
+ ```
188
+
189
+ A source can be selected for subsequent searches:
190
+
191
+ ``` text
192
+ source elements
193
+ search name = "Hydrogen"
194
+ search number = 1
195
+ ```
196
+
197
+ You can always state a source explicitly:
198
+
199
+ ``` text
200
+ search elements name = "Hydrogen"
201
+ search molecules formula = "H2O"
202
+ search reactions reaction_type = "combustion"
203
+ ```
204
+
205
+ To list the available fields for the active source---or the fields
206
+ across all sources when no source is selected---use:
207
+
208
+ ``` text
209
+ list all
210
+ ```
211
+
212
+ ## Sources and data fields
213
+
214
+ ChemQL ships with local JSON datasets for its chemistry sources. Exact
215
+ records and fields depend on the bundled dataset version.
216
+
217
+ ### Elements
218
+
219
+ The element records include fields such as:
220
+
221
+ `name`, `symbol`, `number`, `atomic_mass`, `appearance`, `category`,
222
+ `phase`, `density`, `melt`, `boil`, `molar_heat`, `period`, `group`,
223
+ `block`, `shells`, `electron_configuration`,
224
+ `electron_configuration_semantic`, `electron_affinity`,
225
+ `electronegativity_pauling`, `ionization_energies`, `discovered_by`,
226
+ `named_by`, `summary`, `source`, `image`, `bohr_model_image`,
227
+ `bohr_model_3d`, `spectral_img`, `xpos`, `ypos`, `wxpos`, `wypos`, and
228
+ `cpk-hex`.
229
+
230
+ Example:
231
+
232
+ ``` text
233
+ search elements symbol = "Fe" return name symbol number atomic_mass
234
+ search elements phase = "Gas" return name symbol
235
+ search elements electronegativity_pauling > 3 return name symbol electronegativity_pauling
236
+ ```
237
+
238
+ The element `number` field is the atomic number.
239
+
240
+ ### Molecules
241
+
242
+ Molecule records include:
243
+
244
+ `name`, `formula`, `elements`, `molecular_weight`, `iupac_name`,
245
+ `smiles`, `cid`, `melting_point`, `boiling_point`, `density`, `state`,
246
+ `bonds`, and `total_bond_energy`.
247
+
248
+ Example:
249
+
250
+ ``` text
251
+ search molecules formula = "H2O"
252
+ search molecules molecular_weight < 50 return name formula molecular_weight
253
+ search molecules state = "Liquid" return name formula
254
+ ```
255
+
256
+ Bond information and calculated total bond energy are available when
257
+ present in the bundled bond datasets.
258
+
259
+ ### Reactions
260
+
261
+ Reaction records include:
262
+
263
+ `id`, `name`, `equation`, `reaction_type`, `reversible`, `reactants`,
264
+ `products`, `conditions`, `notes`, and `source`.
265
+
266
+ Example:
267
+
268
+ ``` text
269
+ search reactions reaction_type = "combustion"
270
+ search reactions reversible = true return name equation
271
+ search reactions name like "*Haber*" return name equation source
272
+ ```
273
+
274
+ ## Filtering and query logic
275
+
276
+ ChemQL supports the following comparison and matching operators:
277
+
278
+ -------------------------------------------------------------------------------------------
279
+ Operator Meaning Example
280
+ ----------------------- ----------------------- -------------------------------------------
281
+ `=` Equal `search elements symbol = "O"`
282
+
283
+ `!=` Not equal `search elements phase != "Gas"`
284
+
285
+ `>` Greater than `search molecules molecular_weight > 100`
286
+
287
+ `<` Less than `search elements number < 10`
288
+
289
+ `>=` Greater than or equal `search elements number >= 90`
290
+
291
+ `<=` Less than or equal `search molecules molecular_weight <= 20`
292
+
293
+ `like` Case-insensitive `search molecules name like "*water*"`
294
+ wildcard pattern
295
+
296
+ `like!` Case-sensitive wildcard `search elements name like! "Hydrogen"`
297
+ pattern
298
+
299
+ `likep` Pattern matching with `search molecules formula likep "*H*"`
300
+ the parser's pattern
301
+ mode
302
+
303
+ `has` Check whether a value `search molecules elements has "O"`
304
+ contains an item
305
+ -------------------------------------------------------------------------------------------
306
+
307
+ Use `and` and `or` to combine conditions:
308
+
309
+ ``` text
310
+ search elements number > 10 and number < 20
311
+ search molecules name like "*acid*" or name like "*base*"
312
+ ```
313
+
314
+ Parentheses let you group conditions:
315
+
316
+ ``` text
317
+ search molecules (name like "*water*" or formula = "H2O") and molecular_weight < 25
318
+ ```
319
+
320
+ Patterns are useful when you only know part of a name or formula. For
321
+ exact supported pattern behavior, try a query against the local dataset
322
+ and inspect the results.
323
+
324
+ ## Sorting, limiting, counting, and returning fields
325
+
326
+ These operations can be added to a search query.
327
+
328
+ ### Sort
329
+
330
+ ``` text
331
+ search elements sort number
332
+ search molecules sort molecular_weight desc
333
+ search reactions sort name asc
334
+ ```
335
+
336
+ Use `asc` for ascending or `desc` for descending order.
337
+
338
+ ### Limit
339
+
340
+ ``` text
341
+ search molecules limit 10
342
+ search elements number > 20 sort number limit 5
343
+ ```
344
+
345
+ ### Count
346
+
347
+ ``` text
348
+ search molecules count
349
+ search reactions reversible = true count
350
+ ```
351
+
352
+ ### First and last
353
+
354
+ ``` text
355
+ search elements first number > 10
356
+ search elements last number < 20
357
+ ```
358
+
359
+ You can also put `first` or `last` immediately after `search`:
360
+
361
+ ``` text
362
+ search first elements number > 10
363
+ search last molecules molecular_weight < 100
364
+ ```
365
+
366
+ ### Return only selected fields
367
+
368
+ A single field returns a one-dimensional list. Multiple fields return a
369
+ table.
370
+
371
+ ``` text
372
+ search molecules molecular_weight < 20 return name
373
+ search molecules molecular_weight < 20 return name formula molecular_weight
374
+ search reactions reversible = true return name equation source
375
+ ```
376
+
377
+ Filtering and result operations can be combined:
378
+
379
+ ``` text
380
+ search elements number > 10 and number < 30 sort number desc limit 5 return name symbol number
381
+ ```
382
+
383
+ ### Set operations
384
+
385
+ Query results can be combined using `union` or `intersection`:
386
+
387
+ ``` text
388
+ search elements number < 10 union search elements number > 90
389
+ search molecules name like "*water*" intersection search molecules molecular_weight < 50
390
+ ```
391
+
392
+ These operations are useful when you want to combine or compare result
393
+ sets.
394
+
395
+ ## Quick lookup commands
396
+
397
+ ### Find an element
398
+
399
+ ``` text
400
+ findel "He"
401
+ findel "Hydrogen"
402
+ ```
403
+
404
+ `findel` searches element names and symbols.
405
+
406
+ ### Find a molecule
407
+
408
+ ``` text
409
+ findmol "H2O"
410
+ findmol "Water"
411
+ findmol "Caffeine" return name formula molecular_weight
412
+ ```
413
+
414
+ `findmol` checks the local molecule dataset first, then can try external
415
+ lookup if no local match is found.
416
+
417
+ ### Find a reaction
418
+
419
+ ``` text
420
+ findre "Haber process"
421
+ findre "RHEA:10000"
422
+ findre "H2 + N2"
423
+ findre "Haber process" return name equation source
424
+ ```
425
+
426
+ `findre` searches reaction names, identifiers, and equations.
427
+
428
+ ### View the periodic table
429
+
430
+ ``` text
431
+ view
432
+ ```
433
+
434
+ This opens ChemQL's bundled periodic-table page in your default browser.
435
+
436
+ ## Molecules from external chemistry sources
437
+
438
+ When a molecule is not found locally, ChemQL can attempt an online
439
+ lookup using external chemistry services such as **PubChem** and the
440
+ **NIST Chemistry WebBook**.
441
+
442
+ ``` text
443
+ findmol "acetone"
444
+ findmol "caffeine"
445
+ findmol "water"
446
+ ```
447
+
448
+ The lookup code can retrieve or derive properties including molecular
449
+ identifiers and basic chemical data; availability depends on the
450
+ external service, network access, and whether a matching record exists.
451
+ External lookup is not required for ordinary searches against the
452
+ bundled local dataset.
453
+
454
+ ## Chemical reactions
455
+
456
+ ChemQL can search stored reaction records and has commands for setting
457
+ reaction conditions before attempting to match reactants.
458
+
459
+ ### Set temperature
460
+
461
+ Temperature values support Celsius (`C`), Fahrenheit (`F`), and Kelvin
462
+ (`K`):
463
+
464
+ ``` text
465
+ set temperature 450K
466
+ set temperature 150C
467
+ set temperature 300F
468
+ set temperature standard
469
+ set temperature room
470
+ ```
471
+
472
+ `standard` corresponds to 0 °C; `room` corresponds to 25 °C.
473
+
474
+ ### Set pressure
475
+
476
+ Pressure values support Pa, N/m², Nm⁻², bar, and atm, as well as the
477
+ `standard` and `room` presets:
478
+
479
+ ``` text
480
+ set pressure 101325Pa
481
+ set pressure 2bar
482
+ set pressure 1atm
483
+ set pressure standard
484
+ set pressure room
485
+ ```
486
+
487
+ The presets use 100000 Pa for `standard` and 101325 Pa for `room`.
488
+
489
+ ### Configure catalysts
490
+
491
+ ``` text
492
+ set catalysts iron zinc
493
+ add catalyst "Vanadium oxide"
494
+ remove catalyst "Vanadium oxide"
495
+ set catalysts
496
+ ```
497
+
498
+ `set catalysts` with no values clears the catalyst list. `add catalyst`
499
+ adds a catalyst if it is not already present; `remove catalyst` removes
500
+ a matching catalyst.
501
+
502
+ ### Inspect current conditions
503
+
504
+ ``` text
505
+ conditions
506
+ ```
507
+
508
+ Unset temperature or pressure values are shown as not set.
509
+
510
+ ### Match reactants
511
+
512
+ ``` text
513
+ react N2 3H2
514
+ ```
515
+
516
+ `react` attempts to find a matching reaction using the supplied
517
+ reactants and the current reaction conditions. The implementation uses a
518
+ temperature tolerance of 5 K and a pressure tolerance of 5% for reaction
519
+ matching. A match depends on the available reaction records and their
520
+ conditions.
521
+
522
+ ## Balancing equations
523
+
524
+ Use `balance` to balance a chemical equation:
525
+
526
+ ``` text
527
+ balance H2 + O2 -> H2O
528
+ balance Fe + O2 -> Fe2O3
529
+ balance N2 + H2 <-> NH3
530
+ ```
531
+
532
+ - `->` represents an irreversible reaction.
533
+ - `<->` represents a reversible reaction.
534
+ - ChemQL aims to return the smallest positive integer coefficients.
535
+
536
+ The result is represented as a reaction object, which can also be
537
+ queried or inspected from Python.
538
+
539
+ ## Preprocessor, functions, and macros
540
+
541
+ ChemQL 1.2.0 adds three ways to reuse values and logic. These declarations
542
+ are processed in source order: definitions affect later lines, not earlier
543
+ ones. They persist during the current ChemQL process/session; they are not
544
+ saved automatically between separate launches.
545
+
546
+ ### Literal definitions
547
+
548
+ Use `define NAME value` to store a literal replacement. Reference it as
549
+ `@NAME` in later ChemQL commands, Python blocks, or shell commands.
550
+
551
+ ``` text
552
+ define MAX 9
553
+ define ELEMENT "Hydrogen"
554
+ definitions
555
+
556
+ search elements number <= @MAX return name symbol number
557
+ search elements name = @ELEMENT
558
+ remove definition MAX
559
+ ```
560
+
561
+ Definitions are textual replacements, not typed variables. They are
562
+ expanded literally, including inside quoted strings, and a definition's
563
+ replacement text is not recursively expanded in the same pass. `definitions`
564
+ shows active definitions; `remove definition NAME` removes one.
565
+
566
+ ### User-defined functions
567
+
568
+ Declare a function with `func NAME` and finish it with `endfunc`. Use `\1`,
569
+ `\2`, and so on as positional argument placeholders. A `return` line gives
570
+ the function's result; arguments are evaluated as Python expressions.
571
+
572
+ ``` text
573
+ func square
574
+ return [\1 * \1]
575
+ endfunc
576
+
577
+ square{5}
578
+ search molecules molecular_weight < square{5} return name formula molecular_weight
579
+ ```
580
+
581
+ Functions can contain multiple commands and `[[[` multiline Python blocks.
582
+ Function-local Python assignments are restored after the call; return a value
583
+ explicitly when you need one. Function calls use braces, for example
584
+ `name{argument1, argument2}`.
585
+
586
+ ### Macros
587
+
588
+ Macros expand into ChemQL source lines. Declare one using `define NAME{}`
589
+ and close it with `enddefine`. Use `\1`, `\2`, etc. for arguments, then call
590
+ the macro with `@NAME{arguments}`.
591
+
592
+ ``` text
593
+ define light_molecules{}
594
+ search molecules molecular_weight < \1 return name formula molecular_weight
595
+ enddefine
596
+
597
+ @light_molecules{50}
598
+ ```
599
+
600
+ Macros are useful for reusable query recipes or command sequences. Arguments
601
+ are substituted into the macro's source text, so quote or validate values
602
+ appropriately when passing text that contains spaces or special characters.
603
+
604
+ ## Mixing ChemQL with Python
605
+
606
+ ChemQL is a hybrid language: a single-line Python expression or
607
+ statement can be enclosed in square brackets.
608
+
609
+ ``` text
610
+ [x = 10]
611
+ [print(x)]
612
+ [x * 2]
613
+ ```
614
+
615
+ Python variables persist for the session, so later blocks can use values
616
+ created earlier.
617
+
618
+ ``` text
619
+ [import math]
620
+ [radius = 5]
621
+ [area = math.pi * radius**2]
622
+ [print(area)]
623
+ ```
624
+
625
+ Python's built-in namespace is available, and `math` is preloaded.
626
+ **Only run Python or shell code you trust**: these blocks execute real
627
+ code, not a sandboxed query language.
628
+
629
+ ### Embed ChemQL queries in Python
630
+
631
+ Use `{{ ... }}` to run a ChemQL query and insert its result into Python
632
+ code:
633
+
634
+ ``` text
635
+ [hydrogen = {{ search elements name = "Hydrogen" }}]
636
+ [print(hydrogen)]
637
+ ```
638
+
639
+ A query block can also be used on its own as a value-producing
640
+ expression:
641
+
642
+ ``` text
643
+ {{ search molecules molecular_weight < 20 return name formula }}
644
+ ```
645
+
646
+ This is useful when you want ChemQL to find data and Python to
647
+ calculate, transform, or display something using that data.
648
+
649
+ ### Python control-flow blocks
650
+
651
+ ChemQL supports block-style Python control flow:
652
+
653
+ ``` text
654
+ [if value > 10]
655
+ [print("Large")]
656
+ [elif value == 10]
657
+ [print("Exactly ten")]
658
+ [else]
659
+ [print("Small")]
660
+ [endblock]
661
+ ```
662
+
663
+ Loop example:
664
+
665
+ ``` text
666
+ [for element in {{ search elements number < 5 }}]
667
+ [print(element.name, element.symbol)]
668
+ [endblock]
669
+ ```
670
+
671
+ A `while` block is also supported:
672
+
673
+ ``` text
674
+ [i = 0]
675
+ [while i < 3]
676
+ [print(i)]
677
+ [i += 1]
678
+ [endblock]
679
+ ```
680
+
681
+ Use `[break]` and `[continue]` inside loops. As with ordinary Python,
682
+ make sure a `while` loop has a condition that eventually becomes false
683
+ unless you intentionally want it to continue.
684
+
685
+ ### Multiline Python blocks
686
+
687
+ For longer Python code, use `[[[` to start a block and a line containing
688
+ `]]]` to finish it:
689
+
690
+ ``` text
691
+ [[[
692
+ values = {{ search elements number < 10 return name }}
693
+ for value in values:
694
+ print(value)
695
+ ]]]
696
+ ```
697
+
698
+ ChemQL executes the block as one Python unit and captures its printed
699
+ output as one result. Keep the closing `]]]` on its own line.
700
+
701
+ ## Running shell commands
702
+
703
+ ChemQL can run shell commands using backticks. It keeps a shell session
704
+ alive so commands can share shell state.
705
+
706
+ ``` text
707
+ `echo Hello from the shell`
708
+ `pwd`
709
+ ```
710
+
711
+ For a multiline command, use a fenced block. The opening fence can
712
+ optionally name a shell:
713
+
714
+ ```` text
715
+ ```bash
716
+ echo "First line"
717
+ echo "Second line"
718
+ ```
719
+ ````
720
+
721
+ Windows users can use a `cmd` fence:
722
+
723
+ ```` text
724
+ ```cmd
725
+ echo Hello from Windows
726
+ ver
727
+ ```
728
+ ````
729
+
730
+ Supported opening forms include a plain triple-backtick fence and fences
731
+ labelled `bash`, `sh`, `cmd`, or `terminal`. Close the block with a line
732
+ containing three backticks.
733
+
734
+ **Security note:** shell blocks run real operating-system commands with
735
+ your user's permissions. Review commands before executing them,
736
+ especially commands copied from untrusted sources.
737
+
738
+ ## Comments, semicolons, and line continuation
739
+
740
+ ### Single-line comments
741
+
742
+ Use `//` for comments:
743
+
744
+ ``` text
745
+ search elements number < 10 // The first nine elements
746
+ ```
747
+
748
+ The comment marker is intended to be recognized outside quoted strings.
749
+
750
+ ### Multiline comments
751
+
752
+ Use `///` to begin and end a multiline comment:
753
+
754
+ ``` text
755
+ /// This is a comment.
756
+ It can continue across multiple lines.
757
+ The whole comment is ignored. ///
758
+ search elements symbol = "O"
759
+ ```
760
+
761
+ A multiline comment can also be written with opening and closing markers
762
+ on the same line.
763
+
764
+ ### Semicolon-separated commands
765
+
766
+ Run multiple ChemQL commands on one line with semicolons:
767
+
768
+ ``` text
769
+ source elements; search name = "Hydrogen"; search number = 8
770
+ ```
771
+
772
+ ChemQL's command splitter tracks quotes and bracketed/query expressions
773
+ so semicolons inside quoted strings or protected blocks are not treated
774
+ as command separators.
775
+
776
+ ### Line continuation
777
+
778
+ End a line with `\` to continue the command on the next line:
779
+
780
+ ``` text
781
+ search elements \
782
+ number > 10 and \
783
+ number < 20 \
784
+ sort number desc \
785
+ limit 5
786
+ ```
787
+
788
+ The continued lines are treated as one command.
789
+
790
+ ## Scripts, pipes, and output files
791
+
792
+ ### Run a command
793
+
794
+ ``` bash
795
+ chemql -c 'search elements symbol = "O"'
796
+ ```
797
+
798
+ ### Run a file
799
+
800
+ Save commands in a `.cql` or `.chemql` file, for example `explore.cql`:
801
+
802
+ ``` text
803
+ search elements number < 10 return name symbol number
804
+ search molecules molecular_weight < 50 sort molecular_weight return name formula molecular_weight
805
+ ```
806
+
807
+ Run it:
808
+
809
+ ``` bash
810
+ chemql -f explore.cql
811
+ ```
812
+
813
+ Both `.cql` and `.chemql` are suitable file extensions; the CLI accepts
814
+ a file path.
815
+
816
+ ### Pipe commands through standard input
817
+
818
+ ``` bash
819
+ echo 'search elements symbol = "O"' | chemql
820
+ ```
821
+
822
+ You can also pipe a multi-line script into ChemQL:
823
+
824
+ ``` bash
825
+ cat explore.cql | chemql
826
+ ```
827
+
828
+ On Windows PowerShell, use `Get-Content explore.cql | chemql` or
829
+ redirect a file into the command.
830
+
831
+ ### Show version and upgrade
832
+
833
+ ``` bash
834
+ chemql --version
835
+ chemql --upgrade
836
+ chemql --upgrade 1.2.0
837
+ ```
838
+
839
+ `--upgrade` installs the latest published `chemql-python` release; supplying a
840
+ version requests that specific release. The optional `--force` (also accepted
841
+ as `--dangerously`) bypasses system-package protections. Use that option only
842
+ when you understand the consequences for your Python environment.
843
+
844
+ ### Disable ANSI escape sequences
845
+
846
+ ``` bash
847
+ chemql --no-ansi -c 'search elements symbol = "O"'
848
+ ```
849
+
850
+ This is useful when redirecting output to logs or processing it with
851
+ other tools.
852
+
853
+ ### Write clean output to a file
854
+
855
+ Use `-o` / `--output` together with `-c` or `-f`:
856
+
857
+ ``` bash
858
+ chemql -c 'search elements number < 10 return name symbol' -o elements.txt
859
+ chemql -f explore.cql --output results.txt
860
+ ```
861
+
862
+ The output file is written without ANSI escape sequences. `-o` requires
863
+ either `-c` or `-f`.
864
+
865
+ ## Session history and exports
866
+
867
+ ChemQL records queries and results processed during the session. Use
868
+ `dump` to export that history to a UTF-8 text file.
869
+
870
+ ``` text
871
+ dump session.txt
872
+ dump all session.txt
873
+ dump good session-successes.txt
874
+ dump bad session-errors.txt
875
+ dump all queries queries.txt
876
+ dump good results successful-results.txt
877
+ dump bad results failed-results.txt
878
+ ```
879
+
880
+ Available forms:
881
+
882
+ Command What it exports
883
+ -------------------------- ------------------------------------
884
+ `dump FILE` All recorded queries and results
885
+ `dump all FILE` All recorded queries and results
886
+ `dump good FILE` Successful executions
887
+ `dump bad FILE` Failed executions
888
+ `dump all queries FILE` All recorded queries only
889
+ `dump good queries FILE` Successful queries only
890
+ `dump bad queries FILE` Failed queries only
891
+ `dump all results FILE` All results only
892
+ `dump good results FILE` Results from successful executions
893
+ `dump bad results FILE` Results from failed executions
894
+
895
+ The `good` and `bad` categories use ChemQL's execution-status tracking.
896
+ Shell command exit codes are not necessarily equivalent to ChemQL's own
897
+ error tracking.
898
+
899
+ ## Terminal experience
900
+
901
+ In interactive mode, ChemQL provides:
902
+
903
+ - **Syntax highlighting** for ChemQL commands, operators, fields,
904
+ strings, and related syntax.
905
+ - **Tab completion** for commands, sources, fields, and context-aware
906
+ suggestions.
907
+ - **Built-in help** through `help` or `?`.
908
+ - **A periodic-table viewer** through `view`.
909
+ - **ANSI styling** for readable terminal output, with `--no-ansi`
910
+ available for plain output.
911
+ - **Persistent Python variables** across Python blocks.
912
+ - **A persistent shell session** for backtick and fenced shell
913
+ commands.
914
+ - **Friendly exit controls:** type `exit` or press `Ctrl+C`.
915
+
916
+ ## Python API
917
+
918
+ ChemQL can also be used from Python. The public query function is
919
+ `execute_query_text()`:
920
+
921
+ ``` python
922
+ from chemql import execute_query_text
923
+
924
+ result = execute_query_text('search elements name = "Hydrogen"')
925
+ print(result)
926
+ ```
927
+
928
+ `execute_query_text()` accepts a query string and returns its query
929
+ result. Depending on the query, that result may be a chemistry object,
930
+ list, table-like result, count, string, or `None`.
931
+
932
+ The higher-level `execute_query()` wrapper is also available:
933
+
934
+ ``` python
935
+ from chemql import execute_query
936
+
937
+ result = execute_query('search molecules formula = "H2O"')
938
+ print(result)
939
+ ```
940
+
941
+ The package exposes chemistry classes such as `Element`, `Molecule`, and
942
+ `Reaction`, as well as helper functions including `search`, `union`, and
943
+ `intersection`. Public APIs can evolve between versions; consult the
944
+ installed source and `help()` for the exact version you use.
945
+
946
+ ## Query syntax reference
947
+
948
+ A typical query follows this pattern:
949
+
950
+ ``` text
951
+ search [first|last|all] SOURCE [conditions] [sort FIELD [asc|desc]] [limit N] [count] [return FIELD ...]
952
+ ```
953
+
954
+ Examples:
955
+
956
+ ``` text
957
+ search elements number = 8
958
+ search molecules name like "*acid*" sort molecular_weight limit 10
959
+ search reactions reversible = true return name equation
960
+ ```
961
+
962
+ Common commands:
963
+
964
+ Command Purpose
965
+ ------------------------- -------------------------------------
966
+ `search ...` Query a source
967
+ `source NAME` Set the current source
968
+ `list all` List fields
969
+ `findel VALUE` Find an element
970
+ `findmol VALUE` Find a molecule
971
+ `findre VALUE` Find a reaction
972
+ `react ...` Match reactants to stored reactions
973
+ `balance ...` Balance a chemical equation
974
+ `set temperature VALUE` Set reaction temperature
975
+ `set pressure VALUE` Set reaction pressure
976
+ `set catalysts ...` Replace the catalyst list
977
+ `add catalyst NAME` Add a catalyst
978
+ `remove catalyst NAME` Remove a catalyst
979
+ `conditions` Show reaction conditions
980
+ `view` Open the periodic-table viewer
981
+ `dump ...` Export execution history
982
+ `clear` Clear the terminal
983
+ `help` / `?` Show help
984
+ `version` Print the ChemQL version
985
+ `exit` Leave the interactive prompt
986
+
987
+ ## Examples
988
+
989
+ ### Find noble gases
990
+
991
+ ``` text
992
+ search elements category like "*noble gas*" return name symbol number
993
+ ```
994
+
995
+ ### Find relatively light molecules
996
+
997
+ ``` text
998
+ search molecules molecular_weight < 50 sort molecular_weight asc limit 10 return name formula molecular_weight
999
+ ```
1000
+
1001
+ ### Find reactions of a particular type
1002
+
1003
+ ``` text
1004
+ search reactions reaction_type = "combustion" return name equation reversible
1005
+ ```
1006
+
1007
+ ### Explore and export a session
1008
+
1009
+ ``` text
1010
+ search elements number < 20 return name symbol number
1011
+ search molecules molecular_weight < 100 return name formula molecular_weight
1012
+ dump all results chemistry-results.txt
1013
+ ```
1014
+
1015
+ ### Combine a query with Python
1016
+
1017
+ ``` text
1018
+ [light_molecules = {{ search molecules molecular_weight < 50 return name }}]
1019
+ [print("Found names:", light_molecules)]
1020
+ ```
1021
+
1022
+ ### Use ChemQL from a Python script
1023
+
1024
+ ``` python
1025
+ from chemql import execute_query_text
1026
+
1027
+ elements = execute_query_text(
1028
+ 'search elements number < 10 return name symbol'
1029
+ )
1030
+ print(elements)
1031
+ ```
1032
+
1033
+ ## Troubleshooting
1034
+
1035
+ - **`No source selected`:** specify a source in the query, such as
1036
+ `search elements ...`, or set one with `source elements`.
1037
+ - **Unknown field:** run `list all` after selecting a source to see
1038
+ its available field names. Use `number` for an element's atomic
1039
+ number in the current data model.
1040
+ - **No local molecule match:** `findmol` may try online lookup, which
1041
+ requires network access and an available external service.
1042
+ - **Output contains terminal escape codes:** add `--no-ansi` or use
1043
+ `-o FILE` with `-c` or `-f`.
1044
+ - **A multiline block is incomplete:** close a Python block with `]]]`
1045
+ on its own line or a terminal block with three backticks on its own
1046
+ line.
1047
+ - **Python or shell command behaves unexpectedly:** remember that
1048
+ these execute real code in your environment. Check quotes,
1049
+ indentation, and the exact command before running it.
1050
+ - **A reaction does not match:** check the available reaction records,
1051
+ the reactant spelling and stoichiometry, and the temperature,
1052
+ pressure, and catalyst settings.
1053
+
1054
+ ## Safety and scope
1055
+
1056
+ ChemQL is a chemistry data/query tool, not a replacement for
1057
+ authoritative chemical references, laboratory procedures, or
1058
+ professional safety guidance. Dataset coverage and online service
1059
+ responses may be incomplete. Validate important scientific results
1060
+ against appropriate primary or authoritative sources.
1061
+
1062
+ Python and shell blocks execute real code with your operating-system
1063
+ user's permissions. Do not run scripts or commands you do not trust.
1064
+
1065
+ ------------------------------------------------------------------------
1066
+
1067
+ **ChemQL --- Python Chemistry Query Language**