onetick-py 1.177.0__tar.gz → 1.179.0__tar.gz

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.
Files changed (163) hide show
  1. {onetick_py-1.177.0/src/onetick_py.egg-info → onetick_py-1.179.0}/PKG-INFO +2 -1
  2. {onetick_py-1.177.0 → onetick_py-1.179.0}/pyproject.toml +1 -0
  3. {onetick_py-1.177.0 → onetick_py-1.179.0}/setup.py +1 -0
  4. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/__init__.py +1 -1
  5. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/_version.py +1 -1
  6. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/compatibility.py +81 -18
  7. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/misc.py +73 -13
  8. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/tmp_otq.py +8 -0
  9. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/source.py +25 -3
  10. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/db/_inspection.py +113 -50
  11. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/oqd/sources.py +22 -8
  12. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/run.py +9 -5
  13. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/__init__.py +1 -0
  14. onetick_py-1.179.0/src/onetick/py/sources/dataframe.py +370 -0
  15. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/symbols.py +4 -6
  16. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/ticks.py +10 -2
  17. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/types.py +36 -0
  18. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/__init__.py +1 -0
  19. onetick_py-1.179.0/src/onetick/py/utils/debug.py +17 -0
  20. onetick_py-1.179.0/src/onetick/py/utils/render_cli.py +88 -0
  21. {onetick_py-1.177.0 → onetick_py-1.179.0/src/onetick_py.egg-info}/PKG-INFO +2 -1
  22. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick_py.egg-info/SOURCES.txt +3 -0
  23. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick_py.egg-info/entry_points.txt +1 -0
  24. {onetick_py-1.177.0 → onetick_py-1.179.0}/LICENSE +0 -0
  25. {onetick_py-1.177.0 → onetick_py-1.179.0}/README.md +0 -0
  26. {onetick_py-1.177.0 → onetick_py-1.179.0}/requirements.strict.txt +0 -0
  27. {onetick_py-1.177.0 → onetick_py-1.179.0}/requirements.txt +0 -0
  28. {onetick_py-1.177.0 → onetick_py-1.179.0}/setup.cfg +0 -0
  29. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/locator_parser/__init__.py +0 -0
  30. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/locator_parser/acl.py +0 -0
  31. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/locator_parser/actions.py +0 -0
  32. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/locator_parser/common.py +0 -0
  33. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/locator_parser/io.py +0 -0
  34. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/locator_parser/locator.py +0 -0
  35. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/__init__.py +0 -0
  36. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/doc_utilities/__init__.py +0 -0
  37. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/doc_utilities/napoleon.py +0 -0
  38. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/doc_utilities/ot_doctest.py +0 -0
  39. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/doc_utilities/snippets.py +0 -0
  40. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/lib/__init__.py +0 -0
  41. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/lib/instance.py +0 -0
  42. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/_stack_info.py +0 -0
  43. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/__init__.py +0 -0
  44. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/_base.py +0 -0
  45. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/_docs.py +0 -0
  46. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/compute.py +0 -0
  47. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/functions.py +0 -0
  48. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/generic.py +0 -0
  49. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/high_low.py +0 -0
  50. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/num_distinct.py +0 -0
  51. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/order_book.py +0 -0
  52. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/other.py +0 -0
  53. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/backports.py +0 -0
  54. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/cache.py +0 -0
  55. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/callback/__init__.py +0 -0
  56. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/callback/callback.py +0 -0
  57. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/callback/callbacks.py +0 -0
  58. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/configuration.py +0 -0
  59. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/__init__.py +0 -0
  60. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_csv_inspector.py +0 -0
  61. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/__init__.py +0 -0
  62. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_manually_bound_value.py +0 -0
  63. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_nodes_history.py +0 -0
  64. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_op_utils/__init__.py +0 -0
  65. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_op_utils/every_operand.py +0 -0
  66. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_op_utils/is_const.py +0 -0
  67. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_per_tick_scripts/tick_list_sort_template.script +0 -0
  68. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_proxy_node.py +0 -0
  69. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_state_objects.py +0 -0
  70. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_state_vars.py +0 -0
  71. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/__init__.py +0 -0
  72. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/_symbol_param.py +0 -0
  73. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/schema.py +0 -0
  74. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/__init__.py +0 -0
  75. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/aggregations.py +0 -0
  76. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/applyers.py +0 -0
  77. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/columns.py +0 -0
  78. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/data_quality.py +0 -0
  79. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/debugs.py +0 -0
  80. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/drops.py +0 -0
  81. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/fields.py +0 -0
  82. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/filters.py +0 -0
  83. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/joins.py +0 -0
  84. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/merges.py +0 -0
  85. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/pandases.py +0 -0
  86. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/renames.py +0 -0
  87. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/sorts.py +0 -0
  88. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/switches.py +0 -0
  89. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/symbols.py +0 -0
  90. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/times.py +0 -0
  91. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/writes.py +0 -0
  92. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/symbol.py +0 -0
  93. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column.py +0 -0
  94. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/__init__.py +0 -0
  95. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/_methods/__init__.py +0 -0
  96. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/_methods/_internal.py +0 -0
  97. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/_methods/conversions.py +0 -0
  98. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/_methods/methods.py +0 -0
  99. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/_methods/op_types.py +0 -0
  100. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/accessors/__init__.py +0 -0
  101. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/accessors/_accessor.py +0 -0
  102. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/accessors/decimal_accessor.py +0 -0
  103. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/accessors/dt_accessor.py +0 -0
  104. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/accessors/float_accessor.py +0 -0
  105. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/accessors/str_accessor.py +0 -0
  106. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/base.py +0 -0
  107. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/cut_builder.py +0 -0
  108. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/db_constants.py +0 -0
  109. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/eval_query.py +0 -0
  110. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/lambda_object.py +0 -0
  111. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/multi_output_source.py +0 -0
  112. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/per_tick_script.py +0 -0
  113. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/query_inspector.py +0 -0
  114. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/db/__init__.py +0 -0
  115. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/db/db.py +0 -0
  116. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/db/utils.py +0 -0
  117. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/docs/__init__.py +0 -0
  118. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/docs/docstring_parser.py +0 -0
  119. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/docs/utils.py +0 -0
  120. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/functions.py +0 -0
  121. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/license.py +0 -0
  122. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/log.py +0 -0
  123. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/math.py +0 -0
  124. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/misc.py +0 -0
  125. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/oqd/__init__.py +0 -0
  126. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/oqd/eps.py +0 -0
  127. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/otq.py +0 -0
  128. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/pyomd_mock.py +0 -0
  129. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/servers.py +0 -0
  130. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/session.py +0 -0
  131. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/cache.py +0 -0
  132. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/common.py +0 -0
  133. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/csv.py +0 -0
  134. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/custom.py +0 -0
  135. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/data_file.py +0 -0
  136. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/data_source.py +0 -0
  137. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/empty.py +0 -0
  138. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/odbc.py +0 -0
  139. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/order_book.py +0 -0
  140. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/parquet.py +0 -0
  141. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/pit.py +0 -0
  142. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/query.py +0 -0
  143. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/snapshots.py +0 -0
  144. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/split_query_output_by_symbol.py +0 -0
  145. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/symbology_mapping.py +0 -0
  146. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sql.py +0 -0
  147. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/state.py +0 -0
  148. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/acl.py +0 -0
  149. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/config.py +0 -0
  150. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/default.py +0 -0
  151. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/file.py +0 -0
  152. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/helpers.py +0 -0
  153. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/locator.py +0 -0
  154. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/perf.py +0 -0
  155. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/query.py +0 -0
  156. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/render.py +0 -0
  157. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/script.py +0 -0
  158. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/temp.py +0 -0
  159. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/types.py +0 -0
  160. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/tz.py +0 -0
  161. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick_py.egg-info/dependency_links.txt +0 -0
  162. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick_py.egg-info/requires.txt +0 -0
  163. {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick_py.egg-info/top_level.txt +0 -0
@@ -1,12 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: onetick-py
3
- Version: 1.177.0
3
+ Version: 1.179.0
4
4
  Summary: Python package that allows you to work with OneTick
5
5
  Author-email: solutions <solutions@onetick.com>
6
6
  License-Expression: MIT
7
7
  Project-URL: Documentation, https://docs.pip.distribution.sol.onetick.com
8
8
  Project-URL: OneTick, https://onetick.com
9
9
  Project-URL: GitHub, https://github.com/onemarketdata/onetick-py
10
+ Project-URL: Issues, https://github.com/onemarketdata/onetick-py/issues
10
11
  Classifier: Topic :: Database :: Front-Ends
11
12
  Classifier: Topic :: Scientific/Engineering
12
13
  Classifier: Programming Language :: Python :: 3.9
@@ -39,6 +39,7 @@ classifiers = [
39
39
  Documentation = "https://docs.pip.distribution.sol.onetick.com"
40
40
  OneTick = "https://onetick.com"
41
41
  GitHub = "https://github.com/onemarketdata/onetick-py"
42
+ Issues = "https://github.com/onemarketdata/onetick-py/issues"
42
43
 
43
44
  [tool.setuptools.packages.find]
44
45
  where = ["src"]
@@ -31,6 +31,7 @@ setup(name='onetick-py',
31
31
  },
32
32
  entry_points={
33
33
  'console_scripts': [
34
+ 'onetick-render = onetick.py.utils.render_cli:main',
34
35
  'jupyter-onetick_snippets = onetick.doc_utilities.snippets:main',
35
36
  ],
36
37
  })
@@ -192,7 +192,7 @@ from onetick.py.sources import (Tick, TTicks, Ticks, Orders, Trades, NBBO, Quote
192
192
  Custom, query, Symbols, Empty, DataSource, LocalCSVTicks, SymbologyMapping,
193
193
  ObSnapshot, ObSnapshotWide, ObSnapshotFlat, ObSummary, ObSize, ObVwap, ObNumLevels,
194
194
  by_symbol, ODBC, SplitQueryOutputBySymbol, DataFile, PointInTime,
195
- ReadSnapshot, ShowSnapshotList, FindSnapshotSymbols)
195
+ ReadSnapshot, ShowSnapshotList, FindSnapshotSymbols, ReadFromDataFrame)
196
196
  from onetick.py.utils import adaptive, range, perf
