Skip to content

Commit f0a6ed3

Browse files
authored
fix: auto-load tzdata in pyodide (#2343)
1 parent d304cef commit f0a6ed3

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

cognite/client/utils/_pyodide_helpers.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import logging
34
import os
45
import warnings
56
from collections.abc import Callable, MutableMapping
@@ -16,6 +17,9 @@
1617
from cognite.client._http_client import HTTPClient, HTTPClientConfig
1718

1819

20+
logger = logging.getLogger(__name__)
21+
22+
1923
def patch_sdk_for_pyodide() -> None:
2024
# -------------------
2125
# Patch Pyodide related issues
@@ -56,6 +60,21 @@ def patch_sdk_for_pyodide() -> None:
5660
if os.getenv("COGNITE_FUSION_NOTEBOOK") is not None:
5761
global_config.default_client_config = FusionNotebookConfig()
5862

63+
# - We attempt to load the package 'tzdata' automatically, as pyodide can't read IANA timezone info from
64+
# the OS and thus need this extra package. We need the timezone info because we use zoneinfo.ZoneInfo
65+
# internally for e.g. datapoints and workflows.
66+
# Note: This convenience will only work in chromium-based browsers (as of Sept 2025)
67+
try:
68+
import micropip # type: ignore [import-not-found]
69+
from pyodide.ffi import run_sync # type: ignore [import-not-found]
70+
71+
run_sync(micropip.install("tzdata"))
72+
except Exception:
73+
logger.debug(
74+
"Could not load 'tzdata' package automatically in pyodide. You may need to do this manually:"
75+
"import micropip; await micropip.install('tzdata')"
76+
)
77+
5978

6079
def http_client__init__(
6180
self: HTTPClient,

tests/utils.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
from cognite.client.data_classes.capabilities import Capability, LegacyCapability, UnknownAcl
4242
from cognite.client.data_classes.data_modeling import TypedEdge, TypedEdgeApply, TypedNode, TypedNodeApply
4343
from cognite.client.data_classes.data_modeling.data_types import ListablePropertyType
44+
from cognite.client.data_classes.data_modeling.ids import ContainerId, ViewId
4445
from cognite.client.data_classes.data_modeling.query import NodeResultSetExpression, Query
4546
from cognite.client.data_classes.datapoints import (
4647
_INT_AGGREGATES,
@@ -69,6 +70,7 @@
6970
if TYPE_CHECKING:
7071
import pandas
7172

73+
7274
REPO_ROOT = Path(__file__).resolve().parent.parent
7375

7476
T_Type = TypeVar("T_Type", bound=type)
@@ -530,7 +532,11 @@ def create_value(self, type_: Any, var_name: str | None = None) -> Any:
530532
elif container_type is tuple:
531533
if any(arg is ... for arg in args):
532534
return tuple(self.create_value(first_not_none) for _ in range(self._random.randint(1, 3)))
533-
raise NotImplementedError(f"Tuple with multiple types is not supported. {self._error_msg}")
535+
elif all(arg is str for arg in args):
536+
return tuple(self._random_string(self._random.randint(0, 10)) for _ in range(len(args)))
537+
raise NotImplementedError(
538+
f"Tuple with multiple types is not supported. Add on the above line. {self._error_msg}"
539+
)
534540

535541
if var_name == "external_id" and type_ is str:
536542
return self._random_string(50, sample_from=string.ascii_uppercase + string.digits)
@@ -611,6 +617,8 @@ def _type_checking(cls) -> dict[str, type]:
611617
from cognite.client import CogniteClient
612618

613619
return {
620+
"ContainerId": ContainerId,
621+
"ViewId": ViewId,
614622
"CogniteClient": CogniteClient,
615623
"NumpyDatetime64NSArray": npt.NDArray[np.datetime64],
616624
"NumpyUInt32Array": npt.NDArray[np.uint32],

0 commit comments

Comments
 (0)