Skip to content

Commit

Permalink
fix: CLI options and validators (#8)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
HideBa authored May 4, 2024
1 parent 288b6a0 commit b581d5f
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 20 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# AHN CLI

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![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)
[![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)
[![CICD Status: Passing](https://img.shields.io/badge/CICD-Passing-brightgreen.svg)](https://github.com/HideBa/ahn-cli/actions)

## Description
Expand Down
9 changes: 5 additions & 4 deletions ahn_cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

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


@click.command()
@click.version_option(version="0.1.8", prog_name="ahn_cli")
@click.version_option(version="0.2.0", prog_name="ahn_cli")
@click.option(
"-o",
"--output",
type=str,
required=True,
help="Set the name of the output file where the data will be saved.",
)
@click.option(
Expand Down
38 changes: 24 additions & 14 deletions ahn_cli/validator.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import os
import geopandas as gpd

from click import ClickException
from ahn_cli import config

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


def validate_output(output: str) -> str:
if output is None:
raise ValueError("Output path is required.")
raise ClickException("Output path is required.")
if not os.path.exists(os.path.dirname(output)):
raise ValueError("Output directory does not exist.")
raise ClickException("Output directory does not exist.")
return output


def validate_city(cityname: str, cityfile_path: str) -> str:
if cityname is None:
raise ValueError("City name is required.")
raise ClickException("City name is required.")
city_df = gpd.read_file(cityfile_path)
if cityname.lower() not in city_df["name"].str.lower().tolist():
raise ValueError("City name not found in city list.")
raise ClickException(
"City name not found in city list. Please check if city name is correct."
)
return cityname


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


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


Expand All @@ -48,7 +50,7 @@ def validate_include_exclude(
return
for c in include_classes:
if c in exclude_classes:
raise ValueError(
raise ClickException(
f"Class {c} is in both include and exclude classes."
)

Expand All @@ -57,36 +59,43 @@ def validate_clip_file(clip_file: str | None) -> str | None:
if clip_file is None:
return None
if not os.path.exists(clip_file):
raise ValueError("Clip file does not exist.")
raise ClickException("Clip file does not exist.")
return clip_file


def validate_epsg(epsg: int | None) -> int | None:
if epsg is None:
return None
if epsg < 1000 or epsg > 999999:
raise ValueError("EPSG code is not valid.")
raise ClickException("EPSG code is not valid.")
return epsg


def validate_decimate(decimate: int | None) -> int | None:
if decimate is None:
return None
if decimate < 1:
raise ValueError("Decimate must be greater than 0.")
raise ClickException("Decimate must be greater than 0.")
return decimate


def validate_bbox(bbox: list[float] | None) -> list[float] | None:
if bbox is None:
return None
if len(bbox) != 4:
raise ValueError("Bounding box must have 4 coordinates.")
raise ClickException("Bounding box must have 4 coordinates.")
if bbox[0] >= bbox[2] or bbox[1] >= bbox[3]:
raise ValueError("Bounding box coordinates are not valid.")
raise ClickException("Bounding box coordinates are not valid.")
return bbox


def validate_exclusive_args(bbox: list[float] | None, cityname: str) -> None:
if bbox is not None and cityname is not None:
raise ClickException(
"Cannot specify both a bounding box and a city name."
)


def validate_all(
cfg: config.Config,
output_path: str,
Expand All @@ -109,4 +118,5 @@ def validate_all(
validate_epsg(epsg)
validate_decimate(decimate)
validate_bbox(bbox)
validate_exclusive_args(bbox, city_name)
return True
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "ahn_cli"
version = "0.1.8"
version = "0.2.0"
description = ""
authors = ["HideBa <baba.papa1120.ba@gmail.com>"]
license = "MIT"
Expand Down
42 changes: 42 additions & 0 deletions renovate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"extends": [
"config:base"
],
"prConcurrentLimit": 0,
"rebaseWhen": "never",
"masterIssue": true,
"poetry": {
"fileMatch": [
"pyproject.toml"
]
},
"pip_requirements": {
"fileMatch": [
"requirements.txt"
]
},
"ignorePaths": [],
"packageRules": [
{
"matchUpdateTypes": [
"minor"
],
"extends": [
"schedule:monthly"
]
},
{
"matchUpdateTypes": [
"patch"
],
"extends": [
"schedule:quarterly"
]
}
],
"vulnerabilityAlerts": {
"schedule": [
"at any time"
]
}
}

0 comments on commit b581d5f

Please sign in to comment.