197
197
  from onetick.py.session import Session, TestSession, Config, Locator, HTTPSession
198
198
  from onetick.py.servers import RemoteTS, LoadBalancing, FaultTolerance
@@ -1,2 +1,2 @@
1
1
  # This file was generated automatically. DO NOT CHANGE.
2
- VERSION = '1.177.0'
2
+ VERSION = '1.179.0'
@@ -4,6 +4,7 @@ from dataclasses import dataclass, astuple
4
4
  from datetime import datetime
5
5
  from typing import Optional
6
6
 
7
+ import pandas as pd
7
8
  from packaging.version import parse as parse_version
8
9
 
9
10
  import onetick.py as otp
@@ -103,6 +104,36 @@ def _parse_release_string(release_string: str, build_number: int) -> OnetickVers
103
104
  raise ValueError(f"Unknown release type '{release_type}' in release string '{release_string}'")
104
105
 
105
106
 
107
+ def _get_locator_min_date(db_name, context):
108
+ graph = otq.GraphQuery(otq.DbShowConfiguredTimeRanges(db_name=db_name).tick_type('ANY')
109
+ >> otq.Table(fields='long START_DATE, long END_DATE'))
110
+ symbols = f'{db_name}::'
111
+ result = otq.run(graph,
112
+ symbols=symbols,
113
+ # start and end times don't matter for this query, use some constants
114
+ start=datetime(2003, 12, 1),
115
+ end=datetime(2003, 12, 1),
116
+ # GMT, because start/end timestamp in locator are in GMT
117
+ timezone='GMT',
118
+ context=context)
119
+ data = result.output(symbols).data
120
+ first_date = data['START_DATE'][0]
121
+ return datetime.fromtimestamp(first_date / 1000)
122
+
123
+
124
+ def _get_onetick_version(symbols, context, start, end):
125
+ node = otq.TickGenerator(bucket_interval=0,
126
+ fields='BUILD=GET_ONETICK_VERSION(), RELEASE=GET_ONETICK_RELEASE()')
127
+ graph = otq.GraphQuery(node.tick_type('DUMMY'))
128
+ result = otq.run(graph,
129
+ symbols=symbols,
130
+ start=start,
131
+ end=end,
132
+ context=context,
133
+ timezone='UTC')
134
+ return result
135
+
136
+
106
137
  @cache
