Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: modify type of field_specs #482

Merged
merged 1 commit into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion pygwalker/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from pygwalker.services.global_var import GlobalVarManager
from pygwalker.services.kaggle import show_tips_user_kaggle as __show_tips_user_kaggle

__version__ = "0.4.8a0"
__version__ = "0.4.8a1"
__hash__ = __rand_str()

from pygwalker.api.jupyter import walk, render, table
Expand Down
8 changes: 4 additions & 4 deletions pygwalker/api/gradio.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Union, Dict, Optional
from typing import Union, List, Optional
from typing_extensions import Literal

from .pygwalker import PygWalker
Expand All @@ -18,7 +18,7 @@ def get_html_on_gradio(
dataset: Union[DataFrame, Connector],
gid: Union[int, str] = None,
*,
field_specs: Optional[Dict[str, FieldSpec]] = None,
field_specs: Optional[List[FieldSpec]] = None,
theme_key: Literal['vega', 'g2'] = 'g2',
dark: Literal['media', 'light', 'dark'] = 'media',
spec: str = "",
Expand All @@ -36,7 +36,7 @@ def get_html_on_gradio(

Kargs:
- env: (Literal['Jupyter' | 'Streamlit'], optional): The enviroment using pygwalker. Default as 'Jupyter'
- field_specs (Dict[str, FieldSpec], optional): Specifications of some fields. They'll been automatically inferred from `df` if some fields are not specified.
- field_specs (List[FieldSpec], optional): Specifications of some fields. They'll been automatically inferred from `df` if some fields are not specified.
- theme_key ('vega' | 'g2'): theme type.
- dark (Literal['media' | 'light' | 'dark']): 'media': auto detect OS theme.
- spec (str): chart config data. config id, json, remote file url
Expand All @@ -50,7 +50,7 @@ def get_html_on_gradio(
walker = PygWalker(
gid=gid,
dataset=dataset,
field_specs=field_specs if field_specs is not None else {},
field_specs=field_specs if field_specs is not None else [],
spec=spec,
source_invoke_code="",
theme_key=theme_key,
Expand Down
22 changes: 16 additions & 6 deletions pygwalker/api/html.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Union, Dict, Optional, Any
from typing import Union, Dict, Optional, Any, List
import logging

from typing_extensions import Literal
Expand All @@ -20,7 +20,7 @@ def _to_html(
gid: Union[int, str] = None,
*,
spec: str = "",
field_specs: Optional[Dict[str, FieldSpec]] = None,
field_specs: Optional[List[FieldSpec]] = None,
theme_key: Literal['vega', 'g2'] = 'g2',
dark: Literal['media', 'light', 'dark'] = 'media',
default_tab: Literal["data", "vis"] = "vis",
Expand All @@ -31,14 +31,24 @@ def _to_html(
) -> str:
"""
Generate embeddable HTML code of Graphic Walker with data of `df`.

Args:
- df (pl.DataFrame | pd.DataFrame, optional): dataframe.
- gid (Union[int, str], optional): GraphicWalker container div's id ('gwalker-{gid}')

Kargs:
- field_specs (List[FieldSpec], optional): Specifications of some fields. They'll been automatically inferred from `df` if some fields are not specified.
- spec (str): chart config data. config id, json, remote file url
- theme_key ('vega' | 'g2'): theme type.
- dark ('media' | 'light' | 'dark'): 'media': auto detect OS theme.
"""
check_expired_params(kwargs)

if gid is None:
gid = generate_hash_code()

if field_specs is None:
field_specs = {}
field_specs = []

walker = PygWalker(
gid=gid,
Expand Down Expand Up @@ -68,7 +78,7 @@ def to_html(
gid: Union[int, str] = None,
*,
spec: str = "",
field_specs: Optional[Dict[str, FieldSpec]] = None,
field_specs: Optional[List[FieldSpec]] = None,
theme_key: Literal['vega', 'g2'] = 'g2',
dark: Literal['media', 'light', 'dark'] = 'media',
default_tab: Literal["data", "vis"] = "vis",
Expand Down Expand Up @@ -121,7 +131,7 @@ def to_table_html(
df,
None,
spec="",
field_specs={},
field_specs=[],
theme_key=theme_key,
dark=dark,
gw_mode="table",
Expand Down Expand Up @@ -151,7 +161,7 @@ def to_render_html(
df,
None,
spec=spec,
field_specs={},
field_specs=[],
theme_key=theme_key,
dark=dark,
gw_mode="filter_renderer",
Expand Down
12 changes: 6 additions & 6 deletions pygwalker/api/jupyter.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Union, Dict, Optional
from typing import Union, List, Optional
import inspect

from typing_extensions import Literal
Expand All @@ -18,7 +18,7 @@ def walk(
gid: Union[int, str] = None,
*,
env: Literal['Jupyter', 'JupyterWidget'] = 'JupyterWidget',
field_specs: Optional[Dict[str, FieldSpec]] = None,
field_specs: Optional[List[FieldSpec]] = None,
theme_key: Literal['vega', 'g2'] = 'g2',
dark: Literal['media', 'light', 'dark'] = 'media',
spec: str = "",
Expand All @@ -37,7 +37,7 @@ def walk(

Kargs:
- env: (Literal['Jupyter' | 'JupyterWidget'], optional): The enviroment using pygwalker. Default as 'JupyterWidget'
- field_specs (Dict[str, FieldSpec], optional): Specifications of some fields. They'll been automatically inferred from `df` if some fields are not specified.
- field_specs (List[FieldSpec], optional): Specifications of some fields. They'll been automatically inferred from `df` if some fields are not specified.
- theme_key ('vega' | 'g2'): theme type.
- dark (Literal['media' | 'light' | 'dark']): 'media': auto detect OS theme.
- spec (str): chart config data. config id, json, remote file url
Expand All @@ -49,7 +49,7 @@ def walk(
check_expired_params(kwargs)

if field_specs is None:
field_specs = {}
field_specs = []

source_invoke_code = get_formated_spec_params_code_from_frame(
inspect.stack()[1].frame
Expand Down Expand Up @@ -121,7 +121,7 @@ def render(
walker = PygWalker(
gid=None,
dataset=dataset,
field_specs={},
field_specs=[],
spec=spec,
source_invoke_code="",
theme_key=theme_key,
Expand Down Expand Up @@ -163,7 +163,7 @@ def table(
walker = PygWalker(
gid=None,
dataset=dataset,
field_specs={},
field_specs=[],
spec="",
source_invoke_code="",
theme_key=theme_key,
Expand Down
7 changes: 3 additions & 4 deletions pygwalker/api/kanaries_cloud.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Dict, Optional, Union
from typing import List, Optional, Union
from datetime import datetime

from pygwalker.data_parsers.base import FieldSpec
Expand All @@ -7,7 +7,6 @@
from pygwalker.data_parsers.database_parser import Connector
from pygwalker.services.cloud_service import CloudService
from pygwalker.services.data_parsers import get_parser
from pygwalker.services.global_var import GlobalVarManager


def create_cloud_dataset(
Expand Down Expand Up @@ -44,7 +43,7 @@ def create_cloud_walker(
*,
chart_name: str,
workspace_name: str,
field_specs: Optional[Dict[str, FieldSpec]] = None,
field_specs: Optional[List[FieldSpec]] = None,
kanaries_api_key: str = ""
) -> str:
"""
Expand All @@ -63,7 +62,7 @@ def create_cloud_walker(
str: pygwalker url in kanaries cloud
"""
if field_specs is None:
field_specs = {}
field_specs = []

cloud_service = CloudService(kanaries_api_key)
data_parser = get_parser(dataset, False, field_specs)
Expand Down
10 changes: 5 additions & 5 deletions pygwalker/api/pygwalker.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List, Dict, Any, Optional, Union
from typing import List, Dict, Any, Optional, Union, Tuple
import html as m_html
import urllib
import json
Expand All @@ -9,7 +9,7 @@
import pandas as pd

from pygwalker._typing import DataFrame
from pygwalker.data_parsers.base import BaseDataParser
from pygwalker.data_parsers.base import BaseDataParser, FieldSpec
from pygwalker.data_parsers.database_parser import Connector
from pygwalker.utils.display import display_html
from pygwalker.utils.randoms import rand_str
Expand Down Expand Up @@ -52,7 +52,7 @@ def __init__(
*,
gid: Optional[Union[int, str]],
dataset: Union[DataFrame, Connector, str],
field_specs: Dict[str, Any],
field_specs: List[FieldSpec],
spec: str,
source_invoke_code: str,
theme_key: Literal['vega', 'g2'],
Expand Down Expand Up @@ -120,7 +120,7 @@ def _get_data_parser(
self,
*,
dataset: Union[DataFrame, Connector, str],
field_specs: Dict[str, Any],
field_specs: List[FieldSpec],
use_cloud_calc: bool,
kanaries_api_key: str,
cloud_service: CloudService
Expand Down Expand Up @@ -153,7 +153,7 @@ def _get_parse_dsl_type(self, data_parser: BaseDataParser) -> Literal["server",
return "server"
return "client"

def _init_spec(self, spec: Dict[str, Any], field_specs: List[Dict[str, Any]]):
def _init_spec(self, spec: Dict[str, Any], field_specs: List[FieldSpec]):
spec_obj, spec_type = get_spec_json(spec)
self._update_vis_spec(spec_obj["config"] and fill_new_fields(spec_obj["config"], field_specs))
self.spec_type = spec_type
Expand Down
12 changes: 6 additions & 6 deletions pygwalker/api/streamlit.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def __init__(
dataset: Union[DataFrame, Connector],
gid: Union[int, str] = None,
*,
field_specs: Optional[Dict[str, FieldSpec]] = None,
field_specs: Optional[List[FieldSpec]] = None,
theme_key: Literal['vega', 'g2'] = 'g2',
dark: Literal['media', 'light', 'dark'] = 'media',
spec: str = "",
Expand All @@ -74,7 +74,7 @@ def __init__(
- gid (Union[int, str], optional): GraphicWalker container div's id ('gwalker-{gid}')

Kargs:
- field_specs (Dict[str, FieldSpec], optional): Specifications of some fields. They'll been automatically inferred from `df` if some fields are not specified.
- field_specs (List[FieldSpec], optional): Specifications of some fields. They'll been automatically inferred from `df` if some fields are not specified.
- theme_key ('vega' | 'g2'): theme type.
- dark (Literal['media' | 'light' | 'dark']): 'media': auto detect OS theme.
- spec (str): chart config data. config id, json, remote file url
Expand All @@ -90,7 +90,7 @@ def __init__(
self.walker = PygWalker(
gid=gid,
dataset=dataset,
field_specs=field_specs if field_specs is not None else {},
field_specs=field_specs if field_specs is not None else [],
spec=spec,
source_invoke_code="",
theme_key=theme_key,
Expand Down Expand Up @@ -264,7 +264,7 @@ def get_streamlit_html(
dataset: Union[DataFrame, Connector],
gid: Union[int, str] = None,
*,
field_specs: Optional[Dict[str, FieldSpec]] = None,
field_specs: Optional[List[FieldSpec]] = None,
theme_key: Literal['vega', 'g2'] = 'g2',
dark: Literal['media', 'light', 'dark'] = 'media',
spec: str = "",
Expand All @@ -283,7 +283,7 @@ def get_streamlit_html(
- gid (Union[int, str], optional): GraphicWalker container div's id ('gwalker-{gid}')

Kargs:
- field_specs (Dict[str, FieldSpec], optional): Specifications of some fields. They'll been automatically inferred from `df` if some fields are not specified.
- field_specs (List[FieldSpec], optional): Specifications of some fields. They'll been automatically inferred from `df` if some fields are not specified.
- theme_key ('vega' | 'g2'): theme type.
- dark (Literal['media' | 'light' | 'dark']): 'media': auto detect OS theme.
- spec (str): chart config data. config id, json, remote file url
Expand All @@ -293,7 +293,7 @@ def get_streamlit_html(
- default_tab (Literal["data", "vis"]): default tab to show. Default to "vis"
"""
if field_specs is None:
field_specs = {}
field_specs = []

renderer = StreamlitRenderer(
gid=gid,
Expand Down
32 changes: 18 additions & 14 deletions pygwalker/data_parsers/base.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from typing import Generic, Dict, List, Any, Optional, NamedTuple
from typing import Generic, Dict, List, Any, Optional
from typing_extensions import Literal
from functools import lru_cache
from datetime import datetime, date
from datetime import timedelta
import abc
import io

from pydantic import BaseModel
import duckdb
import arrow
import pytz
Expand All @@ -16,21 +17,21 @@


# pylint: disable=broad-except
class FieldSpec(NamedTuple):
class FieldSpec(BaseModel):
"""Field specification.

Args:
- semanticType: '?' | 'nominal' | 'ordinal' | 'temporal' | 'quantitative'. default to '?'.
- analyticType: '?' | 'dimension' | 'measure'. default to '?'.
- fname: str. The field name.
- semantic_type: '?' | 'nominal' | 'ordinal' | 'temporal' | 'quantitative'. default to '?'.
- analytic_type: '?' | 'dimension' | 'measure'. default to '?'.
- display_as: str. The field name displayed. None means using the original column name.
"""
semanticType: Literal['?', 'nominal', 'ordinal', 'temporal', 'quantitative'] = '?'
analyticType: Literal['?', 'dimension', 'measure'] = '?'
fname: str
semantic_type: Literal['?', 'nominal', 'ordinal', 'temporal', 'quantitative'] = '?'
analytic_type: Literal['?', 'dimension', 'measure'] = '?'
display_as: str = None


default_field_spec = FieldSpec()

INFINITY_DATA_SIZE = 1 << 62


Expand All @@ -41,7 +42,7 @@ class BaseDataParser(abc.ABC):
def __init__(
self,
data: Any,
field_specs: Dict[str, FieldSpec],
field_specs: List[FieldSpec],
infer_string_to_date: bool,
infer_number_to_dimension: bool,
other_params: Dict[str, Any]
Expand Down Expand Up @@ -118,7 +119,7 @@ class BaseDataFrameDataParser(Generic[DataFrame], BaseDataParser):
"""DataFrame property getter"""
def __init__(
self, df: DataFrame,
field_specs: Dict[str, FieldSpec],
field_specs: List[FieldSpec],
infer_string_to_date: bool,
infer_number_to_dimension: bool,
other_params: Dict[str, Any]
Expand Down Expand Up @@ -149,7 +150,7 @@ def raw_fields(self) -> List[Dict[str, str]]:
]

def _infer_prop(
self, col: str, field_specs: Dict[str, FieldSpec] = None
self, col: str, field_specs: List[FieldSpec] = None
) -> Dict[str, str]:
"""get IMutField

Expand All @@ -158,9 +159,12 @@ def _infer_prop(
"""
s = self._example_df[col]
orig_fname = col
field_spec = field_specs.get(orig_fname, default_field_spec)
semantic_type = self._infer_semantic(s, orig_fname) if field_spec.semanticType == '?' else field_spec.semanticType
analytic_type = self._infer_analytic(s, orig_fname) if field_spec.analyticType == '?' else field_spec.analyticType

field_spec_map = {field_spec.fname: field_spec for field_spec in field_specs}

field_spec = field_spec_map.get(orig_fname, FieldSpec(fname=orig_fname))
semantic_type = self._infer_semantic(s, orig_fname) if field_spec.semantic_type == '?' else field_spec.semantic_type
analytic_type = self._infer_analytic(s, orig_fname) if field_spec.analytic_type == '?' else field_spec.analytic_type
fname = orig_fname if field_spec.display_as is None else field_spec.display_as
return {
'fid': col,
Expand Down
2 changes: 1 addition & 1 deletion pygwalker/data_parsers/cloud_dataset_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class CloudDatasetParser(BaseDataParser):
def __init__(
self,
dataset_id: str,
field_specs: Dict[str, FieldSpec],
field_specs: List[FieldSpec],
infer_string_to_date: bool,
infer_number_to_dimension: bool,
other_params: Dict[str, Any]
Expand Down
2 changes: 1 addition & 1 deletion pygwalker/data_parsers/database_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class DatabaseDataParser(BaseDataParser):
def __init__(
self,
conn: Connector,
field_specs: Dict[str, FieldSpec],
field_specs: List[FieldSpec],
infer_string_to_date: bool,
infer_number_to_dimension: bool,
other_params: Dict[str, Any]
Expand Down
Loading
Loading