onetick-py 1.170.0__py3-none-any.whl → 1.172.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- onetick/py/__init__.py +8 -2
- onetick/py/_version.py +1 -1
- onetick/py/cache.py +3 -3
- onetick/py/callback/callbacks.py +1 -1
- onetick/py/configuration.py +35 -9
- onetick/py/core/_source/source_methods/misc.py +1 -1
- onetick/py/core/_source/source_methods/writes.py +48 -33
- onetick/py/core/column_operations/_methods/methods.py +1 -4
- onetick/py/core/column_operations/accessors/_accessor.py +4 -6
- onetick/py/core/column_operations/accessors/decimal_accessor.py +20 -8
- onetick/py/core/column_operations/accessors/dt_accessor.py +137 -68
- onetick/py/core/column_operations/accessors/float_accessor.py +35 -15
- onetick/py/core/column_operations/accessors/str_accessor.py +0 -7
- onetick/py/core/column_operations/base.py +72 -12
- onetick/py/core/multi_output_source.py +41 -2
- onetick/py/core/per_tick_script.py +2 -0
- onetick/py/db/_inspection.py +82 -49
- onetick/py/db/db.py +2 -2
- onetick/py/functions.py +7 -1
- onetick/py/math.py +374 -386
- onetick/py/misc.py +70 -38
- onetick/py/otq.py +18 -12
- onetick/py/run.py +75 -5
- onetick/py/sources/ticks.py +1 -1
- {onetick_py-1.170.0.dist-info → onetick_py-1.172.0.dist-info}/METADATA +4 -2
- {onetick_py-1.170.0.dist-info → onetick_py-1.172.0.dist-info}/RECORD +30 -30
- {onetick_py-1.170.0.dist-info → onetick_py-1.172.0.dist-info}/WHEEL +0 -0
- {onetick_py-1.170.0.dist-info → onetick_py-1.172.0.dist-info}/entry_points.txt +0 -0
- {onetick_py-1.170.0.dist-info → onetick_py-1.172.0.dist-info}/licenses/LICENSE +0 -0
- {onetick_py-1.170.0.dist-info → onetick_py-1.172.0.dist-info}/top_level.txt +0 -0
onetick/py/db/_inspection.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import itertools
|
|
1
2
|
import warnings
|
|
2
3
|
from typing import Union, Iterable, Tuple, Optional, Any, Literal
|
|
3
4
|
from datetime import date as dt_date, datetime, timedelta
|
|
@@ -7,6 +8,7 @@ from dateutil.tz import gettz
|
|
|
7
8
|
|
|
8
9
|
import onetick.py as otp
|
|
9
10
|
from onetick.py import configuration, utils
|
|
11
|
+
from onetick.py import types as ott
|
|
10
12
|
from onetick.py.compatibility import is_native_plus_zstd_supported, is_show_db_list_show_description_supported
|
|
11
13
|
from onetick.py.core import db_constants
|
|
12
14
|
from onetick.py.otq import otq
|
|
@@ -909,10 +911,12 @@ class DB:
|
|
|
909
911
|
|
|
910
912
|
|
|
911
913
|
def databases(
|
|
912
|
-
context=utils.default, derived: bool = False, readable_only: bool = True,
|
|
913
|
-
|
|
914
|
+
context=utils.default, derived: bool = False, readable_only: bool = True,
|
|
915
|
+
fetch_description: Optional[bool] = None,
|
|
916
|
+
as_table: bool = False,
|
|
917
|
+
) -> Union[dict[str, DB], pd.DataFrame]:
|
|
914
918
|
"""
|
|
915
|
-
Gets all available databases in the ``context
|
|
919
|
+
Gets all available databases in the ``context``.
|
|
916
920
|
|
|
917
921
|
Parameters
|
|
918
922
|
----------
|
|
@@ -931,6 +935,9 @@ def databases(
|
|
|
931
935
|
fetch_description: bool
|
|
932
936
|
If set to True, retrieves descriptions for databases and puts them into ``description`` property of
|
|
933
937
|
:py:class:`~onetick.py.DB` objects in a returned dict.
|
|
938
|
+
as_table: bool
|
|
939
|
+
If False (default), this function returns a dictionary of database names and database objects.
|
|
940
|
+
If True, returns a :pandas:`pandas.DataFrame` table where each row contains the info for each database.
|
|
934
941
|
|
|
935
942
|
See also
|
|
936
943
|
--------
|
|
@@ -940,50 +947,66 @@ def databases(
|
|
|
940
947
|
|
|
941
948
|
Returns
|
|
942
949
|
-------
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
with ``context`` specified.
|
|
946
|
-
"""
|
|
947
|
-
if fetch_description and not is_show_db_list_show_description_supported():
|
|
948
|
-
fetch_description = False
|
|
950
|
+
Dict where keys are database names and values are :class:`DB <onetick.py.db._inspection.DB>` objects
|
|
951
|
+
or :pandas:`pandas.DataFrame` object depending on ``as_table`` parameter.
|
|
949
952
|
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
otq.AccessInfo(info_type='DATABASES', show_for_all_users=False, deep_scan=True).tick_type('ANY')
|
|
953
|
-
>> otq.Passthrough('DB_NAME,READ_ACCESS')
|
|
954
|
-
>> otq.WhereClause(where='READ_ACCESS = 1')
|
|
955
|
-
)
|
|
953
|
+
Examples
|
|
954
|
+
--------
|
|
956
955
|
|
|
957
|
-
|
|
958
|
-
join = otq.Join(
|
|
959
|
-
left_source='LEFT', join_type='LEFT_OUTER', join_criteria='LEFT.DB_NAME = RIGHT.DATABASE_NAME'
|
|
960
|
-
)
|
|
961
|
-
|
|
962
|
-
_ = node.set_node_name('LEFT') >> join
|
|
963
|
-
_ = (
|
|
964
|
-
otq.ShowDbList(show_description=fetch_description).tick_type('ANY')
|
|
965
|
-
>> otq.Passthrough('DATABASE_NAME,DESCRIPTION').set_node_name('RIGHT')
|
|
966
|
-
>> join
|
|
967
|
-
)
|
|
968
|
-
|
|
969
|
-
node = (
|
|
970
|
-
join >> otq.Passthrough('LEFT.DB_NAME,RIGHT.DESCRIPTION')
|
|
971
|
-
>> otq.RenameFields("LEFT.DB_NAME=DB_NAME,RIGHT.DESCRIPTION=DESCRIPTION")
|
|
972
|
-
)
|
|
973
|
-
else:
|
|
974
|
-
db_list_kwargs = {}
|
|
975
|
-
output_fields = ['DATABASE_NAME']
|
|
976
|
-
if fetch_description:
|
|
977
|
-
db_list_kwargs['show_description'] = fetch_description
|
|
978
|
-
output_fields.append('DESCRIPTION')
|
|
956
|
+
Get the dictionary of database names and objects:
|
|
979
957
|
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
958
|
+
>>> otp.databases() # doctest: +SKIP
|
|
959
|
+
{'ABU_DHABI': <onetick.py.db._inspection.DB at 0x7f9413a5e8e0>,
|
|
960
|
+
'ABU_DHABI_BARS': <onetick.py.db._inspection.DB at 0x7f9413a5ef40>,
|
|
961
|
+
'ABU_DHABI_DAILY': <onetick.py.db._inspection.DB at 0x7f9413a5eac0>,
|
|
962
|
+
'ALPHA': <onetick.py.db._inspection.DB at 0x7f9413a5e940>,
|
|
963
|
+
'ALPHA_X': <onetick.py.db._inspection.DB at 0x7f9413a5e490>,
|
|
964
|
+
...
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
Get a table with database info:
|
|
984
968
|
|
|
985
|
-
|
|
986
|
-
|
|
969
|
+
>>> otp.databases(as_table=True) # doctest: +SKIP
|
|
970
|
+
Time DB_NAME READ_ACCESS WRITE_ACCESS ...
|
|
971
|
+
0 2003-01-01 ABU_DHABI 1 0 ...
|
|
972
|
+
1 2003-01-01 ABU_DHABI_BARS 1 1 ...
|
|
973
|
+
2 2003-01-01 ABU_DHABI_DAILY 1 1 ...
|
|
974
|
+
3 2003-01-01 ALPHA 1 1 ...
|
|
975
|
+
4 2003-01-01 ALPHA_X 1 1 ...
|
|
976
|
+
... ... ... ... ... ...
|
|
977
|
+
"""
|
|
978
|
+
show_db_list_kwargs = {}
|
|
979
|
+
if fetch_description is not None and is_show_db_list_show_description_supported() and (
|
|
980
|
+
'show_description' in otq.ShowDbList.Parameters.list_parameters()
|
|
981
|
+
):
|
|
982
|
+
show_db_list_kwargs['show_description'] = fetch_description
|
|
983
|
+
|
|
984
|
+
node = otq.AccessInfo(info_type='DATABASES', show_for_all_users=False, deep_scan=True).tick_type('ANY')
|
|
985
|
+
# for some reason ACCESS_INFO sometimes return several ticks
|
|
986
|
+
# for the same database with different SERVER_ADDRESS values
|
|
987
|
+
# so we get only the first tick
|
|
988
|
+
node = (
|
|
989
|
+
node >> otq.NumTicks(is_running_aggr=True, group_by='DB_NAME',
|
|
990
|
+
all_fields_for_sliding=False, output_field_name='NUM_TICKS')
|
|
991
|
+
>> otq.WhereClause(where='NUM_TICKS = 1')
|
|
992
|
+
>> otq.Passthrough('NUM_TICKS', drop_fields=True)
|
|
993
|
+
)
|
|
994
|
+
if readable_only:
|
|
995
|
+
node = node >> otq.WhereClause(where='READ_ACCESS = 1')
|
|
996
|
+
|
|
997
|
+
left = node.set_node_name('LEFT')
|
|
998
|
+
right = otq.ShowDbList(**show_db_list_kwargs).tick_type('ANY').set_node_name('RIGHT')
|
|
999
|
+
join = otq.Join(
|
|
1000
|
+
left_source='LEFT', join_type='INNER', join_criteria='LEFT.DB_NAME = RIGHT.DATABASE_NAME',
|
|
1001
|
+
add_source_prefix=False,
|
|
1002
|
+
)
|
|
1003
|
+
left >> join << right # pylint: disable=pointless-statement
|
|
1004
|
+
node = join >> otq.Passthrough('LEFT.TIMESTAMP,RIGHT.TIMESTAMP,DATABASE_NAME', drop_fields=True)
|
|
1005
|
+
|
|
1006
|
+
# times bigger than datetime.max are not representable in python
|
|
1007
|
+
max_dt = ott.value2str(datetime.max)
|
|
1008
|
+
node = node >> otq.UpdateFields(set=f'INTERVAL_START={max_dt}', where=f'INTERVAL_START > {max_dt}')
|
|
1009
|
+
node = node >> otq.UpdateFields(set=f'INTERVAL_END={max_dt}', where=f'INTERVAL_END > {max_dt}')
|
|
987
1010
|
|
|
988
1011
|
dbs = otp.run(node,
|
|
989
1012
|
symbols='LOCAL::',
|
|
@@ -992,15 +1015,20 @@ def databases(
|
|
|
992
1015
|
end=db_constants.DEFAULT_END_DATE,
|
|
993
1016
|
context=context)
|
|
994
1017
|
|
|
1018
|
+
if as_table:
|
|
1019
|
+
return dbs
|
|
1020
|
+
|
|
995
1021
|
# WebAPI returns empty DataFrame (no columns) if there are no databases
|
|
996
1022
|
if len(dbs) == 0:
|
|
997
1023
|
return {}
|
|
998
1024
|
|
|
999
|
-
db_list = list(dbs['DB_NAME']
|
|
1000
|
-
|
|
1025
|
+
db_list = list(dbs['DB_NAME'])
|
|
1026
|
+
db_description_list = dbs['DESCRIPTION'] if 'DESCRIPTION' in dbs else itertools.repeat('')
|
|
1027
|
+
merged_db_list = list(zip(db_list, db_description_list))
|
|
1001
1028
|
|
|
1002
1029
|
db_dict = {
|
|
1003
|
-
db_name: DB(db_name, description=db_description, context=context)
|
|
1030
|
+
db_name: DB(db_name, description=db_description, context=context)
|
|
1031
|
+
for db_name, db_description in merged_db_list
|
|
1004
1032
|
}
|
|
1005
1033
|
|
|
1006
1034
|
if derived:
|
|
@@ -1018,6 +1046,7 @@ def derived_databases(
|
|
|
1018
1046
|
selection_criteria='all',
|
|
1019
1047
|
db=None,
|
|
1020
1048
|
db_discovery_scope='query_host_only',
|
|
1049
|
+
as_table: bool = False,
|
|
1021
1050
|
) -> dict[str, DB]:
|
|
1022
1051
|
"""
|
|
1023
1052
|
Gets available derived databases.
|
|
@@ -1052,6 +1081,9 @@ def derived_databases(
|
|
|
1052
1081
|
an attempt will be performed to get derived databases from all reachable hosts.
|
|
1053
1082
|
When *query_host_only* is specified,
|
|
1054
1083
|
only derived databases from the host on which the query is performed will be returned.
|
|
1084
|
+
as_table: bool
|
|
1085
|
+
If False (default), this function returns a dictionary of database names and database objects.
|
|
1086
|
+
If True, returns a :pandas:`pandas.DataFrame` table where each row contains the info for each database.
|
|
1055
1087
|
|
|
1056
1088
|
See also
|
|
1057
1089
|
--------
|
|
@@ -1059,9 +1091,8 @@ def derived_databases(
|
|
|
1059
1091
|
|
|
1060
1092
|
Returns
|
|
1061
1093
|
-------
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
with ``context`` specified.
|
|
1094
|
+
Dict where keys are database names and values are :class:`DB <onetick.py.db._inspection.DB>` objects
|
|
1095
|
+
or :pandas:`pandas.DataFrame` object depending on ``as_table`` parameter.
|
|
1065
1096
|
"""
|
|
1066
1097
|
if start and end:
|
|
1067
1098
|
time_range = otq.ShowDerivedDbList.TimeRange.QUERY_TIME_INTERVAL
|
|
@@ -1089,6 +1120,8 @@ def derived_databases(
|
|
|
1089
1120
|
ep = ep.tick_type('ANY')
|
|
1090
1121
|
db = db or 'LOCAL'
|
|
1091
1122
|
dbs = otp.run(ep, symbols=f'{db}::', start=start, end=end, context=context)
|
|
1123
|
+
if as_table:
|
|
1124
|
+
return dbs
|
|
1092
1125
|
if len(dbs) == 0:
|
|
1093
1126
|
return {}
|
|
1094
1127
|
db_list = list(dbs['DERIVED_DB_NAME'])
|
onetick/py/db/db.py
CHANGED
|
@@ -110,8 +110,8 @@ def write_to_db(src: 'otp.Source',
|
|
|
110
110
|
if timezone is None:
|
|
111
111
|
timezone = configuration.config.tz
|
|
112
112
|
if date is None or date is otp.adaptive:
|
|
113
|
-
kwargs['
|
|
114
|
-
kwargs['
|
|
113
|
+
kwargs['start_date'] = start
|
|
114
|
+
kwargs['end_date'] = end
|
|
115
115
|
else:
|
|
116
116
|
kwargs['date'] = date
|
|
117
117
|
|
onetick/py/functions.py
CHANGED
|
@@ -2033,7 +2033,13 @@ def _add_element(cur_res, element, format_spec_additional=None):
|
|
|
2033
2033
|
elif issubclass(element.dtype, float) and re.fullmatch(r'\.\d+f', format_spec_additional):
|
|
2034
2034
|
# float has strange behavior when precision=0
|
|
2035
2035
|
decimal_elem = element.apply(ott.decimal)
|
|
2036
|
-
|
|
2036
|
+
precision_str = re.findall(r'\d+', format_spec_additional)[0]
|
|
2037
|
+
try:
|
|
2038
|
+
precision = int(precision_str)
|
|
2039
|
+
except ValueError as exc:
|
|
2040
|
+
raise ValueError('Incorrect value for `precision` for formatting decimal number') from exc
|
|
2041
|
+
|
|
2042
|
+
cur_res += decimal_elem.decimal.str(precision)
|
|
2037
2043
|
elif issubclass(element.dtype, (ott.nsectime, ott.msectime)):
|
|
2038
2044
|
cur_res += element.dt.strftime(format_spec_additional)
|
|
2039
2045
|
else:
|