107
138
  def get_onetick_version(db=None, context=None) -> OnetickVersionFromServer:
108
139
  """
@@ -132,27 +163,31 @@ def get_onetick_version(db=None, context=None) -> OnetickVersionFromServer:
132
163
  s = otp.Session()
133
164
  else:
134
165
  _ = otli.OneTickLib()
135
- p = otq.TickGenerator(bucket_interval=0,
136
- fields='BUILD=GET_ONETICK_VERSION(), RELEASE=GET_ONETICK_RELEASE()')
137
- graph = otq.GraphQuery(p.tick_type('DUMMY'))
138
166
 
139
167
  # if otp.config.default_db is set, then we use it to check compatibility
140
168
  # otherwise we use LOCAL database available everywhere
141
169
  db = db or otp.config.get('default_db', 'LOCAL')
142
- dummy_symbol = f'{db}::'
170
+ symbols = f'{db}::'
143
171
  context = context or otp.config.context
144
172
 
145
- result = otq.run(graph,
146
- symbols=dummy_symbol,
147
- start=datetime(2003, 12, 1),
148
- end=datetime(2003, 12, 2),
149
- context=context,
150
- timezone='UTC')
151
- if s:
152
- s.close()
173
+ try:
174
+ # let's try some default time range first
175
+ start = end = datetime(2003, 12, 1)
176
+ result = _get_onetick_version(symbols, context, start, end)
177
+ except Exception:
178
+ if db != 'LOCAL':
179
+ # for real db we need to set time range correctly
180
+ # otherwise we may get error "Database locator has a gap"
181
+ start = end = _get_locator_min_date(db, context)
182
+ result = _get_onetick_version(symbols, context, start, end)
183
+ else:
184
+ raise
185
+ finally:
186
+ if s:
187
+ s.close()
153
188
 
154
- build_number = result[dummy_symbol]["BUILD"][0]
155
- release_string = result[dummy_symbol]["RELEASE"][0]
189
+ build_number = result[symbols]["BUILD"][0]
190
+ release_string = result[symbols]["RELEASE"][0]
156
191
 
157
192
  try:
158
193
  onetick_version = _parse_release_string(release_string, build_number=build_number)
@@ -667,7 +702,22 @@ def is_percentile_bug_fixed():
667
702
 
668
703
 
669
704
  def is_limit_ep_supported():
670
- return hasattr(otq, 'Limit')
705
+ # Implemented 0034293: LIMIT ep
706
+ return (
707
+ hasattr(otq, 'Limit') and
708
+ _is_min_build_or_version(1.25, 20241229055942,
709
+ 20241018120000, min_update_number=1)
710
+ )
711
+
712
+
713
+ def is_limit_tick_offset_supported():
714
+ # Implemented OTDEV-37257: LIMIT EP should support TICK_OFFSET parameter
715
+ return (
716
+ is_limit_ep_supported() and
717
+ 'tick_offset' in otq.Limit.Parameters.list_parameters() and
718
+ _is_min_build_or_version(None, None,
719
+ 20251010120000, min_update_number=2)
720
+ )
671
721
 
672
722
 
673
723
  def is_prefer_speed_over_accuracy_supported(**kwargs):
@@ -733,8 +783,11 @@ def is_multi_column_generic_aggregations_supported():
733
783
 
734
784
 
735
785
  def is_max_concurrency_with_webapi_supported():
786
+ # 0036758: in onetick.query_webapi: max_concurrency is not being saved in otq file when set on otq.Query
787
+ # 0036759: in onetick.query_webapi:
788
+ # it's not possible to pass max_concurrency 0 in method otq.run when using otq file
736
789
  return _is_min_build_or_version(None, None,
737
- 20250227120000, min_update_number=2)
790
+ 20250727120000, min_update_number=3)
738
791
 
739
792
 
740
793
  def is_nanoseconds_fixed_in_run():
@@ -783,12 +836,16 @@ def is_show_db_list_show_description_supported():
783
836
 
784
837
  def is_symbols_prepend_db_name_supported():
785
838
  # 20250924: Implemented 0036753: FIND_DB_SYMBOLS should have EP parameter PREPEND_DB_NAME (true by default)
786
- return hasattr(otq.FindDbSymbols.Parameters, 'prepend_db_name')
839
+ return hasattr(otq.FindDbSymbols.Parameters, 'prepend_db_name') and _is_min_build_or_version(
840
+ None, None, 20251010120000,
841
+ )
787
842
 
788
843
 
789
844
  def is_diff_show_all_ticks_supported():
790
845
  # 20250919: Implemented 0036784: Add SHOW_ALL_TICKS(false by default) ep parameter to DIFF EP.
791
- return hasattr(otq.Diff.Parameters, 'show_all_ticks')
846
+ return hasattr(otq.Diff.Parameters, 'show_all_ticks') and _is_min_build_or_version(
847
+ None, None, 20251010120000,
848
+ )
792
849
 
793
850
 
794
851
  def is_max_spread_supported():
@@ -796,3 +853,9 @@ def is_max_spread_supported():
796
853
  # should also support parameter MAX_SPREAD
797
854
  return _is_min_build_or_version(None, None,
798
855
  20251010120000)
856
+
857
+
858
+ def is_not_fixed_bds_484():
859
+ # BDS-484: seems like timezone is ignored in otq.run in some cases
860
+ return _is_min_build_or_version(None, None,
861
+ 20251010120000, min_update_number=2)
@@ -1,9 +1,10 @@
1
1
  import functools
2
2
  import re
3
+ import warnings
3
4
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union
4
- from onetick.py.backports import Literal
5
5
 
6
6
  import onetick.py as otp
7
+ from onetick.py.backports import Literal
7
8
  from onetick.py import types as ott
8
9
  from onetick.py import utils
9
10
  from onetick.py.core.column import _Column
@@ -1109,16 +1110,26 @@ def book_diff(self: 'Source', include_initial_book: bool = False, inplace=False)
1109
1110
 
1110
1111
 
1111
1112
  @inplace_operation
1112
- def limit(self: 'Source', tick_limit: int, inplace=False) -> Optional['Source']:
1113
+ def limit(self: 'Source',
1114
+ tick_limit: int,
1115
+ tick_offset: Optional[int] = None,
1116
+ inplace=False) -> Optional['Source']:
1113
1117
  """
