Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
165 changes: 88 additions & 77 deletions datar/apis/dplyr.py

Large diffs are not rendered by default.

21 changes: 11 additions & 10 deletions datar/apis/tibble.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
register_verb as _register_verb,
register_func as _register_func,
)
from ..core.verb_env import get_verb_ast_fallback as _get_verb_ast_fallback

from ..core.utils import (
NotImplementedByCurrentBackendError as _NotImplementedByCurrentBackendError,
Expand Down Expand Up @@ -112,13 +113,13 @@ def tibble_row(
raise _NotImplementedByCurrentBackendError("tibble_row")


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("as_tibble"))
def as_tibble(df) -> Any:
"""Convert a DataFrame object to Tibble object"""
raise _NotImplementedByCurrentBackendError("as_tibble", df)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("enframe"))
def enframe(x, name="name", value="value") -> Any:
"""Converts mappings or lists to one- or two-column data frames.

Expand All @@ -136,7 +137,7 @@ def enframe(x, name="name", value="value") -> Any:
raise _NotImplementedByCurrentBackendError("enframe", x)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("deframe"))
def deframe(x) -> Any:
"""Converts two-column data frames to a dictionary
using the first column as name and the second column as value.
Expand All @@ -151,7 +152,7 @@ def deframe(x) -> Any:
raise _NotImplementedByCurrentBackendError("deframe", x)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("add_row"))
def add_row(
_data,
*args,
Expand All @@ -178,7 +179,7 @@ def add_row(
raise _NotImplementedByCurrentBackendError("add_row", _data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("add_column"))
def add_column(
_data,
*args,
Expand Down Expand Up @@ -206,7 +207,7 @@ def add_column(
raise _NotImplementedByCurrentBackendError("add_column", _data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("has_rownames"))
def has_rownames(_data) -> bool:
"""Detect if a data frame has row names

Expand All @@ -222,7 +223,7 @@ def has_rownames(_data) -> bool:
raise _NotImplementedByCurrentBackendError("has_rownames", _data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("remove_rownames"))
def remove_rownames(_data) -> Any:
"""Remove the index/rownames of a data frame

Expand All @@ -238,7 +239,7 @@ def remove_rownames(_data) -> Any:
raise _NotImplementedByCurrentBackendError("remove_rownames", _data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("rownames_to_column"))
def rownames_to_column(_data, var="rowname") -> Any:
"""Add rownames as a column

Expand All @@ -255,7 +256,7 @@ def rownames_to_column(_data, var="rowname") -> Any:
raise _NotImplementedByCurrentBackendError("rownames_to_column", _data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("rowid_to_column"))
def rowid_to_column(_data, var="rowid") -> Any:
"""Add rownames as a column

Expand All @@ -270,7 +271,7 @@ def rowid_to_column(_data, var="rowid") -> Any:
raise _NotImplementedByCurrentBackendError("rowid_to_column", _data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("column_to_rownames"))
def column_to_rownames(_data, var="rowname") -> Any:
"""Set rownames/index with one column, and remove it

Expand Down
37 changes: 19 additions & 18 deletions datar/apis/tidyr.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
register_verb as _register_verb,
register_func as _register_func,
)
from ..core.verb_env import get_verb_ast_fallback as _get_verb_ast_fallback

from ..core.utils import (
NotImplementedByCurrentBackendError as _NotImplementedByCurrentBackendError,
Expand All @@ -28,7 +29,7 @@ def full_seq(x, period, tol=1e-6) -> Any:
raise _NotImplementedByCurrentBackendError("full_seq", x)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("chop"))
def chop(
data,
cols=None,
Expand All @@ -46,7 +47,7 @@ def chop(
raise _NotImplementedByCurrentBackendError("chop", data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("unchop"))
def unchop(
data,
cols=None,
Expand Down Expand Up @@ -89,7 +90,7 @@ def unchop(
raise _NotImplementedByCurrentBackendError("unchop", data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("nest"))
def nest(
_data,
_names_sep: str = None,
Expand All @@ -113,7 +114,7 @@ def nest(
raise _NotImplementedByCurrentBackendError("nest", _data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("unnest"))
def unnest(
data,
*cols: str | int,
Expand Down Expand Up @@ -158,7 +159,7 @@ def unnest(
raise _NotImplementedByCurrentBackendError("unnest", data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("pack"))
def pack(
_data,
_names_sep: str = None,
Expand All @@ -179,7 +180,7 @@ def pack(
raise _NotImplementedByCurrentBackendError("pack", _data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("unpack"))
def unpack(
data,
cols,
Expand Down Expand Up @@ -213,7 +214,7 @@ def unpack(
raise _NotImplementedByCurrentBackendError("unpack", data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("expand"))
def expand(
data,
*args,
Expand Down Expand Up @@ -319,7 +320,7 @@ def crossing(
raise _NotImplementedByCurrentBackendError("crossing")


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("complete"))
def complete(
data,
*args,
Expand Down Expand Up @@ -353,7 +354,7 @@ def complete(
raise _NotImplementedByCurrentBackendError("complete", data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("drop_na"))
def drop_na(
_data,
*columns: str,
Expand All @@ -377,7 +378,7 @@ def drop_na(
raise _NotImplementedByCurrentBackendError("drop_na", _data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("extract"))
def extract(
data,
col: str | int,
Expand Down Expand Up @@ -409,7 +410,7 @@ def extract(
raise _NotImplementedByCurrentBackendError("extract", data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("fill"))
def fill(
_data,
*columns: str | int,
Expand All @@ -434,7 +435,7 @@ def fill(
raise _NotImplementedByCurrentBackendError("fill", _data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("pivot_longer"))
def pivot_longer(
_data,
cols,
Expand Down Expand Up @@ -540,7 +541,7 @@ def pivot_longer(
raise _NotImplementedByCurrentBackendError("pivot_longer", _data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("pivot_wider"))
def pivot_wider(
_data,
id_cols=None,
Expand Down Expand Up @@ -593,7 +594,7 @@ def pivot_wider(
raise _NotImplementedByCurrentBackendError("pivot_wider", _data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("separate"))
def separate(
data,
col: int | str,
Expand Down Expand Up @@ -640,7 +641,7 @@ def separate(
raise _NotImplementedByCurrentBackendError("separate", data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("separate_rows"))
def separate_rows(
data,
*columns: str,
Expand All @@ -662,7 +663,7 @@ def separate_rows(
raise _NotImplementedByCurrentBackendError("separate_rows", data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("uncount"))
def uncount(
data,
weights,
Expand All @@ -685,7 +686,7 @@ def uncount(
raise _NotImplementedByCurrentBackendError("uncount", data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("unite"))
def unite(
data,
col: str,
Expand All @@ -711,7 +712,7 @@ def unite(
raise _NotImplementedByCurrentBackendError("unite", data)


@_register_verb()
@_register_verb(ast_fallback=_get_verb_ast_fallback("replace_na"))
def replace_na(
data,
data_or_replace=None,
Expand Down
40 changes: 40 additions & 0 deletions datar/core/verb_env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""Utilities for getting verb AST fallback from environment variables"""
from __future__ import annotations

import os


def get_verb_ast_fallback(verb: str) -> str | None:
"""Get ast_fallback value from environment variables.

Checks for per-verb environment variable first, then falls back to global.

Args:
verb: The name of the verb (e.g., "mutate", "select", "filter")

Returns:
The ast_fallback value from environment variables, or None if not set

Example:
>>> @register_verb(ast_fallback=get_verb_ast_fallback("mutate"))
>>> def mutate(...):
... pass
"""
# Convert verb name to uppercase, removing trailing underscore if present
# e.g., "select" -> "SELECT", "filter_" -> "FILTER"
verb_name = verb.rstrip("_").upper()

# Check for per-verb environment variable first
# e.g., DATAR_MUTATE_AST_FALLBACK
per_verb_key = f"DATAR_{verb_name}_AST_FALLBACK"
per_verb_value = os.environ.get(per_verb_key)
if per_verb_value:
return per_verb_value

# Fall back to global environment variable
global_key = "DATAR_VERB_AST_FALLBACK"
global_value = os.environ.get(global_key)
if global_value:
return global_value

return None
3 changes: 2 additions & 1 deletion datar/misc.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from typing import Any as _Any, Callable as _Callable

from pipda import register_verb as _register_verb
from .core.verb_env import get_verb_ast_fallback as _get_verb_ast_fallback

from .core.load_plugins import plugin as _plugin

locals().update(_plugin.hooks.misc_api())


@_register_verb(object)
@_register_verb(object, ast_fallback=_get_verb_ast_fallback("pipe"))
def pipe(data: _Any, func: _Callable, *args, **kwargs) -> _Any:
"""Apply a function to the data

Expand Down
Loading