sfeos-tools 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl

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.
@@ -0,0 +1,114 @@
1
+ """Bbox shape migration utilities for SFEOS collections."""
2
+
3
+ import logging
4
+
5
+ from stac_fastapi.sfeos_helpers.database import add_bbox_shape_to_collection
6
+ from stac_fastapi.sfeos_helpers.mappings import COLLECTIONS_INDEX
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ async def process_collection_bbox_shape(client, collection_doc, backend):
12
+ """Process a single collection document to add bbox_shape field.
13
+
14
+ Args:
15
+ client: Elasticsearch/OpenSearch client
16
+ collection_doc: Collection document from database
17
+ backend: Backend type ('elasticsearch' or 'opensearch')
18
+
19
+ Returns:
20
+ bool: True if collection was updated, False if no update was needed
21
+ """
22
+ collection = collection_doc["_source"]
23
+ collection_id = collection.get("id", collection_doc["_id"])
24
+
25
+ # Use the shared function to add bbox_shape
26
+ was_added = add_bbox_shape_to_collection(collection)
27
+
28
+ if not was_added:
29
+ return False
30
+
31
+ # Update the collection in the database
32
+ if backend == "elasticsearch":
33
+ await client.index(
34
+ index=COLLECTIONS_INDEX,
35
+ id=collection_id,
36
+ document=collection,
37
+ refresh=True,
38
+ )
39
+ else: # opensearch
40
+ await client.index(
41
+ index=COLLECTIONS_INDEX,
42
+ id=collection_id,
43
+ body=collection,
44
+ refresh=True,
45
+ )
46
+
47
+ logger.info(f"Collection '{collection_id}': Added bbox_shape field")
48
+ return True
49
+
50
+
51
+ async def run_add_bbox_shape(backend):
52
+ """Add bbox_shape field to all existing collections.
53
+
54
+ Args:
55
+ backend: Backend type ('elasticsearch' or 'opensearch')
56
+ """
57
+ import os
58
+
59
+ logger.info(
60
+ f"Starting migration: Adding bbox_shape to existing collections ({backend})"
61
+ )
62
+
63
+ # Log connection info (showing what will be used by the client)
64
+ es_host = os.getenv("ES_HOST", "localhost")
65
+ es_port = os.getenv(
66
+ "ES_PORT", "9200"
67
+ ) # Both backends default to 9200 in their config
68
+ es_use_ssl = os.getenv("ES_USE_SSL", "true")
69
+ logger.info(f"Connecting to {backend} at {es_host}:{es_port} (SSL: {es_use_ssl})")
70
+
71
+ # Create client based on backend
72
+ if backend == "elasticsearch":
73
+ from stac_fastapi.elasticsearch.config import AsyncElasticsearchSettings
74
+
75
+ settings = AsyncElasticsearchSettings()
76
+ else: # opensearch
77
+ from stac_fastapi.opensearch.config import AsyncOpensearchSettings
78
+
79
+ settings = AsyncOpensearchSettings()
80
+
81
+ client = settings.create_client
82
+
83
+ try:
84
+ # Get all collections
85
+ response = await client.search(
86
+ index=COLLECTIONS_INDEX,
87
+ body={
88
+ "query": {"match_all": {}},
89
+ "size": 10000,
90
+ }, # Adjust size if you have more collections
91
+ )
92
+
93
+ total_collections = response["hits"]["total"]["value"]
94
+ logger.info(f"Found {total_collections} collections to process")
95
+
96
+ updated_count = 0
97
+ skipped_count = 0
98
+
99
+ for hit in response["hits"]["hits"]:
100
+ was_updated = await process_collection_bbox_shape(client, hit, backend)
101
+ if was_updated:
102
+ updated_count += 1
103
+ else:
104
+ skipped_count += 1
105
+
106
+ logger.info(
107
+ f"Migration complete: {updated_count} collections updated, {skipped_count} skipped"
108
+ )
109
+
110
+ except Exception as e:
111
+ logger.error(f"Migration failed with error: {e}")
112
+ raise
113
+ finally:
114
+ await client.close()
sfeos_tools/cli.py CHANGED
@@ -13,123 +13,24 @@ import logging
13
13
  import sys