1114
- Propagates ticks until the count limit is reached. Once the limit is reached,
1118
+ Propagates ticks until the count limit is reached.
1119
+
1120
+ Once the limit is reached,
1115
1121
  hidden ticks will still continue to propagate until the next regular tick appears.
1116
1122
 
1117
1123
  Parameters
1118
1124
  ----------
1119
1125
  tick_limit: int
1120
- The number of regular ticks to propagate. Must be a non-negative integer or -1, which will mean no limit.
1121
- inplace : bool
1126
+ The number of regular ticks to propagate.
1127
+ Must be a non-negative integer or -1, which means no limit.
1128
+ tick_offset: int
1129
+ The number of regular ticks to skip before starting to propagate.
1130
+ Must be a non-negative integer.
1131
+ By default no ticks are skipped.
1132
+ inplace: bool
1122
1133
  The flag controls whether operation should be applied inplace or not.
1123
1134
  If ``inplace=True``, then it returns nothing. Otherwise method returns a new modified
1124
1135
  object.
@@ -1134,14 +1145,15 @@ def limit(self: 'Source', tick_limit: int, inplace=False) -> Optional['Source']:
1134
1145
  Examples
1135
1146
  --------
1136
1147
 
1137
- Basic example
1148
+ Simple example, get first 3 ticks:
1138
1149
 
1139
1150
  .. testcode::
1140
1151
  :skipif: not otp.compatibility.is_limit_ep_supported()
1141
1152
 
1142
1153
  data = otp.Ticks(X=[1, 2, 3, 4, 5, 6])
1143
- data = data.limit(tick_limit=3)
1144
- print(otp.run(data))
1154
+ data = data.limit(3)
1155
+ df = otp.run(data)
1156
+ print(df)
1145
1157
 
1146
1158
  .. testoutput::
1147
1159
 
@@ -1150,14 +1162,15 @@ def limit(self: 'Source', tick_limit: int, inplace=False) -> Optional['Source']:
1150
1162
  1 2003-12-01 00:00:00.001 2
1151
1163
  2 2003-12-01 00:00:00.002 3
1152
1164
 
1153
- Disable limit
1165
+ Disable limit by setting it to -1:
1154
1166
 
1155
1167
  .. testcode::
1156
1168
  :skipif: not otp.compatibility.is_limit_ep_supported()
1157
1169
 
1158
1170
  data = otp.Ticks(X=[1, 2, 3, 4, 5, 6])
1159
- data = data.limit(tick_limit=-1)
1160
- print(otp.run(data))
1171
+ data = data.limit(-1)
1172
+ df = otp.run(data)
1173
+ print(df)
1161
1174
 
1162
1175
  .. testoutput::
1163
1176
 
@@ -1168,14 +1181,61 @@ def limit(self: 'Source', tick_limit: int, inplace=False) -> Optional['Source']:
1168
1181
  3 2003-12-01 00:00:00.003 4
1169
1182
  4 2003-12-01 00:00:00.004 5
1170
1183
  5 2003-12-01 00:00:00.005 6
1184
+
1185
+ Setting parameter ``tick_offset`` can be used to skip first ticks before propagating them.
1186
+
1187
+ For example, we can skip first 2 ticks and propagate all other:
1188
+
1189
+ .. testcode::
1190
+ :skipif: not otp.compatibility.is_limit_tick_offset_supported()
1191
+
1192
+ data = otp.Ticks(X=[1, 2, 3, 4, 5, 6])
1193
+ data = data.limit(-1, tick_offset=2)
1194
+ df = otp.run(data)
1195
+ print(df)
1196
+
1197
+ .. testoutput::
1198
+
1199
+ Time X
1200
+ 0 2003-12-01 00:00:00.002 3
1201
+ 1 2003-12-01 00:00:00.003 4
1202
+ 2 2003-12-01 00:00:00.004 5
1203
+ 3 2003-12-01 00:00:00.005 6
1204
+
1205
+ Or we can return ticks from the middle of the stream
1206
+ by skipping first 2 ticks and then returning next 2 ticks like this:
1207
+
1208
+ .. testcode::
1209
+ :skipif: not otp.compatibility.is_limit_tick_offset_supported()
1210
+
1211
+ data = otp.Ticks(X=[1, 2, 3, 4, 5, 6])
1212
+ data = data.limit(2, tick_offset=2)
1213
+ df = otp.run(data)
1214
+ print(df)
1215
+
1216
+ .. testoutput::
1217
+
1218
+ Time X
1219
+ 0 2003-12-01 00:00:00.002 3
1220
+ 1 2003-12-01 00:00:00.003 4
1171
1221
  """
1172
- if not hasattr(otq, 'Limit'):
1222
+ if not otp.compatibility.is_limit_ep_supported():
1173
1223
  raise RuntimeError('LIMIT EP isn\'t supported by the current OneTick version.')
1174
1224
 
1175
1225
  if tick_limit < 0 and tick_limit != -1:
1176
1226
  raise ValueError('Negative values, except -1, not allowed as `tick_limit` in `limit` method.')
1177
1227
 
1178
- self.sink(otq.Limit(tick_limit=tick_limit))
1228
+ ep_kwargs = {}
1229
+ if tick_offset is not None:
1230
+ if not isinstance(tick_offset, int) or tick_offset < 0:
1231
+ raise ValueError("Parameter 'tick_offset' must be non-negative.")
1232
+
1233
+ if not otp.compatibility.is_limit_tick_offset_supported():
1234
+ warnings.warn("Parameter 'tick_offset' is set, but is not supported on this OneTick version")
1235
+ else:
1236
+ ep_kwargs = {'tick_offset': tick_offset}
1237
+
1238
+ self.sink(otq.Limit(tick_limit=tick_limit, **ep_kwargs))
1179
1239
  return self
1180
1240
 
1181
1241
 
@@ -108,6 +108,14 @@ class TmpOtq:
108
108
  res.merge(self)
109
109
  return res
110
110
 
111
+ def _get_symbol_dates(self) -> list[str]:
112
+ # check if any of the saved queries have symbol date set and return them (as strings in %Y%m%d format)
113
+ return [
114
+ utils.symbol_date_to_str(query_params['symbol_date'])
115
+ for _, query_params in self.queries.values()
116
+ if 'symbol_date' in query_params
117
+ ]
118
+
111
119
  def save_to_file(self, query=None, query_name="main_query", file_path=None, file_suffix="",
112
120
  start=None, end=None, start_time_expression=None, end_time_expression=None, timezone=None,
113
121
  running_query_flag=None,
@@ -432,7 +432,7 @@ class Source:
432
432
  end_time_expression=None,
433
433
  symbol_date=None):
434
434
  """
435
- Save data source to .otq file and return path to the saved file.
435
+ Save :class:`otp.Source <onetick.py.Source>` object to .otq file and return path to the saved file.
436
436
 
437
437
  Parameters
438
438
  ----------
@@ -474,10 +474,17 @@ class Source:
474
474
 
475
475
  Returns
476
476
  -------
477
-
478
477
  result: str
479
478
  Relative (if ``file_name`` is relative) or absolute path to the created query
480
479
  in the format ``file_name::query_name``
480
+
481
+ Examples
482
+ --------
483
+ Create the .otq file from a :class:`otp.Source <onetick.py.Source>` object:
484
+
485
+ >>> t = otp.Tick(A=1)
486
+ >>> t.to_otq() # doctest: +SKIP
487
+ '/tmp/test_user/run_20251202_181018_11054/impetuous-bullfrog.to_otq.otq::query'
481
488
  """
482
489
  if raw is not None:
483
490
  warnings.warn('The "raw" flag is deprecated and makes no effect', FutureWarning)
@@ -635,7 +642,22 @@ class Source:
635
642
  timezone=timezone,
636
643
  symbol_date=symbol_date)
637
644
 
638
- return query_to_run, require_dict, node_name
645
+ # PY-1423: we should set symbol_date in otp.run always
646
+ symbol_date_to_run = None
647
+ if symbol_date is not None:
648
+ symbol_date_to_run = utils.symbol_date_to_str(symbol_date)
649
+ else:
650
+ symbol_dates_in_tmp_otq = obj._tmp_otq._get_symbol_dates()
651
+ if symbol_dates_in_tmp_otq:
652
+ symbol_date_to_run = symbol_dates_in_tmp_otq[0]
653
+ if len(set(symbol_dates_in_tmp_otq)) > 1:
654
+ warnings.warn(
655
+ f'There are different symbol dates in resulting .otq file: {set(symbol_dates_in_tmp_otq)}.'
656
+ 'But no symbol date were specified in otp.run.\n'
657
+ f'In this case the first symbol_date ({symbol_date_to_run}) will be used automatically.'
658
+ )
659
+
660
+ return query_to_run, require_dict, node_name, symbol_date_to_run
639
661
 
640
662
  def __call__(self, *args, **kwargs):
641
663
  """
@@ -1,7 +1,9 @@
1
1
  import itertools
2
2
  import warnings
3
- from typing import Union, Iterable, Tuple, Optional, Any, Literal
3
+ from collections import defaultdict
4
+ from typing import Union, Iterable, Tuple, Optional, Literal
4
5
  from datetime import date as dt_date, datetime, timedelta
6
+ from functools import wraps
5
7
 
6
8
  import pandas as pd
7
9
  from dateutil.tz import gettz
@@ -19,6 +21,39 @@ def _datetime2date(dt: Union[dt_date, datetime]) -> dt_date:
19
21
  return dt_date(dt.year, dt.month, dt.day)
20
22
 
21
23
 
24
+ def _method_cache(meth):
25
+ """
26
+ Cache the output of class method.
27
+ Cache is created inside of the self object (in self.__cache property)
28
+ and will be deleted when self object is destroyed.
29
+
30
+ This is a rewrite of functools.cache,
31
+ but it doesn't add self argument to cache key and thus doesn't keep reference to self forever.
32
+ """
33
+ @wraps(meth)
34
+ def wrapper(self, *args, **kwargs):
35
+
36
+ # cache key is a tuple of all arguments
37
+ key = args
38
+ for kw_tup in kwargs.items():
39
+ key += kw_tup
40
+ key = hash(key)
41
+
42
+ if not hasattr(self, '__cache'):
43
+ self.__cache = defaultdict(dict)
44
+
45
+ method_cache = self.__cache[meth.__name__]
46
+
47
+ miss = object()
48
+ result = method_cache.get(key, miss)
49
+ if result is miss:
50
+ result = meth(self, *args, **kwargs)
51
+ method_cache[key] = result
52
+ return result
53
+
54
+ return wrapper
55
+
56
+
22
57
  class DB:
23
58
 
24
59
  """
@@ -37,7 +72,11 @@ class DB:
37
72
  self._locator_date_ranges = None
38
73
 
39
74
  def __eq__(self, obj):
40
- return str(self) == str(obj)
75
+ return all((
76
+ self.name == obj.name,
77
+ self.description == obj.description,
78
+ self.context == obj.context,
79
+ ))
41
80
 
42
81
  def __lt__(self, obj):
43
82
  return str(self) < str(obj)
@@ -45,6 +84,7 @@ class DB:
45
84
  def __str__(self):
46
85
  return self.name
47
86
 
87
+ @_method_cache
48
88
  def access_info(self, deep_scan=False, username=None) -> Union[pd.DataFrame, dict]:
49
89
  """
50
90
  Get access info for this database and ``username``.
@@ -111,13 +151,19 @@ class DB:
111
151
  >> otq.WhereClause(where=f'DB_NAME = "{name}"')
112
152
  )
113
153
  graph = otq.GraphQuery(node)
154
+
155
+ self._set_intervals()
156
+ # start and end times don't matter, but need to fit in the configured time ranges
157
+ start, end = self._locator_date_ranges[-1]
158
+
114
159
  df = otp.run(graph,
115
- symbols='LOCAL::',
116
- # start and end times don't matter
117
- start=db_constants.DEFAULT_START_DATE,
118
- end=db_constants.DEFAULT_END_DATE,
160
+ symbols=f'{self.name}::',
161
+ start=start,
162
+ end=end,
119
163
  # and timezone is GMT, because timestamp parameters in ACL are in GMT
120
164
  timezone='GMT',
165
+ # ACCESS_INFO can return ACL violation error if we use database name as symbol
166
+ query_properties={'IGNORE_TICKS_IN_UNENTITLED_TIME_RANGE': 'TRUE'},
121
167
  username=username,
122
168
  context=self.context)
123
169
  if not df.empty:
@@ -255,6 +301,20 @@ class DB:
255
301
  end = start + otp.Day(1)
256
302
  return self._fit_time_interval_in_acl(start, end, timezone)
257
303
 
304
+ @_method_cache
305
+ def _show_configured_time_ranges(self):
306
+ graph = otq.GraphQuery(otq.DbShowConfiguredTimeRanges(db_name=self.name).tick_type("ANY")
307
+ >> otq.Table(fields='long START_DATE, long END_DATE'))
308
+ result = otp.run(graph,
309
+ symbols=f'{self.name}::',
310
+ # start and end times don't matter for this query, use some constants
311
+ start=db_constants.DEFAULT_START_DATE,
312
+ end=db_constants.DEFAULT_END_DATE,
313
+ # GMT, because start/end timestamp in locator are in GMT
314
+ timezone='GMT',
315
+ context=self.context)
316
+ return result
317
+
258
318
  def _set_intervals(self):
259
319
  """
260
320
  Finds all date ranges from locators.
@@ -264,18 +324,7 @@ class DB:
264
324
  """
265
325
 
266
326
  if self._locator_date_ranges is None:
267
- graph = otq.GraphQuery(otq.DbShowConfiguredTimeRanges(db_name=self.name).tick_type("ANY")
268
- >> otq.Table(fields='long START_DATE, long END_DATE'))
269
-
270
- result = otp.run(graph,
271
- symbols=f'{self.name}::',
272
- # start and end times don't matter for this query, use some constants
273
- start=db_constants.DEFAULT_START_DATE,
274
- end=db_constants.DEFAULT_END_DATE,
275
- # GMT, because start/end timestamp in locator are in GMT
276
- timezone='GMT',
277
- context=self.context)
278
-
327
+ result = self._show_configured_time_ranges()
279
328
  date_ranges = []
280
329
 
281
330
  tz_gmt = gettz('GMT')
@@ -316,10 +365,20 @@ class DB:
316
365
 
317
366
  def _show_loaded_time_ranges(self, start, end, only_last=False, prefer_speed_over_accuracy=False):
318
367
  kwargs = {}
368
+ # PY-1421: we aim to make this query as fast as possible
369
+ # There are two problems with this EP:
370
+ # 1. executing this query without using cache
371
+ # and/or without setting prefer_speed_over_accuracy parameter
372
+ # may be very slow for big time range
373
+ # 2. using cache sometimes returns not precise results
374
+ # So in case prefer_speed_over_accuracy parameter is available we are disabling cache.
319
375
  if prefer_speed_over_accuracy:
