Skip to content

Commit b581d5f

Browse files
authored
fix: CLI options and validators (#8)
* feat: Add validation for exclusive arguments * feat: Update CLI options for city and bbox * chore: Update validator to return click's error message * fix: ahn classes * upgrade tag * chore: add renovate
1 parent 288b6a0 commit b581d5f

File tree

5 files changed

+73
-20
lines changed

5 files changed

+73
-20
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# AHN CLI
22

33
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
4-
[![Version: 1.0.0](https://img.shields.io/badge/Version-0.1.8-green.svg)](https://github.com/HideBa/ahn-cli/releases/tag/v0.1.8)
4+
[![Version: 0.2.0](https://img.shields.io/badge/Version-0.2.0-green.svg)](https://github.com/HideBa/ahn-cli/releases/tag/v0.2.0)
55
[![CICD Status: Passing](https://img.shields.io/badge/CICD-Passing-brightgreen.svg)](https://github.com/HideBa/ahn-cli/actions)
66

77
## Description

ahn_cli/main.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
"""
1111
Options:
12-
-c, --city <city_name> Specify the name of the city to download point cloud data for.
13-
-o, --output <file> Set the name of the output file where the data will be saved.
12+
-c, --city <city_name> Required (when bbox is None): Specify the name of the city to download point cloud data for.
13+
-o, --output <file> Required: Set the name of the output file where the data will be saved.
1414
-i, --include-class <class> Include specific point cloud classes in the download.
1515
Classes should be specified in a comma-separated list.
1616
-e, --exclude-class <class> Exclude specific point cloud classes from the download.
@@ -20,7 +20,7 @@
2020
-cf, --clip-file <file> Specify a file path to a clipping boundary file. The tool will
2121
use this file to clip the point cloud data to a specific area.
2222
-e, --epsg <epsg> Set the EPSG code for user's clip file.
23-
-b, --bbox <bbox> Specify a bounding box to clip the point cloud data. It should be comma-separated list with minx,miny,maxx,maxy
23+
-b, --bbox <bbox> Required (when city is None): Specify a bounding box to clip the point cloud data. It should be comma-separated list with minx,miny,maxx,maxy
2424
-p, --preview Preview the point cloud data in a 3D viewer.
2525
-h, --help [category] Display help information. Optionally, specify a category to get
2626
more detailed help for a specific command.
@@ -29,11 +29,12 @@
2929

3030

3131
@click.command()
32-
@click.version_option(version="0.1.8", prog_name="ahn_cli")
32+
@click.version_option(version="0.2.0", prog_name="ahn_cli")
3333
@click.option(
3434
"-o",
3535
"--output",
3636
type=str,
37+
required=True,
3738
help="Set the name of the output file where the data will be saved.",
3839
)
3940
@click.option(

ahn_cli/validator.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
import os
22
import geopandas as gpd
3-
3+
from click import ClickException
44
from ahn_cli import config
55

6-
AHN_CLASSES = [0, 1, 2, 6, 7, 4, 6]
6+
AHN_CLASSES = [0, 1, 2, 6, 9, 14, 26]
77

88

99
def validate_output(output: str) -> str:
1010
if output is None:
11-
raise ValueError("Output path is required.")
11+
raise ClickException("Output path is required.")
1212
if not os.path.exists(os.path.dirname(output)):
13-
raise ValueError("Output directory does not exist.")
13+
raise ClickException("Output directory does not exist.")
1414
return output
1515

1616

1717
def validate_city(cityname: str, cityfile_path: str) -> str:
1818
if cityname is None:
19-
raise ValueError("City name is required.")
19+
raise ClickException("City name is required.")
2020
city_df = gpd.read_file(cityfile_path)
2121
if cityname.lower() not in city_df["name"].str.lower().tolist():
22-
raise ValueError("City name not found in city list.")
22+
raise ClickException(
23+
"City name not found in city list. Please check if city name is correct."
24+
)
2325
return cityname
2426

2527

@@ -28,7 +30,7 @@ def validate_include_classes(classes: list[int] | None) -> list[int] | None:
2830
return None
2931
for c in classes:
3032
if c not in AHN_CLASSES:
31-
raise ValueError(f"Class {c} is not a valid AHN class.")
33+
raise ClickException(f"Class {c} is not a valid AHN class.")
3234
return classes
3335

3436

@@ -37,7 +39,7 @@ def validate_exclude_classes(classes: list[int] | None) -> list[int] | None:
3739
return None
3840
for c in classes:
3941
if c not in AHN_CLASSES:
40-
raise ValueError(f"Class {c} is not a valid AHN class.")
42+
raise ClickException(f"Class {c} is not a valid AHN class.")
4143
return classes
4244

4345

@@ -48,7 +50,7 @@ def validate_include_exclude(
4850
return
4951
for c in include_classes:
5052
if c in exclude_classes:
51-
raise ValueError(
53+
raise ClickException(
5254
f"Class {c} is in both include and exclude classes."
5355
)
5456

@@ -57,36 +59,43 @@ def validate_clip_file(clip_file: str | None) -> str | None:
5759
if clip_file is None:
5860
return None
5961
if not os.path.exists(clip_file):
60-
raise ValueError("Clip file does not exist.")
62+
raise ClickException("Clip file does not exist.")
6163
return clip_file
6264

6365

6466
def validate_epsg(epsg: int | None) -> int | None:
6567
if epsg is None:
6668
return None
6769
if epsg < 1000 or epsg > 999999:
68-
raise ValueError("EPSG code is not valid.")
70+
raise ClickException("EPSG code is not valid.")
6971
return epsg
7072

7173

7274
def validate_decimate(decimate: int | None) -> int | None:
7375
if decimate is None:
7476
return None
7577
if decimate < 1:
76-
raise ValueError("Decimate must be greater than 0.")
78+
raise ClickException("Decimate must be greater than 0.")
7779
return decimate
7880

7981

8082
def validate_bbox(bbox: list[float] | None) -> list[float] | None:
8183
if bbox is None:
8284
return None
8385
if len(bbox) != 4:
84-
raise ValueError("Bounding box must have 4 coordinates.")
86+
raise ClickException("Bounding box must have 4 coordinates.")
8587
if bbox[0] >= bbox[2] or bbox[1] >= bbox[3]:
86-
raise ValueError("Bounding box coordinates are not valid.")
88+
raise ClickException("Bounding box coordinates are not valid.")
8789
return bbox
8890

8991

92+
def validate_exclusive_args(bbox: list[float] | None, cityname: str) -> None:
93+
if bbox is not None and cityname is not None:
94+
raise ClickException(
95+
"Cannot specify both a bounding box and a city name."
96+
)
97+
98+
9099
def validate_all(
91100
cfg: config.Config,
92101
output_path: str,
@@ -109,4 +118,5 @@ def validate_all(
109118
validate_epsg(epsg)
110119
validate_decimate(decimate)
111120
validate_bbox(bbox)
121+
validate_exclusive_args(bbox, city_name)
112122
return True

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "ahn_cli"
3-
version = "0.1.8"
3+
version = "0.2.0"
44
description = ""
55
authors = ["HideBa <[email protected]>"]
66
license = "MIT"

renovate.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"extends": [
3+
"config:base"
4+
],
5+
"prConcurrentLimit": 0,
6+
"rebaseWhen": "never",
7+
"masterIssue": true,
8+
"poetry": {
9+
"fileMatch": [
10+
"pyproject.toml"
11+
]
12+
},
13+
"pip_requirements": {
14+
"fileMatch": [
15+
"requirements.txt"
16+
]
17+
},
18+
"ignorePaths": [],
19+
"packageRules": [
20+
{
21+
"matchUpdateTypes": [
22+
"minor"
23+
],
24+
"extends": [
25+
"schedule:monthly"
26+
]
27+
},
28+
{
29+
"matchUpdateTypes": [
30+
"patch"
31+
],
32+
"extends": [
33+
"schedule:quarterly"
34+
]
35+
}
36+
],
37+
"vulnerabilityAlerts": {
38+
"schedule": [
39+
"at any time"
40+
]
41+
}
42+
}

0 commit comments

Comments
 (0)