14
14
 
15
15
  import click
16
- from stac_fastapi.sfeos_helpers.database import add_bbox_shape_to_collection
17
- from stac_fastapi.sfeos_helpers.mappings import COLLECTIONS_INDEX
18
16
 
17
+ try:
18
+ from importlib.metadata import version as _get_version
19
+ except ImportError:
20
+ from importlib_metadata import version as _get_version # type: ignore[no-redef]
21
+
22
+ __version__ = _get_version("sfeos-tools")
23
+
24
+ from .bbox_shape import run_add_bbox_shape
25
+ from .data_loader import load_items
19
26
  from .reindex import run as unified_reindex_run
20
27
 
21
28
  logging.basicConfig(level=logging.INFO)
22
29
  logger = logging.getLogger(__name__)
23
30
 
24
31
 
25
- async def process_collection_bbox_shape(client, collection_doc, backend):
26
- """Process a single collection document to add bbox_shape field.
27
-
28
- Args:
29
- client: Elasticsearch/OpenSearch client
30
- collection_doc: Collection document from database
31
- backend: Backend type ('elasticsearch' or 'opensearch')
32
-
33
- Returns:
34
- bool: True if collection was updated, False if no update was needed
35
- """
36
- collection = collection_doc["_source"]
37
- collection_id = collection.get("id", collection_doc["_id"])
38
-
39
- # Use the shared function to add bbox_shape
40
- was_added = add_bbox_shape_to_collection(collection)
41
-
42
- if not was_added:
43
- return False
44
-
45
- # Update the collection in the database
46
- if backend == "elasticsearch":
47
- await client.index(
48
- index=COLLECTIONS_INDEX,
49
- id=collection_id,
50
- document=collection,
51
- refresh=True,
52
- )
53
- else: # opensearch
54
- await client.index(
55
- index=COLLECTIONS_INDEX,
56
- id=collection_id,
57
- body=collection,
58
- refresh=True,
59
- )
60
-
61
- logger.info(f"Collection '{collection_id}': Added bbox_shape field")
62
- return True
63
-
64
-
65
- async def run_add_bbox_shape(backend):
66
- """Add bbox_shape field to all existing collections.
67
-
68
- Args:
69
- backend: Backend type ('elasticsearch' or 'opensearch')
70
- """
71
- import os
72
-
73
- logger.info(
74
- f"Starting migration: Adding bbox_shape to existing collections ({backend})"
75
- )
76
-
77
- # Log connection info (showing what will be used by the client)
78
- es_host = os.getenv("ES_HOST", "localhost")
79
- es_port = os.getenv(
80
- "ES_PORT", "9200"
81
- ) # Both backends default to 9200 in their config
82
- es_use_ssl = os.getenv("ES_USE_SSL", "true")
83
- logger.info(f"Connecting to {backend} at {es_host}:{es_port} (SSL: {es_use_ssl})")
84
-
85
- # Create client based on backend
86
- if backend == "elasticsearch":
87
- from stac_fastapi.elasticsearch.config import AsyncElasticsearchSettings
88
-
89
- settings = AsyncElasticsearchSettings()
90
- else: # opensearch
91
- from stac_fastapi.opensearch.config import AsyncOpensearchSettings
92
-
93
- settings = AsyncOpensearchSettings()
94
-
95
- client = settings.create_client
96
-
97
- try:
98
- # Get all collections
99
- response = await client.search(
100
- index=COLLECTIONS_INDEX,
101
- body={
102
- "query": {"match_all": {}},
103
- "size": 10000,
104
- }, # Adjust size if you have more collections
105
- )
106
-
107
- total_collections = response["hits"]["total"]["value"]
108
- logger.info(f"Found {total_collections} collections to process")
109
-
110
- updated_count = 0
111
- skipped_count = 0
112
-
113
- for hit in response["hits"]["hits"]:
114
- was_updated = await process_collection_bbox_shape(client, hit, backend)
115
- if was_updated:
116
- updated_count += 1
117
- else:
118
- skipped_count += 1
119
-
120
- logger.info(
121
- f"Migration complete: {updated_count} collections updated, {skipped_count} skipped"
122
- )
123
-
124
- except Exception as e:
125
- logger.error(f"Migration failed with error: {e}")
126
- raise
127
- finally:
128
- await client.close()
129
-
130
-
131
32
  @click.group()
