Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b7e5a06
checkpoint: add logic for rendering signature template
sycai Jul 26, 2026
cc3288e
checkpoint: impl operator definition gen
sycai Jul 26, 2026
8019f08
checkout: impl test generation
sycai Jul 26, 2026
310a93a
checkpoint: refactor arg rendering
sycai Jul 26, 2026
5ba9eb3
finish refactoring
sycai Jul 27, 2026
ab100cb
make old script still runnable
sycai Jul 27, 2026
f85141a
fix script reference
sycai Jul 27, 2026
0e6d04a
fix lint
sycai Jul 27, 2026
9353f35
Update packages/bigframes/scripts/bigquery_generator/__main__.py
sycai Jul 27, 2026
78041aa
Update packages/bigframes/scripts/bigquery_generator/file_generator.py
sycai Jul 27, 2026
4fd77b8
Update packages/bigframes/scripts/bigquery_generator/file_generator.py
sycai Jul 27, 2026
aa24eb9
Update packages/bigframes/scripts/bigquery_generator/file_generator.py
sycai Jul 27, 2026
393010b
Update packages/bigframes/scripts/bigquery_generator/template_rendere…
sycai Jul 27, 2026
f1fea76
Update packages/bigframes/scripts/bigquery_generator/yaml_parser.py
sycai Jul 27, 2026
70e9091
Update packages/bigframes/scripts/bigquery_generator/yaml_parser.py
sycai Jul 27, 2026
e1b8a37
Update packages/bigframes/scripts/bigquery_generator/yaml_parser.py
sycai Jul 27, 2026
aa1b51b
Update packages/bigframes/scripts/generate_bigframes_bigquery.py
sycai Jul 27, 2026
aa74300
Update packages/bigframes/scripts/bigquery_generator/template_rendere…
sycai Jul 27, 2026
dcbd2ea
Update packages/bigframes/scripts/bigquery_generator/template_rendere…
sycai Jul 27, 2026
a048b0c
fix lint
sycai Jul 27, 2026
e3fb8fd
fix import
sycai Jul 27, 2026
3049a97
fix format
sycai Jul 27, 2026
83b22f0
fix lint
sycai Jul 27, 2026
4653ca0
Merge branch 'main' into sycai_generator_refactor
sycai Jul 27, 2026
0eb0aef
Merge branch 'main' into sycai_generator_refactor
sycai Jul 28, 2026
ddc6d4c
update script path
sycai Jul 28, 2026
8ef98b9
remove __main__.py from package
sycai Jul 28, 2026
bd136c6
update template loading and module-level docstrings
sycai Jul 28, 2026
9ea30b8
fix format
sycai Jul 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,17 @@ def _to_dataframe(self, bf_df: dataframe.DataFrame) -> T:
def _to_series(self, bf_series: series.Series) -> S:
return cast(S, bf_series)

@property
def ai(self) -> BigframesAiSeriesAccessor[T, S]:
return BigframesAiSeriesAccessor(self._obj)

@property
def aead(self) -> BigframesAeadSeriesAccessor[T, S]:
return BigframesAeadSeriesAccessor(self._obj)

@property
def ai(self) -> BigframesAiSeriesAccessor[T, S]:
return BigframesAiSeriesAccessor(self._obj)


@log_adapter.class_logger
class BigframesAiSeriesAccessor(core_accessor.AiSeriesAccessor[T, S]):
class BigframesAeadSeriesAccessor(core_accessor.AeadSeriesAccessor[T, S]):
def __init__(self, bf_obj: S):
super().__init__(bf_obj)

Expand All @@ -71,7 +71,7 @@ def _to_series(self, bf_series: series.Series) -> S:


@log_adapter.class_logger
class BigframesAeadSeriesAccessor(core_accessor.AeadSeriesAccessor[T, S]):
class BigframesAiSeriesAccessor(core_accessor.AiSeriesAccessor[T, S]):
def __init__(self, bf_obj: S):
super().__init__(bf_obj)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ class BigQuerySeriesAccessor(

@property
@abc.abstractmethod
def ai(self) -> AiSeriesAccessor[T, S]:
"""Accessor for BigQuery ai functions."""
def aead(self) -> AeadSeriesAccessor[T, S]:
"""Accessor for BigQuery aead functions."""

@property
@abc.abstractmethod
def aead(self) -> AeadSeriesAccessor[T, S]:
"""Accessor for BigQuery aead functions."""
def ai(self) -> AiSeriesAccessor[T, S]:
"""Accessor for BigQuery ai functions."""

def deterministic_decrypt_bytes(
self,
Expand Down Expand Up @@ -1112,10 +1112,6 @@ def unix_date(
return self._to_series(cast(series.Series, result))


class AiSeriesAccessor(series_tvf_mixins.AITVFMixin[T, S]):
"""Series accessor for BigQuery ai functions."""


class AeadSeriesAccessor(abstract_series_accessor.AbstractBigQuerySeriesAccessor[T, S]):
"""Series accessor for BigQuery aead functions."""

Expand Down Expand Up @@ -1227,3 +1223,7 @@ def encrypt(
additional_data,
)
return self._to_series(cast(series.Series, result))


class AiSeriesAccessor(series_tvf_mixins.AITVFMixin[T, S]):
"""Series accessor for BigQuery ai functions."""
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,17 @@ def _to_dataframe(self, bf_df: dataframe.DataFrame) -> T:
def _to_series(self, bf_series: series.Series) -> S:
return cast(S, bf_series.to_pandas(ordered=True))

@property
def ai(self) -> PandasAiSeriesAccessor[T, S]:
return PandasAiSeriesAccessor(self._obj)

@property
def aead(self) -> PandasAeadSeriesAccessor[T, S]:
return PandasAeadSeriesAccessor(self._obj)

@property
def ai(self) -> PandasAiSeriesAccessor[T, S]:
return PandasAiSeriesAccessor(self._obj)


@log_adapter.class_logger
class PandasAiSeriesAccessor(core_accessor.AiSeriesAccessor[T, S]):
class PandasAeadSeriesAccessor(core_accessor.AeadSeriesAccessor[T, S]):
def __init__(self, pandas_obj: S):
super().__init__(pandas_obj)

Expand All @@ -80,7 +80,7 @@ def _to_series(self, bf_series: series.Series) -> S:


@log_adapter.class_logger
class PandasAeadSeriesAccessor(core_accessor.AeadSeriesAccessor[T, S]):
class PandasAiSeriesAccessor(core_accessor.AiSeriesAccessor[T, S]):
def __init__(self, pandas_obj: S):
super().__init__(pandas_obj)

Expand Down
13 changes: 13 additions & 0 deletions packages/bigframes/scripts/bigquery_generator/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
194 changes: 194 additions & 0 deletions packages/bigframes/scripts/bigquery_generator/constants.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit (Optional): We don't have to put all constants here. I would prefer that they be defined closer to where they are used or in a purpose-specific module, such as with the templates logic or list of Python built-ins, but that's mostly just a personal preference.

Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import pathlib

import jinja2

SCRIPTS_DIRECTORY = pathlib.Path(__file__).parent.parent.absolute()
PACKAGE_ROOT = SCRIPTS_DIRECTORY.parent
CODE_ROOT = PACKAGE_ROOT / "bigframes"
SCRIPT_PATH_RELATIVE = (
pathlib.Path(__file__).relative_to(PACKAGE_ROOT).parent.parent
/ "generate_bigframes_bigquery.py"
)


# Directory containing the YAML files
DATA_DIR = SCRIPTS_DIRECTORY / "data" / "sql-functions"
# Directory where the generated Python files will be placed
OUTPUT_DIR = CODE_ROOT / "operations" / "googlesql"
# Directory where the generated test files will be placed
TEST_OUTPUT_DIR = PACKAGE_ROOT / "tests" / "unit" / "bigquery" / "generated"
# Directory containing the Jinja2 templates
TEMPLATE_DIR = SCRIPTS_DIRECTORY / "templates"

PYTHON_BUILTINS = {
"abs",
"all",
"any",
"ascii",
"bin",
"bool",
"breakpoint",
"bytearray",
"bytes",
"callable",
"chr",
"classmethod",
"compile",
"complex",
"delattr",
"dict",
"dir",
"divmod",
"enumerate",
"eval",
"exec",
"filter",
"float",
"format",
"frozenset",
"getattr",
"globals",
"hasattr",
"hash",
"help",
"hex",
"id",
"input",
"int",
"isinstance",
"issubclass",
"iter",
"len",
"list",
"locals",
"map",
"max",
"memoryview",
"min",
"next",
"object",
"oct",
"open",
"ord",
"pow",
"print",
"property",
"range",
"repr",
"reversed",
"round",
"set",
"setattr",
"slice",
"sorted",
"staticmethod",
"str",
"sum",
"super",
"tuple",
"type",
"vars",
"zip",
}

DTYPE_MAP = {
"binary": "dtypes.BYTES_DTYPE",
"string": "dtypes.STRING_DTYPE",
"int64": "dtypes.INT_DTYPE",
"i64": "dtypes.INT_DTYPE",
"float64": "dtypes.FLOAT_DTYPE",
"fp64": "dtypes.FLOAT_DTYPE",
"bool": "dtypes.BOOL_DTYPE",
"boolean": "dtypes.BOOL_DTYPE",
"geography": "dtypes.GEO_DTYPE",
"json": "dtypes.JSON_DTYPE",
"date": "dtypes.DATE_DTYPE",
"time": "dtypes.TIME_DTYPE",
"datetime": "dtypes.DATETIME_DTYPE",
"timestamp": "dtypes.TIMESTAMP_DTYPE",
"decimal<38,9>": "dtypes.NUMERIC_DTYPE",
"decimal<76,38>": "dtypes.BIGNUMERIC_DTYPE",
}

PY_TYPE_MAP = {
"binary": "bytes",
"string": "str",
"int64": "int",
"i64": "int",
"float64": "float",
"fp64": "float",
"bool": "bool",
"boolean": "bool",
"geography": "Any",
"json": "Any",
"date": "datetime.date",
"time": "datetime.time",
"datetime": "datetime.datetime",
"timestamp": "datetime.datetime",
"struct": "dict",
"decimal<38,9>": "decimal.Decimal",
"decimal<76,38>": "decimal.Decimal",
"interval_day": "datetime.timedelta",
}

RUFF_COMMON_ARGS = [
"--target-version=py310",
"--line-length=88",
]
RUFF_CHECK_ARGS = [
"check",
"--select",
"I,F",
"--fix",
] + RUFF_COMMON_ARGS
RUFF_FORMAT_ARGS = [
"format",
] + RUFF_COMMON_ARGS


def _load_templates() -> dict[str, jinja2.Template]:
env = jinja2.Environment(
loader=jinja2.FileSystemLoader(TEMPLATE_DIR),
trim_blocks=True,
lstrip_blocks=True,
)
return {
"operation": env.get_template("operation.py.j2"),
"test_operation": env.get_template("test_operation.py.j2"),
"license": env.get_template("license.py.j2"),
"signature_def": env.get_template("signature_def.py.j2"),
"core_series_accessor": env.get_template("core_series_accessor.py.j2"),
"bigframes_series_accessor": env.get_template(
"bigframes_series_accessor.py.j2"
),
"pandas_series_accessor": env.get_template("pandas_series_accessor.py.j2"),
}


TEMPLATES: dict[str, jinja2.Template] = _load_templates()


def __getattr__(name: str):
global _templates

if name != "TEMPLATES":
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")

if _templates is None:
_templates = _load_templates()

return _templates
Loading
Loading