Skip to content

Commit 6b8ee0c

Browse files
committed
Make creating extensions easier via CLI #22, v0.3.2
1 parent 6f03568 commit 6b8ee0c

File tree

6 files changed

+177
-4
lines changed

6 files changed

+177
-4
lines changed

CHANGELOG.md

+9-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
99

1010
### Added
1111

12-
- ...
12+
- `fiboa rename-extension` to quickly replace template placeholders in new extensions
1313

1414
### Changed
1515

@@ -27,6 +27,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
2727

2828
- ...
2929

30+
## [v0.3.2] - 2024-04-12
31+
32+
### Added
33+
34+
- `fiboa rename-extension` to quickly replace template placeholders in new extensions
35+
3036
## [v0.3.1] - 2024-04-11
3137

3238
### Added
@@ -130,7 +136,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
130136

131137
- First release
132138

133-
[Unreleased]: <https://github.com/fiboa/cli/compare/v0.3.1...main>
139+
[Unreleased]: <https://github.com/fiboa/cli/compare/v0.3.2...main>
140+
[v0.3.2]: <https://github.com/fiboa/cli/compare/v0.3.1...v0.3.2>
134141
[v0.3.1]: <https://github.com/fiboa/cli/compare/v0.3.0...v0.3.1>
135142
[v0.3.0]: <https://github.com/fiboa/cli/compare/v0.2.1...v0.3.0>
136143
[v0.2.1]: <https://github.com/fiboa/cli/compare/v0.2.0...v0.2.1>

README.md

+17
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,23 @@ To validate a fiboa Schema YAML file, you can for example run:
7777

7878
Check `fiboa validate-schema --help` for more details.
7979

80+
## Update an extension template with new names
81+
82+
Once you've created and git cloned a new extension, you can use the CLI
83+
to update all template placeholders with proper names.
84+
85+
For example, if your extension is meant to have
86+
- the title "Timestamps Extension",
87+
- the prefix `ts` (e.g. field `ts:created` or `ts:updated`),
88+
- is hosted at `https://github.io/fiboa/timestamps-extension`
89+
(organization: `fiboa`, repository `timestamps-extension`),
90+
- and you run fiboa in the folder of the extension.
91+
92+
Then the following command could be used:
93+
- `fiboa rename-extension . -t Timestamps -p ts -s timestamps-extension -o fiboa`
94+
95+
Check `fiboa rename-extension --help` for more details.
96+
8097
## Converter for existing datasets
8198

8299
To convert an existing dataset to fiboa using the pre-defined converters:

fiboa_cli/__init__.py

+42-1
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
from .create_geojson import create_geojson as create_geojson_
99
from .describe import describe as describe_
1010
from .jsonschema import jsonschema as jsonschema_
11+
from .rename_extension import rename_extension as rename_extension_
1112
from .validate import validate as validate_
1213
from .validate_schema import validate_schema as validate_schema_
1314
from .version import __version__, fiboa_version as fiboa_version_
14-
from .util import log, check_ext_schema_for_cli, valid_file_for_cli, valid_file_for_cli_with_ext, valid_files_folders_for_cli
15+
from .util import log, check_ext_schema_for_cli, valid_file_for_cli, valid_file_for_cli_with_ext, valid_files_folders_for_cli, valid_folder_for_cli
1516

1617
@click.group()
1718
@click.version_option(version=__version__)
@@ -304,13 +305,53 @@ def convert(dataset, out, cache, source_coop, collection):
304305
sys.exit(1)
305306

306307

308+
## RENAME EXTENSION
309+
@click.command()
310+
@click.argument('folder', nargs=1, callback=valid_folder_for_cli)
311+
@click.option(
312+
'--title', '-t',
313+
type=click.STRING,
314+
help='Title of the extension, e.g. `Timestamps`',
315+
required=True
316+
)
317+
@click.option(
318+
'--slug', '-s',
319+
type=click.STRING,
320+
help='Slug of the repository, e.g. for `https://github.com/fiboa/timestamps-extension` it would be `timestamps-extension`',
321+
required=True
322+
)
323+
@click.option(
324+
'--org', '-o',
325+
type=click.STRING,
326+
help='Slug of the GitHub Organization. Defaults to `fiboa`',
327+
default="fiboa"
328+
)
329+
@click.option(
330+
'--prefix', '-p',
331+
type=click.STRING,
332+
help='Prefix for the field, e.g. `time` if the fields should be `time:created` or `time:updated`. An empty string removed the prefix, not providing a prefix leaves it as is.',
333+
default=None
334+
)
335+
def rename_extension(folder, title, slug, org = "fiboa", prefix = None):
336+
"""
337+
Updates placeholders in an extension folder to the new name.
338+
"""
339+
log(f"fiboa CLI {__version__} - Rename placeholders in extensions\n", "success")
340+
try:
341+
rename_extension_(folder, title, slug, gh_org=org, prefix=prefix)
342+
except Exception as e:
343+
log(e, "error")
344+
sys.exit(1)
345+
346+
307347
cli.add_command(describe)
308348
cli.add_command(validate)
309349
cli.add_command(validate_schema)
310350
cli.add_command(create_geoparquet)
311351
cli.add_command(create_geojson)
312352
cli.add_command(jsonschema)
313353
cli.add_command(convert)
354+
cli.add_command(rename_extension)
314355