132
- @click.version_option(version="0.1.0", prog_name="sfeos-tools")
33
+ @click.version_option(version=__version__, prog_name="sfeos-tools")
133
34
  def cli():
134
35
  """SFEOS Tools - Utilities for managing stac-fastapi-elasticsearch-opensearch deployments."""
135
36
  pass
@@ -332,5 +233,47 @@ def reindex(backend, host, port, use_ssl, user, password, yes):
332
233
  sys.exit(1)
333
234
 
334
235
 
236
+ @cli.command("load-data")
237
+ @click.option("--base-url", required=True, help="Base URL of the STAC API")
238
+ @click.option(
239
+ "--collection-id",
240
+ default="test-collection",
241
+ help="ID of the collection to which items are added",
242
+ )
243
+ @click.option("--use-bulk", is_flag=True, help="Use bulk insert method for items")
244
+ @click.option(
245
+ "--data-dir",
246
+ type=click.Path(exists=True),
247
+ default="sample_data/",
248
+ help="Directory containing collection.json and feature collection file",
249
+ )
250
+ def load_data(base_url: str, collection_id: str, use_bulk: bool, data_dir: str) -> None:
251
+ """Load STAC items into the database via STAC API.
252
+
253
+ This command loads a STAC collection and its items from local JSON files
254
+ into a STAC API instance. It expects a directory containing:
255
+ - collection.json: The STAC collection definition
256
+ - One or more feature collection JSON files with STAC items
257
+
258
+ Examples:
259
+ sfeos-tools load-data --base-url http://localhost:8080
260
+ sfeos-tools load-data --base-url http://localhost:8080 --collection-id my-collection --use-bulk
261
+ sfeos-tools load-data --base-url http://localhost:8080 --data-dir /path/to/data
262
+ """
263
+ from httpx import Client
264
+
265
+ try:
266
+ with Client(base_url=base_url) as client:
267
+ load_items(client, collection_id, use_bulk, data_dir)
268
+ click.echo(click.style("✓ Data loading completed successfully", fg="green"))
269
+ except KeyboardInterrupt:
270
+ click.echo(click.style("\n✗ Data loading interrupted by user", fg="yellow"))
271
+ sys.exit(1)
272
+ except Exception as e:
273
+ error_msg = str(e)
274
+ click.echo(click.style(f"✗ Data loading failed: {error_msg}", fg="red"))
275
+ sys.exit(1)
276
+
277
+
335
278
  if __name__ == "__main__":
336
279
  cli()
