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)
|
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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue