move isoformat to compat, allow date, misc fixes
This commit is contained in:
parent
28fd9e4441
commit
8a8bec332e
5 changed files with 36 additions and 35 deletions
|
@ -378,13 +378,14 @@ def query_hpi_functions(
|
|||
pprint(res)
|
||||
else:
|
||||
# output == 'repl'
|
||||
eprint(f"\nInteract with the results by using the {click.style('res', fg='green')} variable\n")
|
||||
try:
|
||||
import IPython # type: ignore[import]
|
||||
except ModuleNotFoundError:
|
||||
eprint("'repl' requires ipython, install it with 'python3 -m pip install ipython'")
|
||||
sys.exit(1)
|
||||
eprint("'repl' typically uses ipython, install it with 'python3 -m pip install ipython'. falling back to stdlib...")
|
||||
import code
|
||||
code.interact(local=locals())
|
||||
else:
|
||||
eprint(f"\nInteract with the results by using the {click.style('res', fg='green')} variable\n")
|
||||
IPython.embed()
|
||||
|
||||
|
||||
|
@ -502,35 +503,35 @@ def module_install_cmd(user: bool, module: str) -> None:
|
|||
@click.option('-k',
|
||||
'--order-key',
|
||||
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')
|
||||
@click.option('-t',
|
||||
'--order-type',
|
||||
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')
|
||||
@click.option('--after',
|
||||
default=None,
|
||||
type=click.STRING,
|
||||
type=str,
|
||||
help='while ordering, filter items for the key or type larger than or equal to this')
|
||||
@click.option('--before',
|
||||
default=None,
|
||||
type=click.STRING,
|
||||
type=str,
|
||||
help='while ordering, filter items for the key or type smaller than this')
|
||||
@click.option('--within',
|
||||
default=None,
|
||||
type=click.STRING,
|
||||
type=str,
|
||||
help="a range 'after' or 'before' to filter items by. see above for further explanation")
|
||||
@click.option('--recent',
|
||||
default=None,
|
||||
type=click.STRING,
|
||||
type=str,
|
||||
help="a shorthand for '--order-type datetime --reverse --before now --within'. e.g. --recent 5d")
|
||||
@click.option('--reverse/--no-reverse',
|
||||
default=False,
|
||||
help='reverse the results returned from the functions')
|
||||
@click.option('--limit',
|
||||
default=None,
|
||||
type=click.INT,
|
||||
type=int,
|
||||
help='limit the number of items returned from the (functions)')
|
||||
@click.option('--drop-unsorted',
|
||||
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
|
||||
'''
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import datetime, date
|
||||
|
||||
chosen_order_type: Optional[Type]
|
||||
if order_type == "datetime":
|
||||
chosen_order_type = datetime
|
||||
if order_type == "date":
|
||||
chosen_order_type = date
|
||||
elif order_type == "int":
|
||||
chosen_order_type = int
|
||||
elif order_type == "float":
|
||||
|
@ -606,7 +609,7 @@ def query_cmd(
|
|||
|
||||
if recent is not None:
|
||||
before = "now"
|
||||
chosen_order_type = datetime
|
||||
chosen_order_type = chosen_order_type or datetime # dont override if the user specified date
|
||||
within = recent
|
||||
reverse = not reverse
|
||||
|
||||
|
|
|
@ -352,21 +352,12 @@ class classproperty(Generic[_R]):
|
|||
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?
|
||||
def isoparse(s: str) -> tzdatetime:
|
||||
"""
|
||||
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 support non-utc.. somehow?
|
||||
assert s.endswith('Z'), s
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
Some backwards compatibility stuff/deprecation helpers
|
||||
'''
|
||||
from types import ModuleType
|
||||
from typing import Callable
|
||||
from datetime import datetime
|
||||
|
||||
from . import warnings
|
||||
from .common import LazyLogger
|
||||
|
@ -10,6 +12,16 @@ from .common import LazyLogger
|
|||
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(
|
||||
name: str,
|
||||
e: ModuleNotFoundError,
|
||||
|
|
|
@ -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)
|
||||
def extract_error_datetime(e: Exception) -> Optional[datetime]:
|
||||
from .common import fromisoformat
|
||||
from .compat import fromisoformat
|
||||
import re
|
||||
for x in reversed(e.args):
|
||||
if isinstance(x, datetime):
|
||||
|
|
|
@ -24,14 +24,8 @@ from .query import (
|
|||
ET,
|
||||
)
|
||||
|
||||
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
|
||||
from .compat import fromisoformat
|
||||
from .common import isoparse
|
||||
|
||||
|
||||
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
|
||||
return 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")
|
||||
# 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
|
||||
|
@ -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
|
||||
itr = select(itr, order_by=order_by_chosen, drop_unsorted=True)
|
||||
filter_func: Optional[Where]
|
||||
if order_by_value_type == datetime:
|
||||
if order_by_value_type in [datetime, date]:
|
||||
filter_func = _create_range_filter(
|
||||
unparsed_range=unparsed_range,
|
||||
end_parser=parse_datetime_float,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue