move isoformat to compat, allow date, misc fixes

This commit is contained in:
Sean Breckenridge 2021-04-06 01:31:04 -07:00
parent 28fd9e4441
commit 8a8bec332e
5 changed files with 36 additions and 35 deletions

View file

@ -378,13 +378,14 @@ def query_hpi_functions(
pprint(res) pprint(res)
else: else:
# output == 'repl' # output == 'repl'
eprint(f"\nInteract with the results by using the {click.style('res', fg='green')} variable\n")
try: try:
import IPython # type: ignore[import] import IPython # type: ignore[import]
except ModuleNotFoundError: except ModuleNotFoundError:
eprint("'repl' requires ipython, install it with 'python3 -m pip install ipython'") eprint("'repl' typically uses ipython, install it with 'python3 -m pip install ipython'. falling back to stdlib...")
sys.exit(1) import code
code.interact(local=locals())
else: else:
eprint(f"\nInteract with the results by using the {click.style('res', fg='green')} variable\n")
IPython.embed() IPython.embed()
@ -502,35 +503,35 @@ def module_install_cmd(user: bool, module: str) -> None:
@click.option('-k', @click.option('-k',
'--order-key', '--order-key',
default=None, default=None,
type=click.STRING, type=str,
help='order by an object attribute or dict key on the individual objects returned by the HPI function') help='order by an object attribute or dict key on the individual objects returned by the HPI function')
@click.option('-t', @click.option('-t',
'--order-type', '--order-type',
default=None, default=None,
type=click.Choice(['datetime', 'int', 'float']), type=click.Choice(['datetime', 'date', 'int', 'float']),
help='order by searching for some type on the iterable') help='order by searching for some type on the iterable')
@click.option('--after', @click.option('--after',
default=None, default=None,
type=click.STRING, type=str,
help='while ordering, filter items for the key or type larger than or equal to this') help='while ordering, filter items for the key or type larger than or equal to this')
@click.option('--before', @click.option('--before',
default=None, default=None,
type=click.STRING, type=str,
help='while ordering, filter items for the key or type smaller than this') help='while ordering, filter items for the key or type smaller than this')
@click.option('--within', @click.option('--within',
default=None, default=None,
type=click.STRING, type=str,
help="a range 'after' or 'before' to filter items by. see above for further explanation") help="a range 'after' or 'before' to filter items by. see above for further explanation")
@click.option('--recent', @click.option('--recent',
default=None, default=None,
type=click.STRING, type=str,
help="a shorthand for '--order-type datetime --reverse --before now --within'. e.g. --recent 5d") help="a shorthand for '--order-type datetime --reverse --before now --within'. e.g. --recent 5d")
@click.option('--reverse/--no-reverse', @click.option('--reverse/--no-reverse',
default=False, default=False,
help='reverse the results returned from the functions') help='reverse the results returned from the functions')
@click.option('--limit', @click.option('--limit',
default=None, default=None,
type=click.INT, type=int,
help='limit the number of items returned from the (functions)') help='limit the number of items returned from the (functions)')
@click.option('--drop-unsorted', @click.option('--drop-unsorted',
default=False, default=False,
@ -592,11 +593,13 @@ def query_cmd(
hpi query --order-type datetime --after '2016-01-01 00:00:00' --before '2019-01-01 00:00:00' my.reddit.comments hpi query --order-type datetime --after '2016-01-01 00:00:00' --before '2019-01-01 00:00:00' my.reddit.comments
''' '''
from datetime import datetime from datetime import datetime, date
chosen_order_type: Optional[Type] chosen_order_type: Optional[Type]
if order_type == "datetime": if order_type == "datetime":
chosen_order_type = datetime chosen_order_type = datetime
if order_type == "date":
chosen_order_type = date
elif order_type == "int": elif order_type == "int":
chosen_order_type = int chosen_order_type = int
elif order_type == "float": elif order_type == "float":
@ -606,7 +609,7 @@ def query_cmd(
if recent is not None: if recent is not None:
before = "now" before = "now"
chosen_order_type = datetime chosen_order_type = chosen_order_type or datetime # dont override if the user specified date
within = recent within = recent
reverse = not reverse reverse = not reverse

View file

@ -352,21 +352,12 @@ class classproperty(Generic[_R]):
tzdatetime = datetime tzdatetime = datetime
fromisoformat: Callable[[str], datetime]
import sys
if sys.version_info[:2] >= (3, 7):
# prevent mypy on py3.6 from complaining...
fromisoformat_real = datetime.fromisoformat
fromisoformat = fromisoformat_real
else:
from .py37 import fromisoformat
# TODO doctests? # TODO doctests?
def isoparse(s: str) -> tzdatetime: def isoparse(s: str) -> tzdatetime:
""" """
Parses timestamps formatted like 2020-05-01T10:32:02.925961Z Parses timestamps formatted like 2020-05-01T10:32:02.925961Z
""" """
from .compat import fromisoformat
# TODO could use dateutil? but it's quite slow as far as I remember.. # TODO could use dateutil? but it's quite slow as far as I remember..
# TODO support non-utc.. somehow? # TODO support non-utc.. somehow?
assert s.endswith('Z'), s assert s.endswith('Z'), s

View file

@ -2,6 +2,8 @@
Some backwards compatibility stuff/deprecation helpers Some backwards compatibility stuff/deprecation helpers
''' '''
from types import ModuleType from types import ModuleType
from typing import Callable
from datetime import datetime
from . import warnings from . import warnings
from .common import LazyLogger from .common import LazyLogger
@ -10,6 +12,16 @@ from .common import LazyLogger
logger = LazyLogger('my.core.compat') logger = LazyLogger('my.core.compat')
fromisoformat: Callable[[str], datetime]
import sys
if sys.version_info[:2] >= (3, 7):
# prevent mypy on py3.6 from complaining...
fromisoformat_real = datetime.fromisoformat
fromisoformat = fromisoformat_real
else:
from .py37 import fromisoformat
def pre_pip_dal_handler( def pre_pip_dal_handler(
name: str, name: str,
e: ModuleNotFoundError, e: ModuleNotFoundError,

View file

@ -127,7 +127,7 @@ def attach_dt(e: Exception, *, dt: Optional[datetime]) -> Exception:
# todo it might be problematic because might mess with timezones (when it's converted to string, it's converted to a shift) # todo it might be problematic because might mess with timezones (when it's converted to string, it's converted to a shift)
def extract_error_datetime(e: Exception) -> Optional[datetime]: def extract_error_datetime(e: Exception) -> Optional[datetime]:
from .common import fromisoformat from .compat import fromisoformat
import re import re
for x in reversed(e.args): for x in reversed(e.args):
if isinstance(x, datetime): if isinstance(x, datetime):

View file

@ -24,14 +24,8 @@ from .query import (
ET, ET,
) )
fromisoformat: Callable[[str], datetime] from .compat import fromisoformat
import sys from .common import isoparse
if sys.version_info[:2] >= (3, 7):
# prevent mypy on py3.6 from complaining...
fromisoformat_real = datetime.fromisoformat
fromisoformat = fromisoformat_real
else:
from .py37 import fromisoformat
timedelta_regex = re.compile(r"^((?P<weeks>[\.\d]+?)w)?((?P<days>[\.\d]+?)d)?((?P<hours>[\.\d]+?)h)?((?P<minutes>[\.\d]+?)m)?((?P<seconds>[\.\d]+?)s)?$") timedelta_regex = re.compile(r"^((?P<weeks>[\.\d]+?)w)?((?P<days>[\.\d]+?)d)?((?P<hours>[\.\d]+?)h)?((?P<minutes>[\.\d]+?)m)?((?P<seconds>[\.\d]+?)s)?$")
@ -82,10 +76,11 @@ def parse_datetime_float(date_str: str) -> float:
# isoformat - default format when you call str() on datetime # isoformat - default format when you call str() on datetime
return fromisoformat(ds).timestamp() return fromisoformat(ds).timestamp()
except ValueError: except ValueError:
pass
try:
return isoparse(ds).timestamp()
except (AssertionError, ValueError):
raise QueryException(f"Was not able to parse {ds} into a datetime") raise QueryException(f"Was not able to parse {ds} into a datetime")
# todo: add isoparse from my.core.common? not sure how it handles
# timezones and this purposefully avoids that by converting all
# datelike items to floats instead
# probably DateLike input? but a user could specify an order_key # probably DateLike input? but a user could specify an order_key
@ -329,7 +324,7 @@ Specify a type or a key to order the value by""")
# sort the iterable by the generated order_by_chosen function # sort the iterable by the generated order_by_chosen function
itr = select(itr, order_by=order_by_chosen, drop_unsorted=True) itr = select(itr, order_by=order_by_chosen, drop_unsorted=True)
filter_func: Optional[Where] filter_func: Optional[Where]
if order_by_value_type == datetime: if order_by_value_type in [datetime, date]:
filter_func = _create_range_filter( filter_func = _create_range_filter(
unparsed_range=unparsed_range, unparsed_range=unparsed_range,
end_parser=parse_datetime_float, end_parser=parse_datetime_float,