Skip to content

Commit

Permalink
Merge branch 'modify_slack_format' of github.com:data-han/great_expec…
Browse files Browse the repository at this point in the history
…tations into modify_slack_format
  • Loading branch information
Low Han Siong committed Jan 29, 2025
2 parents ad2fc3a + e75b900 commit 2506b2b
Show file tree
Hide file tree
Showing 11 changed files with 760 additions and 139 deletions.
194 changes: 157 additions & 37 deletions .github/workflows/ci.yml

Large diffs are not rendered by default.

59 changes: 59 additions & 0 deletions docs/docusaurus/src/css/api_docs/api_docs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
* We apply that class to generated API docs during the build process.
*/

:root {
--turquoise: #4DC0B4;
}

.sphinx-api-doc {

@import "pygments.scss";
Expand Down Expand Up @@ -34,6 +38,16 @@
background-color: #1e1e1e;
}

table a {
color: var(--ifm-color-primary);
}

table code {
color: var(--ifm-font-color-base);
padding-left: .25em;
padding-right: .25em;
}

[data-theme='dark'] & {
p {
color: var(--ifm-font-color-base);
Expand Down Expand Up @@ -61,4 +75,49 @@
color: var(--ifm-font-color-base);
font-weight: var(--ifm-font-weight-bold);
}

#properties, dd {
overflow: auto hidden;
}

table thead {
background-color: white;

th {
border-bottom: 2px solid var(--turquoise);
border-left: 1px solid transparent;
border-right: 1px solid transparent;
border-top: 1px solid transparent;
padding: 0.4rem;
}

th, th p {
color: var(--turquoise);
font-size: 20px;
font-weight: 600;
}
}

table tr {
border: none;
}

table td {
border: none;
border-left: 1px solid rgba(112, 112, 112, 0.4);

&:first-of-type {
border-left: 1px solid transparent;
}
}

.theme-code-block pre {
border: 1px solid transparent;
margin: 0;
padding-top: 0;
}

code {
color: var(--ifm-font-color-base);
}
}
68 changes: 67 additions & 1 deletion docs/sphinx_api_docs_source/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,40 @@ def apply_structure_changes(soup, html_file_path, html_file_contents):
if methods:
add_section_title(soup, methods, "Methods")

# Add h2 title to Properties section
properties = soup.select(".py.property")
if properties:
# Add h2 title to Properties section
add_section_title(soup, properties, "Properties")

# Display properties as table
table = soup.new_tag("table")
tbody = soup.new_tag("tbody")

create_header_row(soup, table)

for prop in properties:
create_row(soup, tbody, prop)

table.append(tbody)
parent_div = soup.select("#properties")[0]
parent_div.append(table)

# Display signatures as code blocks
items = soup.select(".sig-object")
for item in items:
code_block = soup.new_tag("CodeBlock", language="python", title="Signature")
code_block.append("{`" + item.get_text().replace("#", "") + "`}")
item.replace_with(code_block)

# Prevent build from failing when there's code-like text outside code blocks
for item in soup.find_all(text=True):
if item.string and ("CodeBlock" not in item.string):
item.string.replaceWith(item.get_text().replace("<", r"\<"))


def add_section_title(soup, items, title):
wrapper_div = soup.new_tag("div")
wrapper_div.attrs["id"] = title.lower()
title_h2 = soup.new_tag("h2")
title_h2.string = title
parent = items[0].parent
Expand All @@ -62,3 +88,43 @@ def add_section_title(soup, items, title):
wrapper_div.insert(1, title_h2)
wrapper_div.insert(2, "\r\n")
parent.insert_after(wrapper_div)


def create_header_row(soup, table):
thead = soup.new_tag("thead")
thead_row = soup.new_tag("tr")

column_names = ["Name", "Description", "Reference"]

for column_name in column_names:
new_cell = soup.new_tag("th")
new_cell.append(column_name)
thead_row.append(new_cell)

thead.append(thead_row)

