Skip to content

Commit

Permalink
Merge branch 'master' into nx2
Browse files Browse the repository at this point in the history
  • Loading branch information
mariusandra committed Jan 24, 2025
2 parents 23859ab + feee9c7 commit 1c79b29
Show file tree
Hide file tree
Showing 349 changed files with 22,680 additions and 5,660 deletions.
4 changes: 2 additions & 2 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ CMD ["sleep", "infinity"]
RUN apt-get update \
&& apt-get -y install --no-install-recommends \
# Add in useful db debugging tools
"postgresql-client=13+*" \
"postgresql-client=15+*" \
# needed for posthog to run
netcat brotli curl \
netcat-openbsd brotli curl \
&& rm -rf /var/lib/apt/lists/*

RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ body:

- type: markdown
attributes:
value: '#### *Thank you* for your bug report – we love squashing them!'
value: '#### *Thank you* for your feature request – we love each and every one!'
18 changes: 1 addition & 17 deletions .github/workflows/build-hogql-parser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,26 +64,10 @@ jobs:
steps:
- uses: actions/checkout@v4

- if: ${{ !endsWith(matrix.os, '-arm') }}
uses: actions/setup-python@v4
- uses: actions/setup-python@v4
with:
python-version: '3.11'

# Compiling Python 3.11 from source on ARM. We tried using the "deadsnakes" ARM repo, but it was flakey.
- if: ${{ endsWith(matrix.os, '-arm') }}
name: Install Python 3.11 on ARM (compile from source)
run: |
sudo apt-get update
sudo apt-get install -y build-essential libssl-dev zlib1g-dev \
libncurses5-dev libncursesw5-dev libreadline-dev libsqlite3-dev \
libgdbm-dev libdb5.3-dev libbz2-dev libexpat1-dev liblzma-dev tk-dev
wget https://www.python.org/ftp/python/3.11.0/Python-3.11.0.tar.xz
tar -xf Python-3.11.0.tar.xz
cd Python-3.11.0
./configure --enable-optimizations
make -j 2
sudo make altinstall
- name: Build sdist
if: matrix.os == 'ubuntu-22.04' # Only build the sdist once
run: cd common/hogql_parser && python setup.py sdist
Expand Down
20 changes: 12 additions & 8 deletions CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
frontend/src/scenes/settings/project/SurveySettings.tsx @PostHog/team-feature-success
frontend/src/scenes/surveys/ @PostHog/team-feature-success
posthog/admin/admins/survey_admin.py @PostHog/team-feature-success
posthog/api/survey.py @PostHog/team-feature-success
posthog/api/test/test_survey.py @PostHog/team-feature-success
posthog/models/feedback/survey.py @PostHog/team-feature-success
posthog/tasks/stop_surveys_reached_target.py @PostHog/team-feature-success
posthog/tasks/test/test_stop_surveys_reached_target.py @PostHog/team-feature-success
frontend/src/scenes/settings/environment/SurveySettings.tsx @PostHog/team-surveys
frontend/src/scenes/surveys/ @PostHog/team-surveys
frontend/src/scenes/onboarding/sdks/surveys @PostHog/team-surveys
ee/surveys @PostHog/team-surveys
posthog/admin/admins/survey_admin.py @PostHog/team-surveys
posthog/api/survey.py @PostHog/team-surveys
posthog/api/test/test_survey.py @PostHog/team-surveys
posthog/models/feedback/survey.py @PostHog/team-surveys
posthog/tasks/stop_surveys_reached_target.py @PostHog/team-surveys
posthog/tasks/update_survey_adaptive_sampling @PostHog/team-surveys
posthog/tasks/update_survey_iteration @PostHog/team-surveys
posthog/tasks/test/test_stop_surveys_reached_target.py @PostHog/team-surveys
2,853 changes: 1,460 additions & 1,393 deletions common/hogql_parser/HogQLParser.cpp

Large diffs are not rendered by default.

41 changes: 28 additions & 13 deletions common/hogql_parser/HogQLParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ class HogQLParser : public antlr4::Parser {
RuleWindowExpr = 50, RuleWinPartitionByClause = 51, RuleWinOrderByClause = 52,
RuleWinFrameClause = 53, RuleWinFrameExtend = 54, RuleWinFrameBound = 55,
RuleExpr = 56, RuleColumnTypeExpr = 57, RuleColumnExprList = 58, RuleColumnExpr = 59,
RuleColumnLambdaExpr = 60, RuleHogqlxTagElement = 61, RuleHogqlxTagAttribute = 62,
RuleWithExprList = 63, RuleWithExpr = 64, RuleColumnIdentifier = 65,
RuleNestedIdentifier = 66, RuleTableExpr = 67, RuleTableFunctionExpr = 68,
RuleTableIdentifier = 69, RuleTableArgList = 70, RuleDatabaseIdentifier = 71,
RuleFloatingLiteral = 72, RuleNumberLiteral = 73, RuleLiteral = 74,
RuleInterval = 75, RuleKeyword = 76, RuleKeywordForAlias = 77, RuleAlias = 78,
RuleIdentifier = 79, RuleEnumValue = 80, RulePlaceholder = 81, RuleString = 82,
RuleTemplateString = 83, RuleStringContents = 84, RuleFullTemplateString = 85,
RuleStringContentsFull = 86
RuleColumnLambdaExpr = 60, RuleHogqlxChildElement = 61, RuleHogqlxTagElement = 62,
RuleHogqlxTagAttribute = 63, RuleWithExprList = 64, RuleWithExpr = 65,
RuleColumnIdentifier = 66, RuleNestedIdentifier = 67, RuleTableExpr = 68,
RuleTableFunctionExpr = 69, RuleTableIdentifier = 70, RuleTableArgList = 71,
RuleDatabaseIdentifier = 72, RuleFloatingLiteral = 73, RuleNumberLiteral = 74,
RuleLiteral = 75, RuleInterval = 76, RuleKeyword = 77, RuleKeywordForAlias = 78,
RuleAlias = 79, RuleIdentifier = 80, RuleEnumValue = 81, RulePlaceholder = 82,
RuleString = 83, RuleTemplateString = 84, RuleStringContents = 85, RuleFullTemplateString = 86,
RuleStringContentsFull = 87
};

explicit HogQLParser(antlr4::TokenStream *input);
Expand Down Expand Up @@ -152,6 +152,7 @@ class HogQLParser : public antlr4::Parser {
class ColumnExprListContext;
class ColumnExprContext;
class ColumnLambdaExprContext;
class HogqlxChildElementContext;
class HogqlxTagElementContext;
class HogqlxTagAttributeContext;
class WithExprListContext;
Expand Down Expand Up @@ -1912,6 +1913,22 @@ class HogQLParser : public antlr4::Parser {

ColumnLambdaExprContext* columnLambdaExpr();

class HogqlxChildElementContext : public antlr4::ParserRuleContext {
public:
HogqlxChildElementContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
HogqlxTagElementContext *hogqlxTagElement();
antlr4::tree::TerminalNode *LBRACE();
ColumnExprContext *columnExpr();
antlr4::tree::TerminalNode *RBRACE();


virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;

};

HogqlxChildElementContext* hogqlxChildElement();

class HogqlxTagElementContext : public antlr4::ParserRuleContext {
public:
HogqlxTagElementContext(antlr4::ParserRuleContext *parent, size_t invokingState);
Expand Down Expand Up @@ -1952,10 +1969,8 @@ class HogQLParser : public antlr4::Parser {
antlr4::tree::TerminalNode *SLASH();
std::vector<HogqlxTagAttributeContext *> hogqlxTagAttribute();
HogqlxTagAttributeContext* hogqlxTagAttribute(size_t i);
HogqlxTagElementContext *hogqlxTagElement();
antlr4::tree::TerminalNode *LBRACE();
ColumnExprContext *columnExpr();
antlr4::tree::TerminalNode *RBRACE();
std::vector<HogqlxChildElementContext *> hogqlxChildElement();
HogqlxChildElementContext* hogqlxChildElement(size_t i);

virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
Expand Down
3 changes: 2 additions & 1 deletion common/hogql_parser/HogQLParser.interp

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions common/hogql_parser/HogQLParserBaseVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,10 @@ class HogQLParserBaseVisitor : public HogQLParserVisitor {
return visitChildren(ctx);
}

virtual std::any visitHogqlxChildElement(HogQLParser::HogqlxChildElementContext *ctx) override {
return visitChildren(ctx);
}

virtual std::any visitHogqlxTagElementClosed(HogQLParser::HogqlxTagElementClosedContext *ctx) override {
return visitChildren(ctx);
}
Expand Down
2 changes: 2 additions & 0 deletions common/hogql_parser/HogQLParserVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ class HogQLParserVisitor : public antlr4::tree::AbstractParseTreeVisitor {

virtual std::any visitColumnLambdaExpr(HogQLParser::ColumnLambdaExprContext *context) = 0;

virtual std::any visitHogqlxChildElement(HogQLParser::HogqlxChildElementContext *context) = 0;

virtual std::any visitHogqlxTagElementClosed(HogQLParser::HogqlxTagElementClosedContext *context) = 0;

virtual std::any visitHogqlxTagElementNested(HogQLParser::HogqlxTagElementNestedContext *context) = 0;
Expand Down
134 changes: 85 additions & 49 deletions common/hogql_parser/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2536,6 +2536,15 @@ class HogQLParseTreeConverter : public HogQLParserBaseVisitor {
RETURN_NEW_AST_NODE("HogQLXAttribute", "{s:s#,s:N}", "name", name.data(), name.size(), "value", value);
}

VISIT(HogqlxChildElement) {
auto tag_element_ctx = ctx->hogqlxTagElement();
if (tag_element_ctx) {
return visitAsPyObject(tag_element_ctx);
} else {
return visitAsPyObject(ctx->columnExpr());
}
}

VISIT(HogqlxTagElementClosed) {
string kind = visitAsString(ctx->identifier());
RETURN_NEW_AST_NODE(
Expand All @@ -2545,80 +2554,107 @@ class HogQLParseTreeConverter : public HogQLParserBaseVisitor {
}

VISIT(HogqlxTagElementNested) {
string opening = visitAsString(ctx->identifier(0));
string closing = visitAsString(ctx->identifier(1));
std::string opening = visitAsString(ctx->identifier(0));
std::string closing = visitAsString(ctx->identifier(1));
if (opening != closing) {
throw SyntaxError("Opening and closing HogQLX tags must match. Got " + opening + " and " + closing);
}

auto tag_element_ctx = ctx->hogqlxTagElement();
auto column_expr_ctx = ctx->columnExpr();
auto tag_attribute_ctx = ctx->hogqlxTagAttribute();
PyObject* attributes = PyList_New(tag_attribute_ctx.size() + (tag_element_ctx || column_expr_ctx ? 1 : 0));
if (!attributes) throw PyInternalError();
bool found_source = false;
for (size_t i = 0; i < tag_attribute_ctx.size(); i++) {
PyObject* object;
auto attribute_ctxs = ctx->hogqlxTagAttribute();
PyObject *attributes = PyList_New(attribute_ctxs.size());
if (!attributes) {
throw PyInternalError();
}
for (size_t i = 0; i < attribute_ctxs.size(); i++) {
PyObject *attr_obj;
try {
object = visitAsPyObject(tag_attribute_ctx[i]);
attr_obj = visitAsPyObject(attribute_ctxs[i]);
} catch (...) {
Py_DECREF(attributes);
throw;
}
PyList_SET_ITEM(attributes, i, object);
PyList_SET_ITEM(attributes, i, attr_obj); // Steals reference
}

PyObject* name = PyObject_GetAttrString(object, "name");
if (!name) {
Py_DECREF(attributes);
throw PyInternalError();
}
PyObject* source_as_str = PyUnicode_FromString("source");
if (!source_as_str) {
Py_DECREF(name);
Py_DECREF(attributes);
throw PyInternalError();
auto child_element_ctxs = ctx->hogqlxChildElement();
if (!child_element_ctxs.empty()) {
for (size_t i = 0; i < attribute_ctxs.size(); i++) {
PyObject *attr = PyList_GetItem(attributes, i); // borrowed
if (!attr) {
Py_DECREF(attributes);
throw PyInternalError();
}
PyObject *name_obj = PyObject_GetAttrString(attr, "name");
if (!name_obj) {
Py_DECREF(attributes);
throw PyInternalError();
}
PyObject *children_str = PyUnicode_FromString("children");
if (!children_str) {
Py_DECREF(name_obj);
Py_DECREF(attributes);
throw PyInternalError();
}
int is_children = PyObject_RichCompareBool(name_obj, children_str, Py_EQ);
Py_DECREF(children_str);
Py_DECREF(name_obj);
if (is_children == -1) {
Py_DECREF(attributes);
throw PyInternalError();
}
if (is_children == 1) {
Py_DECREF(attributes);
throw SyntaxError("Can't have a HogQLX tag with both children and a 'children' attribute");
}
}
int tentative_found_source = PyObject_RichCompareBool(name, source_as_str, Py_EQ);
Py_DECREF(source_as_str);
Py_DECREF(name);
if (tentative_found_source == -1) {

PyObject *children_list = PyList_New(child_element_ctxs.size());
if (!children_list) {
Py_DECREF(attributes);
throw PyInternalError();
}
if (tentative_found_source) {
found_source = true;
for (size_t i = 0; i < child_element_ctxs.size(); i++) {
PyObject *child_ast;
try {
child_ast = visitAsPyObject(child_element_ctxs[i]);
} catch (...) {
Py_DECREF(children_list);
Py_DECREF(attributes);
throw;
}
PyList_SET_ITEM(children_list, i, child_ast); // Steals reference
}
}

if (tag_element_ctx) {
if (found_source) {
Py_DECREF(attributes);
throw SyntaxError("Nested HogQLX tags cannot have a source attribute");
}
PyObject* source_attribute = build_ast_node(
"HogQLXAttribute", "{s:s#,s:N}", "name", "source", 6, "value", visitAsPyObject(ctx->hogqlxTagElement())
PyObject *children_attr = build_ast_node(
"HogQLXAttribute",
"{s:s#,s:O}",
"name", "children", (Py_ssize_t)8,
"value", children_list
);
if (!source_attribute) {
if (!children_attr) {
Py_DECREF(children_list);
Py_DECREF(attributes);
throw PyInternalError();
}
PyList_SET_ITEM(attributes, tag_attribute_ctx.size(), source_attribute);
} else if (column_expr_ctx) {
if (found_source) {
Py_DECREF(attributes);
throw SyntaxError("Nested HogQLX tags cannot have a source attribute");
}
PyObject* source_attribute = build_ast_node(
"HogQLXAttribute", "{s:s#,s:N}", "name", "source", 6, "value", visitAsPyObject(ctx->columnExpr())
);
if (!source_attribute) {
int appended = PyList_Append(attributes, children_attr);
Py_DECREF(children_attr);
if (appended == -1) {
Py_DECREF(attributes);
throw PyInternalError();
}
PyList_SET_ITEM(attributes, tag_attribute_ctx.size(), source_attribute);
}

RETURN_NEW_AST_NODE("HogQLXTag", "{s:s#,s:N}", "kind", opening.data(), opening.size(), "attributes", attributes);
PyObject *ret = build_ast_node(
"HogQLXTag",
"{s:s#,s:N}",
"kind", opening.data(), (Py_ssize_t)opening.size(),
"attributes", attributes
);
if (!ret) {
Py_DECREF(attributes);
throw PyInternalError();
}
return ret;
}

VISIT(Placeholder) {
Expand Down
6 changes: 3 additions & 3 deletions common/hogql_parser/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@

setup(
name="hogql_parser",
version="1.0.50",
url="https://github.com/PostHog/posthog/tree/master/hogql_parser",
version="1.0.454",
url="https://github.com/PostHog/posthog/tree/master/common/hogql_parser",
description="HogQL parser for internal PostHog use",
author="PostHog Inc.",
author_email="hey@posthog.com",
maintainer="PostHog Inc.",
maintainer_email="hey@posthog.com",
description="HogQL parser for internal PostHog use",
long_description=open("README.md").read(),
long_description_content_type="text/markdown",
package_data={"hogql_parser": ["__init__.pyi", "py.typed"]},
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/dashboard.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ describe('Dashboard', () => {
cy.contains('span', 'Last 14 days').click()
cy.contains('span', 'Save').click()

cy.contains('span[class="text-primary text-sm font-medium"]', 'Refreshing').should('not.exist')
cy.contains('span[class="text-accent-primary text-sm font-medium"]', 'Refreshing').should('not.exist')
cy.get('span').contains('Refreshing').should('not.exist')
})

Expand Down
9 changes: 9 additions & 0 deletions cypress/e2e/featureFlags.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,15 @@ describe('Feature Flags', () => {
cy.get('[data-attr=feature-flag-variant-rollout-percentage-input]').click().type(`4.5`).should('have.value', 4)
})

it('Allows creating remote config flag without setting release conditions', () => {
cy.get('[data-attr=top-bar-name]').should('contain', 'Feature flags')
// Start creating a remote config flag
cy.get('[data-attr=new-feature-flag]').click()
cy.get('[data-attr=feature-flag-key]').click().type(`{moveToEnd}${name}`).should('have.value', name)
cy.get('[data-attr=feature-flag-served-value-segmented-button]').contains('Remote config').click()
cy.get('[data-attr=save-feature-flag]').first().click()
})

it('Sets URL properly when switching between tabs', () => {
cy.get('[data-attr=top-bar-name]').should('contain', 'Feature flags')
cy.get('[data-attr=feature-flags-tab-navigation]').contains('History').click()
Expand Down
7 changes: 0 additions & 7 deletions cypress/e2e/trends.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,6 @@ describe('Trends', () => {
cy.get('[data-attr=trend-line-graph]').should('exist')
})

it('Apply all users cohort breakdown', () => {
cy.get('[data-attr=add-breakdown-button]').click()
cy.get('[data-attr=taxonomic-tab-cohorts_with_all]').click()
cy.contains('All Users*').click()
cy.get('[data-attr=trend-line-graph]').should('exist')
})

it('Show warning on MAU math in total value insight', () => {
cy.get('[data-attr=chart-filter]').click()
cy.get('.Popover').find('.LemonButton').contains('Pie').click()
Expand Down
Loading

0 comments on commit 1c79b29

Please sign in to comment.