query: add --warn-exceptions, dateparser, docs (#290)

* query: add --warn-exceptions, dateparser, docs

added --warn-exceptions (like --raise-exceptions/--drop-exceptions, but
lets you pass a warn_func if you want to customize how the exceptions are
handled. By default this creates a logger in main and logs the exception

added dateparser as a fallback if its installed (it's not a strong dependency, but
I mentioned in the docs that it's useful for parsing dates/times)

added docs for query, and a few examples

--output gpx respects the --{drop,warn,raise}--exceptions flags, have
an example of that in the docs as well
This commit is contained in:
seanbreckenridge 2023-04-17 16:15:35 -07:00 committed by GitHub
parent 82bc51d9fc
commit 7a32302d66
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 407 additions and 24 deletions

View file

@ -73,13 +73,28 @@ def parse_datetime_float(date_str: str) -> float:
return ds_float
try:
# isoformat - default format when you call str() on datetime
# this also parses dates like '2020-01-01'
return datetime.fromisoformat(ds).timestamp()
except ValueError:
pass
try:
return isoparse(ds).timestamp()
except (AssertionError, ValueError):
raise QueryException(f"Was not able to parse {ds} into a datetime")
pass
try:
import dateparser # type: ignore[import]
except ImportError:
pass
else:
# dateparser is a bit more lenient than the above, lets you type
# all sorts of dates as inputs
# https://github.com/scrapinghub/dateparser#how-to-use
res: Optional[datetime] = dateparser.parse(ds, settings={"DATE_ORDER": "YMD"})
if res is not None:
return res.timestamp()
raise QueryException(f"Was not able to parse {ds} into a datetime")
# probably DateLike input? but a user could specify an order_key
@ -267,6 +282,8 @@ def select_range(
limit: Optional[int] = None,
drop_unsorted: bool = False,
wrap_unsorted: bool = False,
warn_exceptions: bool = False,
warn_func: Optional[Callable[[Exception], None]] = None,
drop_exceptions: bool = False,
raise_exceptions: bool = False,
) -> Iterator[ET]:
@ -293,9 +310,15 @@ def select_range(
unparsed_range = None
# some operations to do before ordering/filtering
if drop_exceptions or raise_exceptions or where is not None:
if drop_exceptions or raise_exceptions or where is not None or warn_exceptions:
# doesn't wrap unsortable items, because we pass no order related kwargs
itr = select(itr, where=where, drop_exceptions=drop_exceptions, raise_exceptions=raise_exceptions)
itr = select(
itr,
where=where,
drop_exceptions=drop_exceptions,
raise_exceptions=raise_exceptions,
warn_exceptions=warn_exceptions,
warn_func=warn_func)
order_by_chosen: Optional[OrderFunc] = None