del env py

This commit is contained in:
2024-10-11 17:10:34 -07:00
parent 55b630e6c8
commit b010ab0e6d
19334 changed files with 1 additions and 4003544 deletions

View File

@@ -1,154 +0,0 @@
"""cligj
A package of arguments, options, and parsers for the Python GeoJSON
ecosystem.
"""
import sys
from warnings import warn
import click
from .features import normalize_feature_inputs
__version__ = "0.7.2"
if sys.version_info < (3, 6):
warn("cligj 1.0.0 will require Python >= 3.6", FutureWarning)
# Multiple input files.
files_in_arg = click.argument(
'files',
nargs=-1,
type=click.Path(resolve_path=True),
required=True,
metavar="INPUTS...")
# Multiple files, last of which is an output file.
files_inout_arg = click.argument(
'files',
nargs=-1,
type=click.Path(resolve_path=True),
required=True,
metavar="INPUTS... OUTPUT")
# Features from files, command line args, or stdin.
# Returns the input data as an iterable of GeoJSON Feature-like
# dictionaries.
features_in_arg = click.argument(
'features',
nargs=-1,
callback=normalize_feature_inputs,
metavar="FEATURES...")
# Options.
verbose_opt = click.option(
'--verbose', '-v',
count=True,
help="Increase verbosity.")
quiet_opt = click.option(
'--quiet', '-q',
count=True,
help="Decrease verbosity.")
# Format driver option.
format_opt = click.option(
'-f', '--format', '--driver', 'driver',
default='GTiff',
help="Output format driver")
# JSON formatting options.
indent_opt = click.option(
'--indent',
type=int,
default=None,
help="Indentation level for JSON output")
compact_opt = click.option(
'--compact/--not-compact',
default=False,
help="Use compact separators (',', ':').")
# Coordinate precision option.
precision_opt = click.option(
'--precision',
type=int,
default=-1,
help="Decimal precision of coordinates.")
# Geographic (default), projected, or Mercator switch.
projection_geographic_opt = click.option(
'--geographic',
'projection',
flag_value='geographic',
default=True,
help="Output in geographic coordinates (the default).")
projection_projected_opt = click.option(
'--projected',
'projection',
flag_value='projected',
help="Output in dataset's own, projected coordinates.")
projection_mercator_opt = click.option(
'--mercator',
'projection',
flag_value='mercator',
help="Output in Web Mercator coordinates.")
# Feature collection or feature sequence switch.
sequence_opt = click.option(
'--sequence/--no-sequence',
default=False,
help="Write a LF-delimited sequence of texts containing individual "
"objects or write a single JSON text containing a feature "
"collection object (the default).",
callback=lambda ctx, param, value: warn(
"Sequences of Features, not FeatureCollections, will be the default in version 1.0.0",
FutureWarning,
)
or value,
)
use_rs_opt = click.option(
'--rs/--no-rs',
'use_rs',
default=False,
help="Use RS (0x1E) as a prefix for individual texts in a sequence "
"as per http://tools.ietf.org/html/draft-ietf-json-text-sequence-13 "
"(default is False).")
def geojson_type_collection_opt(default=False):
"""GeoJSON FeatureCollection output mode"""
return click.option(
'--collection',
'geojson_type',
flag_value='collection',
default=default,
help="Output as GeoJSON feature collection(s).")
def geojson_type_feature_opt(default=False):
"""GeoJSON Feature or Feature sequence output mode"""
return click.option(
'--feature',
'geojson_type',
flag_value='feature',
default=default,
help="Output as GeoJSON feature(s).")
def geojson_type_bbox_opt(default=False):
"""GeoJSON bbox output mode"""
return click.option(
'--bbox',
'geojson_type',
flag_value='bbox',
default=default,
help="Output as GeoJSON bounding box array(s).")

View File

