Metadata-Version: 2.4
Name: chemql-python
Version: 1.0.3
Summary: A chemistry-focused query language and REPL
Author-email: Mohammad Rakibul Islam <rakibulofficial1017@gmail.com>
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: prompt_toolkit>=3.0
Provides-Extra: test
Requires-Dist: pytest>=8.0; extra == "test"
Dynamic: license-file

# ChemQL

**ChemQL** is a chemistry-focused query language for searching and
working with chemical data from Python or an interactive terminal. It
provides a compact way to query elements, molecules, and chemical
reactions using filters, logical conditions, sorting, and result
projections.

> Package: `chemql-python`\
> Python import: `chemql`

## Features

-   Query element, molecule, and reaction datasets.
-   Filter records with comparisons and logical conditions.
-   Match text using wildcard patterns with `like` and case-sensitive
    `like!`.
-   Use `and`, `or`, `not`, and parentheses to combine conditions.
-   Use `likep` for Python regular-expression matching.
-   Combine list results with `union` and `intersection`.
-   Sort, limit, count, and project results with `return`.
-   Look up elements, molecules, and reactions using `findel`,
    `findmol`, and `findre`.
-   Balance chemical equations.
-   Set reaction conditions, including temperature, pressure, and
    catalysts.
-   Use Python expressions and control blocks alongside ChemQL queries.
-   Use ChemQL from the command line or through its Python API.

## Installation

Install the Python package from PyPI:

``` bash
pip install chemql-python
```

## Upgrading the package or switching versions

If your chemql-python version is >=1.0.1, you can simply run
```bash
chemql --upgrade
``` 
Or to switch versions to for example 0.2.2
```bash
chemql --upgrade 0.2.2
``` 
However if you do not have chemql-python version >=1.0.1
```bash
pip install --upgrade chemql-python
```
Or to switch versions to for example 0.2.2
```bash
pip install --force-reinstall chemql-python==0.2.2
```

## Quick start

Start the interactive terminal:

``` bash
chemql
```

Then try:

``` text
search elements name = "Hydrogen"
findel "He"
findmol "H2O"
search molecules molecular_weight < 20 return name formula molecular_weight
search reactions reaction_type = "combustion" return name equation
```

Show the built-in command reference from the REPL:

``` text
help
```

## Command-line usage

Run a single command with `-c`:

``` bash
chemql -c 'search elements name = "Hydrogen"'
```

Run commands from a file with `-f`:

``` bash
chemql -f queries.chemql
```

Check the installed version:

``` bash
chemql --version
```

