hogql-parser 1.0.1__tar.gz → 1.0.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hogql_parser
3
- Version: 1.0.1
3
+ Version: 1.0.2
4
4
  Summary: HogQL parser for internal PostHog use
5
5
  Home-page: https://github.com/PostHog/posthog/tree/master/hogql_parser
6
6
  Author: PostHog Inc.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hogql-parser
3
- Version: 1.0.1
3
+ Version: 1.0.2
4
4
  Summary: HogQL parser for internal PostHog use
5
5
  Home-page: https://github.com/PostHog/posthog/tree/master/hogql_parser
6
6
  Author: PostHog Inc.
@@ -17,7 +17,7 @@
17
17
  throw NotImplementedException("Unsupported rule: " #RULE); \
18
18
  }
19
19
 
20
- #define HANDLE_HOGQL_EXCEPTION(TYPE) \
20
+ #define HANDLE_HOGQL_EXCEPTION(TYPE, OTHER_CLEANUP) \
21
21
  (const TYPE& e) { \
22
22
  string err_what = e.what(); \
23
23
  PyObject *error_type = NULL, *py_err_args = NULL, *py_err = NULL, *py_start = NULL, *py_end = NULL; \
@@ -42,6 +42,7 @@
42
42
  Py_XDECREF(py_start); \
43
43
  Py_XDECREF(py_err); \
44
44
  Py_XDECREF(error_type); \
45
+ OTHER_CLEANUP \
45
46
  return NULL; \
46
47
  }
47
48
 
