pylegend 0.12.0__tar.gz → 0.13.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 (180) hide show
  1. {pylegend-0.12.0 → pylegend-0.13.0}/PKG-INFO +1 -1
  2. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/database/sql_to_string/db_extension.py +177 -1
  3. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/expression.py +5 -0
  4. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/literal_expressions.py +22 -1
  5. pylegend-0.13.0/pylegend/core/language/shared/operations/boolean_operation_expressions.py +268 -0
  6. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/operations/date_operation_expressions.py +91 -0
  7. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/operations/integer_operation_expressions.py +183 -1
  8. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/operations/string_operation_expressions.py +31 -1
  9. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/primitives/boolean.py +40 -0
  10. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/primitives/date.py +39 -0
  11. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/primitives/datetime.py +18 -0
  12. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/primitives/integer.py +54 -1
  13. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/primitives/strictdate.py +25 -1
  14. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/primitives/string.py +16 -2
  15. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/sql/metamodel.py +50 -1
  16. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/sql/metamodel_extension.py +77 -1
  17. pylegend-0.13.0/pylegend/core/tds/pandas_api/frames/functions/iloc.py +99 -0
  18. pylegend-0.13.0/pylegend/core/tds/pandas_api/frames/functions/loc.py +136 -0
  19. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/pandas_api_base_tds_frame.py +40 -0
  20. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/pandas_api_tds_frame.py +12 -0
  21. {pylegend-0.12.0 → pylegend-0.13.0}/pyproject.toml +1 -1
  22. pylegend-0.12.0/pylegend/core/language/shared/operations/boolean_operation_expressions.py +0 -124
  23. {pylegend-0.12.0 → pylegend-0.13.0}/LICENSE +0 -0
  24. {pylegend-0.12.0 → pylegend-0.13.0}/LICENSE.spdx +0 -0
  25. {pylegend-0.12.0 → pylegend-0.13.0}/NOTICE +0 -0
  26. {pylegend-0.12.0 → pylegend-0.13.0}/README.md +0 -0
  27. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/__init__.py +0 -0
  28. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/_typing.py +0 -0
  29. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/__init__.py +0 -0
  30. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/database/__init__.py +0 -0
  31. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/database/sql_to_string/__init__.py +0 -0
  32. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/database/sql_to_string/config.py +0 -0
  33. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/database/sql_to_string/generator.py +0 -0
  34. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/__init__.py +0 -0
  35. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/legacy_api/__init__.py +0 -0
  36. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/legacy_api/aggregate_specification.py +0 -0
  37. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/legacy_api/legacy_api_tds_row.py +0 -0
  38. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/legendql_api/__init__.py +0 -0
  39. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/legendql_api/legendql_api_custom_expressions.py +0 -0
  40. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/legendql_api/legendql_api_tds_row.py +0 -0
  41. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/pandas_api/__init__.py +0 -0
  42. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/pandas_api/pandas_api_aggregate_specification.py +0 -0
  43. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/pandas_api/pandas_api_custom_expressions.py +0 -0
  44. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/pandas_api/pandas_api_series.py +0 -0
  45. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/pandas_api/pandas_api_tds_row.py +0 -0
  46. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/__init__.py +0 -0
  47. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/column_expressions.py +0 -0
  48. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/functions.py +0 -0
  49. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/helpers.py +0 -0
  50. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/operations/__init__.py +0 -0
  51. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/operations/binary_expression.py +0 -0
  52. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/operations/collection_operation_expressions.py +0 -0
  53. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/operations/float_operation_expressions.py +0 -0
  54. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/operations/nary_expression.py +0 -0
  55. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/operations/nullary_expression.py +0 -0
  56. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/operations/number_operation_expressions.py +0 -0
  57. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/operations/primitive_operation_expressions.py +0 -0
  58. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/operations/unary_expression.py +0 -0
  59. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/pct_helpers.py +0 -0
  60. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/primitive_collection.py +0 -0
  61. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/primitives/__init__.py +0 -0
  62. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/primitives/float.py +0 -0
  63. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/primitives/number.py +0 -0
  64. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/primitives/primitive.py +0 -0
  65. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/language/shared/tds_row.py +0 -0
  66. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/project_cooridnates.py +0 -0
  67. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/request/__init__.py +0 -0
  68. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/request/auth.py +0 -0
  69. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/request/legend_client.py +0 -0
  70. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/request/response_reader.py +0 -0
  71. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/request/service_client.py +0 -0
  72. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/sql/__init__.py +0 -0
  73. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/__init__.py +0 -0
  74. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/abstract/__init__.py +0 -0
  75. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/abstract/frames/__init__.py +0 -0
  76. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/abstract/frames/applied_function_tds_frame.py +0 -0
  77. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/abstract/frames/base_tds_frame.py +0 -0
  78. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/abstract/frames/input_tds_frame.py +0 -0
  79. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/abstract/function_helpers.py +0 -0
  80. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/__init__.py +0 -0
  81. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/__init__.py +0 -0
  82. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/__init__.py +0 -0
  83. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/legacy_api_concatenate_function.py +0 -0
  84. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/legacy_api_distinct_function.py +0 -0
  85. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/legacy_api_drop_function.py +0 -0
  86. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/legacy_api_extend_function.py +0 -0
  87. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/legacy_api_filter_function.py +0 -0
  88. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/legacy_api_group_by_function.py +0 -0
  89. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/legacy_api_head_function.py +0 -0
  90. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/legacy_api_join_by_columns_function.py +0 -0
  91. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/legacy_api_join_function.py +0 -0
  92. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/legacy_api_rename_columns_function.py +0 -0
  93. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/legacy_api_restrict_function.py +0 -0
  94. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/legacy_api_slice_function.py +0 -0
  95. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/functions/legacy_api_sort_function.py +0 -0
  96. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/legacy_api_applied_function_tds_frame.py +0 -0
  97. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/legacy_api_base_tds_frame.py +0 -0
  98. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/legacy_api_input_tds_frame.py +0 -0
  99. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legacy_api/frames/legacy_api_tds_frame.py +0 -0
  100. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/__init__.py +0 -0
  101. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/__init__.py +0 -0
  102. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/__init__.py +0 -0
  103. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_asofjoin_function.py +0 -0
  104. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_concatenate_function.py +0 -0
  105. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_distinct_function.py +0 -0
  106. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_drop_function.py +0 -0
  107. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_extend_function.py +0 -0
  108. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_filter_function.py +0 -0
  109. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_function_helpers.py +0 -0
  110. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_groupby_function.py +0 -0
  111. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_head_function.py +0 -0
  112. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_join_function.py +0 -0
  113. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_project_function.py +0 -0
  114. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_rename_function.py +0 -0
  115. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_select_function.py +0 -0
  116. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_slice_function.py +0 -0
  117. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_sort_function.py +0 -0
  118. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/functions/legendql_api_window_extend_function.py +0 -0
  119. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/legendql_api_applied_function_tds_frame.py +0 -0
  120. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/legendql_api_base_tds_frame.py +0 -0
  121. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/legendql_api_input_tds_frame.py +0 -0
  122. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/legendql_api/frames/legendql_api_tds_frame.py +0 -0
  123. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/__init__.py +0 -0
  124. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/__init__.py +0 -0
  125. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/functions/__init__.py +0 -0
  126. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/functions/aggregate_function.py +0 -0
  127. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/functions/assign_function.py +0 -0
  128. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/functions/drop.py +0 -0
  129. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/functions/dropna.py +0 -0
  130. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/functions/fillna.py +0 -0
  131. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/functions/filter.py +0 -0
  132. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/functions/filtering.py +0 -0
  133. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/functions/merge.py +0 -0
  134. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/functions/rename.py +0 -0
  135. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/functions/sort_values_function.py +0 -0
  136. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/functions/truncate_function.py +0 -0
  137. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/pandas_api_applied_function_tds_frame.py +0 -0
  138. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/pandas_api_groupby_tds_frame.py +0 -0
  139. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/pandas_api/frames/pandas_api_input_tds_frame.py +0 -0
  140. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/result_handler/__init__.py +0 -0
  141. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/result_handler/result_handler.py +0 -0
  142. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/result_handler/to_csv_file_result_handler.py +0 -0
  143. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/result_handler/to_json_file_result_handler.py +0 -0
  144. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/result_handler/to_string_result_handler.py +0 -0
  145. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/sql_query_helpers.py +0 -0
  146. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/tds_column.py +0 -0
  147. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/core/tds/tds_frame.py +0 -0
  148. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/__init__.py +0 -0
  149. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/database/__init__.py +0 -0
  150. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/database/vendors/__init__.py +0 -0
  151. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/database/vendors/postgres/__init__.py +0 -0
  152. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/database/vendors/postgres/postgres_sql_to_string.py +0 -0
  153. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/__init__.py +0 -0
  154. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/abstract/__init__.py +0 -0
  155. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/abstract/csv_tds_frame.py +0 -0
  156. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/abstract/legend_function_input_frame.py +0 -0
  157. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/abstract/legend_service_input_frame.py +0 -0
  158. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/abstract/table_spec_input_frame.py +0 -0
  159. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/legacy_api/__init__.py +0 -0
  160. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/legacy_api/frames/__init__.py +0 -0
  161. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/legacy_api/frames/legacy_api_legend_function_input_frame.py +0 -0
  162. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/legacy_api/frames/legacy_api_legend_service_input_frame.py +0 -0
  163. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/legacy_api/frames/legacy_api_table_spec_input_frame.py +0 -0
  164. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/legendql_api/__init__.py +0 -0
  165. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/legendql_api/frames/__init__.py +0 -0
  166. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/legendql_api/frames/legendql_api_csv_input_frame.py +0 -0
  167. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/legendql_api/frames/legendql_api_legend_function_input_frame.py +0 -0
  168. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/legendql_api/frames/legendql_api_legend_service_input_frame.py +0 -0
  169. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/legendql_api/frames/legendql_api_table_spec_input_frame.py +0 -0
  170. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/pandas_api/__init__.py +0 -0
  171. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/pandas_api/frames/__init__.py +0 -0
  172. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/pandas_api/frames/pandas_api_legend_function_input_frame.py +0 -0
  173. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/pandas_api/frames/pandas_api_legend_service_input_frame.py +0 -0
  174. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/pandas_api/frames/pandas_api_table_spec_input_frame.py +0 -0
  175. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/result_handler/__init__.py +0 -0
  176. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/extensions/tds/result_handler/to_pandas_df_result_handler.py +0 -0
  177. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/legacy_api_tds_client.py +0 -0
  178. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/legendql_api_tds_client.py +0 -0
  179. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/utils/__init__.py +0 -0
  180. {pylegend-0.12.0 → pylegend-0.13.0}/pylegend/utils/class_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pylegend
