Metadata-Version: 2.4
Name: eocube
Version: 0.3.0
Summary: Support tool and library for EOCube.Ro
License: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Keywords: earth observation,cube,geospatial,cli,s3,cloudnative,stac
Author: Marian Neagul
Author-email: marian.neagul@e-uvt.ro
Requires-Python: >=3.12,<4.0
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: GIS
Provides-Extra: auth
Provides-Extra: cli
Provides-Extra: core
Provides-Extra: cube
Provides-Extra: full
Provides-Extra: ingest
Provides-Extra: ingest-fmask
Provides-Extra: ingest-s1-slc
Provides-Extra: ingest-s2-l1c
Provides-Extra: mcp
Provides-Extra: raster
Provides-Extra: services
Requires-Dist: aiobotocore (>=2.5) ; extra == "cli"
Requires-Dist: ascii-magic ; extra == "cli" or extra == "full"
Requires-Dist: authlib
Requires-Dist: backoff
Requires-Dist: click (>=8.1,<9.0) ; extra == "cli" or extra == "mcp" or extra == "full"
Requires-Dist: cloudevents (>=1.10,<2.0) ; extra == "ingest"
Requires-Dist: dask (>=2025.7,<2026.0) ; extra == "cube" or extra == "full"
Requires-Dist: flask ; extra == "cli" or extra == "full"
Requires-Dist: fsspec (>=2025.10,<2027.0) ; extra == "core" or extra == "cli" or extra == "mcp" or extra == "full"
Requires-Dist: geopandas (>=1.0,<2.0) ; extra == "cli" or extra == "cube" or extra == "services" or extra == "mcp" or extra == "full"
Requires-Dist: matplotlib (>=3.8,<4.0) ; extra == "cli" or extra == "full"
Requires-Dist: mcp (>=1.8,<2.0) ; extra == "mcp" or extra == "full"
Requires-Dist: nest-asyncio (>=1.6,<2.0) ; extra == "cli"
Requires-Dist: numpy (>=1.24,<3.0) ; extra == "raster" or extra == "cube" or extra == "full"
Requires-Dist: owslib ; extra == "cli" or extra == "services" or extra == "mcp" or extra == "full"
Requires-Dist: pydantic (>=2,<3)
Requires-Dist: pystac (>=1.14,<2.0) ; extra == "core" or extra == "ingest" or extra == "mcp"
Requires-Dist: pystac-client (>=0.9,<0.10) ; extra == "core" or extra == "ingest" or extra == "mcp"
Requires-Dist: python-dateutil (>=2.9,<3.0)
Requires-Dist: pyyaml (>=6.0,<7.0)
Requires-Dist: rasterio (>=1.3,<2.0) ; extra == "ingest-fmask" or extra == "raster" or extra == "cube" or extra == "full"
Requires-Dist: requests (>=2.28,<3.0)
Requires-Dist: rich (>=13.0,<15.0) ; extra == "cli" or extra == "mcp" or extra == "full"
Requires-Dist: rio-cogeo (>=5.4,<6.0) ; extra == "raster" or extra == "cube"
Requires-Dist: s3fs (>=2024.1,<2027.0) ; extra == "core" or extra == "cli" or extra == "mcp" or extra == "full"
Requires-Dist: stactools-sentinel1 (>=0.8,<0.9) ; extra == "ingest-s1-slc"
Requires-Dist: stactools-sentinel2 (>=0.8,<0.9) ; extra == "ingest-s2-l1c"
Requires-Dist: xarray (>=2025.12,<2027.0) ; extra == "raster" or extra == "cube" or extra == "full"
Project-URL: Documentation, https://rocs.pages.dev.info.uvt.ro/tools/eocube-tools/
Project-URL: Homepage, https://eocube.ro
Project-URL: Repository, https://gitlab.dev.info.uvt.ro/rocs/tools/eocube-tools
Description-Content-Type: text/markdown