@@ -1,214 +0,0 @@
"""Feature parsing and normalization"""
from itertools import chain
import json
import re
import click
def normalize_feature_inputs(ctx, param, value):
"""Click callback that normalizes feature input values.
Returns a generator over features from the input value.
Parameters
----------
ctx: a Click context
param: the name of the argument or option
value: object
The value argument may be one of the following:
1. A list of paths to files containing GeoJSON feature
collections or feature sequences.
2. A list of string-encoded coordinate pairs of the form
"[lng, lat]", or "lng, lat", or "lng lat".
If no value is provided, features will be read from stdin.
Yields
------
Mapping
A GeoJSON Feature represented by a Python mapping
"""
for feature_like in value or ('-',):
try:
with click.open_file(feature_like, encoding="utf-8") as src:
for feature in iter_features(iter(src)):
yield feature
except IOError:
coords = list(coords_from_query(feature_like))
yield {
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'Point',
'coordinates': coords}}
def iter_features(geojsonfile, func=None):
"""Extract GeoJSON features from a text file object.
Given a file-like object containing a single GeoJSON feature
collection text or a sequence of GeoJSON features, iter_features()
iterates over lines of the file and yields GeoJSON features.
Parameters
----------
geojsonfile: a file-like object
The geojsonfile implements the iterator protocol and yields
lines of JSON text.
func: function, optional
A function that will be applied to each extracted feature. It
takes a feature object and may return a replacement feature or
None -- in which case iter_features does not yield.
Yields
------
Mapping
A GeoJSON Feature represented by a Python mapping
"""
func = func or (lambda x: x)
first_line = next(geojsonfile)
# Does the geojsonfile contain RS-delimited JSON sequences?
if first_line.startswith(u'\x1e'):
text_buffer = first_line.strip(u'\x1e')
for line in geojsonfile:
if line.startswith(u'\x1e'):
if text_buffer:
obj = json.loads(text_buffer)
if 'coordinates' in obj:
obj = to_feature(obj)
newfeat = func(obj)
if newfeat:
yield newfeat
text_buffer = line.strip(u'\x1e')
else:
text_buffer += line
# complete our parsing with a for-else clause.
else:
obj = json.loads(text_buffer)
if 'coordinates' in obj:
obj = to_feature(obj)
newfeat = func(obj)
if newfeat:
yield newfeat
# If not, it may contains LF-delimited GeoJSON objects or a single
# multi-line pretty-printed GeoJSON object.
else:
# Try to parse LF-delimited sequences of features or feature
# collections produced by, e.g., `jq -c ...`.
try:
obj = json.loads(first_line)
if obj['type'] == 'Feature':
newfeat = func(obj)
if newfeat:
yield newfeat
for line in geojsonfile:
newfeat = func(json.loads(line))
if newfeat:
yield newfeat
elif obj['type'] == 'FeatureCollection':
for feat in obj['features']:
newfeat = func(feat)
if newfeat:
yield newfeat
elif 'coordinates' in obj:
newfeat = func(to_feature(obj))
if newfeat:
yield newfeat
for line in geojsonfile:
newfeat = func(to_feature(json.loads(line)))
if newfeat:
yield newfeat
# Indented or pretty-printed GeoJSON features or feature
# collections will fail out of the try clause above since
# they'll have no complete JSON object on their first line.
# To handle these, we slurp in the entire file and parse its
# text.
except ValueError:
text = "".join(chain([first_line], geojsonfile))
obj = json.loads(text)
if obj['type'] == 'Feature':
newfeat = func(obj)
if newfeat:
yield newfeat
elif obj['type'] == 'FeatureCollection':
for feat in obj['features']:
newfeat = func(feat)
if newfeat:
yield newfeat
elif 'coordinates' in obj:
newfeat = func(to_feature(obj))
if newfeat:
yield newfeat
def to_feature(obj):
"""Converts an object to a GeoJSON Feature
Returns feature verbatim or wraps geom in a feature with empty
properties.
Raises
------
ValueError
Returns
-------
Mapping
A GeoJSON Feature represented by a Python mapping
"""
if obj['type'] == 'Feature':
return obj
elif 'coordinates' in obj:
return {
'type': 'Feature',
'properties': {},
'geometry': obj}
else:
raise ValueError("Object is not a feature or geometry")
def iter_query(query):
"""Accept a filename, stream, or string.
Returns an iterator over lines of the query."""
try:
itr = click.open_file(query).readlines()
except IOError:
itr = [query]
return itr
def coords_from_query(query):
"""Transform a query line into a (lng, lat) pair of coordinates."""
try:
coords = json.loads(query)
except ValueError:
query = query.replace(',', ' ')
vals = query.split()
coords = [float(v) for v in vals]
return tuple(coords[:2])
def normalize_feature_objects(feature_objs):
"""Takes an iterable of GeoJSON-like Feature mappings or
an iterable of objects with a geo interface and
normalizes it to the former."""
for obj in feature_objs:
if (
hasattr(obj, "__geo_interface__")
and "type" in obj.__geo_interface__.keys()
and obj.__geo_interface__["type"] == "Feature"
):
yield obj.__geo_interface__
elif isinstance(obj, dict) and "type" in obj and obj["type"] == "Feature":
yield obj
else:
raise ValueError("Did not recognize object as GeoJSON Feature")