3
- Version: 0.12.0
3
+ Version: 0.13.0
4
4
  Summary: Python language binding for Legend data management platform
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -75,7 +75,11 @@ from pylegend.core.sql.metamodel import (
75
75
  WindowFrame,
76
76
  WindowFrameMode,
77
77
  FrameBound,
78
- FrameBoundType
78
+ FrameBoundType,
79
+ BitwiseShiftExpression,
80
+ BitwiseShiftDirection,
81
+ BitwiseBinaryExpression,
82
+ BitwiseBinaryOperator
79
83
  )
80
84
  from pylegend.core.sql.metamodel_extension import (
81
85
  StringLengthExpression,
@@ -137,6 +141,11 @@ from pylegend.core.sql.metamodel_extension import (
137
141
  WindowExpression,
138
142
  ConstantExpression,
139
143
  StringSubStringExpression,
144
+ DateAdjustExpression,
145
+ BitwiseNotExpression,
146
+ DateDiffExpression,
147
+ DateTimeBucketExpression,
148
+ DateType,
140
149
  )
141
150
 
142
151
  __all__: PyLegendSequence[str] = [
@@ -460,6 +469,18 @@ def expression_processor(
460
469
  return expression.name
461
470
  elif isinstance(expression, StringSubStringExpression):
462
471
  return extension.process_string_substring_expression(expression, config)
472
+ elif isinstance(expression, DateAdjustExpression):
473
+ return extension.process_date_adjust_expression(expression, config)
474
+ elif isinstance(expression, DateDiffExpression):
475
+ return extension.process_date_diff_expression(expression, config)
476
+ elif isinstance(expression, DateTimeBucketExpression):
477
+ return extension.process_date_time_bucket_expression(expression, config)
478
+ elif isinstance(expression, BitwiseNotExpression):
479
+ return extension.process_bitwise_not_expression(expression, config)
480
+ elif isinstance(expression, BitwiseShiftExpression):
481
+ return extension.process_bitwise_shift_expression(expression, config)
482
+ elif isinstance(expression, BitwiseBinaryExpression):
483
+ return extension.process_bitwise_binary_expression(expression, config)
463
484
 
464
485
  else:
465
486
  raise ValueError("Unsupported expression type: " + str(type(expression))) # pragma: no cover
@@ -520,6 +541,139 @@ def logical_binary_expression_processor(
520
541
  return f"({left} {op} {right})"
521
542
 
522
543
 
544
+ def bitwise_binary_expression_processor(
545
+ bitwise: BitwiseBinaryExpression,
546
+ extension: "SqlToStringDbExtension",
547
+ config: SqlToStringConfig
548
+ ) -> str:
549
+ op_type = bitwise.operator
550
+ if op_type == BitwiseBinaryOperator.AND:
551
+ op = "&"
552
+ elif op_type == BitwiseBinaryOperator.OR:
553
+ op = "|"
554
+ elif op_type == BitwiseBinaryOperator.XOR:
555
+ op = "#"
556
+ else:
557
+ raise ValueError("Unknown bitwise binary operator type: " + str(op_type)) # pragma: no cover
558
+
559
+ left = extension.process_expression(bitwise.left, config)
560
+ right = extension.process_expression(bitwise.right, config)
561
+ return f"({left} {op} {right})"
562
+
563
+
564
+ def date_diff_processor(
565
+ date_diff: DateDiffExpression,
566
+ extension: "SqlToStringDbExtension",
567
+ config: SqlToStringConfig
568
+ ) -> str:
569
+ unit = date_diff.duration_unit.value
570
+
571
+ end = extension.process_expression(date_diff.end_date, config)
572
+ start = extension.process_expression(date_diff.start_date, config)
573
+
574
+ def extract_diff(part: str) -> str:
575
+ return f"(EXTRACT({part} FROM {end}) - EXTRACT({part} FROM {start}))"
576
+
577
+ year_diff = extract_diff("YEAR")
578
+ month_diff = extract_diff("MONTH")
579
+ # d1 - d2 → Pure dateDiff(d1, d2) → evaluated as d2 - d1
580
+ # Reverse to preserve expected semantics.
581
+ # only for days
582
+ day_diff = f"CAST(CAST({start} AS DATE) - CAST({end} AS DATE) AS INTEGER)"
583
+ epoch_diff = f"(EXTRACT(EPOCH FROM {end}) - EXTRACT(EPOCH FROM {start}))"
584
+
585
+ if unit == "YEARS":
586
+ return year_diff
587
+
588
+ if unit == "MONTHS":
589
+ return f"({year_diff} * 12 + {month_diff})"
590
+
591
+ if unit == "DAYS":
592
+ return day_diff
593
+
594
+ if unit == "WEEKS":
595
+ return f"CAST(FLOOR({day_diff} / 7) AS INTEGER)"
596
+
597
+ if unit == "HOURS":
598
+ return f"CAST(FLOOR({epoch_diff} / 3600) AS INTEGER)"
599
+
600
+ if unit == "MINUTES":
601
+ return f"CAST(FLOOR({epoch_diff} / 60) AS INTEGER)"
602
+
603
+ if unit == "SECONDS":
604
+ return f"CAST({epoch_diff} AS BIGINT)"
605
+
606
+ if unit == "MILLISECONDS":
607
+ return f"CAST({epoch_diff} * 1000 AS BIGINT)"
608
+
609
+ raise ValueError(f"Unsupported DATE DIFF unit: {unit}") # pragma: no cover
610
+
611
+
612
+ def date_time_bucket_processor(
613
+ expression: DateTimeBucketExpression,
614
+ extension: "SqlToStringDbExtension",
615
+ config: SqlToStringConfig
616
+ ) -> str:
617
+ unit = expression.duration_unit.value
618
+ ts = extension.process_expression(expression.date, config)
619
+ q = extension.process_expression(expression.quantity, config)
620
+
621
+ def coerce_to_datetime(sql: str) -> str:
622
+ return (
623
+ f"(({sql}) + INTERVAL '0 second')"
624
+ if expression.date_type == DateType.DateTime
625
+ else sql
626
+ )
627
+
628
+ def epoch() -> str:
629
+ return (
630
+ f"EXTRACT(EPOCH FROM {ts})"
631
+ )
632
+
633
+ if unit == "YEARS":
634
+ return coerce_to_datetime(
635
+ f"make_date(1970,1,1) + "
636
+ f"(FLOOR((EXTRACT(YEAR FROM {ts}) - 1970) / {q}) * {q}) * INTERVAL '1 year'"
637
+ )
638
+
639
+ if unit == "MONTHS":
640
+ total_months_sql = f"((EXTRACT(YEAR FROM {ts}) - 1970) * 12 + (EXTRACT(MONTH FROM {ts}) - 1))"
641
+ return coerce_to_datetime(
642
+ f"make_date(1970,1,1) + "
643
+ f"(FLOOR({total_months_sql} / {q}) * {q}) * INTERVAL '1 month'"
644
+ )
645
+
646
+ if unit == "WEEKS":
647
+ return coerce_to_datetime(
648
+ f"make_date(1969,12,29) + ("
649
+ f"FLOOR(("
650
+ f"{epoch()} - EXTRACT(EPOCH FROM make_date(1969,12,29))"
651
+ f") / (86400 * {q} * 7))"
652
+ f") * ({q} * 7) * INTERVAL '1 day'"
653
+ )
654
+
655
+ if unit == "DAYS":
656
+ days_from_1970 = f"({epoch()} / 86400)"
657
+ return coerce_to_datetime(
658
+ f"make_date(1970,1,1) + "
659
+ f"(FLOOR({days_from_1970} / {q}) * {q}) * INTERVAL '1 day'"
660
+ )
661
+
662
+ unit_seconds_map = {
663
+ "HOURS": 3600,
664
+ "MINUTES": 60,
665
+ "SECONDS": 1
666
+ }
667
+
668
+ if unit in unit_seconds_map:
669
+ seconds_per_unit = unit_seconds_map[unit]
670
+ return (f"(make_date(1970,1,1) + "
671
+ f"(FLOOR({epoch()} / ({q} * {seconds_per_unit})) * ({q} * {seconds_per_unit})) "
672
+ f"* INTERVAL '1 second')")
673
+
674
+ raise ValueError(f"Unsupported TIME BUCKET unit: {unit}") # pragma: no cover
675
+
676
+
523
677
  def not_expression_processor(
524
678
  not_expression: NotExpression,
525
679
  extension: "SqlToStringDbExtension",
@@ -1322,3 +1476,25 @@ class SqlToStringDbExtension:
1322
1476
 
1323
1477
  def process_frame_bound(self, frame_bound: FrameBound, config: SqlToStringConfig) -> str:
1324
1478
  return frame_bound_processor(frame_bound, self, config)
1479
+
1480
+ def process_date_adjust_expression(self, expr: DateAdjustExpression, config: SqlToStringConfig) -> str:
1481
+ return (f"({self.process_expression(expr.date, config)}::DATE + "
1482
+ f"(INTERVAL '{self.process_expression(expr.number, config)} "
1483
+ f"{expr.duration_unit.value.upper()}'))::DATE")
1484
+
1485
+ def process_bitwise_not_expression(self, expr: BitwiseNotExpression, config: SqlToStringConfig) -> str:
1486
+ return f"~({self.process_expression(expr.value, config)})"
1487
+
1488
+ def process_bitwise_shift_expression(self, expr: BitwiseShiftExpression, config: SqlToStringConfig) -> str:
1489
+ return (f"({self.process_expression(expr.value, config)} "
1490
+ f"{'>>' if expr.direction == BitwiseShiftDirection.RIGHT else '<<'} "
1491
+ f"{self.process_expression(expr.shift, config)})")
1492
+
1493
+ def process_bitwise_binary_expression(self, expr: BitwiseBinaryExpression, config: SqlToStringConfig) -> str:
1494
+ return bitwise_binary_expression_processor(expr, self, config)
1495
+
1496
+ def process_date_diff_expression(self, expr: DateDiffExpression, config: SqlToStringConfig) -> str:
1497
+ return date_diff_processor(expr, self, config)
1498
+
1499
+ def process_date_time_bucket_expression(self, expr: DateTimeBucketExpression, config: SqlToStringConfig) -> str:
1500
+ return date_time_bucket_processor(expr, self, config)
@@ -36,6 +36,7 @@ __all__: PyLegendSequence[str] = [
36
36
  "PyLegendExpressionDateReturn",
37
37
  "PyLegendExpressionDateTimeReturn",
38
38
  "PyLegendExpressionStrictDateReturn",
39
+ "PyLegendExpressionNullReturn"
39
40
  ]
40
41
 
41
42
 
@@ -86,3 +87,7 @@ class PyLegendExpressionDateTimeReturn(PyLegendExpressionDateReturn, metaclass=A
86
87
 
87
88
  class PyLegendExpressionStrictDateReturn(PyLegendExpressionDateReturn, metaclass=ABCMeta):
88
89
  pass
90
+
91
+
92
+ class PyLegendExpressionNullReturn(PyLegendExpression, metaclass=ABCMeta):
93
+ pass
@@ -27,6 +27,7 @@ from pylegend.core.language.shared.expression import (
27
27
  PyLegendExpressionFloatReturn,
28
28
  PyLegendExpressionDateTimeReturn,
29
29
  PyLegendExpressionStrictDateReturn,
30
+ PyLegendExpressionNullReturn,
30
31
  )
31
32
  from pylegend.core.sql.metamodel import (
32
33
  Expression,
@@ -37,6 +38,7 @@ from pylegend.core.sql.metamodel import (
37
38
  QuerySpecification,
38
39
  Cast,
39
40
  ColumnType,
41
+ NullLiteral,
40
42
  )
41
43
  from pylegend.core.tds.tds_frame import FrameToSqlConfig
42
44
  from pylegend.core.tds.tds_frame import FrameToPureConfig
@@ -180,8 +182,25 @@ class PyLegendStrictDateLiteralExpression(PyLegendExpressionStrictDateReturn):
180
182
  return True
181
183
 
182
184
 
185
+ class PyLegendNullLiteralExpression(PyLegendExpressionNullReturn):
186
+ __value: None
187
+
188
+ def __init__(self) -> None:
189
+ return
190
+
191
+ def to_sql_expression(
192
+ self,
193
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
194
+ config: FrameToSqlConfig
195
+ ) -> Expression:
196
+ return NullLiteral()
197
+
198
+ def to_pure_expression(self, config: FrameToPureConfig) -> str:
199
+ return "[]"
200
+
201
+
183
202
  def convert_literal_to_literal_expression(
184
- literal: PyLegendUnion[int, float, bool, str, datetime, date]
203
+ literal: PyLegendUnion[int, float, bool, str, datetime, date, None]
185
204
  ) -> PyLegendExpression:
186
205
  if isinstance(literal, bool):
187
206
  return PyLegendBooleanLiteralExpression(literal)
@@ -195,5 +214,7 @@ def convert_literal_to_literal_expression(
195
214
  return PyLegendDateTimeLiteralExpression(literal)
196
215
  if isinstance(literal, date):
197
216
  return PyLegendStrictDateLiteralExpression(literal)
217
+ if isinstance(literal, type(None)):
218
+ return PyLegendNullLiteralExpression()
198
219
 
199
220
  raise TypeError(f"Cannot convert value - {literal} of type {type(literal)} to literal expression")
@@ -0,0 +1,268 @@
1
+ # Copyright 2023 Goldman Sachs
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from pylegend._typing import (
16
+ PyLegendSequence,
17
+ PyLegendDict,
18
+ )
19
+ from pylegend.core.language.shared.expression import (
20
+ PyLegendExpressionBooleanReturn,
21
+ )
22
+ from pylegend.core.language.shared.helpers import generate_pure_functional_call
23
+ from pylegend.core.language.shared.operations.binary_expression import PyLegendBinaryExpression
24
+ from pylegend.core.language.shared.operations.unary_expression import PyLegendUnaryExpression
25
+ from pylegend.core.sql.metamodel import (
26
+ Expression,
27
+ QuerySpecification,
28
+ LogicalBinaryExpression,
29
+ LogicalBinaryType,
30
+ NotExpression,
31
+ ComparisonExpression,
32
+ ComparisonOperator,
33
+ )
34
+ from pylegend.core.tds.tds_frame import FrameToSqlConfig
35
+ from pylegend.core.tds.tds_frame import FrameToPureConfig
36
+
37
+
38
+ __all__: PyLegendSequence[str] = [
39
+ "PyLegendBooleanOrExpression",
40
+ "PyLegendBooleanAndExpression",
41
+ "PyLegendBooleanNotExpression",
42
+ "PyLegendBooleanLessThanExpression",
43
+ "PyLegendBooleanLessThanEqualExpression",
44
+ "PyLegendBooleanGreaterThanExpression",
45
+ "PyLegendBooleanGreaterThanEqualExpression",
46
+ "PyLegendBooleanXorExpression"
47
+ ]
48
+
49
+
50
+ class PyLegendBooleanOrExpression(PyLegendBinaryExpression, PyLegendExpressionBooleanReturn):
51
+
52
+ @staticmethod
53
+ def __to_sql_func(
54
+ expression1: Expression,
55
+ expression2: Expression,
56
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
57
+ config: FrameToSqlConfig
58
+ ) -> Expression:
59
+ return LogicalBinaryExpression(LogicalBinaryType.OR, expression1, expression2)
60
+
61
+ @staticmethod
62
+ def __to_pure_func(op1_expr: str, op2_expr: str, config: FrameToPureConfig) -> str:
63
+ return f"({op1_expr} || {op2_expr})"
64
+
65
+ def __init__(self, operand1: PyLegendExpressionBooleanReturn, operand2: PyLegendExpressionBooleanReturn) -> None:
66
+ PyLegendExpressionBooleanReturn.__init__(self)
67
+ PyLegendBinaryExpression.__init__(
68
+ self,
69
+ operand1,
70
+ operand2,
71
+ PyLegendBooleanOrExpression.__to_sql_func,
72
+ PyLegendBooleanOrExpression.__to_pure_func,
73
+ non_nullable=True,
74
+ first_operand_needs_to_be_non_nullable=True,
75
+ second_operand_needs_to_be_non_nullable=True
76
+ )
77
+
78
+
79
+ class PyLegendBooleanAndExpression(PyLegendBinaryExpression, PyLegendExpressionBooleanReturn):
80
+
81
+ @staticmethod
82
+ def __to_sql_func(
83
+ expression1: Expression,
84
+ expression2: Expression,
85
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
86
+ config: FrameToSqlConfig
87
+ ) -> Expression:
88
+ return LogicalBinaryExpression(LogicalBinaryType.AND, expression1, expression2)
89
+
90
+ @staticmethod
91
+ def __to_pure_func(op1_expr: str, op2_expr: str, config: FrameToPureConfig) -> str:
92
+ return f"({op1_expr} && {op2_expr})"
93
+
94
+ def __init__(self, operand1: PyLegendExpressionBooleanReturn, operand2: PyLegendExpressionBooleanReturn) -> None:
95
+ PyLegendExpressionBooleanReturn.__init__(self)
96
+ PyLegendBinaryExpression.__init__(
97
+ self,
98
+ operand1,
99
+ operand2,
100
+ PyLegendBooleanAndExpression.__to_sql_func,
101
+ PyLegendBooleanAndExpression.__to_pure_func,
102
+ non_nullable=True,
103
+ first_operand_needs_to_be_non_nullable=True,
104
+ second_operand_needs_to_be_non_nullable=True
105
+ )
106
+
107
+
108
+ class PyLegendBooleanLessThanExpression(PyLegendBinaryExpression, PyLegendExpressionBooleanReturn):
109
+
110
+ @staticmethod
111
+ def __to_sql_func(
112
+ expression1: Expression,
113
+ expression2: Expression,
114
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
115
+ config: FrameToSqlConfig
116
+ ) -> Expression:
117
+ return ComparisonExpression(expression1, expression2, ComparisonOperator.LESS_THAN)
118
+
119
+ @staticmethod
120
+ def __to_pure_func(op1_expr: str, op2_expr: str, config: FrameToPureConfig) -> str:
121
+ return f"({op1_expr} < {op2_expr})"
122
+
123
+ def __init__(self, operand1: PyLegendExpressionBooleanReturn, operand2: PyLegendExpressionBooleanReturn) -> None:
124
+ PyLegendExpressionBooleanReturn.__init__(self)
125
+ PyLegendBinaryExpression.__init__(
126
+ self,
127
+ operand1,
128
+ operand2,
129
+ PyLegendBooleanLessThanExpression.__to_sql_func,
130
+ PyLegendBooleanLessThanExpression.__to_pure_func,
131
+ non_nullable=True
132
+ )
133
+
134
+
135
+ class PyLegendBooleanLessThanEqualExpression(PyLegendBinaryExpression, PyLegendExpressionBooleanReturn):
136
+
137
+ @staticmethod
138
+ def __to_sql_func(
139
+ expression1: Expression,
140
+ expression2: Expression,
141
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
142
+ config: FrameToSqlConfig
143
+ ) -> Expression:
144
+ return ComparisonExpression(expression1, expression2, ComparisonOperator.LESS_THAN_OR_EQUAL)
145
+
146
+ @staticmethod
147
+ def __to_pure_func(op1_expr: str, op2_expr: str, config: FrameToPureConfig) -> str:
148
+ return f"({op1_expr} <= {op2_expr})"
149
+
150
+ def __init__(self, operand1: PyLegendExpressionBooleanReturn, operand2: PyLegendExpressionBooleanReturn) -> None:
151
+ PyLegendExpressionBooleanReturn.__init__(self)
152
+ PyLegendBinaryExpression.__init__(
153
+ self,
154
+ operand1,
155
+ operand2,
156
+ PyLegendBooleanLessThanEqualExpression.__to_sql_func,
157
+ PyLegendBooleanLessThanEqualExpression.__to_pure_func,
158
+ non_nullable=True
159
+ )
160
+
161
+
162
+ class PyLegendBooleanGreaterThanExpression(PyLegendBinaryExpression, PyLegendExpressionBooleanReturn):
163
+
164
+ @staticmethod
165
+ def __to_sql_func(
166
+ expression1: Expression,
167
+ expression2: Expression,
168
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
169
+ config: FrameToSqlConfig
170
+ ) -> Expression:
171
+ return ComparisonExpression(expression1, expression2, ComparisonOperator.GREATER_THAN)
172
+
173
+ @staticmethod
174
+ def __to_pure_func(op1_expr: str, op2_expr: str, config: FrameToPureConfig) -> str:
175
+ return f"({op1_expr} > {op2_expr})"
176
+
177
+ def __init__(self, operand1: PyLegendExpressionBooleanReturn, operand2: PyLegendExpressionBooleanReturn) -> None:
178
+ PyLegendExpressionBooleanReturn.__init__(self)
179
+ PyLegendBinaryExpression.__init__(
180
+ self,
181
+ operand1,
182
+ operand2,
183
+ PyLegendBooleanGreaterThanExpression.__to_sql_func,
184
+ PyLegendBooleanGreaterThanExpression.__to_pure_func,
185
+ non_nullable=True
186
+ )
187
+
188
+
189
+ class PyLegendBooleanGreaterThanEqualExpression(PyLegendBinaryExpression, PyLegendExpressionBooleanReturn):
190
+
191
+ @staticmethod
192
+ def __to_sql_func(
193
+ expression1: Expression,
194
+ expression2: Expression,
195
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
196
+ config: FrameToSqlConfig
197
+ ) -> Expression:
198
+ return ComparisonExpression(expression1, expression2, ComparisonOperator.GREATER_THAN_OR_EQUAL)
199
+
200
+ @staticmethod
201
+ def __to_pure_func(op1_expr: str, op2_expr: str, config: FrameToPureConfig) -> str:
202
+ return f"({op1_expr} >= {op2_expr})"
203
+
204
+ def __init__(self, operand1: PyLegendExpressionBooleanReturn, operand2: PyLegendExpressionBooleanReturn) -> None:
205
+ PyLegendExpressionBooleanReturn.__init__(self)
206
+ PyLegendBinaryExpression.__init__(
207
+ self,
208
+ operand1,
209
+ operand2,
210
+ PyLegendBooleanGreaterThanEqualExpression.__to_sql_func,
211
+ PyLegendBooleanGreaterThanEqualExpression.__to_pure_func,
212
+ non_nullable=True
213
+ )
214
+
215
+
216
+ class PyLegendBooleanXorExpression(PyLegendBinaryExpression, PyLegendExpressionBooleanReturn):
217
+
218
+ @staticmethod
219
+ def __to_sql_func(
220
+ expression1: Expression,
221
+ expression2: Expression,
222
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
223
+ config: FrameToSqlConfig
224
+ ) -> Expression:
225
+ return ComparisonExpression(expression1, expression2, ComparisonOperator.NOT_EQUAL)
226
+
227
+ @staticmethod
228
+ def __to_pure_func(op1_expr: str, op2_expr: str, config: FrameToPureConfig) -> str:
229
+ return generate_pure_functional_call("xor", [op1_expr, op2_expr])
230
+
231
+ def __init__(self, operand1: PyLegendExpressionBooleanReturn, operand2: PyLegendExpressionBooleanReturn) -> None:
232
+ PyLegendExpressionBooleanReturn.__init__(self)
233
+ PyLegendBinaryExpression.__init__(
234
+ self,
235
+ operand1,
236
+ operand2,
237
+ PyLegendBooleanXorExpression.__to_sql_func,
238
+ PyLegendBooleanXorExpression.__to_pure_func,
239
+ non_nullable=True,
240
+ first_operand_needs_to_be_non_nullable=True,
241
+ second_operand_needs_to_be_non_nullable=True
242
+ )
243
+
244
+
245
+ class PyLegendBooleanNotExpression(PyLegendUnaryExpression, PyLegendExpressionBooleanReturn):
246
+
247
+ @staticmethod
248
+ def __to_sql_func(
249
+ expression: Expression,
250
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
251
+ config: FrameToSqlConfig
252
+ ) -> Expression:
253
+ return NotExpression(expression)
254
+
255
+ @staticmethod
256
+ def __to_pure_func(op_expr: str, config: FrameToPureConfig) -> str:
257
+ return generate_pure_functional_call("not", [op_expr])
258
+
259
+ def __init__(self, operand: PyLegendExpressionBooleanReturn) -> None:
260
+ PyLegendExpressionBooleanReturn.__init__(self)
261
+ PyLegendUnaryExpression.__init__(
262
+ self,
263
+ operand,
264
+ PyLegendBooleanNotExpression.__to_sql_func,
265
+ PyLegendBooleanNotExpression.__to_pure_func,
266
+ non_nullable=True,
267
+ operand_needs_to_be_non_nullable=True,
268
+ )
@@ -22,8 +22,10 @@ from pylegend.core.language.shared.expression import (
22
22
  PyLegendExpressionStrictDateReturn,
23
23
  PyLegendExpressionIntegerReturn,
24
24
  PyLegendExpressionBooleanReturn,
25
+ PyLegendExpression
25
26
  )
26
27
  from pylegend.core.language.shared.operations.binary_expression import PyLegendBinaryExpression
28
+ from pylegend.core.language.shared.operations.nary_expression import PyLegendNaryExpression
27
29
  from pylegend.core.language.shared.operations.nullary_expression import PyLegendNullaryExpression
28
30
  from pylegend.core.language.shared.operations.unary_expression import PyLegendUnaryExpression
29
31
  from pylegend.core.language.shared.helpers import generate_pure_functional_call
@@ -61,6 +63,10 @@ from pylegend.core.sql.metamodel_extension import (
61
63
  MinuteExpression,
62
64
  SecondExpression,
63
65
  EpochExpression,
66
+ DateAdjustExpression,
67
+ DateDiffExpression,
68
+ DateTimeBucketExpression,
69
+ DateType,
64
70
  )
65
71
 
66
72
 
@@ -91,6 +97,9 @@ __all__: PyLegendSequence[str] = [
91
97
  "PyLegendDateLessThanEqualExpression",
92
98
  "PyLegendDateGreaterThanExpression",
93
99
  "PyLegendDateGreaterThanEqualExpression",
100
+ "PyLegendDateAdjustExpression",
101
+ "PyLegendDateDiffExpression",
102
+ "PyLegendDateTimeBucketExpression",
94
103
  ]
95
104
 
96
105
 
@@ -780,3 +789,85 @@ class PyLegendDateGreaterThanEqualExpression(PyLegendBinaryExpression, PyLegendE
780
789
 
781
790
  def is_non_nullable(self) -> bool:
782
791
  return True
792
+
793
+
794
+ class PyLegendDateAdjustExpression(PyLegendNaryExpression, PyLegendExpressionDateReturn):
795
+
796
+ @staticmethod
797
+ def __to_sql_func(
798
+ expressions: list[Expression],
799
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
800
+ config: FrameToSqlConfig
801
+ ) -> Expression:
802
+ return DateAdjustExpression(expressions[0], expressions[1], expressions[2]) # type:ignore
803
+
804
+ @staticmethod
805
+ def __to_pure_func(op_expr: list[str], config: FrameToPureConfig) -> str:
806
+ return generate_pure_functional_call("adjust", [op_expr[0], op_expr[1], f"DurationUnit.{op_expr[2]}"])
807
+
808
+ def __init__(self, operands: list[PyLegendExpression]) -> None:
809
+ PyLegendExpressionDateReturn.__init__(self)
810
+ PyLegendNaryExpression.__init__(
811
+ self,
812
+ operands,
813
+ PyLegendDateAdjustExpression.__to_sql_func,
814
+ PyLegendDateAdjustExpression.__to_pure_func,
815
+ non_nullable=True,
816
+ operands_non_nullable_flags=[True, True, True]
817
+ )
818
+
819
+
820
+ class PyLegendDateDiffExpression(PyLegendNaryExpression, PyLegendExpressionIntegerReturn):
821
+
822
+ @staticmethod
823
+ def __to_sql_func(
824
+ expressions: list[Expression],
825
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
826
+ config: FrameToSqlConfig
827
+ ) -> Expression:
828
+ return DateDiffExpression(expressions[0], expressions[1], expressions[2]) # type: ignore
829
+
830
+ @staticmethod
831
+ def __to_pure_func(op_expr: list[str], config: FrameToPureConfig) -> str:
832
+ return generate_pure_functional_call("dateDiff", [op_expr[0], op_expr[1], f"DurationUnit.{op_expr[2]}"])
833
+
834
+ def __init__(self, operands: list[PyLegendExpression]) -> None:
835
+ PyLegendExpressionIntegerReturn.__init__(self)
836
+ PyLegendNaryExpression.__init__(
837
+ self,
838
+ operands,
839
+ PyLegendDateDiffExpression.__to_sql_func,
840
+ PyLegendDateDiffExpression.__to_pure_func,
841
+ non_nullable=True,
842
+ operands_non_nullable_flags=[True, True, True]
843
+ )
844
+
845
+
846
+ class PyLegendDateTimeBucketExpression(PyLegendNaryExpression, PyLegendExpressionDateReturn):
847
+
848
+ @staticmethod
849
+ def __to_sql_func(
850
+ expressions: list[Expression],
851
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
852
+ config: FrameToSqlConfig
853
+ ) -> Expression:
854
+ return DateTimeBucketExpression(
855
+ expressions[0],
856
+ expressions[1],
857
+ expressions[2], # type: ignore
858
+ DateType.DateTime if expressions[3].value == "DATETIME" else DateType.StrictDate) # type: ignore
859
+
860
+ @staticmethod
861
+ def __to_pure_func(op_expr: list[str], config: FrameToPureConfig) -> str:
862
+ return generate_pure_functional_call("timeBucket", [op_expr[0], op_expr[1], f"DurationUnit.{op_expr[2]}"])
863
+
864
+ def __init__(self, operands: list[PyLegendExpression]) -> None:
865
+ PyLegendExpressionDateReturn.__init__(self)
866
+ PyLegendNaryExpression.__init__(
867
+ self,
868
+ operands,
869
+ PyLegendDateTimeBucketExpression.__to_sql_func,
870
+ PyLegendDateTimeBucketExpression.__to_pure_func,
871
+ non_nullable=True,
872
+ operands_non_nullable_flags=[True, True, True]
873
+ )