A query file can contain multiple ChemQL commands, one per line. Use the
`//` comment marker for comments and a trailing backslash (`\`) to
continue a command onto the next line.

Example `queries.chemql`:

``` text
// Find lighter molecules
search molecules molecular_weight < 20 return name formula molecular_weight

// Show a subset of the periodic table
search elements atomic_number > 10 and atomic_number < 20 sort atomic_number desc limit 5
```

## Query language

### Data sources

ChemQL provides three main sources:

  Source        Contents
  ------------- ----------------------------------------------
  `elements`    Periodic-table element data
  `molecules`   Molecule properties and identifiers
  `reactions`   Reaction equations, conditions, and metadata

Search a source explicitly:

``` text
search elements
search molecules
search reactions
```

You can also use `search all` before a source name, for example:

``` text
search all elements atomic_mass < 100
```

Change the active source in an interactive session with:

``` text
source elements
source molecules
source reactions
```

### Filtering

Use comparison operators to filter records:

  Operator   Meaning
  ---------- ----------------------------------------
  `=`        Equal
  `!=`       Not equal
  `>`        Greater than
  `<`        Less than
  `>=`       Greater than or equal
  `<=`       Less than or equal
  `like`     Case-insensitive wildcard match
  `like!`    Case-sensitive wildcard match
  `likep`    Python regular-expression match
  `has`      Check whether a value contains an item

Examples:

``` text
search elements atomic_number > 10
search molecules molecular_weight <= 20
search molecules name like "*water*"
search reactions id likep ".*haber(\s*|-|_)process.*"
```

The wildcard matcher supports `*` for a sequence of characters and other
wildcard tokens supported by ChemQL's pattern matcher. Use `likep` when
you need regular expressions rather than wildcard patterns.

### Logical conditions and parentheses

Combine conditions with `and`, `or`, and `not`. Parentheses group
conditions. Comparison operators and parentheses can be written without
surrounding spaces.

``` text
search elements name not like "*ium"
search elements name not like "*ium" and not atomic_mass < 50
search elements atomic_mass > 50 and (density<10 or boil<100)
```

### Combining query results

Use `union` to combine results and `intersection` to keep records
present in both result lists. Operations are evaluated from left to
right.

``` text
search elements name not like "*ium" intersection search elements name like "*um"
```

Use the Python API's query-object operators `|` and `&` for union and
intersection, respectively, when working with `ChemQLQuery` objects.

### Sorting, limiting, counting, and returning fields

``` text
search elements sort atomic_number
search molecules sort molecular_weight desc
search molecules limit 10
search molecules count
search molecules molecular_weight < 20 return name
search molecules molecular_weight < 20 return name formula molecular_weight
```

-   `sort <field> [asc|desc]` sorts results.
-   `limit <number>` limits the number of results.
-   `count` returns the number of matches.
-   `return <field...>` returns only selected fields. One field produces
    a list; multiple fields produce a table-like result.
-   `first` and `last` can be used to select one result.

### Find commands

``` text
findel "He"
findel "Hydrogen"

findmol "H2O"
findmol "Water"

findre "Haber process"
findre "RHEA:10000" return name equation source
```

`findmol` searches the local molecule dataset first and can use external
chemical-data services when a local match is not found. External lookups
require an internet connection and may be unavailable if the service is
down.

## Reactions and equation balancing

ChemQL includes reaction data and commands for working with reaction
conditions.

``` text
findre "Haber process"
balance O2 + H2 -> H2O
balance O2 + H2 <-> H2O
```

The `->` arrow denotes an irreversible reaction, while `<->` denotes a
reversible reaction.

Set conditions before using `react`:

``` text
set temperature 723K
set pressure 20265000pa
set catalysts iron zinc
conditions
react N2 3H2
```

Temperature can be supplied in Celsius (`C`), Fahrenheit (`F`), or
Kelvin (`K`). Pressure supports units such as pascals and bar; the
available unit conversions depend on the installed version. Preset
conditions are also available:

``` text
set temperature standard
set pressure room
```

Use `help` in the terminal for the command reference included with your
installed version.

## Python API

Import ChemQL from Python:

``` python
import chemql

result = chemql.execute_query_text(
    'search elements name = "Hydrogen"'
)
print(result)
```

You can also use `execute_query` for a query string:

``` python
import chemql

result = chemql.execute_query('search molecules molecular_weight < 20')
print(result)
```

The package exposes chemistry data classes and helpers, including
`Element`, `Molecule`, `Reaction`, `ChemQLError`, `Unknown`,
`ReturnTable`, and `balance_stoichiometry`.

### Query builder API

Versions that include the query-builder API also support chaining query
conditions:

``` python
import chemql

x = chemql.search("elements")
y = x.atomic_mass.condition(lt=10)
z = y.return_("name")

print(z)          # The query as text
print(z.execute())  # Execute the query
```

Query objects can be combined with `|` (union) and `&` (intersection).
The convenience functions `chemql.union(x, y)` and
`chemql.intersection(x, y)` are also available in versions that include
this API.

## Hybrid Python

ChemQL can execute Python expressions inside square brackets:

``` text
[x = 10]
[print(x)]
```

It also supports Python control blocks using `[for ...]`, `[if ...]`,
`[elif ...]`, `[else]`, `[while ...]`, `[break]`, `[continue]`, and
`[endblock]`.

Use `{{ ... }}` to evaluate a ChemQL query and insert its result into
Python:

``` text
[print({{ search elements atomic_number = 1 }})]
```

Only run Python code and shell commands from sources you trust.

## Shell Commands

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.

**Syntax**

```chemql
`command`
```

**Examples**

Execute system commands:

```chemql
`whoami`
`dir`
`echo Hello`
```

Change the working directory:

```chemql
`cd ..`
`cd ~`
`dir`
```

The working directory persists between commands.

Environment variables and other shell state can also persist between commands, depending on the shell being used.

**Platform support**

- **Linux:** Bash
- **macOS:** Bash
- **Windows:** Command Prompt (`cmd.exe`)

PowerShell is not supported by the current implementation.

**How it works**

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.

**Notes**

- Commands must be enclosed in backticks to be interpreted as shell commands rather than ChemQL statements.
- Shell syntax differs between operating systems. Use commands appropriate for your platform.
- Commands run with the permissions of the process running ChemQL and may modify files or affect your system.
- Interactive terminal programs and commands requiring direct terminal input may not work correctly because the shell uses pipes rather than a real terminal.

## Data and external services

ChemQL loads bundled JSON datasets for elements, molecules, reactions,
molecule bonds, and bond energies. Some molecule lookups may query
PubChem or other external sources when the local dataset does not
contain a match.

The periodic-table dataset is based on PeriodicTableJSON by
Bowserinator. Review the dataset's accompanying license and attribution
requirements when redistributing it or derivative data. The licenses and
sources for the other bundled datasets should be checked in their
respective files before redistribution.

## Safety note

ChemQL's hybrid Python functionality can execute Python code. If your
installed version supports backtick-wrapped shell commands, those can
execute operating-system commands as well. Do not run untrusted ChemQL
scripts or queries.

## Development notes

-   The interactive shell uses `prompt_toolkit`.
-   The command-line interface supports single-command execution (`-c`)
    and file execution (`-f`).
-   Consult the package's source and included `help` output for the
    exact commands and fields supported by your installed version.

## License

[MIT License](https://github.com/rakibulofficial1017/ChemQL/blob/main/LICENSE)

Created by [Mohammad Rakibul Islam](https://github.com/rakibulofficial1017).
Source code: [rakibulofficial1017/ChemQL](https://github.com/rakibulofficial1017/ChemQL).
