Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add docs #36

Merged
merged 4 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ jobs:
- name: cargo fmt
run: cargo fmt --all --check
- name: cargo clippy
run: cargo clippy --tests --all -- -D warnings
run: cargo clippy --tests --workspace -- -D warnings
- name: cargo check
run: cargo check --all
run: cargo check --workspace
- name: cargo test
run: cargo test
32 changes: 32 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Docs

on:
push:
tags:
- "v*"
workflow_dispatch:

permissions:
contents: write
pages: write

jobs:
docs:
runs-on: ubuntu-latest
env:
GIT_COMMITTER_NAME: ci-bot
GIT_COMMITTER_EMAIL: [email protected]
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
- uses: astral-sh/setup-uv@v3
with:
enable-cache: true
- name: Install Python
run: uv python install # we use uv instead of setup-python so we get python-version resolution between our two packages
- name: Sync
run: uv sync
- name: Deploy
run: |
VERSION=$(git describe --tags --match="v*" --abbrev=0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you expect to ever publish beta versions? I find myself pushing alpha/beta versions decently often, but don't want to publish those to the public docs website: https://github.com/developmentseed/lonboard/blob/4af9e2de490e99092fffafae817078e30da94bc2/.github/workflows/deploy-mkdocs.yml#L59-L63

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't anticipate that very often for this repo — my hope is that we bake it and it just gets used.

uv run mike deploy $VERSION latest --update-aliases --push
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a personal nit to always have an end of line character on the last line. I set this in my editor settings and also have pre-commit setups that enforce this on my own projects: https://github.com/developmentseed/lonboard/blob/4af9e2de490e99092fffafae817078e30da94bc2/.pre-commit-config.yaml#L16

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
target/
debug/
**/*.rs.bk
.cache
site/
66 changes: 66 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# CLI

**cql2-rs** includes a command-line interface (CLI).

## Installation

Install [Rust](https://rustup.rs/).
Then:

```shell
cargo install cql2-cli
```

## Usage

At its simplest, the CLI is a pass-through validator:

```shell
$ cql2 < tests/fixtures/text/example01.txt # will succeed if the CQL2 is valid
("landsat:scene_id" = 'LC82030282019133LGN00')
```

You can convert formats:

```shell
$ cql2 -o json < tests/fixtures/text/example01.txt
{"op":"=","args":[{"property":"landsat:scene_id"},"LC82030282019133LGN00"]}
```

Use `-v` to get detailed validation information:

```shell
$ cql2 'wrong' -v
[ERROR] Invalid CQL2: wrong
For more detailed validation information, use -vv
jsonschema validation failed with file:///tmp/cql2.json#
- at '': oneOf failed, none matched
- at '': missing properties 'op', 'args'
- at '': missing properties 'op', 'args'
- at '': oneOf failed, none matched
- at '': missing properties 'op', 'args'
- at '': missing properties 'op', 'args'
- at '': missing properties 'op', 'args'
- at '': missing properties 'op', 'args'
- at '': missing properties 'op', 'args'
- at '': missing properties 'op', 'args'
- at '': missing properties 'op', 'args'
- at '': missing properties 'op', 'args'
- at '': missing properties 'op', 'args'
- at '': want boolean, but got object
```

cql2-text parsing errors are pretty-printed:

```shell
$ cql2 '(foo ~= "bar")'
[ERROR] Parsing error: (foo ~= "bar")
--> 1:6
|
1 | (foo ~= "bar")
| ^---
|
= expected NotFlag, And, Or, ConcatInfixOp, Add, Subtract, Multiply, Divide, Modulo, Power, Eq, Gt, GtEq, Lt, LtEq, NotEq, Is, or IsNullPostfix
```

Use `cql2 --help` to get a complete listing of the CLI arguments and formats.
17 changes: 17 additions & 0 deletions docs/ds-logo-hor--pos.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# cql2-rs

**cql2-rs** is [Python package](./python.md), [command-line interface (CLI)](./cli.md), and [Rust crate](https://docs.rs/cql2) for parsing, validating, and converting [Common Query Language (CQL2)](https://www.ogc.org/standard/cql2/).

## Python

```python
>>> from cql2 import Expr
>>> expr = Expr("landsat:scene_id = 'LC82030282019133LGN00'")
>>> expr.to_json()
{'op': '=', 'args': [{'property': 'landsat:scene_id'}, 'LC82030282019133LGN00']}
```

## CLI

```shell
$ cql2 < tests/fixtures/text/example01.txt # will succeed if the CQL2 is valid
("landsat:scene_id" = 'LC82030282019133LGN00')
```

## Rust

```rust
use cql2::Expr;
let expr: Expr = "landsat:scene_id = 'LC82030282019133LGN00'".parse();
let json = expr.to_json().unwrap();
```
13 changes: 13 additions & 0 deletions docs/python.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Python
gadomski marked this conversation as resolved.
Show resolved Hide resolved

Python API documentation for the **cql2** package.
Install from PyPI:

```shell
python -m pip install cql2
```

## API

::: cql2.Expr
::: cql2.SqlQuery
65 changes: 65 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
site_name: cql2-rs
site_url: https://developmentseed.org/cql2-rs/
site_description: Command-line interface (CLI), Python package, and Rust crate for parsing, validating, and converting Common Query Language (CQL2)
site_author: David Bitner
repo_name: developmentseed/cql2-rs
repo_url: https://github.com/developmentseed/cql2-rs
edit_uri: edit/main/docs/

extra:
social:
- icon: "fontawesome/brands/github"
version:
provider: mike

theme:
name: material
logo: ds-logo-hor--pos.svg
favicon: favicon.png
icon:
repo: fontawesome/brands/github
palette:
primary: blue
features:
- content.action.edit
- navigation.indexes
- navigation.instant
- navigation.tabs
- navigation.tracking
- search.share
- search.suggest
- toc.integrate
nav:
- cql2-rs: index.md
- Python: python.md
- CLI: cli.md
- Rust: https://docs.rs/cql2
plugins:
- search
- social
- mike:
alias_type: "copy"
canonical_version: "latest"
- mkdocstrings:
enable_inventory: true
handlers:
python:
options:
allow_inspection: false
show_root_heading: true
separate_signature: false
docstring_style: google
docstring_section_style: list
show_symbol_type_toc: true
signature_crossrefs: true
merge_init_into_class: true
docstring_options:
ignore_init_summary: false
markdown_extensions:
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite
- pymdownx.snippets
- pymdownx.superfences
18 changes: 18 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[project]
name = "cql2-rs"
version = "0.0.0"
description = "This Python package is non-releaseable and is only used for building the documentation"
requires-python = ">=3.12"

[tool.uv]
dev-dependencies = [
"mike>=2.1.3",
"mkdocs-material[imaging]>=9.5.39",
"mkdocstrings[python]>=0.26.1",
]

[tool.uv.sources]
python = { workspace = true }

[tool.uv.workspace]
members = ["python/"]
79 changes: 74 additions & 5 deletions python/cql2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,82 @@ from typing import Any
from os import PathLike

class SqlQuery:
"""A SQL query"""

query: str
"""The query, with parameterized fields."""

params: list[str]
"""The parameters, to use for binding."""

class Expr:
@staticmethod
def from_path(path: PathLike) -> Expr: ...
def __init__(self, cql2: str | dict[str, Any]) -> None: ...
def to_json(self) -> dict[str, Any]: ...
def to_text(self) -> str: ...
def to_sql(self) -> SqlQuery: ...
def from_path(path: PathLike | str) -> Expr:
"""Reads CQL2 from a filesystem path.

Args:
path (PathLike | str): The input path

Returns:
Expr: The CQL2 expression

Examples:
>>> from cql2 import Expr
>>> expr = Expr.from_path("fixtures/text/example01.txt")
"""

def __init__(self, cql2: str | dict[str, Any]) -> None:
"""A CQL2 expression.

The cql2 can either be a cql2-text string, a cql2-json string, or a
cql2-json dictionary.

Args:
cql2 (str | dict[str, Any]): The input CQL2

Examples:
>>> from cql2 import Expr
>>> expr = Expr("landsat:scene_id = 'LC82030282019133LGN00'")
>>> expr = Expr({"op":"=","args":[{"property":"landsat:scene_id"},"LC82030282019133LGN00"]})
"""

def to_json(self) -> dict[str, Any]:
"""Converts this cql2 expression to a cql2-json dictionary.

Returns:
dict[str, Any]: The cql2-json

Examples:
>>> from cql2 import Expr
>>> expr = Expr("landsat:scene_id = 'LC82030282019133LGN00'")
>>> expr.to_json()
{'op': '=', 'args': [{'property': 'landsat:scene_id'}, 'LC82030282019133LGN00']}
"""

def to_text(self) -> str:
"""Converts this cql2 expression to cql2-text.

Returns:
str: The cql2-text

Examples:
>>> from cql2 import Expr
>>> expr = Expr({"op":"=","args":[{"property":"landsat:scene_id"},"LC82030282019133LGN00"]})
>>> expr.to_text()
'("landsat:scene_id" = \'LC82030282019133LGN00\')'
"""

def to_sql(self) -> SqlQuery:
"""Converts this cql2 expression to a SQL query.

Returns:
SqlQuery: The SQL query and parameters

Examples:
>>> from cql2 import Expr
>>> expr = Expr("landsat:scene_id = 'LC82030282019133LGN00'")
>>> q.query
'("landsat:scene_id" = $1)'
>>> q.params
['LC82030282019133LGN00']
"""
2 changes: 1 addition & 1 deletion python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ classifiers = [
dynamic = ["version"]

[tool.uv]
dev-dependencies = ["mypy", "pytest", "ruff"]
dev-dependencies = ["mypy>=1.11.2", "pytest>=8.3.3", "ruff>=0.6.9"]
4 changes: 4 additions & 0 deletions python/tests/test_expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def test_from_path(fixtures: Path) -> None:
Expr.from_path(fixtures / "text" / "example01.txt")


def test_from_path_str(fixtures: Path) -> None:
Expr.from_path(str(fixtures / "text" / "example01.txt"))


def test_init(example01_text: str) -> None:
Expr(example01_text)

Expand Down
Loading
Loading