@@ -98,6 +99,7 @@ PyObject* X_PyList_FromStrings(const vector<string>& items) {
98
99
  class HogQLParseTreeConverter : public HogQLParserBaseVisitor {
99
100
  private:
100
101
  parser_state* state;
102
+ bool is_internal;
101
103
 
102
104
  const vector<string> RESERVED_KEYWORDS = {"true", "false", "null", "team_id"};
103
105
 
@@ -151,7 +153,7 @@ class HogQLParseTreeConverter : public HogQLParserBaseVisitor {
151
153
  #undef IS_AST_NODE_INSTANCE_IMPL
152
154
 
153
155
  public:
154
- HogQLParseTreeConverter(parser_state* state) : state(state) {}
156
+ HogQLParseTreeConverter(parser_state* state, bool is_internal) : state(state), is_internal(is_internal) {}
155
157
 
156
158
  any visit(antlr4::tree::ParseTree* tree) override {
157
159
  // Find the start and stop indices of the parse tree node
@@ -169,17 +171,18 @@ class HogQLParseTreeConverter : public HogQLParserBaseVisitor {
169
171
  start = ctx->getStart()->getStartIndex();
170
172
  stop = ctx->getStop()->getStopIndex();
171
173
  }
172
- // Visit the parse tree node
174
+ // Visit the parse tree node (while making sure that nodes/errors have spans - except for internal expressions)
173
175
  any node;
174
176
  try {
175
177
  node = tree->accept(this);
176
178
  } catch (const SyntaxException& e) {
177
- if (e.start == 0 && e.end == 0) { // If start and end are unset, rethrow with the current start and stop
179
+ // If start and end are unset, rethrow with the current start and stop
180
+ if (!is_internal && e.start == 0 && e.end == 0) {
178
181
  throw SyntaxException(e.what(), start, stop + 1);
179
182
  }
180
183
  throw;
181
184
  }
182
- if (node.has_value() && node.type() == typeid(PyObject*)) {
185
+ if (!is_internal && node.has_value() && node.type() == typeid(PyObject*)) {
183
186
  PyObject* py_node = any_cast<PyObject*>(node);
184
187
  if (py_node) {
185
188
  int is_ast = is_ast_node_instance(py_node);
@@ -218,8 +221,9 @@ class HogQLParseTreeConverter : public HogQLParserBaseVisitor {
218
221
  PyObject* visitAsPyObjectFinal(antlr4::tree::ParseTree* tree) {
219
222
  try {
220
223
  return visitAsPyObject(tree);
221
- } catch HANDLE_HOGQL_EXCEPTION(SyntaxException) catch HANDLE_HOGQL_EXCEPTION(NotImplementedException
222
- ) catch HANDLE_HOGQL_EXCEPTION(ParsingException) catch (const PyInternalException& e) {
224
+ } catch HANDLE_HOGQL_EXCEPTION(SyntaxException, ) catch HANDLE_HOGQL_EXCEPTION(
225
+ NotImplementedException,
226
+ ) catch HANDLE_HOGQL_EXCEPTION(ParsingException, ) catch (const PyInternalException& e) {
223
227
  return NULL;
224
228
  } catch (const bad_any_cast& e) {
225
229
  PyObject* error_type = PyObject_GetAttrString(state->errors_module, "ParsingException");
@@ -2031,32 +2035,35 @@ parser_state* get_module_state(PyObject* module) {
2031
2035
 
2032
2036
  // MODULE METHODS
2033
2037
 
2034
- #define METHOD_PARSE_NODE(PASCAL_CASE, CAMEL_CASE, SNAKE_CASE) \
2035
- static PyObject* method_parse_##SNAKE_CASE(PyObject* self, PyObject* args) { \
2036
- parser_state* state = get_module_state(self); \
2037
- const char* str; \
2038
- if (!PyArg_ParseTuple(args, "s", &str)) { \
2039
- return NULL; \
2040
- } \
2041
- auto input_stream = new antlr4::ANTLRInputStream(str, strnlen(str, 65536)); \
2042
- auto lexer = new HogQLLexer(input_stream); \
2043
- auto stream = new antlr4::CommonTokenStream(lexer); \
2044
- auto parser = new HogQLParser(stream); \
2045
- parser->removeErrorListeners(); \
2046
- auto error_listener = new HogQLErrorListener(str); \
2047
- parser->addErrorListener(error_listener); \
2048
- HogQLParser::PASCAL_CASE##Context* parse_tree; \
2049
- try { \
2050
- parse_tree = parser->CAMEL_CASE(); \
2051
- } catch HANDLE_HOGQL_EXCEPTION(SyntaxException); \
2052
- HogQLParseTreeConverter converter = HogQLParseTreeConverter(state); \
2053
- PyObject* result_node = converter.visitAsPyObjectFinal(parse_tree); \
2054
- delete error_listener; \
2055
- delete parser; \
2056
- delete stream; \
2057
- delete lexer; \
2058
- delete input_stream; \
2059
- return result_node; \
2038
+ #define METHOD_PARSE_NODE(PASCAL_CASE, CAMEL_CASE, SNAKE_CASE) \
2039
+ static PyObject* method_parse_##SNAKE_CASE(PyObject* self, PyObject* args, PyObject* kwargs) { \
2040
+ parser_state* state = get_module_state(self); \
2041
+ const char* str; \
2042
+ int internal = 0; \
2043
+ static const char* kwlist[] = {"input", "is_internal", NULL}; \
2044
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|p", (char**)kwlist, &str, &internal)) { \
2045
+ return NULL; \
2046
+ } \
2047
+ auto input_stream = new antlr4::ANTLRInputStream(str, strnlen(str, 65536)); \
2048
+ auto lexer = new HogQLLexer(input_stream); \
2049
+ auto stream = new antlr4::CommonTokenStream(lexer); \
2050
+ auto parser = new HogQLParser(stream); \
2051
+ parser->removeErrorListeners(); \
2052
+ auto error_listener = new HogQLErrorListener(str); \
2053
+ parser->addErrorListener(error_listener); \
2054
+ HogQLParser::PASCAL_CASE##Context* parse_tree; \
2055
+ try { \
2056
+ parse_tree = parser->CAMEL_CASE(); \
2057
+ } catch HANDLE_HOGQL_EXCEPTION(SyntaxException, delete error_listener; delete parser; delete stream; delete lexer; \
2058
+ delete input_stream;); \
2059
+ HogQLParseTreeConverter converter = HogQLParseTreeConverter(state, internal == 1); \
2060
+ PyObject* result_node = converter.visitAsPyObjectFinal(parse_tree); \
2061
+ delete error_listener; \
2062
+ delete parser; \
2063
+ delete stream; \
2064
+ delete lexer; \
2065
+ delete input_stream; \
2066
+ return result_node; \
2060
2067
  }
2061
2068
 
2062
2069
  METHOD_PARSE_NODE(Expr, expr, expr)
@@ -2074,7 +2081,7 @@ static PyObject* method_unquote_string(PyObject* self, PyObject* args) {
2074
2081
  string unquoted_string;
2075
2082
  try {
2076
2083
  unquoted_string = unquote_string(str);
2077
- } catch HANDLE_HOGQL_EXCEPTION(SyntaxException);
2084
+ } catch HANDLE_HOGQL_EXCEPTION(SyntaxException, );
2078
2085
  return PyUnicode_FromStringAndSize(unquoted_string.data(), unquoted_string.size());
2079
2086
  }
2080
2087
 
@@ -2082,16 +2089,16 @@ static PyObject* method_unquote_string(PyObject* self, PyObject* args) {
2082
2089
 
2083
2090
  static PyMethodDef parser_methods[] = {
2084
2091
  {.ml_name = "parse_expr",
2085
- .ml_meth = method_parse_expr,
2086
- .ml_flags = METH_VARARGS,
2092
+ .ml_meth = (PyCFunction)method_parse_expr,
2093
+ .ml_flags = METH_VARARGS | METH_KEYWORDS,
2087
2094
  .ml_doc = "Parse the HogQL expression string into an AST"},
2088
2095
  {.ml_name = "parse_order_expr",
2089
- .ml_meth = method_parse_order_expr,
2090
- .ml_flags = METH_VARARGS,
2096
+ .ml_meth = (PyCFunction)method_parse_order_expr,
2097
+ .ml_flags = METH_VARARGS | METH_KEYWORDS,
2091
2098
  .ml_doc = "Parse the ORDER BY clause string into an AST"},
2092
2099
  {.ml_name = "parse_select",
2093
- .ml_meth = method_parse_select,
2094
- .ml_flags = METH_VARARGS,
2100
+ .ml_meth = (PyCFunction)method_parse_select,
2101
+ .ml_flags = METH_VARARGS | METH_KEYWORDS,
2095
2102
  .ml_doc = "Parse the HogQL SELECT statement string into an AST"},
2096
2103
  {.ml_name = "unquote_string",
2097
2104
  .ml_meth = method_unquote_string,
@@ -32,7 +32,7 @@ module = Extension(
32
32
 
33
33
  setup(
34
34
  name="hogql_parser",
35
- version="1.0.1",
35
+ version="1.0.2",
36
36
  url="https://github.com/PostHog/posthog/tree/master/hogql_parser",
37
37
  author="PostHog Inc.",
38
38
  author_email="hey@posthog.com",
File without changes
File without changes
File without changes
File without changes