table.append(thead)
table.append("\r\n")
table.insert(0, "\r\n")


def create_row(soup, tbody, prop):
new_row = soup.new_tag("tr")
reference_link = prop.select("a")[0]
reference_link.string = reference_link.text.split(".")[-1]

columns = [
"`" + prop.select(".descname")[0].get_text() + "`",
prop.select("dd")[0].get_text(),
reference_link,
]

for column in columns:
new_cell = soup.new_tag("td")
new_cell.append("\r\n")
new_cell.append(column)
new_cell.append("\r\n")
new_row.append(new_cell)

tbody.append(new_row)
prop.extract()
103 changes: 83 additions & 20 deletions great_expectations/compatibility/bigquery.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from __future__ import annotations

from typing import Any, Dict

from great_expectations.compatibility.not_imported import NotImported

SQLALCHEMY_BIGQUERY_NOT_IMPORTED = NotImported(
Expand All @@ -18,24 +16,89 @@
except (ImportError, AttributeError):
sqlalchemy_bigquery = SQLALCHEMY_BIGQUERY_NOT_IMPORTED

BIGQUERY_TYPES: Dict[str, Any] = (
{
"INTEGER": sqlalchemy_bigquery.INTEGER,
"NUMERIC": sqlalchemy_bigquery.NUMERIC,
"STRING": sqlalchemy_bigquery.STRING,
"BIGNUMERIC": sqlalchemy_bigquery.BIGNUMERIC,
"BYTES": sqlalchemy_bigquery.BYTES,
"BOOL": sqlalchemy_bigquery.BOOL,
"BOOLEAN": sqlalchemy_bigquery.BOOLEAN,
"TIMESTAMP": sqlalchemy_bigquery.TIMESTAMP,
"TIME": sqlalchemy_bigquery.TIME,
"FLOAT": sqlalchemy_bigquery.FLOAT,
"DATE": sqlalchemy_bigquery.DATE,
"DATETIME": sqlalchemy_bigquery.DATETIME,
}
if sqlalchemy_bigquery
else {}
)
try:
from sqlalchemy_bigquery import INTEGER
except (ImportError, AttributeError):
INTEGER = SQLALCHEMY_BIGQUERY_NOT_IMPORTED

try:
from sqlalchemy_bigquery import NUMERIC
except (ImportError, AttributeError):
NUMERIC = SQLALCHEMY_BIGQUERY_NOT_IMPORTED

try:
from sqlalchemy_bigquery import STRING
except (ImportError, AttributeError):
STRING = SQLALCHEMY_BIGQUERY_NOT_IMPORTED

try:
from sqlalchemy_bigquery import BIGNUMERIC
except (ImportError, AttributeError):
BIGNUMERIC = SQLALCHEMY_BIGQUERY_NOT_IMPORTED

try:
from sqlalchemy_bigquery import BYTES
except (ImportError, AttributeError):
BYTES = SQLALCHEMY_BIGQUERY_NOT_IMPORTED


try:
from sqlalchemy_bigquery import BOOL
except (ImportError, AttributeError):
BOOL = SQLALCHEMY_BIGQUERY_NOT_IMPORTED


try:
from sqlalchemy_bigquery import BOOLEAN
except (ImportError, AttributeError):
BOOLEAN = SQLALCHEMY_BIGQUERY_NOT_IMPORTED


try:
from sqlalchemy_bigquery import TIMESTAMP
except (ImportError, AttributeError):
TIMESTAMP = SQLALCHEMY_BIGQUERY_NOT_IMPORTED


try:
from sqlalchemy_bigquery import TIME
except (ImportError, AttributeError):
TIME = SQLALCHEMY_BIGQUERY_NOT_IMPORTED

try:
from sqlalchemy_bigquery import FLOAT
except (ImportError, AttributeError):
FLOAT = SQLALCHEMY_BIGQUERY_NOT_IMPORTED


try:
from sqlalchemy_bigquery import DATE
except (ImportError, AttributeError):
DATE = SQLALCHEMY_BIGQUERY_NOT_IMPORTED


try:
from sqlalchemy_bigquery import DATETIME
except (ImportError, AttributeError):
DATETIME = SQLALCHEMY_BIGQUERY_NOT_IMPORTED


class BIGQUERY_TYPES:
"""Namespace for Bigquery dialect types"""

INTEGER = INTEGER
NUMERIC = NUMERIC
STRING = STRING
BIGNUMERIC = BIGNUMERIC
BYTES = BYTES
BOOL = BOOL
BOOLEAN = BOOLEAN
TIMESTAMP = TIMESTAMP
TIME = TIME
FLOAT = FLOAT
DATE = DATE
DATETIME = DATETIME


try:
from sqlalchemy_bigquery import GEOGRAPHY
Expand Down
7 changes: 1 addition & 6 deletions great_expectations/expectations/row_conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,7 @@ def parse_condition_to_sqlalchemy(
) -> sqlalchemy.ColumnElement:
parsed = _parse_great_expectations_condition(row_condition)
column = parsed["column"]
if "date" in parsed:
date_value: str = parsed["condition_value"]
cast_as_date = f"date({date_value})"
return generate_condition_by_operator(sa.column(column), parsed["op"], cast_as_date)

elif "condition_value" in parsed:
if "condition_value" in parsed:
return generate_condition_by_operator(
sa.column(column), parsed["op"], parsed["condition_value"]
)
Expand Down
5 changes: 3 additions & 2 deletions great_expectations/render/renderer/slack_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ def _build_description_block(
validation_result: ExpectationSuiteValidationResult,
validation_result_urls: list[str],
) -> dict:

validation_link = None
summary_text = ""
if validation_result_urls:
Expand All @@ -69,7 +68,9 @@ def _build_description_block(
# Slack does not allow links to local files due to security risks
# DataDocs links will be added in a block after this summary text when applicable
if validation_link and "file://" not in validation_link:
summary_text += f"\n*Expectation Suite*: {expectation_suite_name} <{validation_link}|View Results>"
summary_text += (
f"\n*Expectation Suite*: {expectation_suite_name} <{validation_link}|View Results>"
)
else:
summary_text += f"\n*Expectation Suite*: `{expectation_suite_name}`"

Expand Down
25 changes: 22 additions & 3 deletions great_expectations/self_check/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,31 @@


from great_expectations.compatibility.bigquery import (
BIGQUERY_TYPES,
GEOGRAPHY,
sqlalchemy_bigquery,
)

if GEOGRAPHY:
BIGQUERY_TYPES["GEOGRAPHY"] = GEOGRAPHY
try:
BIGQUERY_TYPES = {
"INTEGER": sqlalchemy_bigquery.INTEGER,
"NUMERIC": sqlalchemy_bigquery.NUMERIC,
"STRING": sqlalchemy_bigquery.STRING,
"BIGNUMERIC": sqlalchemy_bigquery.BIGNUMERIC,
"BYTES": sqlalchemy_bigquery.BYTES,
"BOOL": sqlalchemy_bigquery.BOOL,
"BOOLEAN": sqlalchemy_bigquery.BOOLEAN,
"TIMESTAMP": sqlalchemy_bigquery.TIMESTAMP,
"TIME": sqlalchemy_bigquery.TIME,
"FLOAT": sqlalchemy_bigquery.FLOAT,
"DATE": sqlalchemy_bigquery.DATE,
"DATETIME": sqlalchemy_bigquery.DATETIME,
}

if GEOGRAPHY:
BIGQUERY_TYPES["GEOGRAPHY"] = GEOGRAPHY

except (ImportError, AttributeError):
BIGQUERY_TYPES = {}

try:
import sqlalchemy.dialects.postgresql as postgresqltypes # noqa: TID251 # FIXME CoP
Expand Down
Loading

0 comments on commit 2506b2b

Please sign in to comment.