320
- kwargs['prefer_speed_over_accuracy'] = prefer_speed_over_accuracy
376
+ kwargs['prefer_speed_over_accuracy'] = True
377
+ kwargs['use_cache'] = False
378
+ else:
379
+ kwargs['use_cache'] = True
321
380
 
322
- eps = otq.DbShowLoadedTimeRanges(use_cache=True, **kwargs).tick_type('ANY')
381
+ eps = otq.DbShowLoadedTimeRanges(**kwargs).tick_type('ANY')
323
382
  eps = eps >> otq.WhereClause(where='NUM_LOADED_PARTITIONS > 0')
324
383
  if only_last:
325
384
  eps = eps >> otq.LastTick()
@@ -528,32 +587,45 @@ class DB:
528
587
  ['QTE', 'TRD']
529
588
  """
530
589
  date = self.last_date if date is None else date
590
+
531
591
  if timezone is None:
532
592
  timezone = configuration.config.tz
533
- time_params: dict[str, Any] = {}
534
593
 
535
- if date is not None:
536
- time_params['start'], time_params['end'] = self._fit_date_in_acl(date, timezone=timezone)
594
+ if date is None:
595
+ # in the usual case it would mean that there is no data in the database,
596
+ # but _show_loaded_time_ranges doesn't return dates for database views
597
+ # in this case let's just try to get the database schema with default time range
598
+ start = end = utils.adaptive
599
+ # also it seems that show_schema=True doesn't work for views either
600
+ show_schema = False
601
+ else:
602
+ start, end = self._fit_date_in_acl(date, timezone=timezone) # type: ignore[assignment]
603
+ show_schema = True
537
604
 
538
605
  # PY-458: don't use cache, it can return different result in some cases
539
- result = otp.run(otq.DbShowTickTypes(use_cache=False,
540
- show_schema=False,
541
- include_memdb=True),
542
- symbols=f'{self.name}::',
543
- **time_params,
544
- timezone=timezone,
545
- context=self.context)
546
-
606
+ result = self._get_schema(use_cache=False, start=start, end=end, timezone=timezone, show_schema=show_schema)
547
607
  if len(result) == 0:
548
608
  return []
549
609
 
550
- return result['TICK_TYPE_NAME'].tolist()
610
+ return result['TICK_TYPE_NAME'].unique().tolist()
551
611
 
552
612
  def min_locator_date(self):
553
613
  self._set_intervals()
554
614
  min_date = min(obj[0] for obj in self._locator_date_ranges)
555
615
  return _datetime2date(min_date)
556
616
 
617
+ @_method_cache
618
+ def _get_schema(self, start, end, timezone, use_cache, show_schema):
619
+ ep = otq.DbShowTickTypes(use_cache=use_cache,
620
+ show_schema=show_schema,
621
+ include_memdb=True)
622
+ return otp.run(ep,
623
+ symbols=f'{self.name}::',
624
+ start=start,
625
+ end=end,
626
+ timezone=timezone,
627
+ context=self.context)
628
+
557
629
  def schema(self, date=None, tick_type=None, timezone=None, check_index_file=utils.adaptive) -> dict[str, type]:
558
630
  """
559
631
  Gets the schema of the database.
@@ -615,25 +687,18 @@ class DB:
615
687
 
616
688
  start, end = self._fit_date_in_acl(date, timezone=timezone)
617
689
 
618
- # TODO: refactor into global method, use in tick_types()
619
- def get_schema(use_cache: bool = True):
620
- return otp.run(otq.DbShowTickTypes(use_cache=use_cache,
621
- show_schema=True,
622
- include_memdb=True)
623
- >> otq.WhereClause(where=f'TICK_TYPE_NAME="{tick_type}"'),
624
- symbols=f'{self.name}::',
625
- start=start,
626
- end=end,
627
- timezone=timezone,
628
- context=self.context)
629
-
630
- result = get_schema(use_cache=True)
690
+ kwargs = dict(
691
+ start=start, end=end, timezone=timezone, show_schema=True,
692
+ )
693
+ # PY-458, BEXRTS-1220, PY-1421
694
+ # the results of the query may vary depending on using use_cache parameter, so we are trying both
695
+ result = self._get_schema(use_cache=False, **kwargs)
631
696
  if result.empty:
632
- # in case cache settings in database are bad (e.g. BEXRTS-1220)
633
- result = get_schema(use_cache=False)
697
+ result = self._get_schema(use_cache=True, **kwargs)
634
698
 
635
- fields: Iterable
699
+ fields: Iterable = []
636
700
  if len(result):
701
+ result = result[result['TICK_TYPE_NAME'] == tick_type]
637
702
  # filter schema by date
638
703
  date_to_filter = None
639
704
  if orig_date:
@@ -648,8 +713,6 @@ class DB:
648
713
  fields = zip(result['FIELD_NAME'].tolist(),
649
714
  result['FIELD_TYPE_NAME'].tolist(),
650
715
  result['FIELD_SIZE'].tolist())
651
- else:
652
- fields = []
653
716
 
654
717
  schema = {}
655
718