315356
if __name__ == '__main__':
316357
cli()

fiboa_cli/rename_extension.py

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import os
2+
import re
3+
4+
from .util import log
5+
from .create_geoparquet import create_geoparquet
6+
7+
def replace_in_str(content, search, replace):
8+
if isinstance(search, list) and isinstance(replace, list) and len(search) != len(replace):
9+
raise ValueError("Search and replace lists must have the same length")
10+
11+
if isinstance(search, str):
12+
return content.replace(search, replace)
13+
elif isinstance(search, re.Pattern):
14+
return content.replace(search, replace)
15+
elif isinstance(search, list) and isinstance(replace, list):
16+
for s, r in zip(search, replace):
17+
content = replace_in_str(content, s, r)
18+
return content
19+
elif isinstance(search, list):
20+
for s in search:
21+
content = replace_in_str(content, s, replace)
22+
return content
23+
else:
24+
raise ValueError(f"Invalid search type: {type(search)}")
25+
26+
def replace_in_file(file, search, replace):
27+
try:
28+
with open(file, "r+") as f:
29+
content = f.read()
30+
content = replace_in_str(content, search, replace)
31+
f.seek(0)
32+
f.write(content)
33+
f.truncate()
34+
log(f"Updated {file}", "success")
35+
except Exception as e:
36+
log(f"Can't update {file}: {e}", "error")
37+
38+
def rename_extension(folder, title, slug, gh_org = "fiboa", prefix = None):
39+
if prefix is None:
40+
prefix = "template"
41+
42+
README = os.path.join(folder, "README.md")
43+
CHANGELOG = os.path.join(folder, "CHANGELOG.md")
44+
PIPFILE = os.path.join(folder, "Pipfile")
45+
JSON_COLLECTION = os.path.join(folder, "examples/geojson/collection.json")
46+
GEOJSON_FEATURE = os.path.join(folder, "examples/geojson/example.json")
47+
GEOPARQUET = os.path.join(folder, "examples/geoparquet/example.parquet")
48+
SCHEMA = os.path.join(folder, "schema/schema.yaml")
49+
50+
if prefix == "":
51+
PREFIX_CODE = ""
52+
PREFIX_TITLE = "none"
53+
else:
54+
PREFIX_CODE = f"{prefix}:"
55+
PREFIX_TITLE = prefix
56+
57+
GH_SEARCH = [
58+
"/extension-template/",
59+
"fiboa.github.io"
60+
]
61+
GH_REPLACE = [
62+
f"/{slug}/",
63+
f"{gh_org}.github.io"
64+
]
65+
replace_in_file(PIPFILE, GH_SEARCH, GH_REPLACE)
66+
replace_in_file(JSON_COLLECTION, GH_SEARCH, GH_REPLACE)
67+
68+
replace_in_file(CHANGELOG, "/fiboa/extension-template/", f"/{gh_org}/{slug}/")
69+
70+
PREFIX_SEARCH = "template:"
71+
replace_in_file(GEOJSON_FEATURE, PREFIX_SEARCH, PREFIX_CODE)
72+
replace_in_file(SCHEMA, PREFIX_SEARCH, PREFIX_CODE)
73+
74+
README_SEARCH = GH_SEARCH + [
75+
"Template Extension",
76+
"- **Title:** Template",
77+
"- **Property Name Prefix:** template",
78+
"| template:"
79+
]
80+
README_REPLACE = GH_REPLACE + [
81+
f"{title} Extension",
82+
f"- **Title:** {title}",
83+
f"- **Property Name Prefix:** {PREFIX_TITLE}",
84+
f"| {PREFIX_CODE}"
85+
]
86+
replace_in_file(README, README_SEARCH, README_REPLACE)
87+
88+
try:
89+
config = {
90+
"files": [GEOJSON_FEATURE],
91+
"out": GEOPARQUET,
92+
"schema": None,
93+
"collection": JSON_COLLECTION,
94+
"extension_schemas": {
95+
f"https://{gh_org}.github.io/{slug}/v0.1.0/schema.yaml": SCHEMA
96+
}
97+
}
98+
create_geoparquet(config)
99+
except Exception as e:
100+
log(f"Can't update {GEOPARQUET}: {e}", "error")

fiboa_cli/util.py

+8
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,14 @@ def valid_file_for_cli_with_ext(value, extensions):
192192
return is_valid_file_uri(value, extensions)
193193

194194

195+
def valid_folder_for_cli(ctx, param, value):
196+
"""Determine if the input is a folder."""
197+
if os.path.exists(value) and os.path.isdir(value):
198+
return value
199+
else:
200+
raise click.BadParameter('Input must be an existing local folder')
201+
202+
195203
def get_collection(data, collection_path = None, basepath = None):
196204
# If the user provided a collection, enforce using it
197205
if collection_path is not None:

fiboa_cli/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__version__ = "0.3.1"
1+
__version__ = "0.3.2"
22
fiboa_version = "0.2.0"

0 commit comments

Comments
 (0)