@@ -0,0 +1,102 @@
1
+ """Data Loader CLI STAC_API Ingestion Tool."""
2
+
3
+ import os
4
+ from typing import Any
5
+
6
+ import click
7
+ import orjson
8
+ from httpx import Client
9
+
10
+
11
+ def load_data(filepath: str) -> dict[str, Any]:
12
+ """Load json data from a file within the specified data directory."""
13
+ try:
14
+ with open(filepath, "rb") as file:
15
+ return orjson.loads(file.read())
16
+ except FileNotFoundError as e:
17
+ click.secho(f"File not found: {filepath}", fg="red", err=True)
18
+ raise click.Abort() from e
19
+
20
+
21
+ def load_collection(client: Client, collection_id: str, data_dir: str) -> None:
22
+ """Load a STAC collection into the database."""
23
+ collection = load_data(os.path.join(data_dir, "collection.json"))
24
+ collection["id"] = collection_id
25
+ resp = client.post("/collections", json=collection)
26
+ if resp.status_code == 200 or resp.status_code == 201:
27
+ click.echo(f"Status code: {resp.status_code}")
28
+ click.echo(f"Added collection: {collection['id']}")
29
+ elif resp.status_code == 409:
30
+ click.echo(f"Status code: {resp.status_code}")
31
+ click.echo(f"Collection: {collection['id']} already exists")
32
+ else:
33
+ click.echo(f"Status code: {resp.status_code}")
34
+ click.echo(f"Error writing {collection['id']} collection. Message: {resp.text}")
35
+
36
+
37
+ def load_items(
38
+ client: Client, collection_id: str, use_bulk: bool, data_dir: str
39
+ ) -> None:
40
+ """Load STAC items into the database based on the method selected."""
41
+ with os.scandir(data_dir) as entries:
42
+ # Attempt to dynamically find a suitable feature collection file
43
+ # Use the first found feature collection file
44
+ feature_file = next(
45
+ (
46
+ entry.path
47
+ for entry in entries
48
+ if entry.is_file()
49
+ and entry.name.endswith(".json")
50
+ and entry.name != "collection.json"
51
+ ),
52
+ None,
53
+ )
54
+
55
+ if feature_file is None:
56
+ click.secho(
57
+ "No feature collection files found in the specified directory.",
58
+ fg="red",
59
+ err=True,
60
+ )
61
+ raise click.Abort()
62
+
63
+ feature_collection = load_data(feature_file)
64
+
65
+ load_collection(client, collection_id, data_dir)
66
+ if use_bulk:
67
+ load_items_bulk_insert(client, collection_id, feature_collection)
68
+ else:
69
+ load_items_one_by_one(client, collection_id, feature_collection)
70
+
71
+
72
+ def load_items_one_by_one(
73
+ client: Client, collection_id: str, feature_collection: dict[str, Any]
74
+ ) -> None:
75
+ """Load STAC items into the database one by one."""
76
+ for feature in feature_collection["features"]:
77
+ feature["collection"] = collection_id
78
+ resp = client.post(f"/collections/{collection_id}/items", json=feature)
79
+ if resp.status_code == 200:
80
+ click.echo(f"Status code: {resp.status_code}")
81
+ click.echo(f"Added item: {feature['id']}")
82
+ elif resp.status_code == 409:
83
+ click.echo(f"Status code: {resp.status_code}")
84
+ click.echo(f"Item: {feature['id']} already exists")
85
+
86
+
87
+ def load_items_bulk_insert(
88
+ client: Client, collection_id: str, feature_collection: dict[str, Any]
89
+ ) -> None:
90
+ """Load STAC items into the database via bulk insert."""
91
+ for feature in feature_collection["features"]:
92
+ feature["collection"] = collection_id
93
+ resp = client.post(f"/collections/{collection_id}/items", json=feature_collection)
94
+ if resp.status_code == 200:
95
+ click.echo(f"Status code: {resp.status_code}")
96
+ click.echo("Bulk inserted items successfully.")
97
+ elif resp.status_code == 204:
98
+ click.echo(f"Status code: {resp.status_code}")
99
+ click.echo("Bulk update successful, no content returned.")
100
+ elif resp.status_code == 409:
101
+ click.echo(f"Status code: {resp.status_code}")
102
+ click.echo("Conflict detected, some items might already exist.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sfeos-tools
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: CLI tools for managing stac-fastapi-elasticsearch-opensearch deployments
5
5
  Author: CloudFerro S.A.
6
6
  Author-email: Jonathan Healy <jon@healy-hypersaptial.dev>
@@ -35,11 +35,12 @@ Classifier: Development Status :: 4 - Beta
35
35
  Classifier: Intended Audience :: Developers
36
36
  Classifier: Intended Audience :: Science/Research
37
37
  Classifier: License :: OSI Approved :: MIT License
38
- Classifier: Programming Language :: Python :: 3.8
39
38
  Classifier: Programming Language :: Python :: 3.9
40
39
  Classifier: Programming Language :: Python :: 3.10
41
40
  Classifier: Programming Language :: Python :: 3.11
42
41
  Classifier: Programming Language :: Python :: 3.12
42
+ Classifier: Programming Language :: Python :: 3.13
43
+ Classifier: Programming Language :: Python :: 3.14
43
44
  Classifier: Topic :: Scientific/Engineering
44
45
  Classifier: Topic :: Scientific/Engineering :: GIS
45
46
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
@@ -47,14 +48,17 @@ Requires-Python: >=3.8
47
48
  Description-Content-Type: text/markdown
48
49
  License-File: LICENSE
49
50
  Requires-Dist: click>=8.0.0
51
+ Requires-Dist: httpx>=0.24.0
52
+ Requires-Dist: orjson>=3.0.0
50
53
  Provides-Extra: elasticsearch
51
- Requires-Dist: stac-fastapi-elasticsearch; extra == "elasticsearch"
54
+ Requires-Dist: stac-fastapi-elasticsearch>=6.6.0; extra == "elasticsearch"
52
55
  Provides-Extra: opensearch
53
- Requires-Dist: stac-fastapi-opensearch; extra == "opensearch"
56
+ Requires-Dist: stac-fastapi-opensearch>=6.6.0; extra == "opensearch"
54
57
  Provides-Extra: dev
55
- Requires-Dist: stac-fastapi-elasticsearch; extra == "dev"
56
- Requires-Dist: stac-fastapi-opensearch; extra == "dev"
58
+ Requires-Dist: stac-fastapi-elasticsearch>=6.6.0; extra == "dev"
59
+ Requires-Dist: stac-fastapi-opensearch>=6.6.0; extra == "dev"
57
60
  Requires-Dist: pytest>=6.0; extra == "dev"
61
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
58
62
  Requires-Dist: pytest-cov>=2.0; extra == "dev"
59
63
  Requires-Dist: black>=21.0; extra == "dev"
60
64
  Requires-Dist: isort>=5.0; extra == "dev"
@@ -66,6 +70,22 @@ Dynamic: license-file
66
70
 
67
71
  CLI tools for managing [stac-fastapi-elasticsearch-opensearch](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch) deployments.
68
72
 
73
+ <!-- markdownlint-disable MD033 MD041 -->
74
+
75
+
76
+ <p align="left">
77
+ <img src="https://raw.githubusercontent.com/stac-utils/stac-fastapi-elasticsearch-opensearch/refs/heads/main/assets/sfeos.png" width=1000>
78
+ </p>
79
+
80
+ <!-- **Jump to:** [Project Introduction](#project-introduction---what-is-sfeos) | [Quick Start](#quick-start) | [Table of Contents](#table-of-contents) -->
81
+
82
+ [![Downloads](https://static.pepy.tech/badge/sfeos-tools?color=blue)](https://pepy.tech/project/sfeos-tools)
83
+ [![GitHub contributors](https://img.shields.io/github/contributors/healy-hyperspatial/sfeos-tools?color=blue)](https://github.com/healy-hyperspatial/sfeos-tools/graphs/contributors)
84
+ [![GitHub stars](https://img.shields.io/github/stars/healy-hyperspatial/sfeos-tools.svg?color=blue)](https://github.com/healy-hyperspatial/sfeos-tools/stargazers)
85
+ [![GitHub forks](https://img.shields.io/github/forks/healy-hyperspatial/sfeos-tools.svg?color=blue)](https://github.com/healy-hyperspatial/sfeos-tools/network/members)
86
+ [![PyPI version](https://img.shields.io/pypi/v/sfeos-tools.svg?color=blue)](https://pypi.org/project/sfeos-tools/)
87
+ [![STAC](https://img.shields.io/badge/STAC-1.1.0-blue.svg)](https://github.com/radiantearth/stac-spec/tree/v1.1.0)
88
+
69
89
  ## Table of Contents
70
90
 
71
91
  - [Installation](#installation)
@@ -76,6 +96,7 @@ CLI tools for managing [stac-fastapi-elasticsearch-opensearch](https://github.co
76
96
  - [Commands](#commands)
77
97
  - [add-bbox-shape](#add-bbox-shape)
78
98
  - [reindex](#reindex)
99
+ - [load-data](#load-data)
79
100
  - [Development](#development)
80
101
  - [License](#license)
81
102
 
@@ -165,62 +186,55 @@ Options:
165
186
  - `--password`: Database password (default: ES_PASS env var)
166
187
  - `--yes`: Skip confirmation prompt
167
188
 
168
- Example:
189
+ Examples:
169
190
  ```bash
170
191
  # Reindex Elasticsearch with custom host and no SSL
171
- sfeos-tools reindex --backend elasticsearch --host localhost --port 9200 --no-ssl
192
+ sfeos-tools reindex --backend elasticsearch --host localhost --port 9200 --no-ssl --yes
172
193
 
173
194
  # Reindex OpenSearch with default settings
174
- sfeos-tools reindex --backend opensearch
195
+ sfeos-tools reindex --backend opensearch --yes
175
196
  ```
176
197
 
177
- # Get help for a specific command
178
- sfeos-tools add-bbox-shape --help
179
- ```
180
-
181
- ## Commands
182
-
183
- ### add-bbox-shape
184
-
185
- Add `bbox_shape` field to existing collections for spatial search support.
198
+ ### load-data
186
199
 
187
- **Basic usage:**
200
+ Load STAC collections and items from local JSON files into a STAC API instance. This command is useful for:
201
+ - Populating a new STAC API deployment with test data
202
+ - Migrating data between STAC API instances
203
+ - Bulk loading STAC collections and items
188
204
 
189
205
  ```bash
190
- # Elasticsearch
191
- sfeos-tools add-bbox-shape --backend elasticsearch
192
-
193
- # OpenSearch
194
- sfeos-tools add-bbox-shape --backend opensearch
206
+ sfeos-tools load-data --base-url <stac-api-url> [options]
195
207
  ```
196
208
 
197
- **Connection options:**
209
+ Options:
210
+ - `--base-url`: Base URL of the STAC API (required)
211
+ - `--collection-id`: ID of the collection to create/update (default: test-collection)
212
+ - `--data-dir`: Directory containing collection.json and feature collection files (default: sample_data/)
213
+ - `--use-bulk`: Use bulk insert method for items (faster for large datasets)
198
214
 
199
- ```bash
200
- # Local Docker Compose (no SSL)
201
- sfeos-tools add-bbox-shape --backend elasticsearch --no-ssl
202
-
203
- # Remote server with SSL
204
- sfeos-tools add-bbox-shape \
205
- --backend elasticsearch \
206
- --host db.example.com \
207
- --port 9200 \
208
- --user admin \
209
- --password secret
210
-
211
- # Using environment variables
212
- ES_HOST=my-cluster.cloud.com ES_PORT=9243 ES_USER=elastic ES_PASS=changeme \
213
- sfeos-tools add-bbox-shape --backend elasticsearch
214
- ```
215
+ **Data Directory Structure:**
215
216
 
216
- **Available options:**
217
+ Your data directory should contain:
218
+ - `collection.json`: STAC collection definition
219
+ - One or more `.json` files: Feature collections with STAC items
217
220
 
218
- - `--backend`: Database backend (elasticsearch or opensearch) - **required**
219
- - `--host`: Database host (default: localhost or ES_HOST env var)
220
- - `--port`: Database port (default: 9200 or ES_PORT env var)
221
- - `--use-ssl / --no-ssl`: Use SSL connection (default: true or ES_USE_SSL env var)
222
- - `--user`: Database username (default: ES_USER env var)
223
- - `--password`: Database password (default: ES_PASS env var)
221
+ Examples:
222
+ ```bash
223
+ # Load data from default directory
224
+ sfeos-tools load-data --base-url http://localhost:8080
225
+
226
+ # Load with custom collection ID and bulk insert
227
+ sfeos-tools load-data \
228
+ --base-url http://localhost:8080 \
229
+ --collection-id my-collection \
230
+ --use-bulk
231
+
232
+ # Load from custom directory
233
+ sfeos-tools load-data \
234
+ --base-url http://localhost:8080 \
235
+ --data-dir /path/to/stac/data \
236
+ --collection-id production-data
237
+ ```
224
238
 
225
239
  ## Development
226
240
 
@@ -241,3 +255,6 @@ pre-commit install
241
255
  pre-commit run --all-files
242
256
  ```
243
257
 
258
+ ## License
259
+
260
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,11 @@
1
+ sfeos_tools/__init__.py,sha256=E6dzjiV5qnPvtjRAEfXy3lS6yqgS6olUV9gW3rnKo2Y,117
2
+ sfeos_tools/bbox_shape.py,sha256=lL7vq-lD36XKcZ4ScZF6tDs-KRW9DHCiDquXaE9gL9A,3491
3
+ sfeos_tools/cli.py,sha256=eTm7cfyuYU8x2KQ3ORBMmbw2AX1Ys3ct2tkjbzOBwQc,8838
4
+ sfeos_tools/data_loader.py,sha256=dh_JL7qxIYajVS4Dhz2hJRSJ-L1k-c_6K4V8VXgumcs,3876
5
+ sfeos_tools/reindex.py,sha256=JIglWrRxvmrSwsTSqKrhqcTJgNKP_5blcNxujFesbgw,4277
6
+ sfeos_tools-0.2.0.dist-info/licenses/LICENSE,sha256=euoUdQTBFz_vxdUnYkUnTUeAtrzfmJnBmGrO3NceeO8,1111
7
+ sfeos_tools-0.2.0.dist-info/METADATA,sha256=4I8ebe3FciZ6WsYMC-Q3ZSg_fFgivMJ6G_WmM-7mCV8,9394
8
+ sfeos_tools-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
+ sfeos_tools-0.2.0.dist-info/entry_points.txt,sha256=fgwnuQndU6x7RNOw4twi0ZkqDFgb5HOijB-wRuo1cp8,52
10
+ sfeos_tools-0.2.0.dist-info/top_level.txt,sha256=wBLaEvh7OmhjMhGluVm2vwE0ufSuc90eHrlTph-51kM,12
11
+ sfeos_tools-0.2.0.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- sfeos_tools/__init__.py,sha256=E6dzjiV5qnPvtjRAEfXy3lS6yqgS6olUV9gW3rnKo2Y,117
2
- sfeos_tools/cli.py,sha256=eUauJIRjuQZfrZPTfXAMDm_cn4oFNNi1eJWTkcZh-0U,10209
3
- sfeos_tools/reindex.py,sha256=JIglWrRxvmrSwsTSqKrhqcTJgNKP_5blcNxujFesbgw,4277
4
- sfeos_tools-0.1.0.dist-info/licenses/LICENSE,sha256=euoUdQTBFz_vxdUnYkUnTUeAtrzfmJnBmGrO3NceeO8,1111
5
- sfeos_tools-0.1.0.dist-info/METADATA,sha256=1aHsyPTxW28AjEyOSAt-YkeBhWWsbQoKxwh27P3TIjU,7772
6
- sfeos_tools-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
- sfeos_tools-0.1.0.dist-info/entry_points.txt,sha256=fgwnuQndU6x7RNOw4twi0ZkqDFgb5HOijB-wRuo1cp8,52
8
- sfeos_tools-0.1.0.dist-info/top_level.txt,sha256=wBLaEvh7OmhjMhGluVm2vwE0ufSuc90eHrlTph-51kM,12
9
- sfeos_tools-0.1.0.dist-info/RECORD,,