# EOCube.RO Tools
![Grant Funded](https://img.shields.io/badge/funded_by-UEFISCDI-blueviolet)
[![pipeline status](https://gitlab.dev.info.uvt.ro/rocs/tools/eocube-tools/badges/main/pipeline.svg)](https://gitlab.dev.info.uvt.ro/rocs/tools/eocube-tools/-/pipelines)

This repository holds the `eocube` python library currently providing a set of minimal 
tools aimed to be used on the STAC Catalogs and data hosted by the ROCS Project

## Installing

### Option 1: From PyPI
```bash
pip install "eocube[cli]"
```

> **Note:** always install the latest release: versions up to 0.1.6 on PyPI
> predate the current authentication flow and can no longer log in
> (`eocube auth login` fails with `invalid_scope`).

### Option 2: From the UVT GitLab Package Registry
```bash
pip install "eocube[cli]" --index-url https://gitlab.dev.info.uvt.ro/api/v4/projects/3491/packages/pypi/simple
```
Visit the [UVT GitLab Package Registry](https://gitlab.dev.info.uvt.ro/rocs/tools/eocube-tools/-/packages) for available packages.

### Option 3: From Git (development branch)
```bash
pip install "eocube[cli] @ git+https://gitlab.dev.info.uvt.ro/rocs/tools/eocube-tools.git@main"
```

## Command Line Tools
You can use the command line tool by calling the `eocube` library.

```bash
Usage: eocube [OPTIONS] COMMAND [ARGS]...

Options:
  --version                       Show version, build commit, and exit.
  --log-level [debug|info|warning|error|critical|notset]
                                  Set the logging level.
  --debug                         Enable debug logging (shorthand for --log-
                                  level DEBUG); includes token claim
                                  summaries, never tokens
  --context TEXT                  Configured context to use (default: the
                                  'primary' context from eocube.yml)
  --help                          Show this message and exit.

Commands:
  auth      Authentication related functionality
  doctor    One-shot diagnostic entry point.
  mcp       Model Context Protocol (MCP) server
  services  Various Services
  setup     Initialise the eocube configuration (auth, storage, stac,...
  tools     Offline tools (no API access required)
```

### Configuration

`eocube` reads a single kubectl-style config file at `~/.config/eocube/eocube.yml`
(honouring `$XDG_CONFIG_HOME`, overridable with `$EOCUBE_CONFIG`). It holds named
`authentication`, `storage`, `stac`, `mcp`, and `context` sections.

The quickest start is to write the built-in EOCube.ro defaults:

```bash
eocube setup init      # writes the default auth source, storage, and STAC catalog
eocube auth login      # then authenticate
```

`setup init` resets the configuration to the ROCS defaults (it prompts before
overwriting an existing file; pass `--force` to skip). To build or customise the
configuration by hand instead, use the per-section `add` commands:

```bash
eocube setup auth add --name eocube.ro oidc \
  --discovery-url https://aai.eocube.ro/realms/rocs/.well-known/openid-configuration
eocube setup stac add --name eocube.ro --endpoint https://stac.eocube.ro
eocube setup storage add --name rocs-primary --endpoint https://storage.svc.uvt-01.eocube.ro --auth-ref eocube.ro
eocube setup context add --name eocube.ro --auth eocube.ro --storage rocs-primary --stac eocube.ro --primary
```

A context's storage has two parts (both used by features added later): `providers`
-- named storage backends for components such as upload, where `--storage` sets the
`default` provider and `--user-storage` adds a `user_storage` one -- and `schemes`,
which map a STAC item's `storage:scheme` to a backend.

A global `--context` selects which context to use (default: the `primary` one):

```bash
eocube --context=eocube.ro services geospatialorg get-county-by-name --name Arad
```

The file stores your OIDC refresh tokens, so it is created `0600` in a `0700`
directory and the CLI **refuses to read it if its permissions are group/other
accessible** (ssh-style). Keeping the directory secure is your responsibility.

### Authentication
#### Login
In order to authenticate against our service provider you need to call:

```bash
eocube auth login
```

This will open a browser window and perform the standard authentication. The
resulting refresh token is written into the active context in
`~/.config/eocube/eocube.yml`. (Existing users upgrading from a keychain-based
release simply log in again.)

#### Headless / container authentication

`eocube auth login` writes tokens to the config file, which is typically absent
in containers or CI runners. In those environments provide credentials via
environment variables instead (these always take precedence over the config file):

- `EOCUBE_ACCESS_TOKEN` (or `ROCS_AAI_ACCESS_TOKEN`) -- an OIDC access token to use
  directly (e.g. minted on a workstation with `eocube auth get-access-token`).
- `ROCS_AAI_REFRESH_TOKEN` -- a refresh token; the CLI re-mints a fresh access
  token from it on expiry. Intended for a long-running sidecar (e.g. `eocube
  services proxy` next to a notebook) where KubeSpawner injects the user's
  refresh token. Redeemed via `EOCUBE_CLIENT_ID` / `EOCUBE_CLIENT_SECRET` when
  set, otherwise the public `eocube-cli` client.
- `EOCUBE_CLIENT_ID` + `EOCUBE_CLIENT_SECRET` -- a service-account client; the CLI
  fetches and refreshes the token itself.

```bash
docker run --rm -e EOCUBE_ACCESS_TOKEN="$(eocube auth get-access-token)" \
  harbor.dev.info.uvt.ro/rocs/eocube-tools:<version> auth info
```

#### Logout

In order to invalidate the session and delete local token issue you need to call:
```bash
eocube auth login
```

#### User Info
For obtaining user information you can call:

```bash
eocube auth login
```

### Internal Services
### External Services
#### Geo-Spatial.Org Services

Some basic services from the Geo-Spatial.Org are provided. All the tools provide the 
option to save the result in a `GeoJSON` file. 

```
Usage: eocube services geospatialorg [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  get-administrative-unit-by-code
                                  Uses the SIRUTA Code to retrieve the...
  get-administrative-unit-by-name
                                  Retrieves the administrative unit by name
  get-county-by-mnemonic          Retrieves the county by mnemonic
  get-county-by-name              Retrieves the county by name
```

## Library Tools
### Raster
  - `eocube.raster.utils.get_raster_patches()`: Function generating patches over an rasterio `DatasetReaser`

We welcome contributions! If you'd like to improve `eocube`, fix bugs, or propose new features, follow the steps below to set up your development environment.

## Development Setup (with Poetry)

This project uses [Poetry](https://python-poetry.org/) for dependency management and packaging.

### 1. Install Poetry

Follow the official instructions:  
https://python-poetry.org/docs/#installation

Or, if you're on a Unix-like system:

```bash
pip install poetry
```

Or

```bash
curl -sSL https://install.python-poetry.org | python3 -
```

Make sure it's available:

```bash
poetry --version
```

### 2. Clone the repository
```bash
git clone https://gitlab.dev.info.uvt.ro/rocs/tools/eocube-tools.git
cd eocube-tools
```

### 3. Create a feature branch

**Never commit directly to main!**

Create a new branch for your work:

```bash
git checkout -b my-feature-branch # Replace with something meaningful
```

### 4. Install development dependencies
```bash
poetry install --with dev
```

This will install both the main library and the development tools (`black`, `pip-audit`, `twine`, etc).

### 5. Activate the shell (optional)

```bash
poetry shell
```

You can now run commands like `eocube`, `pytest`, or `black` directly.

## Submitting Changes
1. Push your branch to GitLab:
   ```bash
   git push --set-upstream origin my-feature-branch
   ```
2. Open a Merge Request (MR) via the GitLab UI.
3. Your MR will be reviewed and must be approved by a project maintainer before it can be merged.


## Code Style
Make sure your code is properly formated. Non-compliant code will be rejected.
We use [Black](https://black.readthedocs.io/en/stable/) for consistent formatting. Before committing:

```bash
poetry run black .
```

## Acknowledgements

This work was supported by a grant of the Ministry of Research, Innovation and Digitization, 
CCCDI - UEFISCDI, project number **PN-IV-P6-6.3-SOL-2024-2-0248**, within PNCDI IV.

## Licensing
After updating do not forget to update the NOTICE file with:

```bash
pip-licenses --from=mixed --format=plain --with-urls -i eocube > NOTICE
```

## Releasing a new version

Publication to PyPi is intentionally manual. Each released wheel embeds the
git commit it was built from, surfaced via `eocube --version`:

```bash
$ eocube --version
eocube 0.1.2, commit 5ba2a1f8f812 (clean)
```

The `(clean)` marker is only present when the working tree had no uncommitted
changes at build time -- releases must always be `(clean)`.

### Recommended flow: `scripts/release.sh`

The repository ships a release helper that enforces a clean build, embeds the
git provenance, sanity-checks the produced wheel, and uploads it to PyPi:

```bash
# 1. Bump the version and commit everything
poetry version patch                               # 0.1.1 -> 0.1.2
git add pyproject.toml
git commit -m "release v$(poetry version -s)"
git tag "v$(poetry version -s)"

# 2. Build, verify, and publish
./scripts/release.sh
```

`release.sh` will:

1. Refuse to proceed if the working tree has uncommitted changes or untracked
   files under `src/` -- guaranteeing a `(clean)` stamp.
2. Wipe `dist/`, stamp `src/eocube/_build_info.py` with the current
   `git rev-parse HEAD`, run `poetry build`, then restore the placeholder
   `_build_info.py` so the stamped values never land in the repository.
3. Install the produced wheel into a throwaway virtualenv and assert that
   `eocube --version` reports `(clean)`. If not, the upload is aborted.
4. Prompt for confirmation, then run
   `poetry run twine upload --verbose -s -i 5C5D049F dist/*`.

Useful flags:

| Flag | Purpose |
|---|---|
| `--no-publish` | Build + verify only, skip the PyPi upload |
| `--yes` / `-y` | Skip the confirmation prompt (CI-friendly) |
| `--help` | Print the inline usage block |

Adapt the GPG key id (`5C5D049F`) inside `scripts/release.sh` to match your
own signing key if you maintain a fork.

After a successful upload, push the tag:

```bash
git push --tags
```

### Manual fallback

If you need to build/publish without the helper script, the equivalent
commands are:

```bash
rm -fr build/ dist/*
./scripts/stamp-build-info.sh                              # embed git provenance
poetry build
git checkout -- src/eocube/_build_info.py                  # restore the placeholder
poetry run twine upload --verbose -s -i 5C5D049F dist/*
```

Skipping `stamp-build-info.sh` is allowed but the resulting wheel will report
`eocube X.Y.Z` with no commit suffix.
