Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add write option for geopackage and geoparquet #42

Merged
merged 15 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ click < 9
geopandas >= 0.13, < 0.15
osmium < 3.7
pandas >= 1.5, < 3
pyarrow >= 15.0.2, < 16
pyproj >= 3.1.0, < 4
Rtree >= 1, < 2
shapely >= 1, < 3
1 change: 1 addition & 0 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mkdocs-material >= 9.4, < 10
mkdocs-click < 0.7
mkdocstrings-python < 2
pre-commit < 4
pyarrow >= 15.0.2, < 16
brynpickering marked this conversation as resolved.
Show resolved Hide resolved
pytest >= 8, < 9
pytest-cov < 5
pytest-mock < 4
Expand Down
44 changes: 31 additions & 13 deletions src/osmox/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os

import click
import pyproj

from osmox import build, config
from osmox.helpers import PathPath, path_leaf
Expand Down Expand Up @@ -40,6 +41,13 @@ def validate(config_path):
@click.argument("config_path", type=PathPath(exists=True), nargs=1, required=True)
@click.argument("input_path", type=PathPath(exists=True), nargs=1, required=True)
@click.argument("output_name", nargs=1, required=True)
@click.option(
"-f",
"--format",
type=click.Choice(["geojson", "geopackage", "geoparquet"]),
default="geopackage",
help="Output file format (default: geopackage)",
)
@click.option(
"-crs",
"--crs",
Expand All @@ -59,7 +67,7 @@ def validate(config_path):
is_flag=True,
help="if filtered object already has a label, do not search for more (supresses multi-use)",
)
def run(config_path, input_path, output_name, crs, single_use, lazy):
def run(config_path, input_path, output_name, format, crs, single_use, lazy):
logger.info(f" Loading config from {config_path}")
cnfg = config.load(config_path)
config.validate_activity_config(cnfg)
Expand Down Expand Up @@ -107,17 +115,27 @@ def run(config_path, input_path, output_name, crs, single_use, lazy):

gdf = handler.geodataframe(single_use=single_use)

path = path_leaf(input_path) / f"{output_name}_{crs.replace(':', '_')}.geojson"
logger.info(f" Writting objects to: {path}")
with open(path, "w") as file:
file.write(gdf.to_json())

if not crs == "epsg:4326":
logger.info(" Reprojecting output to epsg:4326 (lat lon)")
gdf.to_crs("epsg:4326", inplace=True)
path = path_leaf(input_path) / f"{output_name}_epsg_4326.geojson"
logger.info(f" Writting objects to: {path}")
with open(path, "w") as file:
file.write(gdf.to_json())
if format == "geojson":
extension = "geojson"
writer_method = 'to_file'
kwargs = {"driver": 'GeoJSON'}
elif format == "geopackage":
extension = "gpkg"
writer_method = 'to_file'
kwargs = {"driver": 'GPKG'}
elif format == "geoparquet":
extension = "parquet"
writer_method = 'to_parquet'
kwargs = {}

logger.info(f" Writing objects to {format} format.")
output_filename = f"{output_name}_{crs.replace(':', '_')}.{extension}"

getattr(gdf, writer_method)(output_filename, **kwargs)

if pyproj.CRS(crs) != pyproj.CRS("epsg:4326"):
logger.info(" Reprojecting additional output to EPSG:4326 (lat lon)")
gdf_4326 = gdf.to_crs("epsg:4326")
getattr(gdf_4326, writer_method)(f"{output_name}_epsg_4326.{extension}", **kwargs)

logger.info("Done.")
54 changes: 54 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import logging
import os
import traceback

import pytest
from click.testing import CliRunner
from osmox import cli

logging.basicConfig(level=logging.INFO)


@pytest.fixture
def fixtures_root():
return os.path.abspath(os.path.join(os.path.dirname(__file__), "fixtures"))


@pytest.fixture
def config_path(fixtures_root):
return os.path.join(fixtures_root, "test_config.json")


@pytest.fixture
def toy_osm_path(fixtures_root):
return os.path.join(fixtures_root, "park.osm")


@pytest.fixture
def runner():
return CliRunner()


def check_exit_code(result):
"Print full traceback if the CLI runner failed"
if result.exit_code != 0:
traceback.print_tb(result.exc_info[-1])
assert result.exit_code == 0


def test_cli_with_default_args(runner, config_path, toy_osm_path):
# Test the command with minimal arguments
result = runner.invoke(cli.run, [config_path, toy_osm_path, "output_test"])

check_exit_code(result)
brynpickering marked this conversation as resolved.
Show resolved Hide resolved
assert "geopackage" in result.exit_code
assert "epsg:4326" in result.exit_code


def test_cli_output_formats(runner, config_path, toy_osm_path):
for output_format in ["geojson", "geopackage", "geoparquet"]:
brynpickering marked this conversation as resolved.
Show resolved Hide resolved
result = runner.invoke(
cli.run,
[config_path, toy_osm_path, "output_test", "-f", output_format, "-crs", "epsg:4326"],
)
check_exit_code(result)
Loading