Skip to content

Commit 6b33a37

Browse files
committed
feat(python): add cli to python package
1 parent 2349119 commit 6b33a37

File tree

5 files changed

+84
-1
lines changed

5 files changed

+84
-1
lines changed

python/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ name = "stacrs"
1313
crate-type = ["cdylib"]
1414

1515
[dependencies]
16+
clap = "4"
1617
pyo3 = "0.22"
1718
pythonize = "0.22"
1819
stac = { path = "../core", features = ["reqwest"] }
20+
stac-cli = { path = "../cli", default-features = false }
1921
stac-validate = { path = "../validate" }
22+
tokio = { version = "1", features = ["rt-multi-thread"] }

python/docs/index.md

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# stacrs
22

3-
A small, no-dependency Python library for working with [STAC](https://stacspec.org), using [Rust](https://github.com/stac-utils/stac-rs) under the hood.
3+
A small, no-dependency Python library and command-line interface (CLI) for working with [STAC](https://stacspec.org), using [Rust](https://github.com/stac-utils/stac-rs) under the hood.
44

55
## Installation
66

@@ -10,10 +10,55 @@ pip install stacrs
1010

1111
## Usage
1212

13+
### API
14+
1315
```python
1416
import stacrs
1517

1618
stacrs.validate_href("https://raw.githubusercontent.com/radiantearth/stac-spec/master/examples/simple-item.json")
1719
```
1820

1921
See [the API documentation](./api.md) for more.
22+
23+
### CLI
24+
25+
```shell
26+
$ stacrs --help
27+
Command line interface for stac-rs
28+
29+
Usage: stacrs [OPTIONS] <COMMAND>
30+
31+
Commands:
32+
item Creates a STAC Item
33+
migrate Migrates a STAC value from one version to another
34+
search Searches a STAC API
35+
serve Serves a STAC API
36+
sort Sorts the fields of STAC object
37+
translate Translates STAC values between formats
38+
validate Validates a STAC object or API endpoint using json-schema validation
39+
help Print this message or the help of the given subcommand(s)
40+
41+
Options:
42+
-c, --compact
43+
Use a compact representation of the output, if possible
44+
45+
-i, --input-format <INPUT_FORMAT>
46+
The input format. If not provided, the format will be detected from the input file extension when possible
47+
48+
Possible values:
49+
- parquet: stac-geoparquet
50+
- json: JSON (the default)
51+
52+
-o, --output-format <OUTPUT_FORMAT>
53+
The output format. If not provided, the format will be detected from the output file extension when possible
54+
55+
Possible values:
56+
- parquet: stac-geoparquet
57+
- json: JSON (the default)
58+
59+
-h, --help
60+
Print help (see a summary with '-h')
61+
62+
-V, --version
63+
Print version
64+
```

python/pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,8 @@ Repository = "https://github.com/stac-utils/stac-rs"
2727
Documentation = "https://stacrs.readthedocs.io/"
2828
Issues = "https://github.com/stac-utils/stac-rs/issues"
2929

30+
[project.scripts]
31+
stacrs = "stacrs:main"
32+
3033
[tool.maturin]
3134
features = ["pyo3/extension-module"]

python/src/lib.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,36 @@
1+
use clap::Parser;
12
use pyo3::{create_exception, exceptions::PyException, prelude::*, types::PyDict};
23
use stac::{Migrate, Value};
4+
use stac_cli::Args;
35
use stac_validate::Validate;
46

57
create_exception!(stacrs, StacrsError, PyException, "An error in stacrs");
68

9+
/// Runs the command-line interface.
10+
///
11+
/// Returns:
12+
/// int: The exit code
13+
#[pyfunction]
14+
fn main() -> PyResult<i64> {
15+
std::process::exit(
16+
tokio::runtime::Builder::new_multi_thread()
17+
.enable_all()
18+
.build()
19+
.unwrap()
20+
.block_on(async {
21+
// We skip one because the first argument is going to be the python interpreter.
22+
let args = Args::parse_from(std::env::args_os().skip(1));
23+
match stac_cli::run(args).await {
24+
Ok(()) => 0,
25+
Err(err) => {
26+
eprintln!("ERROR: {}", err);
27+
err.code()
28+
}
29+
}
30+
}),
31+
)
32+
}
33+
734
/// Migrates a STAC dictionary to another version.
835
///
936
/// Migration can be as simple as updating the `stac_version` attribute, but
@@ -20,6 +47,9 @@ create_exception!(stacrs, StacrsError, PyException, "An error in stacrs");
2047
/// version (str | None): The version to migrate to. If not provided, the
2148
/// value will be migrated to the latest stable version.
2249
///
50+
/// Returns:
51+
/// dict[str, Any]: The migrated dictionary
52+
///
2353
/// Examples:
2454
/// >>> with open("examples/simple-item.json") as f:
2555
/// >>> item = json.load(f)
@@ -102,6 +132,7 @@ fn validate_value(value: Value) -> PyResult<()> {
102132
/// A collection of functions for working with STAC, using Rust under the hood.
103133
#[pymodule]
104134
fn stacrs(m: &Bound<'_, PyModule>) -> PyResult<()> {
135+
m.add_function(wrap_pyfunction!(main, m)?)?;
105136
m.add_function(wrap_pyfunction!(migrate, m)?)?;
106137
m.add_function(wrap_pyfunction!(validate_href, m)?)?;
107138
m.add_function(wrap_pyfunction!(validate, m)?)?;

python/stacrs.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ from typing import Any, Optional
22

33
class StacrsError(Exception): ...
44

5+
def main() -> int: ...
56
def migrate(value: dict[str, Any], version: Optional[str] = None) -> dict[str, Any]: ...
67
def validate_href(href: str) -> None: ...
78
def validate(value: dict[str, Any]) -> None: ...

0 commit comments

Comments
 (0)