├── tests
├── __init__.py
├── ceil_test.py
├── julian_date_test.py
├── test_date_range.py
├── test_is_busday.py
├── test_format_localized.py
├── test_timezone.py
└── test_month_delta.py
├── polars_xdt
├── py.typed
├── .mypy.ini
├── _internal.pyi
├── typing.py
├── namespace.py
├── __init__.py
├── utils.py
├── ranges.py
└── functions.py
├── rust-toolchain.toml
├── assets
├── .DS_Store
└── polars-business.png
├── docs
├── api
│ └── polars_xdt.date_range.rst
├── requirements-docs.txt
├── API.rst
├── installation.rst
├── index.rst
├── Makefile
└── conf.py
├── requirements.txt
├── .gitignore
├── dprint.json
├── src
├── lib.rs
├── arg_previous_greater.rs
├── format_localized.rs
├── to_julian.rs
├── expressions.rs
├── month_delta.rs
└── timezone.rs
├── Cargo.toml
├── .readthedocs.yaml
├── Makefile
├── LICENSE
├── bump_version.py
├── licenses
├── NUMPY_LICENSE.txt
└── PANDAS_LICENSE.txt
├── pyproject.toml
├── README.md
├── CODE_OF_CONDUCT.md
├── .github
└── workflows
│ └── CI.yml
└── Cargo.lock
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/polars_xdt/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/polars_xdt/.mypy.ini:
--------------------------------------------------------------------------------
1 | [mypy]
2 | strict=True
3 |
--------------------------------------------------------------------------------
/polars_xdt/_internal.pyi:
--------------------------------------------------------------------------------
1 | __version__: str
2 |
--------------------------------------------------------------------------------
/rust-toolchain.toml:
--------------------------------------------------------------------------------
1 | [toolchain]
2 | channel = "nightly-2025-10-24"
3 |
4 |
--------------------------------------------------------------------------------
/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pola-rs/polars-xdt/HEAD/assets/.DS_Store
--------------------------------------------------------------------------------
/assets/polars-business.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pola-rs/polars-xdt/HEAD/assets/polars-business.png
--------------------------------------------------------------------------------
/docs/api/polars_xdt.date_range.rst:
--------------------------------------------------------------------------------
1 | polars\_xdt.date\_range
2 | =======================
3 |
4 | .. currentmodule:: polars_xdt
5 |
6 | .. autofunction:: date_range
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | maturin
2 | python-dateutil
3 | polars
4 | hypothesis
5 | numpy
6 | pandas
7 | pytest
8 | holidays
9 | mypy
10 | black
11 | ruff
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /pyo3-polars/target
2 | .idea/
3 | venv/
4 | target/
5 | *.pyc
6 | .hypothesis/
7 | *.html
8 | *.bat
9 | *.js
10 | docs/_build
11 | docs/api/*
12 | *.so
13 |
--------------------------------------------------------------------------------
/docs/requirements-docs.txt:
--------------------------------------------------------------------------------
1 | sphinx
2 | numpydoc
3 | sphinx_autosummary_accessors
4 | sphinx_copybutton
5 | sphinx-design
6 | sphinx-favicon
7 | pydata_sphinx_theme
8 | polars-xdt
9 |
--------------------------------------------------------------------------------
/dprint.json:
--------------------------------------------------------------------------------
1 | {
2 | "json": {
3 | },
4 | "markdown": {
5 | },
6 | "toml": {
7 | },
8 | "includes": ["**/*.{json,md,toml}"],
9 | "excludes": [
10 | "**/*-lock.json"
11 | ],
12 | "plugins": [
13 | "https://plugins.dprint.dev/json-0.17.4.wasm",
14 | "https://plugins.dprint.dev/markdown-0.16.1.wasm",
15 | "https://plugins.dprint.dev/toml-0.5.4.wasm"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/docs/API.rst:
--------------------------------------------------------------------------------
1 | API
2 | ===
3 |
4 | .. autosummary::
5 | :toctree: api/
6 |
7 | polars_xdt.date_range
8 | polars_xdt.ceil
9 | polars_xdt.day_name
10 | polars_xdt.format_localized
11 | polars_xdt.from_local_datetime
12 | polars_xdt.is_workday
13 | polars_xdt.month_name
14 | polars_xdt.month_delta
15 | polars_xdt.to_local_datetime
16 | polars_xdt.to_julian_date
17 |
--------------------------------------------------------------------------------
/docs/installation.rst:
--------------------------------------------------------------------------------
1 | Installation
2 | ============
3 |
4 | First, you need to `install Polars `_.
5 |
6 | Then, you'll need to install `polars-xdt`:
7 |
8 | .. code-block::
9 |
10 | pip install polars-xdt
11 |
12 | Then, if you can run
13 |
14 | .. code-block::
15 |
16 | import polars as pl
17 | import polars_xdt
18 |
19 | without errors it means installation all worked correctly!
20 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | polars-xdt
2 | ===============
3 |
4 | **polars-xdt** is a Python library which is a plugin for
5 | Polars, a blazingly fast dataframe library.
6 |
7 | .. image:: https://github.com/MarcoGorelli/polars-xdt/assets/33491632/928c68c4-4e71-45a7-bc89-14922c7ce61b
8 | :width: 400
9 | :alt: Polar bear in an office with a nice warm cup of coffee
10 |
11 | .. toctree::
12 | :maxdepth: 2
13 | :caption: Contents:
14 |
15 | installation
16 | API
17 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | mod arg_previous_greater;
2 | mod expressions;
3 | mod format_localized;
4 | mod month_delta;
5 | mod timezone;
6 | mod to_julian;
7 |
8 | use pyo3::prelude::*;
9 | use pyo3_polars::PolarsAllocator;
10 |
11 | #[pymodule]
12 | fn _internal(_py: Python, m: &Bound) -> PyResult<()> {
13 | m.add("__version__", env!("CARGO_PKG_VERSION"))?;
14 | Ok(())
15 | }
16 |
17 | #[global_allocator]
18 | static ALLOC: PolarsAllocator = PolarsAllocator::new();
19 |
--------------------------------------------------------------------------------
/polars_xdt/typing.py:
--------------------------------------------------------------------------------
1 | from typing import TYPE_CHECKING, Union
2 |
3 | if TYPE_CHECKING:
4 | import sys
5 |
6 | import polars as pl
7 |
8 | if sys.version_info >= (3, 10):
9 | from typing import TypeAlias
10 | else:
11 | from typing_extensions import TypeAlias
12 | from polars.datatypes import DataType, DataTypeClass
13 |
14 | IntoExprColumn: TypeAlias = Union[pl.Expr, str, pl.Series]
15 | PolarsDataType: TypeAlias = Union[DataType, DataTypeClass]
16 |
--------------------------------------------------------------------------------
/tests/ceil_test.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 |
3 | import polars as pl
4 |
5 | import polars_xdt as xdt
6 |
7 |
8 | def test_ceil() -> None:
9 | df = pl.DataFrame(
10 | {
11 | "date_col": [
12 | datetime(2024, 8, 24, 1, 2, 3, 123456),
13 | datetime(2024, 10, 1),
14 | ],
15 | },
16 | schema={"date_col": pl.Datetime("ms")},
17 | )
18 | result = df.select(result=xdt.ceil("date_col", "1mo"))["result"]
19 | assert result[0] == datetime(2024, 9, 1, 0, 0, 0, 0)
20 | assert result[1] == datetime(2024, 10, 1, 0, 0, 0, 0)
21 |
--------------------------------------------------------------------------------
/polars_xdt/namespace.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import Any, Callable
4 |
5 | import polars as pl
6 |
7 | from polars_xdt import functions
8 |
9 |
10 | @pl.api.register_expr_namespace("xdt")
11 | class ExprXDTNamespace:
12 | """eXtra stuff for DateTimes."""
13 |
14 | def __init__(self, expr: pl.Expr) -> None:
15 | self._expr = expr
16 |
17 | def __getattr__(self, function_name: str) -> Callable[[Any], pl.Expr]:
18 | def func(*args: Any, **kwargs: Any) -> pl.Expr:
19 | return getattr(functions, function_name)(
20 | self._expr, *args, **kwargs
21 | )
22 |
23 | return func
24 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/polars_xdt/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import polars_xdt.namespace # noqa: F401
4 | from polars_xdt.functions import (
5 | arg_previous_greater,
6 | ceil,
7 | day_name,
8 | format_localized,
9 | from_local_datetime,
10 | is_workday,
11 | month_delta,
12 | month_name,
13 | to_julian_date,
14 | to_local_datetime,
15 | )
16 | from polars_xdt.ranges import date_range
17 |
18 | from ._internal import __version__
19 |
20 | __all__ = [
21 | "__version__",
22 | "arg_previous_greater",
23 | "ceil",
24 | "date_range",
25 | "day_name",
26 | "format_localized",
27 | "from_local_datetime",
28 | "is_workday",
29 | "month_delta",
30 | "month_name",
31 | "to_julian_date",
32 | "to_local_datetime",
33 | ]
34 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "polars_xdt"
3 | version = "0.17.1"
4 | edition = "2021"
5 |
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 | [lib]
8 | name = "polars_xdt"
9 | crate-type = ["cdylib"]
10 |
11 | [dependencies]
12 | pyo3 = { version = "0.26", features = ["extension-module", "abi3-py39"] }
13 | pyo3-polars = { version = "0.25.0", features = ["derive", "dtype-struct", "dtype-array"] }
14 | serde = { version = "1", features = ["derive"] }
15 | chrono = { version = "0.4.42", default-features = false, features = ["std", "unstable-locales"] }
16 | chrono-tz = "0.10.4"
17 | polars = { version = "0.52.0", features = ["strings", "timezones"]}
18 | polars-ops = { version = "0.52.0", default-features = false }
19 | polars-arrow = { version = "0.52.0", default-features = false }
20 |
21 |
--------------------------------------------------------------------------------
/.readthedocs.yaml:
--------------------------------------------------------------------------------
1 | # .readthedocs.yaml
2 | # Read the Docs configuration file
3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
4 |
5 | # Required
6 | version: 2
7 |
8 | # Set the OS, Python version and other tools you might need
9 | build:
10 | os: ubuntu-22.04
11 | tools:
12 | python: "3.11"
13 | # You can also specify other tool versions:
14 | # nodejs: "19"
15 | # rust: "1.64"
16 | # golang: "1.19"
17 |
18 | # Build documentation in the "docs/" directory with Sphinx
19 | sphinx:
20 | configuration: polars_xdt/docs/conf.py
21 |
22 | # Optionally build your docs in additional formats such as PDF and ePub
23 | # formats:
24 | # - pdf
25 | # - epub
26 |
27 | # Optional but recommended, declare the Python requirements required
28 | # to build your documentation
29 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
30 | python:
31 | install:
32 | - requirements: polars_xdt/docs/requirements-docs.txt
33 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 |
2 | SHELL=/bin/bash
3 |
4 | venv: ## Set up virtual environment
5 | python3 -m venv .venv
6 | .venv/bin/pip install -r requirements.txt -r docs/requirements-docs.txt
7 |
8 | install: venv
9 | unset CONDA_PREFIX && \
10 | source .venv/bin/activate && maturin develop
11 |
12 | install-release: venv
13 | unset CONDA_PREFIX && \
14 | source .venv/bin/activate && maturin develop --release
15 |
16 | pre-commit: venv
17 | rustup component add rustfmt clippy --toolchain nightly-2025-10-24
18 | cargo fmt --all && cargo clippy --all-features
19 | .venv/bin/python -m ruff check polars_xdt tests --fix --exit-non-zero-on-fix
20 | .venv/bin/python -m ruff format polars_xdt tests
21 | .venv/bin/python -m mypy polars_xdt tests
22 |
23 | test: venv
24 | .venv/bin/python -m pytest tests
25 | .venv/bin/python -m pytest polars_xdt --doctest-modules
26 |
27 | run: install
28 | source .venv/bin/activate && python run.py
29 |
30 | run-release: install-release
31 | source .venv/bin/activate && python run.py
32 |
--------------------------------------------------------------------------------
/tests/julian_date_test.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import datetime as dt
4 |
5 | import hypothesis.strategies as st
6 | import pandas as pd
7 | import polars as pl
8 | from hypothesis import given
9 |
10 | import polars_xdt as xdt
11 |
12 |
13 | @given(
14 | date=st.datetimes(
15 | min_value=dt.datetime(1, 1, 1), max_value=dt.datetime(9999, 12, 31)
16 | ),
17 | )
18 | def test_against_pandas(
19 | date: dt.date,
20 | ) -> None:
21 | df = pl.DataFrame({"a": [date]}, schema={"a": pl.Datetime("ms")})
22 | result = df.select(xdt.to_julian_date("a"))["a"].item()
23 | expected = pd.Timestamp(df["a"].item()).to_julian_date()
24 | assert result == expected
25 |
26 |
27 | @given(
28 | date=st.dates(min_value=dt.date(1, 1, 1), max_value=dt.date(9999, 12, 31)),
29 | )
30 | def test_against_pandas_date(
31 | date: dt.date,
32 | ) -> None:
33 | df = pl.DataFrame({"a": [date]})
34 | result = df.select(xdt.to_julian_date("a"))["a"].item()
35 | expected = pd.Timestamp(df["a"].item()).to_julian_date()
36 | assert result == expected
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Marco Edward Gorelli
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/arg_previous_greater.rs:
--------------------------------------------------------------------------------
1 | use polars::prelude::*;
2 |
3 | pub(crate) fn impl_arg_previous_greater(ca: &ChunkedArray) -> IdxCa
4 | where
5 | T: PolarsNumericType,
6 | {
7 | let mut idx: Vec = Vec::with_capacity(ca.len());
8 | let out: IdxCa = ca
9 | .iter()
10 | .enumerate()
11 | .map(|(i, opt_val)| {
12 | if opt_val.is_none() {
13 | idx.push(-1);
14 | return None;
15 | }
16 | let i_curr = i;
17 | let mut i = (i as i32) - 1; // look at previous element
18 | while i >= 0 && ca.get(i as usize).is_none() {
19 | // find previous non-null value
20 | i -= 1;
21 | }
22 | if i < 0 {
23 | idx.push(-1);
24 | return None;
25 | }
26 | while (i != -1) && opt_val >= ca.get(i as usize) {
27 | i = idx[i as usize];
28 | }
29 | if i == -1 {
30 | idx.push(-1);
31 | return Some(i_curr as IdxSize);
32 | }
33 | idx.push(i);
34 | if i == -1 {
35 | None
36 | } else {
37 | Some(i as IdxSize)
38 | }
39 | })
40 | .collect();
41 | out
42 | }
43 |
--------------------------------------------------------------------------------
/polars_xdt/utils.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import polars as pl
6 |
7 | if TYPE_CHECKING:
8 | from polars_xdt.typing import IntoExprColumn, PolarsDataType
9 |
10 |
11 | def parse_into_expr(
12 | expr: IntoExprColumn,
13 | *,
14 | str_as_lit: bool = False,
15 | list_as_lit: bool = True,
16 | dtype: PolarsDataType | None = None,
17 | ) -> pl.Expr:
18 | """
19 | Parse a single input into an expression.
20 |
21 | Parameters
22 | ----------
23 | expr
24 | The input to be parsed as an expression.
25 | str_as_lit
26 | Interpret string input as a string literal. If set to `False` (default),
27 | strings are parsed as column names.
28 | list_as_lit
29 | Interpret list input as a lit literal, If set to `False`,
30 | lists are parsed as `Series` literals.
31 | dtype
32 | If the input is expected to resolve to a literal with a known dtype, pass
33 | this to the `lit` constructor.
34 |
35 | Returns
36 | -------
37 | polars.Expr
38 |
39 | """
40 | if isinstance(expr, pl.Expr):
41 | pass
42 | elif isinstance(expr, str) and not str_as_lit:
43 | expr = pl.col(expr)
44 | elif isinstance(expr, list) and not list_as_lit:
45 | expr = pl.lit(pl.Series(expr), dtype=dtype)
46 | else:
47 | expr = pl.lit(expr, dtype=dtype)
48 |
49 | return expr
50 |
--------------------------------------------------------------------------------
/bump_version.py:
--------------------------------------------------------------------------------
1 | # ruff: noqa
2 | # type: ignore
3 | import sys
4 | import re
5 | import subprocess
6 | import os
7 |
8 | # Docs are in a a separate repo cause I couldn't figure out
9 | # how to deploy from readthedocs
10 | subprocess.run(["make", "install"])
11 | subprocess.run(["make", "clean"], cwd="docs")
12 | subprocess.run(["make", "html"], cwd="docs")
13 | os.system("cp docs/_build/html/* ../docs-polars-xdt/ -r")
14 | subprocess.run(["git", "add", "."], cwd="../docs-polars-xdt")
15 | subprocess.run(
16 | ["git", "commit", "-m", '"new version"', "--allow-empty"],
17 | cwd="../docs-polars-xdt",
18 | )
19 | subprocess.run(["git", "push", "origin", "HEAD"], cwd="../docs-polars-xdt")
20 |
21 | how = sys.argv[1]
22 |
23 | with open("Cargo.toml", "r", encoding="utf-8") as f:
24 | content = f.read()
25 | old_version = re.search(r'^version = "(.*)"', content, re.MULTILINE).group(1)
26 | version = old_version.split(".")
27 | if how == "patch":
28 | version = ".".join(version[:-1] + [str(int(version[-1]) + 1)])
29 | elif how == "minor":
30 | version = ".".join(version[:-2] + [str(int(version[-2]) + 1), "0"])
31 | elif how == "major":
32 | version = ".".join([str(int(version[0]) + 1), "0", "0"])
33 | else:
34 | sys.exit(1)
35 | content = content.replace(
36 | f'version = "{old_version}"', f'version = "{version}"'
37 | )
38 | with open("Cargo.toml", "w", encoding="utf-8") as f:
39 | f.write(content)
40 |
41 | subprocess.run(["git", "commit", "-a", "-m", f"Bump version to {version}"])
42 | subprocess.run(["git", "tag", "-a", version, "-m", version])
43 | subprocess.run(["git", "push", "origin", "HEAD", "--follow-tags"])
44 |
--------------------------------------------------------------------------------
/licenses/NUMPY_LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2005-2023, NumPy Developers.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 |
11 | * Redistributions in binary form must reproduce the above
12 | copyright notice, this list of conditions and the following
13 | disclaimer in the documentation and/or other materials provided
14 | with the distribution.
15 |
16 | * Neither the name of the NumPy Developers nor the names of any
17 | contributors may be used to endorse or promote products derived
18 | from this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
--------------------------------------------------------------------------------
/licenses/PANDAS_LICENSE.txt:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2008-2011, AQR Capital Management, LLC, Lambda Foundry, Inc. and PyData Development Team
4 | All rights reserved.
5 |
6 | Copyright (c) 2011-2023, Open source contributors.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | * Redistributions of source code must retain the above copyright notice, this
12 | list of conditions and the following disclaimer.
13 |
14 | * Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | * Neither the name of the copyright holder nor the names of its
19 | contributors may be used to endorse or promote products derived from
20 | this software without specific prior written permission.
21 |
22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | # ruff: noqa
2 | # Configuration file for the Sphinx documentation builder.
3 | #
4 | # For the full list of built-in configuration values, see the documentation:
5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
6 |
7 | # -- Project information -----------------------------------------------------
8 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
9 | import sphinx_autosummary_accessors # noqa: F401
10 |
11 | project = "polars-xdt"
12 | copyright = "2023, Marco Gorelli"
13 | author = "Marco Gorelli"
14 |
15 |
16 | # -- General configuration ---------------------------------------------------
17 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
18 |
19 | extensions = [
20 | "sphinx.ext.autodoc",
21 | "sphinx.ext.autosummary",
22 | "sphinx.ext.githubpages",
23 | "sphinx.ext.intersphinx",
24 | "numpydoc",
25 | "sphinx_copybutton",
26 | "sphinx_design",
27 | "sphinx_favicon",
28 | ]
29 |
30 | templates_path = ["_templates"]
31 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
32 | numpydoc_show_class_members = False
33 |
34 |
35 | # -- Options for HTML output -------------------------------------------------
36 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
37 |
38 | html_theme = "alabaster"
39 | # html_static_path = ["_static"]
40 |
41 | intersphinx_mapping = {
42 | "polars": ("https://pola-rs.github.io/polars/py-polars/html/", None),
43 | }
44 |
45 | copybutton_prompt_text = r">>> |\.\.\. "
46 | copybutton_prompt_is_regexp = True
47 |
48 | html_theme = "pydata_sphinx_theme"
49 |
50 | html_theme_options = {
51 | "navigation_with_keys": False,
52 | }
53 |
54 | numpydoc_show_class_members = False
55 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["maturin>=1.0,<2.0", "polars>=1.5.0"]
3 | build-backend = "maturin"
4 |
5 | [project]
6 | name = "polars-xdt"
7 | description = "eXtra stuff for Dates and Times in Polars"
8 | readme = "README.md"
9 | authors = [
10 | { name="Marco Gorelli", email="33491632+MarcoGorelli@users.noreply.github.com" },
11 | ]
12 | license = { file = "LICENSE" }
13 | classifiers = [
14 | "Programming Language :: Rust",
15 | "Programming Language :: Python :: Implementation :: CPython",
16 | "Programming Language :: Python :: Implementation :: PyPy",
17 | ]
18 | requires-python = ">=3.9"
19 | dynamic = ["version"]
20 |
21 | [project.urls]
22 | "Repository" = "https://github.com/MarcoGorelli/polars-xdt"
23 | "Documentation" = "https://marcogorelli.github.io/polars-xdt-docs/"
24 | "Change Log" = "https://github.com/MarcoGorelli/polars-xdt/releases"
25 | "Issue Tracker" = "https://github.com/MarcoGorelli/polars-xdt/issues"
26 |
27 |
28 | [tool.maturin]
29 | module-name = "polars_xdt._internal"
30 |
31 | [tool.ruff.format]
32 | docstring-code-format = true
33 |
34 | [tool.ruff]
35 | lint.select = [
36 | "ALL",
37 | ]
38 | lint.ignore = [
39 | 'A003',
40 | 'ANN401',
41 | 'ARG002', # todo: enable
42 | 'ARG003', # todo: enable
43 | 'C901',
44 | 'COM812',
45 | 'D100',
46 | 'D103',
47 | 'D104',
48 | 'D105',
49 | 'D107',
50 | 'D203',
51 | 'D212',
52 | 'DTZ',
53 | 'E501',
54 | 'FBT003', # todo: enable
55 | 'FIX',
56 | 'ISC001',
57 | 'PD',
58 | 'PLR0911',
59 | 'PLR0912',
60 | 'PLR5501',
61 | 'PLR2004',
62 | 'PT011',
63 | 'PTH',
64 | 'RET505',
65 | 'S',
66 | 'SLF001',
67 | 'TD',
68 | 'TRY004'
69 | ]
70 |
71 | # Allow autofix for all enabled rules (when `--fix`) is provided.
72 | lint.fixable = ["ALL"]
73 |
74 | # Exclude a variety of commonly ignored directories.
75 | exclude = [
76 | "tests",
77 | ".git",
78 | ".git-rewrite",
79 | ".mypy_cache",
80 | ".ruff_cache",
81 | "venv",
82 | ".ipynb",
83 | "venv",
84 | ]
85 | line-length = 80
86 |
87 | [[tool.mypy.overrides]]
88 | module = [
89 | "pandas",
90 | "dateutil.*",
91 | ]
92 | ignore_missing_imports = true
93 |
--------------------------------------------------------------------------------
/tests/test_date_range.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from datetime import date
4 |
5 | import polars as pl
6 | import pytest
7 | from polars.testing import assert_series_equal
8 |
9 | import polars_xdt as xdt
10 |
11 |
12 | def test_eager() -> None:
13 | result = xdt.date_range(date(2023, 1, 1), date(2023, 1, 10), eager=True)
14 | expected = pl.Series(
15 | "literal",
16 | [
17 | date(2023, 1, 2),
18 | date(2023, 1, 3),
19 | date(2023, 1, 4),
20 | date(2023, 1, 5),
21 | date(2023, 1, 6),
22 | date(2023, 1, 9),
23 | date(2023, 1, 10),
24 | ],
25 | )
26 | assert_series_equal(result, expected)
27 |
28 |
29 | def test_expr() -> None:
30 | expected = pl.Series(
31 | "literal",
32 | [
33 | date(2023, 1, 2),
34 | date(2023, 1, 3),
35 | date(2023, 1, 4),
36 | date(2023, 1, 5),
37 | date(2023, 1, 6),
38 | date(2023, 1, 9),
39 | date(2023, 1, 10),
40 | ],
41 | )
42 | result = pl.select(
43 | xdt.date_range(date(2023, 1, 1), date(2023, 1, 10), eager=True)
44 | )["literal"]
45 | assert_series_equal(result, expected)
46 |
47 |
48 | def test_invalid() -> None:
49 | with pytest.raises(ValueError):
50 | xdt.date_range(date(2023, 1, 1), date(2023, 1, 10), "1bd1h")
51 |
52 |
53 | def test_eager_custom_weekend() -> None:
54 | result = xdt.date_range(
55 | date(2023, 1, 1), date(2023, 1, 10), eager=True, weekend=["Fri", "Sat"]
56 | )
57 | expected = pl.Series(
58 | "literal",
59 | [
60 | date(2023, 1, 1),
61 | date(2023, 1, 2),
62 | date(2023, 1, 3),
63 | date(2023, 1, 4),
64 | date(2023, 1, 5),
65 | date(2023, 1, 8),
66 | date(2023, 1, 9),
67 | date(2023, 1, 10),
68 | ],
69 | )
70 | assert_series_equal(result, expected)
71 |
72 |
73 | def test_eager_custom_holiday() -> None:
74 | result = xdt.date_range(
75 | date(2023, 1, 1),
76 | date(2023, 1, 10),
77 | eager=True,
78 | weekend=["Fri", "Sat"],
79 | holidays=[date(2023, 1, 2)],
80 | )
81 | expected = pl.Series(
82 | "literal",
83 | [
84 | date(2023, 1, 1),
85 | date(2023, 1, 3),
86 | date(2023, 1, 4),
87 | date(2023, 1, 5),
88 | date(2023, 1, 8),
89 | date(2023, 1, 9),
90 | date(2023, 1, 10),
91 | ],
92 | )
93 | assert_series_equal(result, expected)
94 |
--------------------------------------------------------------------------------
/tests/test_is_busday.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import datetime as dt
4 |
5 | import hypothesis.strategies as st
6 | import numpy as np
7 | import polars as pl
8 | from hypothesis import given
9 |
10 | import polars_xdt as xdt
11 |
12 | mapping = {"Mon": 1, "Tue": 2, "Wed": 3, "Thu": 4, "Fri": 5, "Sat": 6, "Sun": 7}
13 | reverse_mapping = {value: key for key, value in mapping.items()}
14 |
15 |
16 | def get_result(
17 | date: dt.date,
18 | weekend: list[str],
19 | holidays: list[dt.date],
20 | ) -> int:
21 | return ( # type: ignore[no-any-return]
22 | pl.DataFrame({"date": [date]})
23 | .select(xdt.is_workday("date", weekend=weekend, holidays=holidays))[
24 | "date"
25 | ]
26 | .item()
27 | )
28 |
29 |
30 | @given(
31 | date=st.dates(
32 | min_value=dt.date(2000, 1, 1), max_value=dt.date(2000, 12, 31)
33 | ),
34 | weekend=st.lists(
35 | st.sampled_from(["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]),
36 | min_size=0,
37 | max_size=6,
38 | unique=True,
39 | ),
40 | holidays=st.lists(
41 | st.dates(
42 | min_value=dt.date(2000, 1, 1), max_value=dt.date(2000, 12, 31)
43 | ),
44 | min_size=1,
45 | max_size=300,
46 | ),
47 | )
48 | def test_against_np_is_busday(
49 | date: dt.date,
50 | weekend: list[str],
51 | holidays: list[dt.date],
52 | ) -> None:
53 | result = get_result(date, weekend=weekend, holidays=holidays)
54 | weekmask = [0 if reverse_mapping[i] in weekend else 1 for i in range(1, 8)]
55 | expected = np.is_busday(date, weekmask=weekmask, holidays=holidays)
56 | assert result == expected
57 |
58 |
59 | @given(
60 | datetime=st.datetimes(
61 | min_value=dt.datetime(2000, 1, 1), max_value=dt.datetime(2000, 12, 31)
62 | ),
63 | weekend=st.lists(
64 | st.sampled_from(["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]),
65 | min_size=0,
66 | max_size=6,
67 | unique=True,
68 | ),
69 | holidays=st.lists(
70 | st.dates(
71 | min_value=dt.date(2000, 1, 1), max_value=dt.date(2000, 12, 31)
72 | ),
73 | min_size=1,
74 | max_size=300,
75 | ),
76 | )
77 | def test_against_np_is_busday_datetime(
78 | datetime: dt.datetime,
79 | weekend: list[str],
80 | holidays: list[dt.date],
81 | ) -> None:
82 | result = get_result(datetime, weekend=weekend, holidays=holidays)
83 | weekmask = [0 if reverse_mapping[i] in weekend else 1 for i in range(1, 8)]
84 | date = dt.date(datetime.year, datetime.month, datetime.day)
85 | expected = np.is_busday(date, weekmask=weekmask, holidays=holidays)
86 | assert result == expected
87 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # polars-xdt
2 |
3 | ## eXtra stuff for DateTimes
4 |
5 |
6 |
10 |
11 |
12 | [](https://badge.fury.io/py/polars-xdt)
13 | [](https://marcogorelli.github.io/polars-xdt-docs/)
14 |
15 | eXtra stuff for DateTimes in [Polars](https://www.pola.rs/).
16 |
17 | - ✅ blazingly fast, written in Rust
18 | - ✅ convert to and from multiple time zones
19 | - ✅ format datetime in different locales
20 | - ✅ convert to Julian Dates
21 | - ✅ ~time-based EWMA~ (upstreamed to Polars itself)
22 | - ✅ ~custom business-day arithmetic~ (upstreamed to Polars itself)
23 |
24 | Installation
25 | ------------
26 |
27 | First, you need to [install Polars](https://pola-rs.github.io/polars/user-guide/installation/).
28 |
29 | Then, you'll need to install `polars-xdt`:
30 | ```console
31 | pip install polars-xdt
32 | ```
33 |
34 | Read the [documentation](https://marcogorelli.github.io/polars-xdt-docs/) for a more examples and functionality.
35 |
36 | Basic Example
37 | -------------
38 | Say we start with
39 | ```python
40 | from datetime import datetime
41 |
42 | import polars as pl
43 | import polars_xdt as xdt
44 |
45 | df = pl.DataFrame(
46 | {
47 | "local_dt": [
48 | datetime(2020, 10, 10, 1),
49 | datetime(2020, 10, 10, 2),
50 | datetime(2020, 10, 9, 20),
51 | ],
52 | "timezone": [
53 | "Europe/London",
54 | "Africa/Kigali",
55 | "America/New_York",
56 | ],
57 | }
58 | )
59 | ```
60 |
61 | Let's localize each datetime to the given timezone and convert to
62 | UTC, all in one step:
63 |
64 | ```python
65 | result = df.with_columns(
66 | xdt.from_local_datetime(
67 | "local_dt", pl.col("timezone"), "UTC"
68 | ).alias("date")
69 | )
70 | print(result)
71 | ```
72 | ```
73 | shape: (3, 3)
74 | ┌─────────────────────┬──────────────────┬─────────────────────────┐
75 | │ local_dt ┆ timezone ┆ date │
76 | │ --- ┆ --- ┆ --- │
77 | │ datetime[μs] ┆ str ┆ datetime[μs, UTC] │
78 | ╞═════════════════════╪══════════════════╪═════════════════════════╡
79 | │ 2020-10-10 01:00:00 ┆ Europe/London ┆ 2020-10-10 00:00:00 UTC │
80 | │ 2020-10-10 02:00:00 ┆ Africa/Kigali ┆ 2020-10-10 00:00:00 UTC │
81 | │ 2020-10-09 20:00:00 ┆ America/New_York ┆ 2020-10-10 00:00:00 UTC │
82 | └─────────────────────┴──────────────────┴─────────────────────────┘
83 | ```
84 |
85 | Read the [documentation](https://marcogorelli.github.io/polars-xdt-docs/) for more examples!
86 |
87 | Logo
88 | ----
89 |
90 | Thanks to [Olha Urdeichuk](https://www.fiverr.com/olhaurdeichuk) for the illustration.
91 |
--------------------------------------------------------------------------------
/tests/test_format_localized.py:
--------------------------------------------------------------------------------
1 | from datetime import date, datetime
2 | from typing import Any
3 |
4 | import polars as pl
5 | import pytest
6 |
7 | import polars_xdt as xdt
8 |
9 |
10 | @pytest.mark.parametrize(
11 | ("time_unit", "expected_us", "expected_ukr"),
12 | [
13 | (
14 | "ms",
15 | "Wednesday, 01 January 2020 00:00:00.123",
16 | "середа, 01 січня 2020 00:00:00,123",
17 | ),
18 | (
19 | "us",
20 | "Wednesday, 01 January 2020 00:00:00.123456",
21 | "середа, 01 січня 2020 00:00:00,123456",
22 | ),
23 | (
24 | "ns",
25 | "Wednesday, 01 January 2020 00:00:00.123456789",
26 | "середа, 01 січня 2020 00:00:00,123456789",
27 | ),
28 | ],
29 | )
30 | def test_format_localized_datetime(
31 | time_unit: Any, expected_us: str, expected_ukr: str
32 | ) -> None:
33 | df = pl.DataFrame(
34 | {
35 | "date_col": ["2020-01-01T00:00:00.123456789"],
36 | },
37 | ).select(pl.col("date_col").str.to_datetime(time_unit=time_unit))
38 | result = df.select(
39 | result=xdt.format_localized(
40 | "date_col", "%A, %d %B %Y %H:%M:%S%.f", "en_US"
41 | )
42 | )["result"]
43 | assert result[0] == expected_us
44 | result = df.select(
45 | result=xdt.format_localized(
46 | "date_col", "%A, %d %B %Y %H:%M:%S%.f", "uk_UA"
47 | )
48 | )["result"]
49 | assert result[0] == expected_ukr
50 |
51 |
52 | def test_format_localized_date() -> None:
53 | df = pl.DataFrame(
54 | {
55 | "date_col": [date(2024, 8, 24), date(2024, 10, 1)],
56 | },
57 | )
58 | result = df.select(
59 | result=xdt.format_localized("date_col", "%A, %d %B %Y", "en_US")
60 | )["result"]
61 | assert result[0] == "Saturday, 24 August 2024"
62 | assert result[1] == "Tuesday, 01 October 2024"
63 | result = df.select(
64 | result=xdt.format_localized("date_col", "%A, %d %B %Y", "uk_UA")
65 | )["result"]
66 | assert result[0] == "субота, 24 серпня 2024"
67 | assert result[1] == "вівторок, 01 жовтня 2024"
68 |
69 |
70 | def test_tz_aware() -> None:
71 | df = pl.DataFrame(
72 | {
73 | "date_col": [datetime(2024, 8, 24), datetime(2024, 10, 1)],
74 | },
75 | schema={"date_col": pl.Datetime("ns", "Europe/London")},
76 | )
77 | result = df.select(
78 | result=xdt.format_localized("date_col", "%A, %d %B %Y %z", "uk_UA")
79 | )
80 | assert result["result"][0] == "субота, 24 серпня 2024 +0100"
81 | assert result["result"][1] == "вівторок, 01 жовтня 2024 +0100"
82 |
83 |
84 | @pytest.mark.parametrize("time_unit", ["ms", "us", "ns"])
85 | def test_pre_epoch(time_unit: Any) -> None:
86 | df = pl.DataFrame(
87 | {
88 | "date_col": [datetime(1960, 1, 1, 0, 0, 0, 1)],
89 | },
90 | schema={"date_col": pl.Datetime(time_unit, "Europe/London")},
91 | )
92 | result = df.select(
93 | result=xdt.format_localized("date_col", "%A, %d %B %Y %z", "en_US")
94 | )
95 | assert result["result"][0] == "Friday, 01 January 1960 +0000"
96 |
--------------------------------------------------------------------------------
/src/format_localized.rs:
--------------------------------------------------------------------------------
1 | use chrono::format::StrftimeItems;
2 | use chrono::TimeZone;
3 | use chrono::{self, format::DelayedFormat};
4 | use polars::prelude::*;
5 | use polars_arrow::array::MutablePlString;
6 | use polars_arrow::temporal_conversions::MILLISECONDS_IN_DAY;
7 | use polars_arrow::temporal_conversions::{
8 | timestamp_ms_to_datetime, timestamp_ns_to_datetime, timestamp_us_to_datetime,
9 | };
10 | use std::fmt::Write;
11 | use std::str::FromStr;
12 |
13 | fn format_ndt(
14 | ndt: chrono::NaiveDateTime,
15 | format: &str,
16 | locale: chrono::prelude::Locale,
17 | tz: chrono_tz::Tz,
18 | ) -> DelayedFormat> {
19 | let dt = tz.from_utc_datetime(&ndt);
20 | dt.format_localized(format, locale)
21 | }
22 |
23 | pub(crate) fn impl_format_localized(
24 | s: &Series,
25 | format: &str,
26 | locale: &str,
27 | ) -> PolarsResult {
28 | let locale = chrono::Locale::try_from(locale).map_err(
29 | |_| polars_err!(ComputeError: format!("given locale {} could not be parsed", locale)),
30 | )?;
31 |
32 | let ca: StringChunked = match s.dtype() {
33 | DataType::Date => {
34 | let ca = s.date()?;
35 | ca.phys.apply_kernel_cast(&|arr| {
36 | let mut buf = String::new();
37 | let mut mutarr = MutablePlString::with_capacity(arr.len());
38 |
39 | for opt in arr.into_iter() {
40 | match opt {
41 | None => mutarr.push_null(),
42 | Some(timestamp) => {
43 | buf.clear();
44 | let ndt =
45 | timestamp_ms_to_datetime((*timestamp as i64) * MILLISECONDS_IN_DAY);
46 | let fmted = format_ndt(ndt, format, locale, chrono_tz::UTC);
47 | write!(buf, "{fmted}").unwrap();
48 | mutarr.push(Some(&buf))
49 | }
50 | }
51 | }
52 |
53 | mutarr.freeze().boxed()
54 | })
55 | }
56 | DataType::Datetime(time_unit, time_zone) => {
57 | let ca = s.datetime()?;
58 | let timestamp_to_datetime = match time_unit {
59 | TimeUnit::Nanoseconds => timestamp_ns_to_datetime,
60 | TimeUnit::Microseconds => timestamp_us_to_datetime,
61 | TimeUnit::Milliseconds => timestamp_ms_to_datetime,
62 | };
63 | let tz = match time_zone {
64 | None => chrono_tz::UTC,
65 | Some(tz) => chrono_tz::Tz::from_str(tz).unwrap(),
66 | };
67 | ca.phys.apply_kernel_cast(&|arr| {
68 | let mut buf = String::new();
69 | let mut mutarr = MutablePlString::with_capacity(arr.len());
70 |
71 | for opt in arr.into_iter() {
72 | match opt {
73 | None => mutarr.push_null(),
74 | Some(timestamp) => {
75 | buf.clear();
76 | let ndt = timestamp_to_datetime(*timestamp);
77 | let fmted = format_ndt(ndt, format, locale, tz);
78 | write!(buf, "{fmted}").unwrap();
79 | mutarr.push(Some(&buf))
80 | }
81 | }
82 | }
83 |
84 | mutarr.freeze().boxed()
85 | })
86 | }
87 | _ => unreachable!(),
88 | };
89 | Ok(ca.into_series())
90 | }
91 |
--------------------------------------------------------------------------------
/src/to_julian.rs:
--------------------------------------------------------------------------------
1 | use chrono::{Datelike, Timelike};
2 | use polars::prelude::*;
3 | use polars_arrow::legacy::utils::CustomIterTools;
4 | use polars_arrow::temporal_conversions::{
5 | timestamp_ms_to_datetime, timestamp_ns_to_datetime, timestamp_us_to_datetime,
6 | };
7 | use polars_arrow::{array::Float64Array, temporal_conversions::MILLISECONDS_IN_DAY};
8 |
9 | fn to_julian_date(
10 | mut year: i32,
11 | mut month: u32,
12 | day: u32,
13 | hour: u32,
14 | minute: u32,
15 | second: u32,
16 | nanosecond: u32,
17 | ) -> f64 {
18 | if month < 3 {
19 | year -= 1;
20 | month += 12;
21 | }
22 | day as f64 + (((153 * month - 457) / 5) as i64) as f64 + (365 * year) as f64 + (year / 4) as f64
23 | - (year / 100) as f64
24 | + (year / 400) as f64
25 | + 1_721_118.5
26 | + (hour as f64
27 | + minute as f64 / 60.
28 | + second as f64 / 3600.
29 | + nanosecond as f64 / 3600. / (10_i32.pow(9) as f64))
30 | / 24.
31 | }
32 |
33 | pub(crate) fn impl_to_julian_date(s: &Series) -> PolarsResult {
34 | match s.dtype() {
35 | DataType::Date => {
36 | let ca = s.date()?;
37 | let chunks = ca.phys.downcast_iter().map(|arr| -> Float64Array {
38 | arr.into_iter()
39 | .map(|timestamp_opt| {
40 | timestamp_opt.map(|timestamp| {
41 | let ndt =
42 | timestamp_ms_to_datetime((*timestamp as i64) * MILLISECONDS_IN_DAY);
43 | to_julian_date(ndt.year(), ndt.month(), ndt.day(), 0, 0, 0, 0)
44 | })
45 | })
46 | .collect_trusted()
47 | });
48 | Ok(Float64Chunked::from_chunk_iter(PlSmallStr::EMPTY, chunks).into_series())
49 | }
50 | DataType::Datetime(time_unit, time_zone) => {
51 | if !(time_zone.is_none() || time_zone.as_deref() == Some(&PlSmallStr::from("UTC"))) {
52 | polars_bail!(InvalidOperation: "polars_xdt to_julian currently only works on UTC or naive Datetime type. \
53 | For now, please cast to UTC Datetime first.")
54 | };
55 | let timestamp_to_datetime = match time_unit {
56 | TimeUnit::Nanoseconds => timestamp_ns_to_datetime,
57 | TimeUnit::Microseconds => timestamp_us_to_datetime,
58 | TimeUnit::Milliseconds => timestamp_ms_to_datetime,
59 | };
60 | let ca = &polars_ops::prelude::replace_time_zone(
61 | s.datetime()?,
62 | None,
63 | &StringChunked::from_iter(std::iter::once("raise")),
64 | NonExistent::Raise,
65 | )?;
66 | let chunks = ca.phys.downcast_iter().map(|arr| -> Float64Array {
67 | arr.into_iter()
68 | .map(|timestamp_opt| {
69 | timestamp_opt.map(|timestamp| {
70 | let ndt = timestamp_to_datetime(*timestamp);
71 | to_julian_date(
72 | ndt.year(),
73 | ndt.month(),
74 | ndt.day(),
75 | ndt.hour(),
76 | ndt.minute(),
77 | ndt.second(),
78 | ndt.nanosecond(),
79 | )
80 | })
81 | })
82 | .collect_trusted()
83 | });
84 | Ok(Float64Chunked::from_chunk_iter(PlSmallStr::EMPTY, chunks).into_series())
85 | }
86 | _ => {
87 | polars_bail!(InvalidOperation: "polars_xdt to_julian currently only works on Date type. \
88 | For now, please cast to Date first.")
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/expressions.rs:
--------------------------------------------------------------------------------
1 | #![allow(clippy::unit_arg, clippy::unused_unit)]
2 | use crate::arg_previous_greater::*;
3 | use crate::format_localized::*;
4 | use crate::month_delta::*;
5 | use crate::timezone::*;
6 | use crate::to_julian::*;
7 | use polars::prelude::*;
8 | use pyo3_polars::derive::polars_expr;
9 | use pyo3_polars::export::polars_core::datatypes::TimeZone as PolarsTimeZone;
10 | use serde::Deserialize;
11 |
12 | #[derive(Deserialize)]
13 | pub struct FromLocalDatetimeKwargs {
14 | to_tz: String,
15 | ambiguous: String,
16 | }
17 | #[derive(Deserialize)]
18 | pub struct FormatLocalizedKwargs {
19 | format: String,
20 | locale: String,
21 | }
22 |
23 | pub fn to_local_datetime_output(input_fields: &[Field]) -> PolarsResult {
24 | let field = input_fields[0].clone();
25 | let dtype = match field.dtype {
26 | DataType::Datetime(unit, _) => DataType::Datetime(unit, None),
27 | _ => polars_bail!(InvalidOperation:
28 | "dtype '{}' not supported", field.dtype
29 | ),
30 | };
31 | Ok(Field::new(field.name, dtype))
32 | }
33 |
34 | pub fn from_local_datetime_output(
35 | input_fields: &[Field],
36 | kwargs: FromLocalDatetimeKwargs,
37 | ) -> PolarsResult {
38 | let field = input_fields[0].clone();
39 | let dtype = match field.dtype {
40 | DataType::Datetime(unit, _) => {
41 | DataType::Datetime(unit, PolarsTimeZone::opt_try_new(Some(&kwargs.to_tz))?)
42 | }
43 | _ => polars_bail!(InvalidOperation:
44 | "dtype '{}' not supported", field.dtype
45 | ),
46 | };
47 | Ok(Field::new(field.name, dtype))
48 | }
49 |
50 | #[polars_expr(output_type=Int32)]
51 | fn month_delta(inputs: &[Series]) -> PolarsResult {
52 | let start_dates = &inputs[0];
53 | let end_dates = &inputs[1];
54 | impl_month_delta(start_dates, end_dates)
55 | }
56 |
57 | #[polars_expr(output_type_func=to_local_datetime_output)]
58 | fn to_local_datetime(inputs: &[Series]) -> PolarsResult {
59 | let s1 = &inputs[0];
60 | let ca = s1.datetime()?;
61 | let s2 = &inputs[1].str()?;
62 | Ok(elementwise_to_local_datetime(ca, s2)?.into_series())
63 | }
64 |
65 | #[polars_expr(output_type_func_with_kwargs=from_local_datetime_output)]
66 | fn from_local_datetime(inputs: &[Series], kwargs: FromLocalDatetimeKwargs) -> PolarsResult {
67 | let s1 = &inputs[0];
68 | let ca = s1.datetime().unwrap();
69 | let s2 = &inputs[1].str().unwrap();
70 | Ok(elementwise_from_local_datetime(ca, s2, &kwargs.to_tz, &kwargs.ambiguous)?.into_series())
71 | }
72 |
73 | #[polars_expr(output_type=String)]
74 | fn format_localized(inputs: &[Series], kwargs: FormatLocalizedKwargs) -> PolarsResult {
75 | let s = &inputs[0];
76 | let locale = kwargs.locale;
77 | let format = kwargs.format;
78 | impl_format_localized(s, &format, &locale)
79 | }
80 |
81 | #[polars_expr(output_type=Float64)]
82 | fn to_julian_date(inputs: &[Series]) -> PolarsResult {
83 | let s = &inputs[0];
84 | impl_to_julian_date(s)
85 | }
86 |
87 | fn idx_dtype(input_fields: &[Field]) -> PolarsResult {
88 | let field = Field::new(
89 | input_fields[0].name.clone(),
90 | IDX_DTYPE
91 | );
92 | Ok(field.clone())
93 | }
94 |
95 | #[polars_expr(output_type_func=idx_dtype)]
96 | fn arg_previous_greater(inputs: &[Series]) -> PolarsResult {
97 | let ser = &inputs[0];
98 | match ser.dtype() {
99 | DataType::Int64 => Ok(impl_arg_previous_greater(ser.i64().unwrap()).into_series()),
100 | DataType::Int32 => Ok(impl_arg_previous_greater(ser.i32().unwrap()).into_series()),
101 | DataType::UInt64 => Ok(impl_arg_previous_greater(ser.u64().unwrap()).into_series()),
102 | DataType::UInt32 => Ok(impl_arg_previous_greater(ser.u32().unwrap()).into_series()),
103 | DataType::Float64 => Ok(impl_arg_previous_greater(ser.f64().unwrap()).into_series()),
104 | DataType::Float32 => Ok(impl_arg_previous_greater(ser.f32().unwrap()).into_series()),
105 | dt => polars_bail!(ComputeError:"Expected numeric data type, got: {}", dt),
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/tests/test_timezone.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from datetime import datetime, timezone
4 |
5 | import polars as pl
6 | import pytest
7 | from polars.testing import (
8 | assert_frame_equal,
9 | )
10 |
11 | import polars_xdt as xdt
12 |
13 |
14 | @pytest.mark.parametrize(
15 | ("date", "timezone", "local_date"),
16 | [
17 | (
18 | datetime(2020, 10, 10, tzinfo=timezone.utc),
19 | "Europe/London",
20 | datetime(2020, 10, 10, 1, 0),
21 | ),
22 | (
23 | datetime(2020, 10, 15, tzinfo=timezone.utc),
24 | "Africa/Kigali",
25 | datetime(2020, 10, 15, 2, 0),
26 | ),
27 | (
28 | datetime(2020, 10, 15, tzinfo=timezone.utc),
29 | "America/New_York",
30 | datetime(2020, 10, 14, 20, 0),
31 | ),
32 | ],
33 | )
34 | def test_convert_tz_to_local_datetime(
35 | date: datetime, timezone: str, local_date: datetime
36 | ) -> None:
37 | df = pl.DataFrame({"date": [date], "timezone": [timezone]}).with_columns(
38 | pl.col("date").dt.convert_time_zone("Europe/London")
39 | )
40 |
41 | expected = df.with_columns(pl.lit(local_date).alias("local_dt"))
42 |
43 | result = df.lazy().with_columns(
44 | xdt.to_local_datetime("date", pl.col("timezone")).alias("local_dt")
45 | )
46 | assert result.collect_schema() == expected.schema
47 | assert_frame_equal(result.collect(), expected)
48 |
49 |
50 | @pytest.mark.parametrize(
51 | ("local_date", "timezone", "date"),
52 | [
53 | (
54 | datetime(2020, 10, 10, 1, 0),
55 | "Europe/London",
56 | datetime(2020, 10, 10, tzinfo=timezone.utc),
57 | ),
58 | (
59 | datetime(2020, 10, 15, 2, 0),
60 | "Africa/Kigali",
61 | datetime(2020, 10, 15, tzinfo=timezone.utc),
62 | ),
63 | (
64 | datetime(2020, 10, 14, 20, 0),
65 | "America/New_York",
66 | datetime(2020, 10, 15, tzinfo=timezone.utc),
67 | ),
68 | ],
69 | )
70 | def test_convert_tz_from_local_datetime(
71 | local_date: datetime, timezone: str, date: datetime
72 | ) -> None:
73 | df = pl.DataFrame({"local_date": [local_date], "timezone": [timezone]})
74 |
75 | expected = df.with_columns(
76 | pl.lit(date).alias("date").dt.convert_time_zone("Europe/London")
77 | )
78 |
79 | result = df.lazy().with_columns(
80 | xdt.from_local_datetime(
81 | "local_date", pl.col("timezone"), "Europe/London"
82 | ).alias("date")
83 | )
84 | assert result.collect_schema() == expected.schema
85 | assert_frame_equal(result.collect(), expected)
86 |
87 |
88 | def test_convert_tz_from_local_datetime_literal() -> None:
89 | df = pl.DataFrame({"local_date": [datetime(2020, 10, 14, 20, 0)]})
90 |
91 | expected = df.with_columns(
92 | pl.lit(datetime(2020, 10, 15, tzinfo=timezone.utc))
93 | .alias("date")
94 | .dt.convert_time_zone("Europe/London")
95 | )
96 |
97 | result = df.with_columns(
98 | xdt.from_local_datetime(
99 | "local_date", "America/New_York", "Europe/London"
100 | ).alias("date")
101 | )
102 | assert_frame_equal(result, expected)
103 |
104 |
105 | def test_convert_tz_to_local_datetime_literal() -> None:
106 | df = pl.DataFrame(
107 | {"date": [datetime(2020, 10, 15, tzinfo=timezone.utc)]}
108 | ).with_columns(pl.col("date").dt.convert_time_zone("Europe/London"))
109 |
110 | expected = df.with_columns(
111 | pl.lit(datetime(2020, 10, 14, 20, 0)).alias("local_dt")
112 | )
113 |
114 | result = df.with_columns(
115 | xdt.to_local_datetime("date", "America/New_York").alias("local_dt")
116 | )
117 |
118 | assert_frame_equal(result, expected)
119 |
120 |
121 | def test_convert_tz_to_local_datetime_schema() -> None:
122 | df = pl.LazyFrame({"date": [datetime(2020, 10, 15, tzinfo=timezone.utc)]})
123 | result = df.with_columns(
124 | xdt.from_local_datetime("date", "America/New_York", "Asia/Kathmandu")
125 | )
126 | assert result.collect_schema()["date"] == pl.Datetime(
127 | "us", "Asia/Kathmandu"
128 | )
129 | assert result.collect().schema["date"] == pl.Datetime(
130 | "us", "Asia/Kathmandu"
131 | )
132 |
--------------------------------------------------------------------------------
/tests/test_month_delta.py:
--------------------------------------------------------------------------------
1 | from datetime import date
2 |
3 | import polars as pl
4 | from dateutil.relativedelta import relativedelta
5 | from hypothesis import example, given, settings
6 | from hypothesis import strategies as st
7 | from polars.testing import assert_frame_equal
8 |
9 | import polars_xdt as xdt
10 |
11 |
12 | @given(
13 | start_date=st.dates(
14 | min_value=date(1924, 1, 1), max_value=date(2024, 12, 31)
15 | ),
16 | end_date=st.dates(min_value=date(1960, 1, 1), max_value=date(2024, 12, 31)),
17 | )
18 | @example(start_date=date(2022, 2, 28), end_date=date(2024, 2, 29)) # Leap year
19 | @example(start_date=date(2024, 1, 1), end_date=date(2024, 1, 31)) # Same month
20 | @example(start_date=date(1973, 1, 1), end_date=date(1973, 1, 1)) # Same date
21 | @example(start_date=date(2019, 12, 31), end_date=date(2020, 1, 1)) # Border
22 | @example(start_date=date(2018, 12, 1), end_date=date(2020, 1, 1)) # End of year
23 | @example(start_date=date(2022, 12, 1), end_date=date(2020, 1, 1)) # Negative
24 | @example(start_date=date(2000, 3, 29), end_date=date(2003, 1, 28))
25 | @settings(max_examples=500)
26 | def test_month_delta_hypothesis(start_date: date, end_date: date) -> None:
27 | df = pl.DataFrame(
28 | {
29 | "start_date": [start_date],
30 | "end_date": [end_date],
31 | }
32 | )
33 | result = df.select(result=xdt.month_delta("start_date", "end_date"))[
34 | "result"
35 | ].item()
36 |
37 | expected = 0
38 | if start_date <= end_date:
39 | while start_date + relativedelta(months=expected + 1) <= end_date:
40 | expected += 1
41 | else:
42 | while start_date + relativedelta(months=expected - 1) >= end_date:
43 | expected -= 1
44 | assert result == expected
45 |
46 |
47 | def test_month_delta_broadcasting() -> None:
48 | df = pl.DataFrame(
49 | {
50 | "start_date": [
51 | date(2024, 3, 1),
52 | date(2024, 3, 31),
53 | date(2022, 2, 28),
54 | date(2023, 1, 31),
55 | date(2019, 12, 31),
56 | ],
57 | },
58 | )
59 | result = df.with_columns(
60 | xdt.month_delta("start_date", date(2023, 2, 28)).alias("month_delta")
61 | )
62 | expected = pl.DataFrame(
63 | {
64 | "start_date": [
65 | date(2024, 3, 1),
66 | date(2024, 3, 31),
67 | date(2022, 2, 28),
68 | date(2023, 1, 31),
69 | date(2019, 12, 31),
70 | ],
71 | "month_delta": [-12, -13, 12, 1, 38],
72 | },
73 | schema_overrides={"month_delta": pl.Int32},
74 | )
75 | assert_frame_equal(result, expected)
76 |
77 |
78 | def test_month_delta_broadcasting_all_nulls() -> None:
79 | df = pl.DataFrame(
80 | {
81 | "start_date": [
82 | date(2024, 3, 1),
83 | date(2024, 3, 31),
84 | date(2022, 2, 28),
85 | date(2023, 1, 31),
86 | date(2019, 12, 31),
87 | ],
88 | },
89 | )
90 | result = df.with_columns(
91 | xdt.month_delta("start_date", pl.Series([None], dtype=pl.Date)).alias(
92 | "month_delta"
93 | )
94 | )
95 | expected = pl.DataFrame(
96 | {
97 | "start_date": [
98 | date(2024, 3, 1),
99 | date(2024, 3, 31),
100 | date(2022, 2, 28),
101 | date(2023, 1, 31),
102 | date(2019, 12, 31),
103 | ],
104 | "month_delta": [None, None, None, None, None],
105 | },
106 | schema_overrides={"month_delta": pl.Int32},
107 | )
108 | assert_frame_equal(result, expected)
109 |
110 |
111 | def test_month_delta_nulls() -> None:
112 | df = pl.DataFrame(
113 | {
114 | "start_date": [
115 | date(2024, 3, 1),
116 | None,
117 | None,
118 | date(2023, 1, 31),
119 | date(2019, 12, 31),
120 | ],
121 | "end_date": [
122 | None,
123 | date(2024, 3, 31),
124 | None,
125 | date(2023, 1, 31),
126 | date(2019, 12, 31),
127 | ],
128 | },
129 | )
130 | result = df.with_columns(
131 | xdt.month_delta("start_date", "end_date").alias("month_delta")
132 | )["month_delta"].to_list()
133 | expected = [None, None, None, 0, 0]
134 | assert result == expected
135 |
--------------------------------------------------------------------------------
/polars_xdt/ranges.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import re
4 | from typing import TYPE_CHECKING, Literal, Union, overload
5 |
6 | import polars as pl
7 |
8 | mapping = {"Mon": 1, "Tue": 2, "Wed": 3, "Thu": 4, "Fri": 5, "Sat": 6, "Sun": 7}
9 |
10 | if TYPE_CHECKING:
11 | import sys
12 | from collections.abc import Sequence
13 |
14 | if sys.version_info >= (3, 10):
15 | from typing import TypeAlias
16 | else:
17 | from typing_extensions import TypeAlias
18 | from datetime import date, datetime, timedelta
19 |
20 | ClosedInterval: TypeAlias = Literal[
21 | "left", "right", "both", "none"
22 | ] # ClosedWindow
23 | IntoExprColumn: TypeAlias = Union["pl.Expr", "pl.Series", str]
24 |
25 |
26 | @overload
27 | def date_range(
28 | start: date | datetime | IntoExprColumn,
29 | end: date | datetime | IntoExprColumn,
30 | interval: str | timedelta = "1d",
31 | *,
32 | closed: ClosedInterval = ...,
33 | eager: Literal[False] = ...,
34 | weekend: Sequence[str] = ...,
35 | holidays: Sequence[date] | None = ...,
36 | ) -> pl.Expr: ...
37 |
38 |
39 | @overload
40 | def date_range(
41 | start: date | IntoExprColumn,
42 | end: date | IntoExprColumn,
43 | interval: str | timedelta = "1d",
44 | *,
45 | closed: ClosedInterval = ...,
46 | eager: Literal[True],
47 | weekend: Sequence[str] = ...,
48 | holidays: Sequence[date] | None = ...,
49 | ) -> pl.Series: ...
50 |
51 |
52 | @overload
53 | def date_range(
54 | start: date | IntoExprColumn,
55 | end: date | IntoExprColumn,
56 | interval: str | timedelta = "1d",
57 | *,
58 | closed: ClosedInterval = ...,
59 | eager: bool = ...,
60 | weekend: Sequence[str] = ...,
61 | holidays: Sequence[date] | None = ...,
62 | ) -> pl.Series | pl.Expr: ...
63 |
64 |
65 | def date_range( # noqa: PLR0913
66 | start: date | IntoExprColumn,
67 | end: date | IntoExprColumn,
68 | interval: str | timedelta = "1bd",
69 | *,
70 | closed: ClosedInterval = "both",
71 | eager: bool = False,
72 | weekend: Sequence[str] = ("Sat", "Sun"),
73 | holidays: Sequence[date] | None = None,
74 | ) -> pl.Series | pl.Expr:
75 | """
76 | Create a range of dates with a given interval and filter out weekends and holidays.
77 |
78 | Parameters
79 | ----------
80 | start
81 | Lower bound of the date range.
82 | end
83 | Upper bound of the date range.
84 | interval
85 | Interval of the range periods, specified as a Python ``timedelta`` object
86 | or using the Polars duration string language (see "Notes" section below).
87 |
88 | To create a month-end date series, combine with :meth:`Expr.dt.month_end` (see
89 | "Examples" section below).
90 | closed : {'both', 'left', 'right', 'none'}
91 | Define which sides of the range are closed (inclusive).
92 | eager
93 | Evaluate immediately and return a ``Series``.
94 | If set to ``False`` (default), return an expression instead.
95 | weekend
96 | The days of the week that are considered weekends. Defaults to ("Sat", "Sun").
97 | holidays
98 | The holidays to exclude from the calculation. Defaults to None. This should
99 | be a list of ``datetime.date`` s.
100 |
101 | Returns
102 | -------
103 | Expr or Series
104 | Column of data type :class:`Date`.
105 |
106 | Examples
107 | --------
108 | >>> from datetime import date
109 | >>> import polars as pl
110 | >>> import polars_xdt
111 | >>> pl.DataFrame(
112 | ... {
113 | ... "date": polars_xdt.date_range(
114 | ... date(2023, 1, 1), date(2023, 1, 10), "1bd", eager=True
115 | ... ),
116 | ... }
117 | ... )
118 | shape: (7, 1)
119 | ┌────────────┐
120 | │ date │
121 | │ --- │
122 | │ date │
123 | ╞════════════╡
124 | │ 2023-01-02 │
125 | │ 2023-01-03 │
126 | │ 2023-01-04 │
127 | │ 2023-01-05 │
128 | │ 2023-01-06 │
129 | │ 2023-01-09 │
130 | │ 2023-01-10 │
131 | └────────────┘
132 |
133 | """
134 | if weekend == ("Sat", "Sun"):
135 | weekend_int = [6, 7]
136 | else:
137 | weekend_int = sorted({mapping[name] for name in weekend})
138 | if holidays is None:
139 | holidays = []
140 |
141 | if not (isinstance(interval, str) and re.match(r"^-?\d+bd$", interval)):
142 | msg = "Only intervals of the form 'nbd' (where n is an integer) are supported."
143 | raise ValueError(msg)
144 | interval = interval.replace("bd", "d")
145 |
146 | expr = pl.date_range(
147 | start,
148 | end,
149 | interval,
150 | closed=closed,
151 | eager=False,
152 | )
153 | expr = expr.filter(~expr.dt.date().is_in(holidays))
154 | expr = expr.filter(~expr.dt.weekday().is_in(weekend_int))
155 | if eager:
156 | df = pl.select(expr)
157 | return df[df.columns[0]]
158 | return expr
159 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | https://www.linkedin.com/in/marcogorelli/.
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/src/month_delta.rs:
--------------------------------------------------------------------------------
1 | use chrono::Datelike;
2 | use chrono::NaiveDate;
3 | use polars::prelude::*;
4 |
5 | const EPOCH_DAYS_FROM_CE: i32 = 719_163;
6 |
7 | // Copied from https://docs.pola.rs/docs/rust/dev/src/polars_time/windows/duration.rs.html#398
8 | // `add_month` is a private function.
9 | fn add_month(ts: NaiveDate, n_months: i64) -> NaiveDate {
10 | // Have to define, because it is hidden
11 | const DAYS_PER_MONTH: [[i64; 12]; 2] = [
12 | //J F M A M J J A S O N D
13 | [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], // non-leap year
14 | [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], // leap year
15 | ];
16 | let months = n_months;
17 |
18 | // Retrieve the current date and increment the values
19 | // based on the number of months
20 |
21 | let mut year = ts.year();
22 | let mut month = ts.month() as i32;
23 | let mut day = ts.day();
24 | year += (months / 12) as i32;
25 | month += (months % 12) as i32;
26 |
27 | // if the month overflowed or underflowed, adjust the year
28 | // accordingly. Because we add the modulo for the months
29 | // the year will only adjust by one
30 | if month > 12 {
31 | year += 1;
32 | month -= 12;
33 | } else if month <= 0 {
34 | year -= 1;
35 | month += 12;
36 | }
37 |
38 | // Adding this not to import copy pasta again
39 | let leap_year = year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
40 | // Normalize the day if we are past the end of the month.
41 | let last_day_of_month = DAYS_PER_MONTH[leap_year as usize][(month - 1) as usize] as u32;
42 |
43 | if day > last_day_of_month {
44 | day = last_day_of_month
45 | }
46 |
47 | NaiveDate::from_ymd_opt(year, month as u32, day).unwrap()
48 | }
49 |
50 | /// Calculates the difference in months between two dates.
51 | ///
52 | /// The difference is expressed as the number of whole months between the two dates.
53 | /// If `right` is before `left`, the return value will be negative.
54 | ///
55 | /// # Arguments
56 | ///
57 | /// * `left`: `NaiveDate` - The start date.
58 | /// * `right`: `NaiveDate` - The end date.
59 | ///
60 | /// # Returns
61 | ///
62 | /// * `i32` - The number of whole months between `left` and `right`.
63 | ///
64 | /// # Examples
65 | ///
66 | /// ```
67 | /// let start_date = NaiveDate::from_ymd(2023, 1, 1);
68 | /// let end_date = NaiveDate::from_ymd(2023, 4, 1);
69 | /// assert_eq!(get_m_diff(start_date, end_date), 3);
70 | /// ```
71 | fn get_m_diff(left: NaiveDate, right: NaiveDate) -> i32 {
72 | let mut n = 0;
73 | if right >= left {
74 | if right.year() + 1 > left.year() {
75 | n = (right.year() - left.year() - 1) * 12;
76 | }
77 | while add_month(left, (n + 1).into()) <= right {
78 | n += 1;
79 | }
80 | } else {
81 | if left.year() + 1 > right.year() {
82 | n = -(left.year() - right.year() - 1) * 12;
83 | }
84 | while add_month(left, (n - 1).into()) >= right {
85 | n -= 1;
86 | }
87 | }
88 | n
89 | }
90 |
91 | /// Implements the month delta operation for Polars series containing dates.
92 | ///
93 | /// This function calculates the difference in months between two series of dates.
94 | /// The operation is pairwise: it computes the month difference for each pair
95 | /// of start and end dates in the input series.
96 | ///
97 | /// # Arguments
98 | ///
99 | /// * `start_dates`: `&Series` - A series of start dates.
100 | /// * `end_dates`: `&Series` - A series of end dates.
101 | ///
102 | /// # Returns
103 | ///
104 | /// * `PolarsResult` - A new series containing the month differences as `i32` values.
105 | ///
106 | /// # Errors
107 | ///
108 | /// Returns an error if the input series are not of the `Date` type.
109 | ///
110 | /// # Examples
111 | ///
112 | /// ```
113 | /// use polars::prelude::*;
114 | /// let date1 = NaiveDate::from_ymd(2023, 1, 1); // January 1, 2023
115 | /// let date2 = NaiveDate::from_ymd(2023, 3, 1); // March 1, 2023
116 | /// let date3 = NaiveDate::from_ymd(2023, 4, 1); // April 1, 2023
117 | /// let date4 = NaiveDate::from_ymd(2023, 6, 1); // June 1, 2023
118 | /// let start_dates = Series::new("start_dates", &[date1, date2]);
119 | /// let end_dates = Series::new("end_dates", &[date3, date4]);
120 | /// let month_deltas = impl_month_delta(&start_dates, &end_dates).unwrap();
121 | /// ```
122 | pub(crate) fn impl_month_delta(start_dates: &Series, end_dates: &Series) -> PolarsResult {
123 | if (start_dates.dtype() != &DataType::Date) || (end_dates.dtype() != &DataType::Date) {
124 | polars_bail!(InvalidOperation: "polars_xdt.month_delta only works on Date type. Please cast to Date first.");
125 | }
126 | let start_dates = start_dates.date()?;
127 | let end_dates = end_dates.date()?;
128 |
129 | let month_diff: Int32Chunked = match end_dates.len() {
130 | 1 => match unsafe { end_dates.phys.get_unchecked(0) } {
131 | Some(end_date_i32) => {
132 | let end_date =
133 | NaiveDate::from_num_days_from_ce_opt(EPOCH_DAYS_FROM_CE + end_date_i32)
134 | .unwrap();
135 | start_dates
136 | .as_date_iter()
137 | .map(|s_arr| s_arr.map(|start_date| get_m_diff(start_date, end_date)))
138 | .collect()
139 | }
140 | _ => Int32Chunked::full_null(PlSmallStr::EMPTY, start_dates.len())
141 | },
142 | _ => start_dates
143 | .as_date_iter()
144 | .zip(end_dates.as_date_iter())
145 | .map(|(s_arr, e_arr)| {
146 | s_arr
147 | .zip(e_arr)
148 | .map(|(start_date, end_date)| get_m_diff(start_date, end_date))
149 | })
150 | .collect(),
151 | };
152 |
153 | Ok(month_diff.into_series())
154 | }
155 |
--------------------------------------------------------------------------------
/.github/workflows/CI.yml:
--------------------------------------------------------------------------------
1 | # This file is based on the autogenerated one by maturin v1.7.8 with:
2 | #
3 | # maturin generate-ci github
4 | #
5 | # Differences are:
6 | # - removed x86, armv7, s390x, ppc64le targets from Linux
7 | # - removed free-threaded wheels
8 | # - removed musllinux
9 | # - have separate linux-just-test and linux-min-versions-just-test jobs
10 | # - add the `RUSTFLAGS: "-Dwarnings"` env variable
11 |
12 | name: CI
13 |
14 | on:
15 | push:
16 | branches:
17 | - main
18 | - master
19 | tags:
20 | - '*'
21 | pull_request:
22 | workflow_dispatch:
23 |
24 | permissions:
25 | contents: read
26 |
27 | # Make sure CI fails on all warnings, including Clippy lints
28 | env:
29 | RUSTFLAGS: "-Dwarnings"
30 |
31 | jobs:
32 | linux-just-test:
33 | runs-on: ubuntu-latest
34 | strategy:
35 | matrix:
36 | target: [x86_64]
37 | python-version: ["3.9", "3.11", "3.13"]
38 | steps:
39 | - uses: actions/checkout@v5
40 | - uses: actions/setup-python@v6
41 | with:
42 | python-version: ${{ matrix.python-version }}
43 |
44 | - name: Set up Rust
45 | run: rustup show
46 | - uses: mozilla-actions/sccache-action@v0.0.6
47 | - run: make venv
48 | - run: make pre-commit
49 | - run: make install
50 | - run: make test
51 |
52 | linux-min-versions-just-test:
53 | runs-on: ubuntu-latest
54 | strategy:
55 | matrix:
56 | target: [x86_64]
57 | python-version: ["3.9"]
58 | steps:
59 | - uses: actions/checkout@v5
60 | - uses: actions/setup-python@v6
61 | with:
62 | python-version: ${{ matrix.python-version }}
63 |
64 | - name: Set up Rust
65 | run: rustup show
66 | - uses: mozilla-actions/sccache-action@v0.0.6
67 | - run: make venv
68 | - run: .venv/bin/python -m pip install polars==1.5.0 # min version
69 | - run: make install
70 | - run: make test
71 |
72 | linux:
73 | runs-on: ${{ matrix.platform.runner }}
74 | strategy:
75 | matrix:
76 | platform:
77 | - runner: ubuntu-22.04
78 | target: x86_64
79 | - runner: ubuntu-22.04
80 | target: aarch64
81 | steps:
82 | - uses: actions/checkout@v5
83 | - uses: actions/setup-python@v6
84 | with:
85 | python-version: 3.x
86 | - name: Build wheels
87 | uses: PyO3/maturin-action@v1
88 | with:
89 | target: ${{ matrix.platform.target }}
90 | args: --release --out dist
91 | sccache: 'true'
92 | manylinux: auto
93 | - name: Upload wheels
94 | uses: actions/upload-artifact@v4
95 | with:
96 | name: wheels-linux-${{ matrix.platform.target }}
97 | path: dist
98 |
99 | windows:
100 | runs-on: ${{ matrix.platform.runner }}
101 | strategy:
102 | matrix:
103 | platform:
104 | - runner: windows-latest
105 | target: x64
106 | steps:
107 | - uses: actions/checkout@v5
108 | - uses: actions/setup-python@v6
109 | with:
110 | python-version: 3.x
111 | architecture: ${{ matrix.platform.target }}
112 | - name: Build wheels
113 | uses: PyO3/maturin-action@v1
114 | with:
115 | target: ${{ matrix.platform.target }}
116 | args: --release --out dist
117 | sccache: 'true'
118 | - name: Upload wheels
119 | uses: actions/upload-artifact@v4
120 | with:
121 | name: wheels-windows-${{ matrix.platform.target }}
122 | path: dist
123 |
124 | macos:
125 | runs-on: ${{ matrix.platform.runner }}
126 | strategy:
127 | matrix:
128 | platform:
129 | - runner: macos-13
130 | target: x86_64
131 | - runner: macos-14
132 | target: aarch64
133 | steps:
134 | - uses: actions/checkout@v5
135 | - uses: actions/setup-python@v6
136 | with:
137 | python-version: 3.x
138 | - name: Build wheels
139 | uses: PyO3/maturin-action@v1
140 | with:
141 | target: ${{ matrix.platform.target }}
142 | args: --release --out dist
143 | sccache: 'true'
144 | - name: Upload wheels
145 | uses: actions/upload-artifact@v4
146 | with:
147 | name: wheels-macos-${{ matrix.platform.target }}
148 | path: dist
149 |
150 | sdist:
151 | runs-on: ubuntu-latest
152 | steps:
153 | - uses: actions/checkout@v5
154 | - name: Build sdist
155 | uses: PyO3/maturin-action@v1
156 | with:
157 | command: sdist
158 | args: --out dist
159 | - name: Upload sdist
160 | uses: actions/upload-artifact@v4
161 | with:
162 | name: wheels-sdist
163 | path: dist
164 |
165 | release:
166 | name: Release
167 | runs-on: ubuntu-latest
168 | if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
169 | needs: [linux, windows, macos, sdist]
170 | environment: pypi
171 | permissions:
172 | # Use to sign the release artifacts
173 | id-token: write
174 | # Used to upload release artifacts
175 | contents: write
176 | # Used to generate artifact attestation
177 | attestations: write
178 | steps:
179 | - uses: actions/download-artifact@v5
180 | - name: Generate artifact attestation
181 | uses: actions/attest-build-provenance@v3
182 | with:
183 | subject-path: 'wheels-*/*'
184 | - name: Publish to PyPI
185 | if: ${{ startsWith(github.ref, 'refs/tags/') }}
186 | uses: PyO3/maturin-action@v1
187 | env:
188 | MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
189 | with:
190 | command: upload
191 | args: --non-interactive --skip-existing wheels-*/*
192 |
193 |
--------------------------------------------------------------------------------
/src/timezone.rs:
--------------------------------------------------------------------------------
1 | use arity::try_binary_elementwise;
2 | use chrono::{LocalResult, NaiveDateTime, TimeZone};
3 | use polars::prelude::*;
4 | use polars_arrow::legacy::time_zone::Tz;
5 | use pyo3_polars::export::polars_core::datatypes::time_zone::parse_time_zone;
6 | use pyo3_polars::export::polars_core::datatypes::TimeZone as PolarsTimeZone;
7 | use pyo3_polars::export::polars_core::utils::arrow::legacy::kernels::Ambiguous;
8 | use pyo3_polars::export::polars_core::utils::arrow::temporal_conversions::{
9 | timestamp_ms_to_datetime, timestamp_ns_to_datetime, timestamp_us_to_datetime,
10 | };
11 | use std::str::FromStr;
12 |
13 | fn naive_utc_to_naive_local_in_new_time_zone(
14 | from_tz: &Tz,
15 | to_tz: &Tz,
16 | ndt: NaiveDateTime,
17 | ) -> NaiveDateTime {
18 | // ndt is the UTC datetime corresponding to the datetime in from_tz timezone
19 | from_tz
20 | .from_utc_datetime(&ndt)
21 | .with_timezone(to_tz)
22 | .naive_local()
23 | }
24 |
25 | fn naive_local_to_naive_utc_in_new_time_zone(
26 | from_tz: &Tz,
27 | to_tz: &Tz,
28 | ndt: NaiveDateTime,
29 | ambiguous: &Ambiguous,
30 | ) -> PolarsResult {
31 | match from_tz.from_local_datetime(&ndt) {
32 | LocalResult::Single(dt) => Ok(dt.with_timezone(to_tz).naive_utc()),
33 | LocalResult::Ambiguous(dt_earliest, dt_latest) => match ambiguous {
34 | Ambiguous::Earliest => Ok(dt_earliest.with_timezone(to_tz).naive_utc()),
35 | Ambiguous::Latest => Ok(dt_latest.with_timezone(to_tz).naive_utc()),
36 | Ambiguous::Raise => {
37 | polars_bail!(ComputeError: "datetime '{}' is ambiguous in time zone '{}'. Please use `ambiguous` to tell how it should be localized.", ndt, to_tz)
38 | }
39 | Ambiguous::Null => {
40 | unimplemented!("Ambiguous::Null is not yet supported");
41 | }
42 | },
43 | LocalResult::None => polars_bail!(ComputeError:
44 | "datetime '{}' is non-existent in time zone '{}'. Non-existent datetimes are not yet supported",
45 | ndt, to_tz
46 | ),
47 | }
48 | }
49 |
50 | pub fn elementwise_to_local_datetime(
51 | datetime: &Logical,
52 | tz: &StringChunked,
53 | ) -> PolarsResult {
54 | let binding = PlSmallStr::from("UTC");
55 | let from_time_zone = datetime.time_zone().as_deref().unwrap_or(&binding);
56 | let from_tz = parse_time_zone(from_time_zone)?;
57 |
58 | let timestamp_to_datetime: fn(i64) -> NaiveDateTime = match datetime.time_unit() {
59 | TimeUnit::Milliseconds => timestamp_ms_to_datetime,
60 | TimeUnit::Microseconds => timestamp_us_to_datetime,
61 | TimeUnit::Nanoseconds => timestamp_ns_to_datetime,
62 | };
63 | let datetime_to_timestamp: fn(NaiveDateTime) -> i64 = match datetime.time_unit() {
64 | TimeUnit::Milliseconds => datetime_to_timestamp_ms,
65 | TimeUnit::Microseconds => datetime_to_timestamp_us,
66 | TimeUnit::Nanoseconds => datetime_to_timestamp_ns,
67 | };
68 | let out: Result, PolarsError> = match tz.len() {
69 | 1 => match unsafe { tz.get_unchecked(0) } {
70 | Some(convert_tz) => {
71 | let to_tz = parse_time_zone(convert_tz)?;
72 | Ok(datetime.phys.apply(|timestamp_opt| {
73 | timestamp_opt.map(|ts| {
74 | let ndt = timestamp_to_datetime(ts);
75 | datetime_to_timestamp(naive_utc_to_naive_local_in_new_time_zone(
76 | &from_tz, &to_tz, ndt,
77 | ))
78 | })
79 | }))
80 | }
81 | _ => Ok(Int64Chunked::full_null(PlSmallStr::EMPTY, datetime.len())),
82 | },
83 | _ => try_binary_elementwise(&datetime.phys, tz, |timestamp_opt, convert_tz_opt| {
84 | match (timestamp_opt, convert_tz_opt) {
85 | (Some(timestamp), Some(convert_tz)) => {
86 | let ndt = timestamp_to_datetime(timestamp);
87 | let to_tz = parse_time_zone(convert_tz)?;
88 | Ok(Some(datetime_to_timestamp(
89 | naive_utc_to_naive_local_in_new_time_zone(&from_tz, &to_tz, ndt),
90 | )))
91 | }
92 | _ => Ok(None),
93 | }
94 | }),
95 | };
96 | let out = out?.into_datetime(datetime.time_unit(), None);
97 | Ok(out)
98 | }
99 |
100 | pub fn elementwise_from_local_datetime(
101 | datetime: &Logical,
102 | from_tz: &StringChunked,
103 | out_tz: &str,
104 | ambiguous: &str,
105 | ) -> PolarsResult {
106 | let to_tz = parse_time_zone(out_tz)?;
107 | let ambig = Ambiguous::from_str(ambiguous)?;
108 | let timestamp_to_datetime: fn(i64) -> NaiveDateTime = match datetime.time_unit() {
109 | TimeUnit::Milliseconds => timestamp_ms_to_datetime,
110 | TimeUnit::Microseconds => timestamp_us_to_datetime,
111 | TimeUnit::Nanoseconds => timestamp_ns_to_datetime,
112 | };
113 | let datetime_to_timestamp: fn(NaiveDateTime) -> i64 = match datetime.time_unit() {
114 | TimeUnit::Milliseconds => datetime_to_timestamp_ms,
115 | TimeUnit::Microseconds => datetime_to_timestamp_us,
116 | TimeUnit::Nanoseconds => datetime_to_timestamp_ns,
117 | };
118 | let out = match from_tz.len() {
119 | 1 => match unsafe { from_tz.get_unchecked(0) } {
120 | Some(from_tz) => {
121 | let from_tz = parse_time_zone(from_tz)?;
122 | datetime.phys.try_apply_nonnull_values_generic(|timestamp| {
123 | let ndt = timestamp_to_datetime(timestamp);
124 | Ok::(datetime_to_timestamp(
125 | naive_local_to_naive_utc_in_new_time_zone(&from_tz, &to_tz, ndt, &ambig)?,
126 | ))
127 | })
128 | }
129 | _ => Ok(Int64Chunked::full_null(PlSmallStr::EMPTY, datetime.len())),
130 | },
131 | _ => try_binary_elementwise(&datetime.phys, from_tz, |timestamp_opt, from_tz_opt| {
132 | match (timestamp_opt, from_tz_opt) {
133 | (Some(timestamp), Some(from_tz)) => {
134 | let ndt = timestamp_to_datetime(timestamp);
135 | let from_tz = parse_time_zone(from_tz)?;
136 | Ok(Some(datetime_to_timestamp(
137 | naive_local_to_naive_utc_in_new_time_zone(&from_tz, &to_tz, ndt, &ambig)?,
138 | )))
139 | }
140 | _ => Ok(None),
141 | }
142 | }),
143 | };
144 | let out = out?.into_datetime(
145 | datetime.time_unit(),
146 | PolarsTimeZone::opt_try_new(Some(out_tz))?,
147 | );
148 | Ok(out)
149 | }
150 |
--------------------------------------------------------------------------------
/polars_xdt/functions.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import sys
4 | from datetime import date
5 | from pathlib import Path
6 | from typing import TYPE_CHECKING, Literal
7 |
8 | import polars as pl
9 | from polars.plugins import register_plugin_function
10 |
11 | from polars_xdt.utils import parse_into_expr
12 |
13 | if sys.version_info >= (3, 10):
14 | from typing import TypeAlias
15 | else:
16 | from typing_extensions import TypeAlias
17 |
18 | if TYPE_CHECKING:
19 | from collections.abc import Sequence
20 |
21 | from polars import Expr
22 |
23 | from polars_xdt.typing import IntoExprColumn
24 |
25 | Ambiguous: TypeAlias = Literal["earliest", "latest", "raise", "null"]
26 |
27 | RollStrategy: TypeAlias = Literal["raise", "forward", "backward"]
28 |
29 |
30 | PLUGIN_PATH = Path(__file__).parent
31 |
32 | mapping = {"Mon": 1, "Tue": 2, "Wed": 3, "Thu": 4, "Fri": 5, "Sat": 6, "Sun": 7}
33 | reverse_mapping = {value: key for key, value in mapping.items()}
34 |
35 |
36 | def get_weekmask(weekend: Sequence[str]) -> list[bool]:
37 | if weekend == ("Sat", "Sun"):
38 | weekmask = [True, True, True, True, True, False, False]
39 | else:
40 | weekmask = [reverse_mapping[i] not in weekend for i in range(1, 8)]
41 | if sum(weekmask) == 0:
42 | msg = f"At least one day of the week must be a business day. Got weekend={weekend}"
43 | raise ValueError(msg)
44 | return weekmask
45 |
46 |
47 | def is_workday(
48 | expr: IntoExprColumn,
49 | *,
50 | weekend: Sequence[str] = ("Sat", "Sun"),
51 | holidays: Sequence[date] | None = None,
52 | ) -> pl.Expr:
53 | """
54 | Determine whether a day is a workday.
55 |
56 | Parameters
57 | ----------
58 | expr
59 | Input expression.
60 | weekend
61 | The days of the week that are considered weekends. Defaults to ("Sat", "Sun").
62 | holidays
63 | The holidays to exclude from the calculation. Defaults to None. This should
64 | be a list of ``datetime.date`` s.
65 |
66 | Returns
67 | -------
68 | polars.Expr
69 |
70 | Examples
71 | --------
72 | >>> from datetime import date
73 | >>> import polars as pl
74 | >>> import polars_xdt as xdt
75 | >>> df = pl.DataFrame(
76 | ... {
77 | ... "date": [
78 | ... date(2023, 1, 4),
79 | ... date(2023, 5, 1),
80 | ... date(2023, 9, 9),
81 | ... ],
82 | ... }
83 | ... )
84 | >>> df.with_columns(is_workday=xdt.is_workday("date"))
85 | shape: (3, 2)
86 | ┌────────────┬────────────┐
87 | │ date ┆ is_workday │
88 | │ --- ┆ --- │
89 | │ date ┆ bool │
90 | ╞════════════╪════════════╡
91 | │ 2023-01-04 ┆ true │
92 | │ 2023-05-01 ┆ true │
93 | │ 2023-09-09 ┆ false │
94 | └────────────┴────────────┘
95 |
96 | """
97 | expr = parse_into_expr(expr)
98 | weekend_int = [mapping[x] for x in weekend]
99 | if holidays is not None:
100 | return ~(
101 | expr.dt.date().is_in(holidays)
102 | | expr.dt.weekday().is_in(weekend_int)
103 | )
104 | return ~expr.dt.weekday().is_in(weekend_int)
105 |
106 |
107 | def from_local_datetime(
108 | expr: IntoExprColumn,
109 | from_tz: str | Expr,
110 | to_tz: str,
111 | ambiguous: Ambiguous = "raise",
112 | ) -> pl.Expr:
113 | """
114 | Convert from local datetime in given time zone to new timezone.
115 |
116 | Parameters
117 | ----------
118 | expr
119 | Expression to convert.
120 | from_tz
121 | Current timezone of each datetime
122 | to_tz
123 | Timezone to convert to
124 | ambiguous
125 | Determine how to deal with ambiguous datetimes:
126 |
127 | - `'raise'` (default): raise
128 | - `'earliest'`: use the earliest datetime
129 | - `'latest'`: use the latest datetime
130 |
131 | Returns
132 | -------
133 | Expr
134 | Expression of data type :class:`DateTime`.
135 |
136 | Examples
137 | --------
138 | You can go from a localized datetime back to expressing the datetimes
139 | in a single timezone with `from_local_datetime`.
140 |
141 | >>> from datetime import datetime
142 | >>> import polars_xdt as xdt
143 | >>> df = pl.DataFrame(
144 | ... {
145 | ... "local_dt": [
146 | ... datetime(2020, 10, 10, 1),
147 | ... datetime(2020, 10, 10, 2),
148 | ... datetime(2020, 10, 9, 20),
149 | ... ],
150 | ... "timezone": [
151 | ... "Europe/London",
152 | ... "Africa/Kigali",
153 | ... "America/New_York",
154 | ... ],
155 | ... }
156 | ... )
157 | >>> df.with_columns(
158 | ... xdt.from_local_datetime(
159 | ... "local_dt", pl.col("timezone"), "UTC"
160 | ... ).alias("date")
161 | ... )
162 | shape: (3, 3)
163 | ┌─────────────────────┬──────────────────┬─────────────────────────┐
164 | │ local_dt ┆ timezone ┆ date │
165 | │ --- ┆ --- ┆ --- │
166 | │ datetime[μs] ┆ str ┆ datetime[μs, UTC] │
167 | ╞═════════════════════╪══════════════════╪═════════════════════════╡
168 | │ 2020-10-10 01:00:00 ┆ Europe/London ┆ 2020-10-10 00:00:00 UTC │
169 | │ 2020-10-10 02:00:00 ┆ Africa/Kigali ┆ 2020-10-10 00:00:00 UTC │
170 | │ 2020-10-09 20:00:00 ┆ America/New_York ┆ 2020-10-10 00:00:00 UTC │
171 | └─────────────────────┴──────────────────┴─────────────────────────┘
172 |
173 | """
174 | expr = parse_into_expr(expr)
175 | from_tz = parse_into_expr(from_tz, str_as_lit=True)
176 | return register_plugin_function(
177 | plugin_path=PLUGIN_PATH,
178 | function_name="from_local_datetime",
179 | is_elementwise=True,
180 | args=[expr, from_tz],
181 | kwargs={
182 | "to_tz": to_tz,
183 | "ambiguous": ambiguous,
184 | },
185 | )
186 |
187 |
188 | def to_local_datetime(
189 | expr: IntoExprColumn,
190 | time_zone: str | Expr,
191 | ) -> pl.Expr:
192 | """
193 | Convert to local datetime in given time zone.
194 |
195 | Parameters
196 | ----------
197 | expr
198 | Expression to convert.
199 | time_zone
200 | Time zone to convert to.
201 |
202 | Returns
203 | -------
204 | Expr
205 | Expression of data type :class:`DateTime`.
206 |
207 | Examples
208 | --------
209 | You can use `to_local_datetime` to figure out how a tz-aware datetime
210 | will be expressed as a local datetime.
211 |
212 | >>> from datetime import datetime
213 | >>> import polars_xdt as xdt
214 | >>> df = pl.DataFrame(
215 | ... {
216 | ... "date_col": [datetime(2020, 10, 10)] * 3,
217 | ... "timezone": [
218 | ... "Europe/London",
219 | ... "Africa/Kigali",
220 | ... "America/New_York",
221 | ... ],
222 | ... }
223 | ... ).with_columns(pl.col("date_col").dt.replace_time_zone("UTC"))
224 | >>> df.with_columns(
225 | ... xdt.to_local_datetime("date_col", pl.col("timezone")).alias(
226 | ... "local_dt"
227 | ... )
228 | ... )
229 | shape: (3, 3)
230 | ┌─────────────────────────┬──────────────────┬─────────────────────┐
231 | │ date_col ┆ timezone ┆ local_dt │
232 | │ --- ┆ --- ┆ --- │
233 | │ datetime[μs, UTC] ┆ str ┆ datetime[μs] │
234 | ╞═════════════════════════╪══════════════════╪═════════════════════╡
235 | │ 2020-10-10 00:00:00 UTC ┆ Europe/London ┆ 2020-10-10 01:00:00 │
236 | │ 2020-10-10 00:00:00 UTC ┆ Africa/Kigali ┆ 2020-10-10 02:00:00 │
237 | │ 2020-10-10 00:00:00 UTC ┆ America/New_York ┆ 2020-10-09 20:00:00 │
238 | └─────────────────────────┴──────────────────┴─────────────────────┘
239 |
240 | """
241 | expr = parse_into_expr(expr)
242 | time_zone = parse_into_expr(time_zone, str_as_lit=True)
243 | return register_plugin_function(
244 | plugin_path=PLUGIN_PATH,
245 | function_name="to_local_datetime",
246 | is_elementwise=True,
247 | args=[expr, time_zone],
248 | )
249 |
250 |
251 | def format_localized(
252 | expr: IntoExprColumn,
253 | format: str, # noqa: A002
254 | locale: str = "uk_UA",
255 | ) -> pl.Expr:
256 | """
257 | Convert to local datetime in given time zone.
258 |
259 | Parameters
260 | ----------
261 | expr
262 | Expression to format.
263 | format
264 | Format string, see https://docs.rs/chrono/latest/chrono/format/strftime/index.html
265 | for what's available.
266 | locale
267 | Locale to use for formatting. Defaults to "uk_UA", because that's what the OP
268 | requested https://github.com/pola-rs/polars/issues/12341.
269 |
270 | Returns
271 | -------
272 | Expr
273 | Expression of data type :class:`Utf8`.
274 |
275 | Examples
276 | --------
277 | >>> from datetime import datetime
278 | >>> import polars_xdt as xdt
279 | >>> df = pl.DataFrame(
280 | ... {
281 | ... "date_col": [datetime(2024, 8, 24), datetime(2024, 10, 1)],
282 | ... }
283 | ... )
284 | >>> df.with_columns(
285 | ... result=xdt.format_localized(
286 | ... "date_col", format="%A, %d %B %Y", locale="uk_UA"
287 | ... )
288 | ... )
289 | shape: (2, 2)
290 | ┌─────────────────────┬──────────────────────────┐
291 | │ date_col ┆ result │
292 | │ --- ┆ --- │
293 | │ datetime[μs] ┆ str │
294 | ╞═════════════════════╪══════════════════════════╡
295 | │ 2024-08-24 00:00:00 ┆ субота, 24 серпня 2024 │
296 | │ 2024-10-01 00:00:00 ┆ вівторок, 01 жовтня 2024 │
297 | └─────────────────────┴──────────────────────────┘
298 |
299 | """
300 | expr = parse_into_expr(expr)
301 | return register_plugin_function(
302 | plugin_path=PLUGIN_PATH,
303 | function_name="format_localized",
304 | is_elementwise=True,
305 | args=[expr],
306 | kwargs={"format": format, "locale": locale},
307 | )
308 |
309 |
310 | def to_julian_date(expr: str | pl.Expr) -> pl.Expr:
311 | """
312 | Return the Julian date corresponding to given datetimes.
313 |
314 | Examples
315 | --------
316 | >>> from datetime import datetime
317 | >>> import polars_xdt as xdt
318 | >>> df = pl.DataFrame(
319 | ... {
320 | ... "date_col": [
321 | ... datetime(2013, 1, 1, 0, 30),
322 | ... datetime(2024, 1, 7, 13, 18, 51),
323 | ... ],
324 | ... }
325 | ... )
326 | >>> with pl.Config(float_precision=10) as cfg:
327 | ... df.with_columns(julian_date=xdt.to_julian_date("date_col"))
328 | shape: (2, 2)
329 | ┌─────────────────────┬────────────────────┐
330 | │ date_col ┆ julian_date │
331 | │ --- ┆ --- │
332 | │ datetime[μs] ┆ f64 │
333 | ╞═════════════════════╪════════════════════╡
334 | │ 2013-01-01 00:30:00 ┆ 2456293.5208333335 │
335 | │ 2024-01-07 13:18:51 ┆ 2460317.0547569445 │
336 | └─────────────────────┴────────────────────┘
337 |
338 | """
339 | expr = parse_into_expr(expr)
340 | return register_plugin_function(
341 | plugin_path=PLUGIN_PATH,
342 | function_name="to_julian_date",
343 | is_elementwise=True,
344 | args=[expr],
345 | )
346 |
347 |
348 | def ceil(
349 | expr: IntoExprColumn,
350 | every: str | pl.Expr,
351 | ) -> pl.Expr:
352 | """
353 | Find "ceiling" of datetime.
354 |
355 | Parameters
356 | ----------
357 | expr
358 | Expression to take "ceiling" of.
359 | every
360 | Duration string, created with the
361 | the following string language:
362 |
363 | - 1ns (1 nanosecond)
364 | - 1us (1 microsecond)
365 | - 1ms (1 millisecond)
366 | - 1s (1 second)
367 | - 1m (1 minute)
368 | - 1h (1 hour)
369 | - 1d (1 calendar day)
370 | - 1w (1 calendar week)
371 | - 1mo (1 calendar month)
372 | - 1q (1 calendar quarter)
373 | - 1y (1 calendar year)
374 |
375 | These strings can be combined:
376 |
377 | - 3d12h4m25s # 3 days, 12 hours, 4 minutes, and 25 seconds
378 |
379 | By "calendar day", we mean the corresponding time on the next day (which may
380 | not be 24 hours, due to daylight savings). Similarly for "calendar week",
381 | "calendar month", "calendar quarter", and "calendar year".
382 |
383 | Returns
384 | -------
385 | Expr
386 | Expression of the same type.
387 |
388 | Examples
389 | --------
390 | >>> from datetime import datetime
391 | >>> import polars_xdt as xdt
392 | >>> df = pl.DataFrame(
393 | ... {
394 | ... "date_col": [datetime(2024, 8, 24), datetime(2024, 10, 1)],
395 | ... }
396 | ... )
397 | >>> df.with_columns(result=xdt.ceil("date_col", "1mo"))
398 | shape: (2, 2)
399 | ┌─────────────────────┬─────────────────────┐
400 | │ date_col ┆ result │
401 | │ --- ┆ --- │
402 | │ datetime[μs] ┆ datetime[μs] │
403 | ╞═════════════════════╪═════════════════════╡
404 | │ 2024-08-24 00:00:00 ┆ 2024-09-01 00:00:00 │
405 | │ 2024-10-01 00:00:00 ┆ 2024-10-01 00:00:00 │
406 | └─────────────────────┴─────────────────────┘
407 |
408 | """
409 | expr = parse_into_expr(expr)
410 | truncated = expr.dt.truncate(every)
411 | return (
412 | pl.when(expr == truncated)
413 | .then(expr)
414 | .otherwise(truncated.dt.offset_by(every))
415 | )
416 |
417 |
418 | def day_name(expr: str | pl.Expr, locale: str | None = None) -> pl.Expr:
419 | """
420 | Return day name, in specified locale (if specified).
421 |
422 | Returns
423 | -------
424 | Expr
425 | Expression of data type :class:`Utf8`.
426 |
427 | See Also
428 | --------
429 | format_localized : format according to locale.
430 |
431 | Examples
432 | --------
433 | >>> from datetime import datetime
434 | >>> import polars_xdt as xdt
435 | >>> df = pl.DataFrame(
436 | ... {
437 | ... "ts": [datetime(2020, 10, 25), datetime(2020, 10, 26)],
438 | ... }
439 | ... )
440 | >>> df.with_columns(
441 | ... english_day_name=xdt.day_name("ts"),
442 | ... french_day_name=xdt.day_name("ts", locale="fr_FR"),
443 | ... ukrainian_day_name=xdt.day_name("ts", locale="uk_UA"),
444 | ... )
445 | shape: (2, 4)
446 | ┌─────────────────────┬──────────────────┬─────────────────┬────────────────────┐
447 | │ ts ┆ english_day_name ┆ french_day_name ┆ ukrainian_day_name │
448 | │ --- ┆ --- ┆ --- ┆ --- │
449 | │ datetime[μs] ┆ str ┆ str ┆ str │
450 | ╞═════════════════════╪══════════════════╪═════════════════╪════════════════════╡
451 | │ 2020-10-25 00:00:00 ┆ Sunday ┆ dimanche ┆ неділя │
452 | │ 2020-10-26 00:00:00 ┆ Monday ┆ lundi ┆ понеділок │
453 | └─────────────────────┴──────────────────┴─────────────────┴────────────────────┘
454 |
455 | """
456 | expr = parse_into_expr(expr)
457 | if locale is None:
458 | result = expr.dt.to_string("%A")
459 | else:
460 | result = format_localized(expr, "%A", locale=locale) # type: ignore[attr-defined]
461 | return result
462 |
463 |
464 | def month_name(expr: str | pl.Expr, locale: str | None = None) -> pl.Expr:
465 | """
466 | Return month name, in specified locale (if specified).
467 |
468 | Returns
469 | -------
470 | Expr
471 | Expression of data type :class:`Utf8`.
472 |
473 | See Also
474 | --------
475 | format_localized : format according to locale.
476 |
477 | Examples
478 | --------
479 | >>> from datetime import datetime
480 | >>> import polars_xdt as xdt
481 | >>> df = pl.DataFrame(
482 | ... {
483 | ... "ts": [datetime(2020, 10, 25), datetime(2020, 11, 26)],
484 | ... }
485 | ... )
486 | >>> df.with_columns(
487 | ... english_month_name=xdt.month_name("ts"),
488 | ... french_month_name=xdt.month_name("ts", locale="fr_FR"),
489 | ... ukrainian_month_name=xdt.month_name("ts", locale="uk_UA"),
490 | ... )
491 | shape: (2, 4)
492 | ┌─────────────────────┬────────────────────┬───────────────────┬──────────────────────┐
493 | │ ts ┆ english_month_name ┆ french_month_name ┆ ukrainian_month_name │
494 | │ --- ┆ --- ┆ --- ┆ --- │
495 | │ datetime[μs] ┆ str ┆ str ┆ str │
496 | ╞═════════════════════╪════════════════════╪═══════════════════╪══════════════════════╡
497 | │ 2020-10-25 00:00:00 ┆ October ┆ octobre ┆ жовтня │
498 | │ 2020-11-26 00:00:00 ┆ November ┆ novembre ┆ листопада │
499 | └─────────────────────┴────────────────────┴───────────────────┴──────────────────────┘
500 |
501 | """
502 | expr = parse_into_expr(expr)
503 | if locale is None:
504 | result = expr.dt.to_string("%B")
505 | else:
506 | result = format_localized(expr, "%B", locale=locale)
507 | return result
508 |
509 |
510 | def month_delta(
511 | start_dates: IntoExprColumn,
512 | end_dates: IntoExprColumn | date,
513 | ) -> pl.Expr:
514 | """
515 | Calculate the number of months between two Series.
516 |
517 | Parameters
518 | ----------
519 | start_dates
520 | A Series object containing the start dates.
521 | end_dates
522 | A Series object containing the end dates.
523 |
524 | Returns
525 | -------
526 | polars.Expr
527 |
528 | Examples
529 | --------
530 | >>> from datetime import date
531 | >>> import polars as pl
532 | >>> import polars_xdt as xdt
533 | >>> df = pl.DataFrame(
534 | ... {
535 | ... "start_date": [
536 | ... date(2024, 3, 1),
537 | ... date(2024, 3, 31),
538 | ... date(2022, 2, 28),
539 | ... date(2023, 1, 31),
540 | ... date(2019, 12, 31),
541 | ... ],
542 | ... "end_date": [
543 | ... date(2023, 2, 28),
544 | ... date(2023, 2, 28),
545 | ... date(2023, 2, 28),
546 | ... date(2023, 1, 31),
547 | ... date(2023, 1, 1),
548 | ... ],
549 | ... },
550 | ... )
551 | >>> df.with_columns(
552 | ... xdt.month_delta("start_date", "end_date").alias("month_delta")
553 | ... )
554 | shape: (5, 3)
555 | ┌────────────┬────────────┬─────────────┐
556 | │ start_date ┆ end_date ┆ month_delta │
557 | │ --- ┆ --- ┆ --- │
558 | │ date ┆ date ┆ i32 │
559 | ╞════════════╪════════════╪═════════════╡
560 | │ 2024-03-01 ┆ 2023-02-28 ┆ -12 │
561 | │ 2024-03-31 ┆ 2023-02-28 ┆ -13 │
562 | │ 2022-02-28 ┆ 2023-02-28 ┆ 12 │
563 | │ 2023-01-31 ┆ 2023-01-31 ┆ 0 │
564 | │ 2019-12-31 ┆ 2023-01-01 ┆ 36 │
565 | └────────────┴────────────┴─────────────┘
566 |
567 | """
568 | start_dates = parse_into_expr(start_dates)
569 | if not isinstance(end_dates, date):
570 | end_dates = parse_into_expr(end_dates)
571 |
572 | return register_plugin_function(
573 | plugin_path=PLUGIN_PATH,
574 | function_name="month_delta",
575 | is_elementwise=True,
576 | args=[start_dates, end_dates],
577 | )
578 |
579 |
580 | def arg_previous_greater(expr: IntoExprColumn) -> pl.Expr:
581 | """
582 | Find the row count of the previous value greater than the current one.
583 |
584 | Parameters
585 | ----------
586 | expr
587 | Expression.
588 |
589 | Returns
590 | -------
591 | Expr
592 | UInt64 or UInt32 type, depending on the platform.
593 |
594 | Examples
595 | --------
596 | >>> import polars as pl
597 | >>> import polars_xdt as xdt
598 | >>> df = pl.DataFrame({"value": [1, 9, 6, 7, 3]})
599 | >>> df.with_columns(result=xdt.arg_previous_greater("value"))
600 | shape: (5, 2)
601 | ┌───────┬────────┐
602 | │ value ┆ result │
603 | │ --- ┆ --- │
604 | │ i64 ┆ u32 │
605 | ╞═══════╪════════╡
606 | │ 1 ┆ null │
607 | │ 9 ┆ 1 │
608 | │ 6 ┆ 1 │
609 | │ 7 ┆ 1 │
610 | │ 3 ┆ 3 │
611 | └───────┴────────┘
612 |
613 | This can be useful when working with time series. For example,
614 | if you a dataset like this:
615 |
616 | >>> df = pl.DataFrame(
617 | ... {
618 | ... "date": [
619 | ... "2024-02-01",
620 | ... "2024-02-02",
621 | ... "2024-02-03",
622 | ... "2024-02-04",
623 | ... "2024-02-05",
624 | ... "2024-02-06",
625 | ... "2024-02-07",
626 | ... "2024-02-08",
627 | ... "2024-02-09",
628 | ... "2024-02-10",
629 | ... ],
630 | ... "group": ["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"],
631 | ... "value": [1, 9, None, 7, 3, 2, 4, 5, 1, 9],
632 | ... }
633 | ... )
634 | >>> df = df.with_columns(pl.col("date").str.to_date())
635 |
636 | and want find out, for each day and each item, how many days it's
637 | been since `'value'` was higher than it currently is, you could do
638 |
639 | >>> df.with_columns(
640 | ... result=(
641 | ... (
642 | ... pl.col("date")
643 | ... - pl.col("date")
644 | ... .gather(xdt.arg_previous_greater("value"))
645 | ... .over("group")
646 | ... ).dt.total_days()
647 | ... ),
648 | ... )
649 | shape: (10, 4)
650 | ┌────────────┬───────┬───────┬────────┐
651 | │ date ┆ group ┆ value ┆ result │
652 | │ --- ┆ --- ┆ --- ┆ --- │
653 | │ date ┆ str ┆ i64 ┆ i64 │
654 | ╞════════════╪═══════╪═══════╪════════╡
655 | │ 2024-02-01 ┆ A ┆ 1 ┆ null │
656 | │ 2024-02-02 ┆ A ┆ 9 ┆ 0 │
657 | │ 2024-02-03 ┆ A ┆ null ┆ null │
658 | │ 2024-02-04 ┆ A ┆ 7 ┆ 2 │
659 | │ 2024-02-05 ┆ A ┆ 3 ┆ 1 │
660 | │ 2024-02-06 ┆ B ┆ 2 ┆ null │
661 | │ 2024-02-07 ┆ B ┆ 4 ┆ 0 │
662 | │ 2024-02-08 ┆ B ┆ 5 ┆ 0 │
663 | │ 2024-02-09 ┆ B ┆ 1 ┆ 1 │
664 | │ 2024-02-10 ┆ B ┆ 9 ┆ 0 │
665 | └────────────┴───────┴───────┴────────┘
666 |
667 | """
668 | expr = parse_into_expr(expr)
669 | return register_plugin_function(
670 | plugin_path=PLUGIN_PATH,
671 | function_name="arg_previous_greater",
672 | is_elementwise=False,
673 | args=[expr],
674 | )
675 |
--------------------------------------------------------------------------------
/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 4
4 |
5 | [[package]]
6 | name = "addr2line"
7 | version = "0.22.0"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
10 | dependencies = [
11 | "gimli",
12 | ]
13 |
14 | [[package]]
15 | name = "adler"
16 | version = "1.0.2"
17 | source = "registry+https://github.com/rust-lang/crates.io-index"
18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
19 |
20 | [[package]]
21 | name = "adler2"
22 | version = "2.0.1"
23 | source = "registry+https://github.com/rust-lang/crates.io-index"
24 | checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
25 |
26 | [[package]]
27 | name = "ahash"
28 | version = "0.8.11"
29 | source = "registry+https://github.com/rust-lang/crates.io-index"
30 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
31 | dependencies = [
32 | "cfg-if",
33 | "getrandom 0.2.15",
34 | "once_cell",
35 | "version_check",
36 | "zerocopy",
37 | ]
38 |
39 | [[package]]
40 | name = "aho-corasick"
41 | version = "1.1.3"
42 | source = "registry+https://github.com/rust-lang/crates.io-index"
43 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
44 | dependencies = [
45 | "memchr",
46 | ]
47 |
48 | [[package]]
49 | name = "allocator-api2"
50 | version = "0.2.18"
51 | source = "registry+https://github.com/rust-lang/crates.io-index"
52 | checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
53 |
54 | [[package]]
55 | name = "android_system_properties"
56 | version = "0.1.5"
57 | source = "registry+https://github.com/rust-lang/crates.io-index"
58 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
59 | dependencies = [
60 | "libc",
61 | ]
62 |
63 | [[package]]
64 | name = "argminmax"
65 | version = "0.6.3"
66 | source = "registry+https://github.com/rust-lang/crates.io-index"
67 | checksum = "70f13d10a41ac8d2ec79ee34178d61e6f47a29c2edfe7ef1721c7383b0359e65"
68 | dependencies = [
69 | "num-traits",
70 | ]
71 |
72 | [[package]]
73 | name = "array-init-cursor"
74 | version = "0.2.0"
75 | source = "registry+https://github.com/rust-lang/crates.io-index"
76 | checksum = "bf7d0a018de4f6aa429b9d33d69edf69072b1c5b1cb8d3e4a5f7ef898fc3eb76"
77 |
78 | [[package]]
79 | name = "arrayref"
80 | version = "0.3.9"
81 | source = "registry+https://github.com/rust-lang/crates.io-index"
82 | checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
83 |
84 | [[package]]
85 | name = "arrayvec"
86 | version = "0.7.6"
87 | source = "registry+https://github.com/rust-lang/crates.io-index"
88 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
89 |
90 | [[package]]
91 | name = "async-channel"
92 | version = "2.5.0"
93 | source = "registry+https://github.com/rust-lang/crates.io-index"
94 | checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2"
95 | dependencies = [
96 | "concurrent-queue",
97 | "event-listener-strategy",
98 | "futures-core",
99 | "pin-project-lite",
100 | ]
101 |
102 | [[package]]
103 | name = "async-stream"
104 | version = "0.3.6"
105 | source = "registry+https://github.com/rust-lang/crates.io-index"
106 | checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
107 | dependencies = [
108 | "async-stream-impl",
109 | "futures-core",
110 | "pin-project-lite",
111 | ]
112 |
113 | [[package]]
114 | name = "async-stream-impl"
115 | version = "0.3.6"
116 | source = "registry+https://github.com/rust-lang/crates.io-index"
117 | checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
118 | dependencies = [
119 | "proc-macro2",
120 | "quote",
121 | "syn",
122 | ]
123 |
124 | [[package]]
125 | name = "async-trait"
126 | version = "0.1.83"
127 | source = "registry+https://github.com/rust-lang/crates.io-index"
128 | checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
129 | dependencies = [
130 | "proc-macro2",
131 | "quote",
132 | "syn",
133 | ]
134 |
135 | [[package]]
136 | name = "atoi_simd"
137 | version = "0.16.0"
138 | source = "registry+https://github.com/rust-lang/crates.io-index"
139 | checksum = "4790f9e8961209112beb783d85449b508673cf4a6a419c8449b210743ac4dbe9"
140 |
141 | [[package]]
142 | name = "atomic-waker"
143 | version = "1.1.2"
144 | source = "registry+https://github.com/rust-lang/crates.io-index"
145 | checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
146 |
147 | [[package]]
148 | name = "autocfg"
149 | version = "1.3.0"
150 | source = "registry+https://github.com/rust-lang/crates.io-index"
151 | checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
152 |
153 | [[package]]
154 | name = "backtrace"
155 | version = "0.3.73"
156 | source = "registry+https://github.com/rust-lang/crates.io-index"
157 | checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
158 | dependencies = [
159 | "addr2line",
160 | "cc",
161 | "cfg-if",
162 | "libc",
163 | "miniz_oxide 0.7.4",
164 | "object",
165 | "rustc-demangle",
166 | ]
167 |
168 | [[package]]
169 | name = "base64"
170 | version = "0.22.1"
171 | source = "registry+https://github.com/rust-lang/crates.io-index"
172 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
173 |
174 | [[package]]
175 | name = "bincode"
176 | version = "2.0.1"
177 | source = "registry+https://github.com/rust-lang/crates.io-index"
178 | checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740"
179 | dependencies = [
180 | "bincode_derive",
181 | "serde",
182 | "unty",
183 | ]
184 |
185 | [[package]]
186 | name = "bincode_derive"
187 | version = "2.0.1"
188 | source = "registry+https://github.com/rust-lang/crates.io-index"
189 | checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09"
190 | dependencies = [
191 | "virtue",
192 | ]
193 |
194 | [[package]]
195 | name = "bitflags"
196 | version = "2.5.0"
197 | source = "registry+https://github.com/rust-lang/crates.io-index"
198 | checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
199 | dependencies = [
200 | "serde",
201 | ]
202 |
203 | [[package]]
204 | name = "blake3"
205 | version = "1.8.2"
206 | source = "registry+https://github.com/rust-lang/crates.io-index"
207 | checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0"
208 | dependencies = [
209 | "arrayref",
210 | "arrayvec",
211 | "cc",
212 | "cfg-if",
213 | "constant_time_eq",
214 | ]
215 |
216 | [[package]]
217 | name = "block-buffer"
218 | version = "0.10.4"
219 | source = "registry+https://github.com/rust-lang/crates.io-index"
220 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
221 | dependencies = [
222 | "generic-array",
223 | ]
224 |
225 | [[package]]
226 | name = "boxcar"
227 | version = "0.2.13"
228 | source = "registry+https://github.com/rust-lang/crates.io-index"
229 | checksum = "26c4925bc979b677330a8c7fe7a8c94af2dbb4a2d37b4a20a80d884400f46baa"
230 |
231 | [[package]]
232 | name = "bumpalo"
233 | version = "3.16.0"
234 | source = "registry+https://github.com/rust-lang/crates.io-index"
235 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
236 |
237 | [[package]]
238 | name = "bytemuck"
239 | version = "1.22.0"
240 | source = "registry+https://github.com/rust-lang/crates.io-index"
241 | checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
242 | dependencies = [
243 | "bytemuck_derive",
244 | ]
245 |
246 | [[package]]
247 | name = "bytemuck_derive"
248 | version = "1.7.0"
249 | source = "registry+https://github.com/rust-lang/crates.io-index"
250 | checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b"
251 | dependencies = [
252 | "proc-macro2",
253 | "quote",
254 | "syn",
255 | ]
256 |
257 | [[package]]
258 | name = "byteorder"
259 | version = "1.5.0"
260 | source = "registry+https://github.com/rust-lang/crates.io-index"
261 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
262 |
263 | [[package]]
264 | name = "bytes"
265 | version = "1.10.1"
266 | source = "registry+https://github.com/rust-lang/crates.io-index"
267 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
268 | dependencies = [
269 | "serde",
270 | ]
271 |
272 | [[package]]
273 | name = "castaway"
274 | version = "0.2.3"
275 | source = "registry+https://github.com/rust-lang/crates.io-index"
276 | checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5"
277 | dependencies = [
278 | "rustversion",
279 | ]
280 |
281 | [[package]]
282 | name = "cc"
283 | version = "1.2.30"
284 | source = "registry+https://github.com/rust-lang/crates.io-index"
285 | checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7"
286 | dependencies = [
287 | "jobserver",
288 | "libc",
289 | "shlex",
290 | ]
291 |
292 | [[package]]
293 | name = "cfg-if"
294 | version = "1.0.0"
295 | source = "registry+https://github.com/rust-lang/crates.io-index"
296 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
297 |
298 | [[package]]
299 | name = "cfg_aliases"
300 | version = "0.2.1"
301 | source = "registry+https://github.com/rust-lang/crates.io-index"
302 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
303 |
304 | [[package]]
305 | name = "chrono"
306 | version = "0.4.42"
307 | source = "registry+https://github.com/rust-lang/crates.io-index"
308 | checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
309 | dependencies = [
310 | "iana-time-zone",
311 | "num-traits",
312 | "pure-rust-locales",
313 | "serde",
314 | "windows-link",
315 | ]
316 |
317 | [[package]]
318 | name = "chrono-tz"
319 | version = "0.10.4"
320 | source = "registry+https://github.com/rust-lang/crates.io-index"
321 | checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3"
322 | dependencies = [
323 | "chrono",
324 | "phf",
325 | ]
326 |
327 | [[package]]
328 | name = "comfy-table"
329 | version = "7.1.1"
330 | source = "registry+https://github.com/rust-lang/crates.io-index"
331 | checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7"
332 | dependencies = [
333 | "crossterm",
334 | "strum",
335 | "strum_macros 0.26.4",
336 | "unicode-width",
337 | ]
338 |
339 | [[package]]
340 | name = "compact_str"
341 | version = "0.9.0"
342 | source = "registry+https://github.com/rust-lang/crates.io-index"
343 | checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a"
344 | dependencies = [
345 | "castaway",
346 | "cfg-if",
347 | "itoa",
348 | "rustversion",
349 | "ryu",
350 | "serde",
351 | "static_assertions",
352 | ]
353 |
354 | [[package]]
355 | name = "concurrent-queue"
356 | version = "2.5.0"
357 | source = "registry+https://github.com/rust-lang/crates.io-index"
358 | checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
359 | dependencies = [
360 | "crossbeam-utils",
361 | ]
362 |
363 | [[package]]
364 | name = "constant_time_eq"
365 | version = "0.3.1"
366 | source = "registry+https://github.com/rust-lang/crates.io-index"
367 | checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
368 |
369 | [[package]]
370 | name = "core-foundation"
371 | version = "0.9.4"
372 | source = "registry+https://github.com/rust-lang/crates.io-index"
373 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
374 | dependencies = [
375 | "core-foundation-sys",
376 | "libc",
377 | ]
378 |
379 | [[package]]
380 | name = "core-foundation-sys"
381 | version = "0.8.7"
382 | source = "registry+https://github.com/rust-lang/crates.io-index"
383 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
384 |
385 | [[package]]
386 | name = "cpufeatures"
387 | version = "0.2.17"
388 | source = "registry+https://github.com/rust-lang/crates.io-index"
389 | checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
390 | dependencies = [
391 | "libc",
392 | ]
393 |
394 | [[package]]
395 | name = "crc32fast"
396 | version = "1.5.0"
397 | source = "registry+https://github.com/rust-lang/crates.io-index"
398 | checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
399 | dependencies = [
400 | "cfg-if",
401 | ]
402 |
403 | [[package]]
404 | name = "crossbeam-channel"
405 | version = "0.5.15"
406 | source = "registry+https://github.com/rust-lang/crates.io-index"
407 | checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
408 | dependencies = [
409 | "crossbeam-utils",
410 | ]
411 |
412 | [[package]]
413 | name = "crossbeam-deque"
414 | version = "0.8.5"
415 | source = "registry+https://github.com/rust-lang/crates.io-index"
416 | checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
417 | dependencies = [
418 | "crossbeam-epoch",
419 | "crossbeam-utils",
420 | ]
421 |
422 | [[package]]
423 | name = "crossbeam-epoch"
424 | version = "0.9.18"
425 | source = "registry+https://github.com/rust-lang/crates.io-index"
426 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
427 | dependencies = [
428 | "crossbeam-utils",
429 | ]
430 |
431 | [[package]]
432 | name = "crossbeam-queue"
433 | version = "0.3.11"
434 | source = "registry+https://github.com/rust-lang/crates.io-index"
435 | checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
436 | dependencies = [
437 | "crossbeam-utils",
438 | ]
439 |
440 | [[package]]
441 | name = "crossbeam-utils"
442 | version = "0.8.20"
443 | source = "registry+https://github.com/rust-lang/crates.io-index"
444 | checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
445 |
446 | [[package]]
447 | name = "crossterm"
448 | version = "0.27.0"
449 | source = "registry+https://github.com/rust-lang/crates.io-index"
450 | checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
451 | dependencies = [
452 | "bitflags",
453 | "crossterm_winapi",
454 | "libc",
455 | "parking_lot",
456 | "winapi",
457 | ]
458 |
459 | [[package]]
460 | name = "crossterm_winapi"
461 | version = "0.9.1"
462 | source = "registry+https://github.com/rust-lang/crates.io-index"
463 | checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
464 | dependencies = [
465 | "winapi",
466 | ]
467 |
468 | [[package]]
469 | name = "crypto-common"
470 | version = "0.1.6"
471 | source = "registry+https://github.com/rust-lang/crates.io-index"
472 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
473 | dependencies = [
474 | "generic-array",
475 | "typenum",
476 | ]
477 |
478 | [[package]]
479 | name = "digest"
480 | version = "0.10.7"
481 | source = "registry+https://github.com/rust-lang/crates.io-index"
482 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
483 | dependencies = [
484 | "block-buffer",
485 | "crypto-common",
486 | ]
487 |
488 | [[package]]
489 | name = "displaydoc"
490 | version = "0.2.5"
491 | source = "registry+https://github.com/rust-lang/crates.io-index"
492 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
493 | dependencies = [
494 | "proc-macro2",
495 | "quote",
496 | "syn",
497 | ]
498 |
499 | [[package]]
500 | name = "dyn-clone"
501 | version = "1.0.17"
502 | source = "registry+https://github.com/rust-lang/crates.io-index"
503 | checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
504 |
505 | [[package]]
506 | name = "either"
507 | version = "1.15.0"
508 | source = "registry+https://github.com/rust-lang/crates.io-index"
509 | checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
510 | dependencies = [
511 | "serde",
512 | ]
513 |
514 | [[package]]
515 | name = "equivalent"
516 | version = "1.0.1"
517 | source = "registry+https://github.com/rust-lang/crates.io-index"
518 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
519 |
520 | [[package]]
521 | name = "errno"
522 | version = "0.3.13"
523 | source = "registry+https://github.com/rust-lang/crates.io-index"
524 | checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
525 | dependencies = [
526 | "libc",
527 | "windows-sys 0.59.0",
528 | ]
529 |
530 | [[package]]
531 | name = "ethnum"
532 | version = "1.5.0"
533 | source = "registry+https://github.com/rust-lang/crates.io-index"
534 | checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c"
535 |
536 | [[package]]
537 | name = "event-listener"
538 | version = "5.4.0"
539 | source = "registry+https://github.com/rust-lang/crates.io-index"
540 | checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae"
541 | dependencies = [
542 | "concurrent-queue",
543 | "parking",
544 | "pin-project-lite",
545 | ]
546 |
547 | [[package]]
548 | name = "event-listener-strategy"
549 | version = "0.5.4"
550 | source = "registry+https://github.com/rust-lang/crates.io-index"
551 | checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
552 | dependencies = [
553 | "event-listener",
554 | "pin-project-lite",
555 | ]
556 |
557 | [[package]]
558 | name = "fallible-streaming-iterator"
559 | version = "0.1.9"
560 | source = "registry+https://github.com/rust-lang/crates.io-index"
561 | checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
562 |
563 | [[package]]
564 | name = "fast-float2"
565 | version = "0.2.3"
566 | source = "registry+https://github.com/rust-lang/crates.io-index"
567 | checksum = "f8eb564c5c7423d25c886fb561d1e4ee69f72354d16918afa32c08811f6b6a55"
568 |
569 | [[package]]
570 | name = "flate2"
571 | version = "1.1.2"
572 | source = "registry+https://github.com/rust-lang/crates.io-index"
573 | checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d"
574 | dependencies = [
575 | "crc32fast",
576 | "miniz_oxide 0.8.9",
577 | ]
578 |
579 | [[package]]
580 | name = "float-cmp"
581 | version = "0.10.0"
582 | source = "registry+https://github.com/rust-lang/crates.io-index"
583 | checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8"
584 | dependencies = [
585 | "num-traits",
586 | ]
587 |
588 | [[package]]
589 | name = "fnv"
590 | version = "1.0.7"
591 | source = "registry+https://github.com/rust-lang/crates.io-index"
592 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
593 |
594 | [[package]]
595 | name = "foldhash"
596 | version = "0.1.5"
597 | source = "registry+https://github.com/rust-lang/crates.io-index"
598 | checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
599 |
600 | [[package]]
601 | name = "foldhash"
602 | version = "0.2.0"
603 | source = "registry+https://github.com/rust-lang/crates.io-index"
604 | checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
605 |
606 | [[package]]
607 | name = "form_urlencoded"
608 | version = "1.2.1"
609 | source = "registry+https://github.com/rust-lang/crates.io-index"
610 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
611 | dependencies = [
612 | "percent-encoding",
613 | ]
614 |
615 | [[package]]
616 | name = "fs4"
617 | version = "0.13.1"
618 | source = "registry+https://github.com/rust-lang/crates.io-index"
619 | checksum = "8640e34b88f7652208ce9e88b1a37a2ae95227d84abec377ccd3c5cfeb141ed4"
620 | dependencies = [
621 | "rustix",
622 | "windows-sys 0.59.0",
623 | ]
624 |
625 | [[package]]
626 | name = "futures"
627 | version = "0.3.31"
628 | source = "registry+https://github.com/rust-lang/crates.io-index"
629 | checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
630 | dependencies = [
631 | "futures-channel",
632 | "futures-core",
633 | "futures-executor",
634 | "futures-io",
635 | "futures-sink",
636 | "futures-task",
637 | "futures-util",
638 | ]
639 |
640 | [[package]]
641 | name = "futures-channel"
642 | version = "0.3.31"
643 | source = "registry+https://github.com/rust-lang/crates.io-index"
644 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
645 | dependencies = [
646 | "futures-core",
647 | "futures-sink",
648 | ]
649 |
650 | [[package]]
651 | name = "futures-core"
652 | version = "0.3.31"
653 | source = "registry+https://github.com/rust-lang/crates.io-index"
654 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
655 |
656 | [[package]]
657 | name = "futures-executor"
658 | version = "0.3.31"
659 | source = "registry+https://github.com/rust-lang/crates.io-index"
660 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
661 | dependencies = [
662 | "futures-core",
663 | "futures-task",
664 | "futures-util",
665 | ]
666 |
667 | [[package]]
668 | name = "futures-io"
669 | version = "0.3.31"
670 | source = "registry+https://github.com/rust-lang/crates.io-index"
671 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
672 |
673 | [[package]]
674 | name = "futures-macro"
675 | version = "0.3.31"
676 | source = "registry+https://github.com/rust-lang/crates.io-index"
677 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
678 | dependencies = [
679 | "proc-macro2",
680 | "quote",
681 | "syn",
682 | ]
683 |
684 | [[package]]
685 | name = "futures-sink"
686 | version = "0.3.31"
687 | source = "registry+https://github.com/rust-lang/crates.io-index"
688 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
689 |
690 | [[package]]
691 | name = "futures-task"
692 | version = "0.3.31"
693 | source = "registry+https://github.com/rust-lang/crates.io-index"
694 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
695 |
696 | [[package]]
697 | name = "futures-util"
698 | version = "0.3.31"
699 | source = "registry+https://github.com/rust-lang/crates.io-index"
700 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
701 | dependencies = [
702 | "futures-channel",
703 | "futures-core",
704 | "futures-io",
705 | "futures-macro",
706 | "futures-sink",
707 | "futures-task",
708 | "memchr",
709 | "pin-project-lite",
710 | "pin-utils",
711 | "slab",
712 | ]
713 |
714 | [[package]]
715 | name = "generic-array"
716 | version = "0.14.9"
717 | source = "registry+https://github.com/rust-lang/crates.io-index"
718 | checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
719 | dependencies = [
720 | "typenum",
721 | "version_check",
722 | ]
723 |
724 | [[package]]
725 | name = "getrandom"
726 | version = "0.2.15"
727 | source = "registry+https://github.com/rust-lang/crates.io-index"
728 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
729 | dependencies = [
730 | "cfg-if",
731 | "js-sys",
732 | "libc",
733 | "wasi 0.11.0+wasi-snapshot-preview1",
734 | "wasm-bindgen",
735 | ]
736 |
737 | [[package]]
738 | name = "getrandom"
739 | version = "0.3.3"
740 | source = "registry+https://github.com/rust-lang/crates.io-index"
741 | checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
742 | dependencies = [
743 | "cfg-if",
744 | "js-sys",
745 | "libc",
746 | "r-efi",
747 | "wasi 0.14.2+wasi-0.2.4",
748 | "wasm-bindgen",
749 | ]
750 |
751 | [[package]]
752 | name = "gimli"
753 | version = "0.29.0"
754 | source = "registry+https://github.com/rust-lang/crates.io-index"
755 | checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
756 |
757 | [[package]]
758 | name = "glob"
759 | version = "0.3.1"
760 | source = "registry+https://github.com/rust-lang/crates.io-index"
761 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
762 |
763 | [[package]]
764 | name = "h2"
765 | version = "0.4.11"
766 | source = "registry+https://github.com/rust-lang/crates.io-index"
767 | checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785"
768 | dependencies = [
769 | "atomic-waker",
770 | "bytes",
771 | "fnv",
772 | "futures-core",
773 | "futures-sink",
774 | "http",
775 | "indexmap",
776 | "slab",
777 | "tokio",
778 | "tokio-util",
779 | "tracing",
780 | ]
781 |
782 | [[package]]
783 | name = "halfbrown"
784 | version = "0.4.0"
785 | source = "registry+https://github.com/rust-lang/crates.io-index"
786 | checksum = "0c7ed2f2edad8a14c8186b847909a41fbb9c3eafa44f88bd891114ed5019da09"
787 | dependencies = [
788 | "hashbrown 0.16.1",
789 | "serde",
790 | ]
791 |
792 | [[package]]
793 | name = "hashbrown"
794 | version = "0.15.2"
795 | source = "registry+https://github.com/rust-lang/crates.io-index"
796 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
797 | dependencies = [
798 | "allocator-api2",
799 | "equivalent",
800 | "foldhash 0.1.5",
801 | ]
802 |
803 | [[package]]
804 | name = "hashbrown"
805 | version = "0.16.1"
806 | source = "registry+https://github.com/rust-lang/crates.io-index"
807 | checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
808 | dependencies = [
809 | "allocator-api2",
810 | "equivalent",
811 | "foldhash 0.2.0",
812 | "rayon",
813 | "serde",
814 | "serde_core",
815 | ]
816 |
817 | [[package]]
818 | name = "heck"
819 | version = "0.5.0"
820 | source = "registry+https://github.com/rust-lang/crates.io-index"
821 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
822 |
823 | [[package]]
824 | name = "hex"
825 | version = "0.4.3"
826 | source = "registry+https://github.com/rust-lang/crates.io-index"
827 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
828 |
829 | [[package]]
830 | name = "home"
831 | version = "0.5.9"
832 | source = "registry+https://github.com/rust-lang/crates.io-index"
833 | checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
834 | dependencies = [
835 | "windows-sys 0.52.0",
836 | ]
837 |
838 | [[package]]
839 | name = "http"
840 | version = "1.3.1"
841 | source = "registry+https://github.com/rust-lang/crates.io-index"
842 | checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
843 | dependencies = [
844 | "bytes",
845 | "fnv",
846 | "itoa",
847 | ]
848 |
849 | [[package]]
850 | name = "http-body"
851 | version = "1.0.1"
852 | source = "registry+https://github.com/rust-lang/crates.io-index"
853 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
854 | dependencies = [
855 | "bytes",
856 | "http",
857 | ]
858 |
859 | [[package]]
860 | name = "http-body-util"
861 | version = "0.1.3"
862 | source = "registry+https://github.com/rust-lang/crates.io-index"
863 | checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
864 | dependencies = [
865 | "bytes",
866 | "futures-core",
867 | "http",
868 | "http-body",
869 | "pin-project-lite",
870 | ]
871 |
872 | [[package]]
873 | name = "httparse"
874 | version = "1.10.1"
875 | source = "registry+https://github.com/rust-lang/crates.io-index"
876 | checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
877 |
878 | [[package]]
879 | name = "humantime"
880 | version = "2.2.0"
881 | source = "registry+https://github.com/rust-lang/crates.io-index"
882 | checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
883 |
884 | [[package]]
885 | name = "hyper"
886 | version = "1.6.0"
887 | source = "registry+https://github.com/rust-lang/crates.io-index"
888 | checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
889 | dependencies = [
890 | "bytes",
891 | "futures-channel",
892 | "futures-util",
893 | "h2",
894 | "http",
895 | "http-body",
896 | "httparse",
897 | "itoa",
898 | "pin-project-lite",
899 | "smallvec",
900 | "tokio",
901 | "want",
902 | ]
903 |
904 | [[package]]
905 | name = "hyper-rustls"
906 | version = "0.27.7"
907 | source = "registry+https://github.com/rust-lang/crates.io-index"
908 | checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58"
909 | dependencies = [
910 | "http",
911 | "hyper",
912 | "hyper-util",
913 | "rustls",
914 | "rustls-native-certs",
915 | "rustls-pki-types",
916 | "tokio",
917 | "tokio-rustls",
918 | "tower-service",
919 | ]
920 |
921 | [[package]]
922 | name = "hyper-util"
923 | version = "0.1.16"
924 | source = "registry+https://github.com/rust-lang/crates.io-index"
925 | checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e"
926 | dependencies = [
927 | "base64",
928 | "bytes",
929 | "futures-channel",
930 | "futures-core",
931 | "futures-util",
932 | "http",
933 | "http-body",
934 | "hyper",
935 | "ipnet",
936 | "libc",
937 | "percent-encoding",
938 | "pin-project-lite",
939 | "socket2 0.6.0",
940 | "tokio",
941 | "tower-service",
942 | "tracing",
943 | ]
944 |
945 | [[package]]
946 | name = "iana-time-zone"
947 | version = "0.1.60"
948 | source = "registry+https://github.com/rust-lang/crates.io-index"
949 | checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
950 | dependencies = [
951 | "android_system_properties",
952 | "core-foundation-sys",
953 | "iana-time-zone-haiku",
954 | "js-sys",
955 | "wasm-bindgen",
956 | "windows-core",
957 | ]
958 |
959 | [[package]]
960 | name = "iana-time-zone-haiku"
961 | version = "0.1.2"
962 | source = "registry+https://github.com/rust-lang/crates.io-index"
963 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
964 | dependencies = [
965 | "cc",
966 | ]
967 |
968 | [[package]]
969 | name = "icu_collections"
970 | version = "2.0.0"
971 | source = "registry+https://github.com/rust-lang/crates.io-index"
972 | checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
973 | dependencies = [
974 | "displaydoc",
975 | "potential_utf",
976 | "yoke",
977 | "zerofrom",
978 | "zerovec",
979 | ]
980 |
981 | [[package]]
982 | name = "icu_locale_core"
983 | version = "2.0.0"
984 | source = "registry+https://github.com/rust-lang/crates.io-index"
985 | checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
986 | dependencies = [
987 | "displaydoc",
988 | "litemap",
989 | "tinystr",
990 | "writeable",
991 | "zerovec",
992 | ]
993 |
994 | [[package]]
995 | name = "icu_normalizer"
996 | version = "2.0.0"
997 | source = "registry+https://github.com/rust-lang/crates.io-index"
998 | checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"
999 | dependencies = [
1000 | "displaydoc",
1001 | "icu_collections",
1002 | "icu_normalizer_data",
1003 | "icu_properties",
1004 | "icu_provider",
1005 | "smallvec",
1006 | "zerovec",
1007 | ]
1008 |
1009 | [[package]]
1010 | name = "icu_normalizer_data"
1011 | version = "2.0.0"
1012 | source = "registry+https://github.com/rust-lang/crates.io-index"
1013 | checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"
1014 |
1015 | [[package]]
1016 | name = "icu_properties"
1017 | version = "2.0.1"
1018 | source = "registry+https://github.com/rust-lang/crates.io-index"
1019 | checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b"
1020 | dependencies = [
1021 | "displaydoc",
1022 | "icu_collections",
1023 | "icu_locale_core",
1024 | "icu_properties_data",
1025 | "icu_provider",
1026 | "potential_utf",
1027 | "zerotrie",
1028 | "zerovec",
1029 | ]
1030 |
1031 | [[package]]
1032 | name = "icu_properties_data"
1033 | version = "2.0.1"
1034 | source = "registry+https://github.com/rust-lang/crates.io-index"
1035 | checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632"
1036 |
1037 | [[package]]
1038 | name = "icu_provider"
1039 | version = "2.0.0"
1040 | source = "registry+https://github.com/rust-lang/crates.io-index"
1041 | checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
1042 | dependencies = [
1043 | "displaydoc",
1044 | "icu_locale_core",
1045 | "stable_deref_trait",
1046 | "tinystr",
1047 | "writeable",
1048 | "yoke",
1049 | "zerofrom",
1050 | "zerotrie",
1051 | "zerovec",
1052 | ]
1053 |
1054 | [[package]]
1055 | name = "idna"
1056 | version = "1.0.3"
1057 | source = "registry+https://github.com/rust-lang/crates.io-index"
1058 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
1059 | dependencies = [
1060 | "idna_adapter",
1061 | "smallvec",
1062 | "utf8_iter",
1063 | ]
1064 |
1065 | [[package]]
1066 | name = "idna_adapter"
1067 | version = "1.2.1"
1068 | source = "registry+https://github.com/rust-lang/crates.io-index"
1069 | checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
1070 | dependencies = [
1071 | "icu_normalizer",
1072 | "icu_properties",
1073 | ]
1074 |
1075 | [[package]]
1076 | name = "indexmap"
1077 | version = "2.12.1"
1078 | source = "registry+https://github.com/rust-lang/crates.io-index"
1079 | checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
1080 | dependencies = [
1081 | "equivalent",
1082 | "hashbrown 0.16.1",
1083 | "serde",
1084 | "serde_core",
1085 | ]
1086 |
1087 | [[package]]
1088 | name = "indoc"
1089 | version = "2.0.5"
1090 | source = "registry+https://github.com/rust-lang/crates.io-index"
1091 | checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
1092 |
1093 | [[package]]
1094 | name = "io-uring"
1095 | version = "0.7.9"
1096 | source = "registry+https://github.com/rust-lang/crates.io-index"
1097 | checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
1098 | dependencies = [
1099 | "bitflags",
1100 | "cfg-if",
1101 | "libc",
1102 | ]
1103 |
1104 | [[package]]
1105 | name = "ipnet"
1106 | version = "2.11.0"
1107 | source = "registry+https://github.com/rust-lang/crates.io-index"
1108 | checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
1109 |
1110 | [[package]]
1111 | name = "iri-string"
1112 | version = "0.7.8"
1113 | source = "registry+https://github.com/rust-lang/crates.io-index"
1114 | checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2"
1115 | dependencies = [
1116 | "memchr",
1117 | "serde",
1118 | ]
1119 |
1120 | [[package]]
1121 | name = "iter-read"
1122 | version = "0.3.1"
1123 | source = "registry+https://github.com/rust-lang/crates.io-index"
1124 | checksum = "c397ca3ea05ad509c4ec451fea28b4771236a376ca1c69fd5143aae0cf8f93c4"
1125 |
1126 | [[package]]
1127 | name = "itertools"
1128 | version = "0.14.0"
1129 | source = "registry+https://github.com/rust-lang/crates.io-index"
1130 | checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
1131 | dependencies = [
1132 | "either",
1133 | ]
1134 |
1135 | [[package]]
1136 | name = "itoa"
1137 | version = "1.0.11"
1138 | source = "registry+https://github.com/rust-lang/crates.io-index"
1139 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
1140 |
1141 | [[package]]
1142 | name = "jobserver"
1143 | version = "0.1.31"
1144 | source = "registry+https://github.com/rust-lang/crates.io-index"
1145 | checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
1146 | dependencies = [
1147 | "libc",
1148 | ]
1149 |
1150 | [[package]]
1151 | name = "js-sys"
1152 | version = "0.3.77"
1153 | source = "registry+https://github.com/rust-lang/crates.io-index"
1154 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
1155 | dependencies = [
1156 | "once_cell",
1157 | "wasm-bindgen",
1158 | ]
1159 |
1160 | [[package]]
1161 | name = "libc"
1162 | version = "0.2.174"
1163 | source = "registry+https://github.com/rust-lang/crates.io-index"
1164 | checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
1165 |
1166 | [[package]]
1167 | name = "libm"
1168 | version = "0.2.8"
1169 | source = "registry+https://github.com/rust-lang/crates.io-index"
1170 | checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
1171 |
1172 | [[package]]
1173 | name = "linux-raw-sys"
1174 | version = "0.9.4"
1175 | source = "registry+https://github.com/rust-lang/crates.io-index"
1176 | checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
1177 |
1178 | [[package]]
1179 | name = "litemap"
1180 | version = "0.8.0"
1181 | source = "registry+https://github.com/rust-lang/crates.io-index"
1182 | checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
1183 |
1184 | [[package]]
1185 | name = "lock_api"
1186 | version = "0.4.12"
1187 | source = "registry+https://github.com/rust-lang/crates.io-index"
1188 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
1189 | dependencies = [
1190 | "autocfg",
1191 | "scopeguard",
1192 | ]
1193 |
1194 | [[package]]
1195 | name = "log"
1196 | version = "0.4.21"
1197 | source = "registry+https://github.com/rust-lang/crates.io-index"
1198 | checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
1199 |
1200 | [[package]]
1201 | name = "lru-slab"
1202 | version = "0.1.2"
1203 | source = "registry+https://github.com/rust-lang/crates.io-index"
1204 | checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
1205 |
1206 | [[package]]
1207 | name = "lz4"
1208 | version = "1.25.0"
1209 | source = "registry+https://github.com/rust-lang/crates.io-index"
1210 | checksum = "d6eab492fe7f8651add23237ea56dbf11b3c4ff762ab83d40a47f11433421f91"
1211 | dependencies = [
1212 | "libc",
1213 | "lz4-sys",
1214 | ]
1215 |
1216 | [[package]]
1217 | name = "lz4-sys"
1218 | version = "1.9.5"
1219 | source = "registry+https://github.com/rust-lang/crates.io-index"
1220 | checksum = "e9764018d143cc854c9f17f0b907de70f14393b1f502da6375dce70f00514eb3"
1221 | dependencies = [
1222 | "cc",
1223 | "libc",
1224 | ]
1225 |
1226 | [[package]]
1227 | name = "memchr"
1228 | version = "2.7.4"
1229 | source = "registry+https://github.com/rust-lang/crates.io-index"
1230 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
1231 |
1232 | [[package]]
1233 | name = "memmap2"
1234 | version = "0.9.5"
1235 | source = "registry+https://github.com/rust-lang/crates.io-index"
1236 | checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f"
1237 | dependencies = [
1238 | "libc",
1239 | ]
1240 |
1241 | [[package]]
1242 | name = "memoffset"
1243 | version = "0.9.1"
1244 | source = "registry+https://github.com/rust-lang/crates.io-index"
1245 | checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
1246 | dependencies = [
1247 | "autocfg",
1248 | ]
1249 |
1250 | [[package]]
1251 | name = "miniz_oxide"
1252 | version = "0.7.4"
1253 | source = "registry+https://github.com/rust-lang/crates.io-index"
1254 | checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
1255 | dependencies = [
1256 | "adler",
1257 | ]
1258 |
1259 | [[package]]
1260 | name = "miniz_oxide"
1261 | version = "0.8.9"
1262 | source = "registry+https://github.com/rust-lang/crates.io-index"
1263 | checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
1264 | dependencies = [
1265 | "adler2",
1266 | ]
1267 |
1268 | [[package]]
1269 | name = "mio"
1270 | version = "1.0.3"
1271 | source = "registry+https://github.com/rust-lang/crates.io-index"
1272 | checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
1273 | dependencies = [
1274 | "libc",
1275 | "wasi 0.11.0+wasi-snapshot-preview1",
1276 | "windows-sys 0.52.0",
1277 | ]
1278 |
1279 | [[package]]
1280 | name = "now"
1281 | version = "0.1.3"
1282 | source = "registry+https://github.com/rust-lang/crates.io-index"
1283 | checksum = "6d89e9874397a1f0a52fc1f197a8effd9735223cb2390e9dcc83ac6cd02923d0"
1284 | dependencies = [
1285 | "chrono",
1286 | ]
1287 |
1288 | [[package]]
1289 | name = "num-bigint"
1290 | version = "0.4.5"
1291 | source = "registry+https://github.com/rust-lang/crates.io-index"
1292 | checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7"
1293 | dependencies = [
1294 | "num-integer",
1295 | "num-traits",
1296 | ]
1297 |
1298 | [[package]]
1299 | name = "num-integer"
1300 | version = "0.1.46"
1301 | source = "registry+https://github.com/rust-lang/crates.io-index"
1302 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
1303 | dependencies = [
1304 | "num-traits",
1305 | ]
1306 |
1307 | [[package]]
1308 | name = "num-traits"
1309 | version = "0.2.19"
1310 | source = "registry+https://github.com/rust-lang/crates.io-index"
1311 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
1312 | dependencies = [
1313 | "autocfg",
1314 | "libm",
1315 | ]
1316 |
1317 | [[package]]
1318 | name = "object"
1319 | version = "0.36.5"
1320 | source = "registry+https://github.com/rust-lang/crates.io-index"
1321 | checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
1322 | dependencies = [
1323 | "memchr",
1324 | ]
1325 |
1326 | [[package]]
1327 | name = "object_store"
1328 | version = "0.12.3"
1329 | source = "registry+https://github.com/rust-lang/crates.io-index"
1330 | checksum = "efc4f07659e11cd45a341cd24d71e683e3be65d9ff1f8150061678fe60437496"
1331 | dependencies = [
1332 | "async-trait",
1333 | "base64",
1334 | "bytes",
1335 | "chrono",
1336 | "form_urlencoded",
1337 | "futures",
1338 | "http",
1339 | "http-body-util",
1340 | "humantime",
1341 | "hyper",
1342 | "itertools",
1343 | "parking_lot",
1344 | "percent-encoding",
1345 | "quick-xml",
1346 | "rand",
1347 | "reqwest",
1348 | "ring",
1349 | "serde",
1350 | "serde_json",
1351 | "serde_urlencoded",
1352 | "thiserror 2.0.5",
1353 | "tokio",
1354 | "tracing",
1355 | "url",
1356 | "walkdir",
1357 | "wasm-bindgen-futures",
1358 | "web-time",
1359 | ]
1360 |
1361 | [[package]]
1362 | name = "once_cell"
1363 | version = "1.21.3"
1364 | source = "registry+https://github.com/rust-lang/crates.io-index"
1365 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
1366 |
1367 | [[package]]
1368 | name = "openssl-probe"
1369 | version = "0.1.6"
1370 | source = "registry+https://github.com/rust-lang/crates.io-index"
1371 | checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
1372 |
1373 | [[package]]
1374 | name = "parking"
1375 | version = "2.2.1"
1376 | source = "registry+https://github.com/rust-lang/crates.io-index"
1377 | checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
1378 |
1379 | [[package]]
1380 | name = "parking_lot"
1381 | version = "0.12.3"
1382 | source = "registry+https://github.com/rust-lang/crates.io-index"
1383 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
1384 | dependencies = [
1385 | "lock_api",
1386 | "parking_lot_core",
1387 | ]
1388 |
1389 | [[package]]
1390 | name = "parking_lot_core"
1391 | version = "0.9.10"
1392 | source = "registry+https://github.com/rust-lang/crates.io-index"
1393 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
1394 | dependencies = [
1395 | "cfg-if",
1396 | "libc",
1397 | "redox_syscall",
1398 | "smallvec",
1399 | "windows-targets",
1400 | ]
1401 |
1402 | [[package]]
1403 | name = "paste"
1404 | version = "1.0.15"
1405 | source = "registry+https://github.com/rust-lang/crates.io-index"
1406 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
1407 |
1408 | [[package]]
1409 | name = "percent-encoding"
1410 | version = "2.3.1"
1411 | source = "registry+https://github.com/rust-lang/crates.io-index"
1412 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
1413 |
1414 | [[package]]
1415 | name = "phf"
1416 | version = "0.12.1"
1417 | source = "registry+https://github.com/rust-lang/crates.io-index"
1418 | checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
1419 | dependencies = [
1420 | "phf_shared",
1421 | ]
1422 |
1423 | [[package]]
1424 | name = "phf_shared"
1425 | version = "0.12.1"
1426 | source = "registry+https://github.com/rust-lang/crates.io-index"
1427 | checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
1428 | dependencies = [
1429 | "siphasher",
1430 | ]
1431 |
1432 | [[package]]
1433 | name = "pin-project-lite"
1434 | version = "0.2.15"
1435 | source = "registry+https://github.com/rust-lang/crates.io-index"
1436 | checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
1437 |
1438 | [[package]]
1439 | name = "pin-utils"
1440 | version = "0.1.0"
1441 | source = "registry+https://github.com/rust-lang/crates.io-index"
1442 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
1443 |
1444 | [[package]]
1445 | name = "pkg-config"
1446 | version = "0.3.30"
1447 | source = "registry+https://github.com/rust-lang/crates.io-index"
1448 | checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
1449 |
1450 | [[package]]
1451 | name = "planus"
1452 | version = "1.1.1"
1453 | source = "registry+https://github.com/rust-lang/crates.io-index"
1454 | checksum = "3daf8e3d4b712abe1d690838f6e29fb76b76ea19589c4afa39ec30e12f62af71"
1455 | dependencies = [
1456 | "array-init-cursor",
1457 | "hashbrown 0.15.2",
1458 | ]
1459 |
1460 | [[package]]
1461 | name = "polars"
1462 | version = "0.52.0"
1463 | source = "registry+https://github.com/rust-lang/crates.io-index"
1464 | checksum = "6bc9ea901050c1bb8747ee411bc7fbb390f3b399931e7484719512965132a248"
1465 | dependencies = [
1466 | "getrandom 0.2.15",
1467 | "getrandom 0.3.3",
1468 | "polars-arrow",
1469 | "polars-compute",
1470 | "polars-core",
1471 | "polars-error",
1472 | "polars-io",
1473 | "polars-lazy",
1474 | "polars-ops",
1475 | "polars-parquet",
1476 | "polars-plan",
1477 | "polars-sql",
1478 | "polars-time",
1479 | "polars-utils",
1480 | "version_check",
1481 | ]
1482 |
1483 | [[package]]
1484 | name = "polars-arrow"
1485 | version = "0.52.0"
1486 | source = "registry+https://github.com/rust-lang/crates.io-index"
1487 | checksum = "33d3fe43f8702cf7899ff3d516c2e5f7dc84ee6f6a3007e1a831a0ff87940704"
1488 | dependencies = [
1489 | "atoi_simd",
1490 | "bitflags",
1491 | "bytemuck",
1492 | "chrono",
1493 | "chrono-tz",
1494 | "dyn-clone",
1495 | "either",
1496 | "ethnum",
1497 | "getrandom 0.2.15",
1498 | "getrandom 0.3.3",
1499 | "hashbrown 0.16.1",
1500 | "itoa",
1501 | "lz4",
1502 | "num-traits",
1503 | "polars-arrow-format",
1504 | "polars-error",
1505 | "polars-schema",
1506 | "polars-utils",
1507 | "serde",
1508 | "simdutf8",
1509 | "streaming-iterator",
1510 | "strum_macros 0.27.2",
1511 | "version_check",
1512 | "zstd",
1513 | ]
1514 |
1515 | [[package]]
1516 | name = "polars-arrow-format"
1517 | version = "0.2.0"
1518 | source = "registry+https://github.com/rust-lang/crates.io-index"
1519 | checksum = "863c04c514be005eced7db7053e20d49f7e7a58048a282fa52dfea1fd5434e78"
1520 | dependencies = [
1521 | "planus",
1522 | "serde",
1523 | ]
1524 |
1525 | [[package]]
1526 | name = "polars-compute"
1527 | version = "0.52.0"
1528 | source = "registry+https://github.com/rust-lang/crates.io-index"
1529 | checksum = "d29cc7497378dee3a002f117e0b4e16b7cbe6c8ed3da16a0229c89294af7c3bf"
1530 | dependencies = [
1531 | "atoi_simd",
1532 | "bytemuck",
1533 | "chrono",
1534 | "either",
1535 | "fast-float2",
1536 | "hashbrown 0.16.1",
1537 | "itoa",
1538 | "num-traits",
1539 | "polars-arrow",
1540 | "polars-error",
1541 | "polars-utils",
1542 | "rand",
1543 | "ryu",
1544 | "serde",
1545 | "strength_reduce",
1546 | "strum_macros 0.27.2",
1547 | "version_check",
1548 | ]
1549 |
1550 | [[package]]
1551 | name = "polars-core"
1552 | version = "0.52.0"
1553 | source = "registry+https://github.com/rust-lang/crates.io-index"
1554 | checksum = "48409b7440cb1a4aa84953fe3a4189dfbfb300a3298266a92a37363476641e40"
1555 | dependencies = [
1556 | "bitflags",
1557 | "boxcar",
1558 | "bytemuck",
1559 | "chrono",
1560 | "chrono-tz",
1561 | "comfy-table",
1562 | "either",
1563 | "hashbrown 0.16.1",
1564 | "indexmap",
1565 | "itoa",
1566 | "num-traits",
1567 | "polars-arrow",
1568 | "polars-compute",
1569 | "polars-dtype",
1570 | "polars-error",
1571 | "polars-row",
1572 | "polars-schema",
1573 | "polars-utils",
1574 | "rand",
1575 | "rand_distr",
1576 | "rayon",
1577 | "regex",
1578 | "serde",
1579 | "serde_json",
1580 | "strum_macros 0.27.2",
1581 | "uuid",
1582 | "version_check",
1583 | "xxhash-rust",
1584 | ]
1585 |
1586 | [[package]]
1587 | name = "polars-dtype"
1588 | version = "0.52.0"
1589 | source = "registry+https://github.com/rust-lang/crates.io-index"
1590 | checksum = "7007e9e8b7b657cbd339b65246af7e87f5756ee9a860119b9424ddffd2aaf133"
1591 | dependencies = [
1592 | "boxcar",
1593 | "hashbrown 0.16.1",
1594 | "polars-arrow",
1595 | "polars-error",
1596 | "polars-utils",
1597 | "serde",
1598 | "uuid",
1599 | ]
1600 |
1601 | [[package]]
1602 | name = "polars-error"
1603 | version = "0.52.0"
1604 | source = "registry+https://github.com/rust-lang/crates.io-index"
1605 | checksum = "f9a6be22566c89f6405f553bfdb7c8a6cb20ec51b35f3172de9a25fa3e252d85"
1606 | dependencies = [
1607 | "object_store",
1608 | "parking_lot",
1609 | "polars-arrow-format",
1610 | "pyo3",
1611 | "regex",
1612 | "signal-hook",
1613 | "simdutf8",
1614 | ]
1615 |
1616 | [[package]]
1617 | name = "polars-expr"
1618 | version = "0.52.0"
1619 | source = "registry+https://github.com/rust-lang/crates.io-index"
1620 | checksum = "6199a50d3e1afd0674fb009e340cbfb0010682b2387187a36328c00f3f2ca87b"
1621 | dependencies = [
1622 | "bitflags",
1623 | "hashbrown 0.16.1",
1624 | "num-traits",
1625 | "polars-arrow",
1626 | "polars-compute",
1627 | "polars-core",
1628 | "polars-io",
1629 | "polars-ops",
1630 | "polars-plan",
1631 | "polars-row",
1632 | "polars-time",
1633 | "polars-utils",
1634 | "rand",
1635 | "rayon",
1636 | "recursive",
1637 | "regex",
1638 | "version_check",
1639 | ]
1640 |
1641 | [[package]]
1642 | name = "polars-ffi"
1643 | version = "0.52.0"
1644 | source = "registry+https://github.com/rust-lang/crates.io-index"
1645 | checksum = "e57ae94d00719556ce242d265f77720287d0c02b78e204aaeee8885db59c7a58"
1646 | dependencies = [
1647 | "polars-arrow",
1648 | "polars-core",
1649 | ]
1650 |
1651 | [[package]]
1652 | name = "polars-io"
1653 | version = "0.52.0"
1654 | source = "registry+https://github.com/rust-lang/crates.io-index"
1655 | checksum = "be3714acdff87170141880a07f5d9233490d3bd5531c41898f6969d440feee11"
1656 | dependencies = [
1657 | "async-trait",
1658 | "atoi_simd",
1659 | "blake3",
1660 | "bytes",
1661 | "chrono",
1662 | "chrono-tz",
1663 | "fast-float2",
1664 | "fs4",
1665 | "futures",
1666 | "glob",
1667 | "hashbrown 0.16.1",
1668 | "home",
1669 | "itoa",
1670 | "memchr",
1671 | "memmap2",
1672 | "num-traits",
1673 | "object_store",
1674 | "percent-encoding",
1675 | "polars-arrow",
1676 | "polars-compute",
1677 | "polars-core",
1678 | "polars-error",
1679 | "polars-json",
1680 | "polars-parquet",
1681 | "polars-schema",
1682 | "polars-time",
1683 | "polars-utils",
1684 | "rayon",
1685 | "regex",
1686 | "reqwest",
1687 | "ryu",
1688 | "serde",
1689 | "serde_json",
1690 | "simdutf8",
1691 | "tokio",
1692 | ]
1693 |
1694 | [[package]]
1695 | name = "polars-json"
1696 | version = "0.52.0"
1697 | source = "registry+https://github.com/rust-lang/crates.io-index"
1698 | checksum = "3dd2126daebf58da564fc5840cd55eb8eb2479d24dfced0a1aea2178a9b33b12"
1699 | dependencies = [
1700 | "chrono",
1701 | "chrono-tz",
1702 | "fallible-streaming-iterator",
1703 | "hashbrown 0.16.1",
1704 | "indexmap",
1705 | "itoa",
1706 | "num-traits",
1707 | "polars-arrow",
1708 | "polars-compute",
1709 | "polars-error",
1710 | "polars-utils",
1711 | "ryu",
1712 | "simd-json",
1713 | "streaming-iterator",
1714 | ]
1715 |
1716 | [[package]]
1717 | name = "polars-lazy"
1718 | version = "0.52.0"
1719 | source = "registry+https://github.com/rust-lang/crates.io-index"
1720 | checksum = "ea136c360d03aafe56e0233495e30044ce43639b8b0360a4a38e840233f048a1"
1721 | dependencies = [
1722 | "bitflags",
1723 | "chrono",
1724 | "either",
1725 | "memchr",
1726 | "polars-arrow",
1727 | "polars-compute",
1728 | "polars-core",
1729 | "polars-expr",
1730 | "polars-io",
1731 | "polars-mem-engine",
1732 | "polars-ops",
1733 | "polars-plan",
1734 | "polars-stream",
1735 | "polars-time",
1736 | "polars-utils",
1737 | "rayon",
1738 | "version_check",
1739 | ]
1740 |
1741 | [[package]]
1742 | name = "polars-mem-engine"
1743 | version = "0.52.0"
1744 | source = "registry+https://github.com/rust-lang/crates.io-index"
1745 | checksum = "0f6e455ceb6e5aee7ed7d5c8944104e66992173e03a9c42f9670226318672249"
1746 | dependencies = [
1747 | "memmap2",
1748 | "polars-arrow",
1749 | "polars-core",
1750 | "polars-error",
1751 | "polars-expr",
1752 | "polars-io",
1753 | "polars-ops",
1754 | "polars-plan",
1755 | "polars-time",
1756 | "polars-utils",
1757 | "rayon",
1758 | "recursive",
1759 | ]
1760 |
1761 | [[package]]
1762 | name = "polars-ops"
1763 | version = "0.52.0"
1764 | source = "registry+https://github.com/rust-lang/crates.io-index"
1765 | checksum = "7b59c80a019ef0e6f09b4416d2647076a52839305c9eb11919e8298ec667f853"
1766 | dependencies = [
1767 | "argminmax",
1768 | "base64",
1769 | "bytemuck",
1770 | "chrono",
1771 | "chrono-tz",
1772 | "either",
1773 | "hashbrown 0.16.1",
1774 | "hex",
1775 | "indexmap",
1776 | "libm",
1777 | "memchr",
1778 | "num-traits",
1779 | "polars-arrow",
1780 | "polars-compute",
1781 | "polars-core",
1782 | "polars-error",
1783 | "polars-schema",
1784 | "polars-utils",
1785 | "rayon",
1786 | "regex",
1787 | "regex-syntax",
1788 | "serde",
1789 | "strum_macros 0.27.2",
1790 | "unicode-normalization",
1791 | "unicode-reverse",
1792 | "version_check",
1793 | ]
1794 |
1795 | [[package]]
1796 | name = "polars-parquet"
1797 | version = "0.52.0"
1798 | source = "registry+https://github.com/rust-lang/crates.io-index"
1799 | checksum = "93c2439d127c59e6bfc9d698419bdb45210068a6f501d44e6096429ad72c2eaa"
1800 | dependencies = [
1801 | "async-stream",
1802 | "base64",
1803 | "bytemuck",
1804 | "ethnum",
1805 | "futures",
1806 | "hashbrown 0.16.1",
1807 | "num-traits",
1808 | "polars-arrow",
1809 | "polars-compute",
1810 | "polars-error",
1811 | "polars-parquet-format",
1812 | "polars-utils",
1813 | "serde",
1814 | "simdutf8",
1815 | "streaming-decompression",
1816 | ]
1817 |
1818 | [[package]]
1819 | name = "polars-parquet-format"
1820 | version = "0.1.0"
1821 | source = "registry+https://github.com/rust-lang/crates.io-index"
1822 | checksum = "c025243dcfe8dbc57e94d9f82eb3bef10b565ab180d5b99bed87fd8aea319ce1"
1823 | dependencies = [
1824 | "async-trait",
1825 | "futures",
1826 | ]
1827 |
1828 | [[package]]
1829 | name = "polars-plan"
1830 | version = "0.52.0"
1831 | source = "registry+https://github.com/rust-lang/crates.io-index"
1832 | checksum = "65b4619f5c7e9b91f18611c9ed82ebeee4b10052160825c1316ecf4dbd4d97e6"
1833 | dependencies = [
1834 | "bitflags",
1835 | "bytemuck",
1836 | "bytes",
1837 | "chrono",
1838 | "chrono-tz",
1839 | "either",
1840 | "hashbrown 0.16.1",
1841 | "memmap2",
1842 | "num-traits",
1843 | "percent-encoding",
1844 | "polars-arrow",
1845 | "polars-compute",
1846 | "polars-core",
1847 | "polars-error",
1848 | "polars-ffi",
1849 | "polars-io",
1850 | "polars-ops",
1851 | "polars-time",
1852 | "polars-utils",
1853 | "pyo3",
1854 | "rayon",
1855 | "recursive",
1856 | "regex",
1857 | "serde",
1858 | "sha2",
1859 | "slotmap",
1860 | "strum_macros 0.27.2",
1861 | "version_check",
1862 | ]
1863 |
1864 | [[package]]
1865 | name = "polars-row"
1866 | version = "0.52.0"
1867 | source = "registry+https://github.com/rust-lang/crates.io-index"
1868 | checksum = "a18d232f25b83032e280a279a1f40beb8a6f8fc43907b13dc07b1c56f3b11eea"
1869 | dependencies = [
1870 | "bitflags",
1871 | "bytemuck",
1872 | "polars-arrow",
1873 | "polars-compute",
1874 | "polars-dtype",
1875 | "polars-error",
1876 | "polars-utils",
1877 | ]
1878 |
1879 | [[package]]
1880 | name = "polars-schema"
1881 | version = "0.52.0"
1882 | source = "registry+https://github.com/rust-lang/crates.io-index"
1883 | checksum = "f73e21d429ae1c23f442b0220ccfe773a9734a44e997b5062a741842909d9441"
1884 | dependencies = [
1885 | "indexmap",
1886 | "polars-error",
1887 | "polars-utils",
1888 | "serde",
1889 | "version_check",
1890 | ]
1891 |
1892 | [[package]]
1893 | name = "polars-sql"
1894 | version = "0.52.0"
1895 | source = "registry+https://github.com/rust-lang/crates.io-index"
1896 | checksum = "3e67ac1cbb0c972a57af3be12f19aa9803898863fe95c33cdd39df05f5738a75"
1897 | dependencies = [
1898 | "bitflags",
1899 | "hex",
1900 | "polars-core",
1901 | "polars-error",
1902 | "polars-lazy",
1903 | "polars-ops",
1904 | "polars-plan",
1905 | "polars-time",
1906 | "polars-utils",
1907 | "rand",
1908 | "regex",
1909 | "serde",
1910 | "sqlparser",
1911 | ]
1912 |
1913 | [[package]]
1914 | name = "polars-stream"
1915 | version = "0.52.0"
1916 | source = "registry+https://github.com/rust-lang/crates.io-index"
1917 | checksum = "2ff19612074640a9d65e5928b7223db76ffee63e55b276f1e466d06719eb7362"
1918 | dependencies = [
1919 | "async-channel",
1920 | "async-trait",
1921 | "atomic-waker",
1922 | "bitflags",
1923 | "chrono-tz",
1924 | "crossbeam-channel",
1925 | "crossbeam-deque",
1926 | "crossbeam-queue",
1927 | "crossbeam-utils",
1928 | "futures",
1929 | "memmap2",
1930 | "parking_lot",
1931 | "percent-encoding",
1932 | "pin-project-lite",
1933 | "polars-arrow",
1934 | "polars-compute",
1935 | "polars-core",
1936 | "polars-error",
1937 | "polars-expr",
1938 | "polars-io",
1939 | "polars-mem-engine",
1940 | "polars-ops",
1941 | "polars-parquet",
1942 | "polars-plan",
1943 | "polars-time",
1944 | "polars-utils",
1945 | "rand",
1946 | "rayon",
1947 | "recursive",
1948 | "slotmap",
1949 | "tokio",
1950 | "version_check",
1951 | ]
1952 |
1953 | [[package]]
1954 | name = "polars-time"
1955 | version = "0.52.0"
1956 | source = "registry+https://github.com/rust-lang/crates.io-index"
1957 | checksum = "ddce7a9f81d5f47d981bcee4a8db004f9596bb51f0f4d9d93667a1a00d88166c"
1958 | dependencies = [
1959 | "atoi_simd",
1960 | "bytemuck",
1961 | "chrono",
1962 | "chrono-tz",
1963 | "now",
1964 | "num-traits",
1965 | "polars-arrow",
1966 | "polars-compute",
1967 | "polars-core",
1968 | "polars-error",
1969 | "polars-ops",
1970 | "polars-utils",
1971 | "rayon",
1972 | "regex",
1973 | "serde",
1974 | "strum_macros 0.27.2",
1975 | ]
1976 |
1977 | [[package]]
1978 | name = "polars-utils"
1979 | version = "0.52.0"
1980 | source = "registry+https://github.com/rust-lang/crates.io-index"
1981 | checksum = "667c1bc2d2313f934d711f6e3b58d8d9f80351d14ea60af936a26b7dfb06e309"
1982 | dependencies = [
1983 | "bincode",
1984 | "bytemuck",
1985 | "bytes",
1986 | "compact_str",
1987 | "either",
1988 | "flate2",
1989 | "foldhash 0.2.0",
1990 | "hashbrown 0.16.1",
1991 | "indexmap",
1992 | "libc",
1993 | "memmap2",
1994 | "num-traits",
1995 | "polars-error",
1996 | "pyo3",
1997 | "rand",
1998 | "raw-cpuid",
1999 | "rayon",
2000 | "regex",
2001 | "rmp-serde",
2002 | "serde",
2003 | "serde_json",
2004 | "serde_stacker",
2005 | "slotmap",
2006 | "stacker",
2007 | "uuid",
2008 | "version_check",
2009 | ]
2010 |
2011 | [[package]]
2012 | name = "polars_xdt"
2013 | version = "0.17.1"
2014 | dependencies = [
2015 | "chrono",
2016 | "chrono-tz",
2017 | "polars",
2018 | "polars-arrow",
2019 | "polars-ops",
2020 | "pyo3",
2021 | "pyo3-polars",
2022 | "serde",
2023 | ]
2024 |
2025 | [[package]]
2026 | name = "portable-atomic"
2027 | version = "1.6.0"
2028 | source = "registry+https://github.com/rust-lang/crates.io-index"
2029 | checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
2030 |
2031 | [[package]]
2032 | name = "potential_utf"
2033 | version = "0.1.2"
2034 | source = "registry+https://github.com/rust-lang/crates.io-index"
2035 | checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
2036 | dependencies = [
2037 | "zerovec",
2038 | ]
2039 |
2040 | [[package]]
2041 | name = "ppv-lite86"
2042 | version = "0.2.17"
2043 | source = "registry+https://github.com/rust-lang/crates.io-index"
2044 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
2045 |
2046 | [[package]]
2047 | name = "proc-macro2"
2048 | version = "1.0.92"
2049 | source = "registry+https://github.com/rust-lang/crates.io-index"
2050 | checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
2051 | dependencies = [
2052 | "unicode-ident",
2053 | ]
2054 |
2055 | [[package]]
2056 | name = "psm"
2057 | version = "0.1.21"
2058 | source = "registry+https://github.com/rust-lang/crates.io-index"
2059 | checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874"
2060 | dependencies = [
2061 | "cc",
2062 | ]
2063 |
2064 | [[package]]
2065 | name = "pure-rust-locales"
2066 | version = "0.8.1"
2067 | source = "registry+https://github.com/rust-lang/crates.io-index"
2068 | checksum = "1190fd18ae6ce9e137184f207593877e70f39b015040156b1e05081cdfe3733a"
2069 |
2070 | [[package]]
2071 | name = "pyo3"
2072 | version = "0.26.0"
2073 | source = "registry+https://github.com/rust-lang/crates.io-index"
2074 | checksum = "7ba0117f4212101ee6544044dae45abe1083d30ce7b29c4b5cbdfa2354e07383"
2075 | dependencies = [
2076 | "indoc",
2077 | "libc",
2078 | "memoffset",
2079 | "once_cell",
2080 | "portable-atomic",
2081 | "pyo3-build-config",
2082 | "pyo3-ffi",
2083 | "pyo3-macros",
2084 | "unindent",
2085 | ]
2086 |
2087 | [[package]]
2088 | name = "pyo3-build-config"
2089 | version = "0.26.0"
2090 | source = "registry+https://github.com/rust-lang/crates.io-index"
2091 | checksum = "4fc6ddaf24947d12a9aa31ac65431fb1b851b8f4365426e182901eabfb87df5f"
2092 | dependencies = [
2093 | "target-lexicon",
2094 | ]
2095 |
2096 | [[package]]
2097 | name = "pyo3-ffi"
2098 | version = "0.26.0"
2099 | source = "registry+https://github.com/rust-lang/crates.io-index"
2100 | checksum = "025474d3928738efb38ac36d4744a74a400c901c7596199e20e45d98eb194105"
2101 | dependencies = [
2102 | "libc",
2103 | "pyo3-build-config",
2104 | ]
2105 |
2106 | [[package]]
2107 | name = "pyo3-macros"
2108 | version = "0.26.0"
2109 | source = "registry+https://github.com/rust-lang/crates.io-index"
2110 | checksum = "2e64eb489f22fe1c95911b77c44cc41e7c19f3082fc81cce90f657cdc42ffded"
2111 | dependencies = [
2112 | "proc-macro2",
2113 | "pyo3-macros-backend",
2114 | "quote",
2115 | "syn",
2116 | ]
2117 |
2118 | [[package]]
2119 | name = "pyo3-macros-backend"
2120 | version = "0.26.0"
2121 | source = "registry+https://github.com/rust-lang/crates.io-index"
2122 | checksum = "100246c0ecf400b475341b8455a9213344569af29a3c841d29270e53102e0fcf"
2123 | dependencies = [
2124 | "heck",
2125 | "proc-macro2",
2126 | "pyo3-build-config",
2127 | "quote",
2128 | "syn",
2129 | ]
2130 |
2131 | [[package]]
2132 | name = "pyo3-polars"
2133 | version = "0.25.0"
2134 | source = "registry+https://github.com/rust-lang/crates.io-index"
2135 | checksum = "94a1e9d697dd76f39b269a5c2f2904469092c0ef6452f47caaf20879891a6a62"
2136 | dependencies = [
2137 | "libc",
2138 | "once_cell",
2139 | "polars",
2140 | "polars-arrow",
2141 | "polars-core",
2142 | "polars-error",
2143 | "polars-ffi",
2144 | "polars-plan",
2145 | "pyo3",
2146 | "pyo3-polars-derive",
2147 | "serde",
2148 | "serde-pickle",
2149 | "thiserror 1.0.61",
2150 | ]
2151 |
2152 | [[package]]
2153 | name = "pyo3-polars-derive"
2154 | version = "0.19.0"
2155 | source = "registry+https://github.com/rust-lang/crates.io-index"
2156 | checksum = "1f5ac697f68e98220c506a933d83398a2687d279de42713b1a0b8e0b4b88cead"
2157 | dependencies = [
2158 | "polars-arrow",
2159 | "polars-core",
2160 | "polars-ffi",
2161 | "polars-plan",
2162 | "proc-macro2",
2163 | "quote",
2164 | "syn",
2165 | ]
2166 |
2167 | [[package]]
2168 | name = "quick-xml"
2169 | version = "0.38.0"
2170 | source = "registry+https://github.com/rust-lang/crates.io-index"
2171 | checksum = "8927b0664f5c5a98265138b7e3f90aa19a6b21353182469ace36d4ac527b7b1b"
2172 | dependencies = [
2173 | "memchr",
2174 | "serde",
2175 | ]
2176 |
2177 | [[package]]
2178 | name = "quinn"
2179 | version = "0.11.8"
2180 | source = "registry+https://github.com/rust-lang/crates.io-index"
2181 | checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8"
2182 | dependencies = [
2183 | "bytes",
2184 | "cfg_aliases",
2185 | "pin-project-lite",
2186 | "quinn-proto",
2187 | "quinn-udp",
2188 | "rustc-hash",
2189 | "rustls",
2190 | "socket2 0.5.8",
2191 | "thiserror 2.0.5",
2192 | "tokio",
2193 | "tracing",
2194 | "web-time",
2195 | ]
2196 |
2197 | [[package]]
2198 | name = "quinn-proto"
2199 | version = "0.11.12"
2200 | source = "registry+https://github.com/rust-lang/crates.io-index"
2201 | checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e"
2202 | dependencies = [
2203 | "bytes",
2204 | "getrandom 0.3.3",
2205 | "lru-slab",
2206 | "rand",
2207 | "ring",
2208 | "rustc-hash",
2209 | "rustls",
2210 | "rustls-pki-types",
2211 | "slab",
2212 | "thiserror 2.0.5",
2213 | "tinyvec",
2214 | "tracing",
2215 | "web-time",
2216 | ]
2217 |
2218 | [[package]]
2219 | name = "quinn-udp"
2220 | version = "0.5.13"
2221 | source = "registry+https://github.com/rust-lang/crates.io-index"
2222 | checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970"
2223 | dependencies = [
2224 | "cfg_aliases",
2225 | "libc",
2226 | "once_cell",
2227 | "socket2 0.5.8",
2228 | "tracing",
2229 | "windows-sys 0.59.0",
2230 | ]
2231 |
2232 | [[package]]
2233 | name = "quote"
2234 | version = "1.0.36"
2235 | source = "registry+https://github.com/rust-lang/crates.io-index"
2236 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
2237 | dependencies = [
2238 | "proc-macro2",
2239 | ]
2240 |
2241 | [[package]]
2242 | name = "r-efi"
2243 | version = "5.3.0"
2244 | source = "registry+https://github.com/rust-lang/crates.io-index"
2245 | checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
2246 |
2247 | [[package]]
2248 | name = "rand"
2249 | version = "0.9.2"
2250 | source = "registry+https://github.com/rust-lang/crates.io-index"
2251 | checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
2252 | dependencies = [
2253 | "rand_chacha",
2254 | "rand_core",
2255 | ]
2256 |
2257 | [[package]]
2258 | name = "rand_chacha"
2259 | version = "0.9.0"
2260 | source = "registry+https://github.com/rust-lang/crates.io-index"
2261 | checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
2262 | dependencies = [
2263 | "ppv-lite86",
2264 | "rand_core",
2265 | ]
2266 |
2267 | [[package]]
2268 | name = "rand_core"
2269 | version = "0.9.3"
2270 | source = "registry+https://github.com/rust-lang/crates.io-index"
2271 | checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
2272 | dependencies = [
2273 | "getrandom 0.3.3",
2274 | ]
2275 |
2276 | [[package]]
2277 | name = "rand_distr"
2278 | version = "0.5.1"
2279 | source = "registry+https://github.com/rust-lang/crates.io-index"
2280 | checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463"
2281 | dependencies = [
2282 | "num-traits",
2283 | "rand",
2284 | ]
2285 |
2286 | [[package]]
2287 | name = "raw-cpuid"
2288 | version = "11.0.2"
2289 | source = "registry+https://github.com/rust-lang/crates.io-index"
2290 | checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd"
2291 | dependencies = [
2292 | "bitflags",
2293 | ]
2294 |
2295 | [[package]]
2296 | name = "rayon"
2297 | version = "1.10.0"
2298 | source = "registry+https://github.com/rust-lang/crates.io-index"
2299 | checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
2300 | dependencies = [
2301 | "either",
2302 | "rayon-core",
2303 | ]
2304 |
2305 | [[package]]
2306 | name = "rayon-core"
2307 | version = "1.12.1"
2308 | source = "registry+https://github.com/rust-lang/crates.io-index"
2309 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
2310 | dependencies = [
2311 | "crossbeam-deque",
2312 | "crossbeam-utils",
2313 | ]
2314 |
2315 | [[package]]
2316 | name = "recursive"
2317 | version = "0.1.1"
2318 | source = "registry+https://github.com/rust-lang/crates.io-index"
2319 | checksum = "0786a43debb760f491b1bc0269fe5e84155353c67482b9e60d0cfb596054b43e"
2320 | dependencies = [
2321 | "recursive-proc-macro-impl",
2322 | "stacker",
2323 | ]
2324 |
2325 | [[package]]
2326 | name = "recursive-proc-macro-impl"
2327 | version = "0.1.1"
2328 | source = "registry+https://github.com/rust-lang/crates.io-index"
2329 | checksum = "76009fbe0614077fc1a2ce255e3a1881a2e3a3527097d5dc6d8212c585e7e38b"
2330 | dependencies = [
2331 | "quote",
2332 | "syn",
2333 | ]
2334 |
2335 | [[package]]
2336 | name = "redox_syscall"
2337 | version = "0.5.2"
2338 | source = "registry+https://github.com/rust-lang/crates.io-index"
2339 | checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
2340 | dependencies = [
2341 | "bitflags",
2342 | ]
2343 |
2344 | [[package]]
2345 | name = "ref-cast"
2346 | version = "1.0.23"
2347 | source = "registry+https://github.com/rust-lang/crates.io-index"
2348 | checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931"
2349 | dependencies = [
2350 | "ref-cast-impl",
2351 | ]
2352 |
2353 | [[package]]
2354 | name = "ref-cast-impl"
2355 | version = "1.0.23"
2356 | source = "registry+https://github.com/rust-lang/crates.io-index"
2357 | checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6"
2358 | dependencies = [
2359 | "proc-macro2",
2360 | "quote",
2361 | "syn",
2362 | ]
2363 |
2364 | [[package]]
2365 | name = "regex"
2366 | version = "1.10.5"
2367 | source = "registry+https://github.com/rust-lang/crates.io-index"
2368 | checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
2369 | dependencies = [
2370 | "aho-corasick",
2371 | "memchr",
2372 | "regex-automata",
2373 | "regex-syntax",
2374 | ]
2375 |
2376 | [[package]]
2377 | name = "regex-automata"
2378 | version = "0.4.7"
2379 | source = "registry+https://github.com/rust-lang/crates.io-index"
2380 | checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
2381 | dependencies = [
2382 | "aho-corasick",
2383 | "memchr",
2384 | "regex-syntax",
2385 | ]
2386 |
2387 | [[package]]
2388 | name = "regex-syntax"
2389 | version = "0.8.5"
2390 | source = "registry+https://github.com/rust-lang/crates.io-index"
2391 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
2392 |
2393 | [[package]]
2394 | name = "reqwest"
2395 | version = "0.12.22"
2396 | source = "registry+https://github.com/rust-lang/crates.io-index"
2397 | checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531"
2398 | dependencies = [
2399 | "base64",
2400 | "bytes",
2401 | "futures-core",
2402 | "futures-util",
2403 | "h2",
2404 | "http",
2405 | "http-body",
2406 | "http-body-util",
2407 | "hyper",
2408 | "hyper-rustls",
2409 | "hyper-util",
2410 | "js-sys",
2411 | "log",
2412 | "percent-encoding",
2413 | "pin-project-lite",
2414 | "quinn",
2415 | "rustls",
2416 | "rustls-native-certs",
2417 | "rustls-pki-types",
2418 | "serde",
2419 | "serde_json",
2420 | "serde_urlencoded",
2421 | "sync_wrapper",
2422 | "tokio",
2423 | "tokio-rustls",
2424 | "tokio-util",
2425 | "tower",
2426 | "tower-http",
2427 | "tower-service",
2428 | "url",
2429 | "wasm-bindgen",
2430 | "wasm-bindgen-futures",
2431 | "wasm-streams",
2432 | "web-sys",
2433 | ]
2434 |
2435 | [[package]]
2436 | name = "ring"
2437 | version = "0.17.14"
2438 | source = "registry+https://github.com/rust-lang/crates.io-index"
2439 | checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
2440 | dependencies = [
2441 | "cc",
2442 | "cfg-if",
2443 | "getrandom 0.2.15",
2444 | "libc",
2445 | "untrusted",
2446 | "windows-sys 0.52.0",
2447 | ]
2448 |
2449 | [[package]]
2450 | name = "rmp"
2451 | version = "0.8.14"
2452 | source = "registry+https://github.com/rust-lang/crates.io-index"
2453 | checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4"
2454 | dependencies = [
2455 | "byteorder",
2456 | "num-traits",
2457 | "paste",
2458 | ]
2459 |
2460 | [[package]]
2461 | name = "rmp-serde"
2462 | version = "1.3.0"
2463 | source = "registry+https://github.com/rust-lang/crates.io-index"
2464 | checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db"
2465 | dependencies = [
2466 | "byteorder",
2467 | "rmp",
2468 | "serde",
2469 | ]
2470 |
2471 | [[package]]
2472 | name = "rustc-demangle"
2473 | version = "0.1.24"
2474 | source = "registry+https://github.com/rust-lang/crates.io-index"
2475 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
2476 |
2477 | [[package]]
2478 | name = "rustc-hash"
2479 | version = "2.1.1"
2480 | source = "registry+https://github.com/rust-lang/crates.io-index"
2481 | checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
2482 |
2483 | [[package]]
2484 | name = "rustix"
2485 | version = "1.0.8"
2486 | source = "registry+https://github.com/rust-lang/crates.io-index"
2487 | checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
2488 | dependencies = [
2489 | "bitflags",
2490 | "errno",
2491 | "libc",
2492 | "linux-raw-sys",
2493 | "windows-sys 0.59.0",
2494 | ]
2495 |
2496 | [[package]]
2497 | name = "rustls"
2498 | version = "0.23.29"
2499 | source = "registry+https://github.com/rust-lang/crates.io-index"
2500 | checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1"
2501 | dependencies = [
2502 | "once_cell",
2503 | "ring",
2504 | "rustls-pki-types",
2505 | "rustls-webpki",
2506 | "subtle",
2507 | "zeroize",
2508 | ]
2509 |
2510 | [[package]]
2511 | name = "rustls-native-certs"
2512 | version = "0.8.0"
2513 | source = "registry+https://github.com/rust-lang/crates.io-index"
2514 | checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a"
2515 | dependencies = [
2516 | "openssl-probe",
2517 | "rustls-pemfile",
2518 | "rustls-pki-types",
2519 | "schannel",
2520 | "security-framework",
2521 | ]
2522 |
2523 | [[package]]
2524 | name = "rustls-pemfile"
2525 | version = "2.2.0"
2526 | source = "registry+https://github.com/rust-lang/crates.io-index"
2527 | checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
2528 | dependencies = [
2529 | "rustls-pki-types",
2530 | ]
2531 |
2532 | [[package]]
2533 | name = "rustls-pki-types"
2534 | version = "1.12.0"
2535 | source = "registry+https://github.com/rust-lang/crates.io-index"
2536 | checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
2537 | dependencies = [
2538 | "web-time",
2539 | "zeroize",
2540 | ]
2541 |
2542 | [[package]]
2543 | name = "rustls-webpki"
2544 | version = "0.103.4"
2545 | source = "registry+https://github.com/rust-lang/crates.io-index"
2546 | checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc"
2547 | dependencies = [
2548 | "ring",
2549 | "rustls-pki-types",
2550 | "untrusted",
2551 | ]
2552 |
2553 | [[package]]
2554 | name = "rustversion"
2555 | version = "1.0.17"
2556 | source = "registry+https://github.com/rust-lang/crates.io-index"
2557 | checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
2558 |
2559 | [[package]]
2560 | name = "ryu"
2561 | version = "1.0.18"
2562 | source = "registry+https://github.com/rust-lang/crates.io-index"
2563 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
2564 |
2565 | [[package]]
2566 | name = "same-file"
2567 | version = "1.0.6"
2568 | source = "registry+https://github.com/rust-lang/crates.io-index"
2569 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
2570 | dependencies = [
2571 | "winapi-util",
2572 | ]
2573 |
2574 | [[package]]
2575 | name = "schannel"
2576 | version = "0.1.27"
2577 | source = "registry+https://github.com/rust-lang/crates.io-index"
2578 | checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
2579 | dependencies = [
2580 | "windows-sys 0.59.0",
2581 | ]
2582 |
2583 | [[package]]
2584 | name = "scopeguard"
2585 | version = "1.2.0"
2586 | source = "registry+https://github.com/rust-lang/crates.io-index"
2587 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
2588 |
2589 | [[package]]
2590 | name = "security-framework"
2591 | version = "2.11.0"
2592 | source = "registry+https://github.com/rust-lang/crates.io-index"
2593 | checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0"
2594 | dependencies = [
2595 | "bitflags",
2596 | "core-foundation",
2597 | "core-foundation-sys",
2598 | "libc",
2599 | "security-framework-sys",
2600 | ]
2601 |
2602 | [[package]]
2603 | name = "security-framework-sys"
2604 | version = "2.14.0"
2605 | source = "registry+https://github.com/rust-lang/crates.io-index"
2606 | checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
2607 | dependencies = [
2608 | "core-foundation-sys",
2609 | "libc",
2610 | ]
2611 |
2612 | [[package]]
2613 | name = "serde"
2614 | version = "1.0.228"
2615 | source = "registry+https://github.com/rust-lang/crates.io-index"
2616 | checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
2617 | dependencies = [
2618 | "serde_core",
2619 | "serde_derive",
2620 | ]
2621 |
2622 | [[package]]
2623 | name = "serde-pickle"
2624 | version = "1.1.1"
2625 | source = "registry+https://github.com/rust-lang/crates.io-index"
2626 | checksum = "c762ad136a26407c6a80825813600ceeab5e613660d93d79a41f0ec877171e71"
2627 | dependencies = [
2628 | "byteorder",
2629 | "iter-read",
2630 | "num-bigint",
2631 | "num-traits",
2632 | "serde",
2633 | ]
2634 |
2635 | [[package]]
2636 | name = "serde_core"
2637 | version = "1.0.228"
2638 | source = "registry+https://github.com/rust-lang/crates.io-index"
2639 | checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
2640 | dependencies = [
2641 | "serde_derive",
2642 | ]
2643 |
2644 | [[package]]
2645 | name = "serde_derive"
2646 | version = "1.0.228"
2647 | source = "registry+https://github.com/rust-lang/crates.io-index"
2648 | checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
2649 | dependencies = [
2650 | "proc-macro2",
2651 | "quote",
2652 | "syn",
2653 | ]
2654 |
2655 | [[package]]
2656 | name = "serde_json"
2657 | version = "1.0.117"
2658 | source = "registry+https://github.com/rust-lang/crates.io-index"
2659 | checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
2660 | dependencies = [
2661 | "itoa",
2662 | "ryu",
2663 | "serde",
2664 | ]
2665 |
2666 | [[package]]
2667 | name = "serde_stacker"
2668 | version = "0.1.14"
2669 | source = "registry+https://github.com/rust-lang/crates.io-index"
2670 | checksum = "d4936375d50c4be7eff22293a9344f8e46f323ed2b3c243e52f89138d9bb0f4a"
2671 | dependencies = [
2672 | "serde",
2673 | "serde_core",
2674 | "stacker",
2675 | ]
2676 |
2677 | [[package]]
2678 | name = "serde_urlencoded"
2679 | version = "0.7.1"
2680 | source = "registry+https://github.com/rust-lang/crates.io-index"
2681 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
2682 | dependencies = [
2683 | "form_urlencoded",
2684 | "itoa",
2685 | "ryu",
2686 | "serde",
2687 | ]
2688 |
2689 | [[package]]
2690 | name = "sha2"
2691 | version = "0.10.9"
2692 | source = "registry+https://github.com/rust-lang/crates.io-index"
2693 | checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
2694 | dependencies = [
2695 | "cfg-if",
2696 | "cpufeatures",
2697 | "digest",
2698 | ]
2699 |
2700 | [[package]]
2701 | name = "shlex"
2702 | version = "1.3.0"
2703 | source = "registry+https://github.com/rust-lang/crates.io-index"
2704 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
2705 |
2706 | [[package]]
2707 | name = "signal-hook"
2708 | version = "0.3.18"
2709 | source = "registry+https://github.com/rust-lang/crates.io-index"
2710 | checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
2711 | dependencies = [
2712 | "libc",
2713 | "signal-hook-registry",
2714 | ]
2715 |
2716 | [[package]]
2717 | name = "signal-hook-registry"
2718 | version = "1.4.5"
2719 | source = "registry+https://github.com/rust-lang/crates.io-index"
2720 | checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
2721 | dependencies = [
2722 | "libc",
2723 | ]
2724 |
2725 | [[package]]
2726 | name = "simd-json"
2727 | version = "0.17.0"
2728 | source = "registry+https://github.com/rust-lang/crates.io-index"
2729 | checksum = "4255126f310d2ba20048db6321c81ab376f6a6735608bf11f0785c41f01f64e3"
2730 | dependencies = [
2731 | "ahash",
2732 | "halfbrown",
2733 | "once_cell",
2734 | "ref-cast",
2735 | "serde",
2736 | "serde_json",
2737 | "simdutf8",
2738 | "value-trait",
2739 | ]
2740 |
2741 | [[package]]
2742 | name = "simdutf8"
2743 | version = "0.1.4"
2744 | source = "registry+https://github.com/rust-lang/crates.io-index"
2745 | checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
2746 |
2747 | [[package]]
2748 | name = "siphasher"
2749 | version = "1.0.1"
2750 | source = "registry+https://github.com/rust-lang/crates.io-index"
2751 | checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
2752 |
2753 | [[package]]
2754 | name = "slab"
2755 | version = "0.4.9"
2756 | source = "registry+https://github.com/rust-lang/crates.io-index"
2757 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
2758 | dependencies = [
2759 | "autocfg",
2760 | ]
2761 |
2762 | [[package]]
2763 | name = "slotmap"
2764 | version = "1.0.7"
2765 | source = "registry+https://github.com/rust-lang/crates.io-index"
2766 | checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a"
2767 | dependencies = [
2768 | "serde",
2769 | "version_check",
2770 | ]
2771 |
2772 | [[package]]
2773 | name = "smallvec"
2774 | version = "1.13.2"
2775 | source = "registry+https://github.com/rust-lang/crates.io-index"
2776 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
2777 |
2778 | [[package]]
2779 | name = "socket2"
2780 | version = "0.5.8"
2781 | source = "registry+https://github.com/rust-lang/crates.io-index"
2782 | checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
2783 | dependencies = [
2784 | "libc",
2785 | "windows-sys 0.52.0",
2786 | ]
2787 |
2788 | [[package]]
2789 | name = "socket2"
2790 | version = "0.6.0"
2791 | source = "registry+https://github.com/rust-lang/crates.io-index"
2792 | checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
2793 | dependencies = [
2794 | "libc",
2795 | "windows-sys 0.59.0",
2796 | ]
2797 |
2798 | [[package]]
2799 | name = "sqlparser"
2800 | version = "0.53.0"
2801 | source = "registry+https://github.com/rust-lang/crates.io-index"
2802 | checksum = "05a528114c392209b3264855ad491fcce534b94a38771b0a0b97a79379275ce8"
2803 | dependencies = [
2804 | "log",
2805 | ]
2806 |
2807 | [[package]]
2808 | name = "stable_deref_trait"
2809 | version = "1.2.0"
2810 | source = "registry+https://github.com/rust-lang/crates.io-index"
2811 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
2812 |
2813 | [[package]]
2814 | name = "stacker"
2815 | version = "0.1.15"
2816 | source = "registry+https://github.com/rust-lang/crates.io-index"
2817 | checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce"
2818 | dependencies = [
2819 | "cc",
2820 | "cfg-if",
2821 | "libc",
2822 | "psm",
2823 | "winapi",
2824 | ]
2825 |
2826 | [[package]]
2827 | name = "static_assertions"
2828 | version = "1.1.0"
2829 | source = "registry+https://github.com/rust-lang/crates.io-index"
2830 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
2831 |
2832 | [[package]]
2833 | name = "streaming-decompression"
2834 | version = "0.1.2"
2835 | source = "registry+https://github.com/rust-lang/crates.io-index"
2836 | checksum = "bf6cc3b19bfb128a8ad11026086e31d3ce9ad23f8ea37354b31383a187c44cf3"
2837 | dependencies = [
2838 | "fallible-streaming-iterator",
2839 | ]
2840 |
2841 | [[package]]
2842 | name = "streaming-iterator"
2843 | version = "0.1.9"
2844 | source = "registry+https://github.com/rust-lang/crates.io-index"
2845 | checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520"
2846 |
2847 | [[package]]
2848 | name = "strength_reduce"
2849 | version = "0.2.4"
2850 | source = "registry+https://github.com/rust-lang/crates.io-index"
2851 | checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82"
2852 |
2853 | [[package]]
2854 | name = "strum"
2855 | version = "0.26.2"
2856 | source = "registry+https://github.com/rust-lang/crates.io-index"
2857 | checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29"
2858 |
2859 | [[package]]
2860 | name = "strum_macros"
2861 | version = "0.26.4"
2862 | source = "registry+https://github.com/rust-lang/crates.io-index"
2863 | checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
2864 | dependencies = [
2865 | "heck",
2866 | "proc-macro2",
2867 | "quote",
2868 | "rustversion",
2869 | "syn",
2870 | ]
2871 |
2872 | [[package]]
2873 | name = "strum_macros"
2874 | version = "0.27.2"
2875 | source = "registry+https://github.com/rust-lang/crates.io-index"
2876 | checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7"
2877 | dependencies = [
2878 | "heck",
2879 | "proc-macro2",
2880 | "quote",
2881 | "syn",
2882 | ]
2883 |
2884 | [[package]]
2885 | name = "subtle"
2886 | version = "2.6.1"
2887 | source = "registry+https://github.com/rust-lang/crates.io-index"
2888 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
2889 |
2890 | [[package]]
2891 | name = "syn"
2892 | version = "2.0.90"
2893 | source = "registry+https://github.com/rust-lang/crates.io-index"
2894 | checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
2895 | dependencies = [
2896 | "proc-macro2",
2897 | "quote",
2898 | "unicode-ident",
2899 | ]
2900 |
2901 | [[package]]
2902 | name = "sync_wrapper"
2903 | version = "1.0.2"
2904 | source = "registry+https://github.com/rust-lang/crates.io-index"
2905 | checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
2906 | dependencies = [
2907 | "futures-core",
2908 | ]
2909 |
2910 | [[package]]
2911 | name = "synstructure"
2912 | version = "0.13.2"
2913 | source = "registry+https://github.com/rust-lang/crates.io-index"
2914 | checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
2915 | dependencies = [
2916 | "proc-macro2",
2917 | "quote",
2918 | "syn",
2919 | ]
2920 |
2921 | [[package]]
2922 | name = "target-lexicon"
2923 | version = "0.13.2"
2924 | source = "registry+https://github.com/rust-lang/crates.io-index"
2925 | checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
2926 |
2927 | [[package]]
2928 | name = "thiserror"
2929 | version = "1.0.61"
2930 | source = "registry+https://github.com/rust-lang/crates.io-index"
2931 | checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
2932 | dependencies = [
2933 | "thiserror-impl 1.0.61",
2934 | ]
2935 |
2936 | [[package]]
2937 | name = "thiserror"
2938 | version = "2.0.5"
2939 | source = "registry+https://github.com/rust-lang/crates.io-index"
2940 | checksum = "643caef17e3128658ff44d85923ef2d28af81bb71e0d67bbfe1d76f19a73e053"
2941 | dependencies = [
2942 | "thiserror-impl 2.0.5",
2943 | ]
2944 |
2945 | [[package]]
2946 | name = "thiserror-impl"
2947 | version = "1.0.61"
2948 | source = "registry+https://github.com/rust-lang/crates.io-index"
2949 | checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
2950 | dependencies = [
2951 | "proc-macro2",
2952 | "quote",
2953 | "syn",
2954 | ]
2955 |
2956 | [[package]]
2957 | name = "thiserror-impl"
2958 | version = "2.0.5"
2959 | source = "registry+https://github.com/rust-lang/crates.io-index"
2960 | checksum = "995d0bbc9995d1f19d28b7215a9352b0fc3cd3a2d2ec95c2cadc485cdedbcdde"
2961 | dependencies = [
2962 | "proc-macro2",
2963 | "quote",
2964 | "syn",
2965 | ]
2966 |
2967 | [[package]]
2968 | name = "tinystr"
2969 | version = "0.8.1"
2970 | source = "registry+https://github.com/rust-lang/crates.io-index"
2971 | checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
2972 | dependencies = [
2973 | "displaydoc",
2974 | "zerovec",
2975 | ]
2976 |
2977 | [[package]]
2978 | name = "tinyvec"
2979 | version = "1.8.0"
2980 | source = "registry+https://github.com/rust-lang/crates.io-index"
2981 | checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
2982 | dependencies = [
2983 | "tinyvec_macros",
2984 | ]
2985 |
2986 | [[package]]
2987 | name = "tinyvec_macros"
2988 | version = "0.1.1"
2989 | source = "registry+https://github.com/rust-lang/crates.io-index"
2990 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
2991 |
2992 | [[package]]
2993 | name = "tokio"
2994 | version = "1.46.1"
2995 | source = "registry+https://github.com/rust-lang/crates.io-index"
2996 | checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17"
2997 | dependencies = [
2998 | "backtrace",
2999 | "bytes",
3000 | "io-uring",
3001 | "libc",
3002 | "mio",
3003 | "pin-project-lite",
3004 | "slab",
3005 | "socket2 0.5.8",
3006 | "tokio-macros",
3007 | "windows-sys 0.52.0",
3008 | ]
3009 |
3010 | [[package]]
3011 | name = "tokio-macros"
3012 | version = "2.5.0"
3013 | source = "registry+https://github.com/rust-lang/crates.io-index"
3014 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
3015 | dependencies = [
3016 | "proc-macro2",
3017 | "quote",
3018 | "syn",
3019 | ]
3020 |
3021 | [[package]]
3022 | name = "tokio-rustls"
3023 | version = "0.26.2"
3024 | source = "registry+https://github.com/rust-lang/crates.io-index"
3025 | checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
3026 | dependencies = [
3027 | "rustls",
3028 | "tokio",
3029 | ]
3030 |
3031 | [[package]]
3032 | name = "tokio-util"
3033 | version = "0.7.13"
3034 | source = "registry+https://github.com/rust-lang/crates.io-index"
3035 | checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078"
3036 | dependencies = [
3037 | "bytes",
3038 | "futures-core",
3039 | "futures-sink",
3040 | "pin-project-lite",
3041 | "tokio",
3042 | ]
3043 |
3044 | [[package]]
3045 | name = "tower"
3046 | version = "0.5.2"
3047 | source = "registry+https://github.com/rust-lang/crates.io-index"
3048 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
3049 | dependencies = [
3050 | "futures-core",
3051 | "futures-util",
3052 | "pin-project-lite",
3053 | "sync_wrapper",
3054 | "tokio",
3055 | "tower-layer",
3056 | "tower-service",
3057 | ]
3058 |
3059 | [[package]]
3060 | name = "tower-http"
3061 | version = "0.6.6"
3062 | source = "registry+https://github.com/rust-lang/crates.io-index"
3063 | checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
3064 | dependencies = [
3065 | "bitflags",
3066 | "bytes",
3067 | "futures-util",
3068 | "http",
3069 | "http-body",
3070 | "iri-string",
3071 | "pin-project-lite",
3072 | "tower",
3073 | "tower-layer",
3074 | "tower-service",
3075 | ]
3076 |
3077 | [[package]]
3078 | name = "tower-layer"
3079 | version = "0.3.3"
3080 | source = "registry+https://github.com/rust-lang/crates.io-index"
3081 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
3082 |
3083 | [[package]]
3084 | name = "tower-service"
3085 | version = "0.3.3"
3086 | source = "registry+https://github.com/rust-lang/crates.io-index"
3087 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
3088 |
3089 | [[package]]
3090 | name = "tracing"
3091 | version = "0.1.41"
3092 | source = "registry+https://github.com/rust-lang/crates.io-index"
3093 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
3094 | dependencies = [
3095 | "pin-project-lite",
3096 | "tracing-attributes",
3097 | "tracing-core",
3098 | ]
3099 |
3100 | [[package]]
3101 | name = "tracing-attributes"
3102 | version = "0.1.30"
3103 | source = "registry+https://github.com/rust-lang/crates.io-index"
3104 | checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
3105 | dependencies = [
3106 | "proc-macro2",
3107 | "quote",
3108 | "syn",
3109 | ]
3110 |
3111 | [[package]]
3112 | name = "tracing-core"
3113 | version = "0.1.34"
3114 | source = "registry+https://github.com/rust-lang/crates.io-index"
3115 | checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
3116 | dependencies = [
3117 | "once_cell",
3118 | ]
3119 |
3120 | [[package]]
3121 | name = "try-lock"
3122 | version = "0.2.5"
3123 | source = "registry+https://github.com/rust-lang/crates.io-index"
3124 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
3125 |
3126 | [[package]]
3127 | name = "typenum"
3128 | version = "1.19.0"
3129 | source = "registry+https://github.com/rust-lang/crates.io-index"
3130 | checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
3131 |
3132 | [[package]]
3133 | name = "unicode-ident"
3134 | version = "1.0.12"
3135 | source = "registry+https://github.com/rust-lang/crates.io-index"
3136 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
3137 |
3138 | [[package]]
3139 | name = "unicode-normalization"
3140 | version = "0.1.24"
3141 | source = "registry+https://github.com/rust-lang/crates.io-index"
3142 | checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
3143 | dependencies = [
3144 | "tinyvec",
3145 | ]
3146 |
3147 | [[package]]
3148 | name = "unicode-reverse"
3149 | version = "1.0.9"
3150 | source = "registry+https://github.com/rust-lang/crates.io-index"
3151 | checksum = "4b6f4888ebc23094adfb574fdca9fdc891826287a6397d2cd28802ffd6f20c76"
3152 | dependencies = [
3153 | "unicode-segmentation",
3154 | ]
3155 |
3156 | [[package]]
3157 | name = "unicode-segmentation"
3158 | version = "1.11.0"
3159 | source = "registry+https://github.com/rust-lang/crates.io-index"
3160 | checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
3161 |
3162 | [[package]]
3163 | name = "unicode-width"
3164 | version = "0.1.13"
3165 | source = "registry+https://github.com/rust-lang/crates.io-index"
3166 | checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
3167 |
3168 | [[package]]
3169 | name = "unindent"
3170 | version = "0.2.3"
3171 | source = "registry+https://github.com/rust-lang/crates.io-index"
3172 | checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce"
3173 |
3174 | [[package]]
3175 | name = "untrusted"
3176 | version = "0.9.0"
3177 | source = "registry+https://github.com/rust-lang/crates.io-index"
3178 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
3179 |
3180 | [[package]]
3181 | name = "unty"
3182 | version = "0.0.4"
3183 | source = "registry+https://github.com/rust-lang/crates.io-index"
3184 | checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
3185 |
3186 | [[package]]
3187 | name = "url"
3188 | version = "2.5.4"
3189 | source = "registry+https://github.com/rust-lang/crates.io-index"
3190 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
3191 | dependencies = [
3192 | "form_urlencoded",
3193 | "idna",
3194 | "percent-encoding",
3195 | ]
3196 |
3197 | [[package]]
3198 | name = "utf8_iter"
3199 | version = "1.0.4"
3200 | source = "registry+https://github.com/rust-lang/crates.io-index"
3201 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
3202 |
3203 | [[package]]
3204 | name = "uuid"
3205 | version = "1.17.0"
3206 | source = "registry+https://github.com/rust-lang/crates.io-index"
3207 | checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
3208 | dependencies = [
3209 | "getrandom 0.3.3",
3210 | "js-sys",
3211 | "serde",
3212 | "wasm-bindgen",
3213 | ]
3214 |
3215 | [[package]]
3216 | name = "value-trait"
3217 | version = "0.12.1"
3218 | source = "registry+https://github.com/rust-lang/crates.io-index"
3219 | checksum = "8e80f0c733af0720a501b3905d22e2f97662d8eacfe082a75ed7ffb5ab08cb59"
3220 | dependencies = [
3221 | "float-cmp",
3222 | "halfbrown",
3223 | "itoa",
3224 | "ryu",
3225 | ]
3226 |
3227 | [[package]]
3228 | name = "version_check"
3229 | version = "0.9.4"
3230 | source = "registry+https://github.com/rust-lang/crates.io-index"
3231 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
3232 |
3233 | [[package]]
3234 | name = "virtue"
3235 | version = "0.0.18"
3236 | source = "registry+https://github.com/rust-lang/crates.io-index"
3237 | checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
3238 |
3239 | [[package]]
3240 | name = "walkdir"
3241 | version = "2.5.0"
3242 | source = "registry+https://github.com/rust-lang/crates.io-index"
3243 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
3244 | dependencies = [
3245 | "same-file",
3246 | "winapi-util",
3247 | ]
3248 |
3249 | [[package]]
3250 | name = "want"
3251 | version = "0.3.1"
3252 | source = "registry+https://github.com/rust-lang/crates.io-index"
3253 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
3254 | dependencies = [
3255 | "try-lock",
3256 | ]
3257 |
3258 | [[package]]
3259 | name = "wasi"
3260 | version = "0.11.0+wasi-snapshot-preview1"
3261 | source = "registry+https://github.com/rust-lang/crates.io-index"
3262 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
3263 |
3264 | [[package]]
3265 | name = "wasi"
3266 | version = "0.14.2+wasi-0.2.4"
3267 | source = "registry+https://github.com/rust-lang/crates.io-index"
3268 | checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
3269 | dependencies = [
3270 | "wit-bindgen-rt",
3271 | ]
3272 |
3273 | [[package]]
3274 | name = "wasm-bindgen"
3275 | version = "0.2.100"
3276 | source = "registry+https://github.com/rust-lang/crates.io-index"
3277 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
3278 | dependencies = [
3279 | "cfg-if",
3280 | "once_cell",
3281 | "rustversion",
3282 | "wasm-bindgen-macro",
3283 | ]
3284 |
3285 | [[package]]
3286 | name = "wasm-bindgen-backend"
3287 | version = "0.2.100"
3288 | source = "registry+https://github.com/rust-lang/crates.io-index"
3289 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
3290 | dependencies = [
3291 | "bumpalo",
3292 | "log",
3293 | "proc-macro2",
3294 | "quote",
3295 | "syn",
3296 | "wasm-bindgen-shared",
3297 | ]
3298 |
3299 | [[package]]
3300 | name = "wasm-bindgen-futures"
3301 | version = "0.4.50"
3302 | source = "registry+https://github.com/rust-lang/crates.io-index"
3303 | checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61"
3304 | dependencies = [
3305 | "cfg-if",
3306 | "js-sys",
3307 | "once_cell",
3308 | "wasm-bindgen",
3309 | "web-sys",
3310 | ]
3311 |
3312 | [[package]]
3313 | name = "wasm-bindgen-macro"
3314 | version = "0.2.100"
3315 | source = "registry+https://github.com/rust-lang/crates.io-index"
3316 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
3317 | dependencies = [
3318 | "quote",
3319 | "wasm-bindgen-macro-support",
3320 | ]
3321 |
3322 | [[package]]
3323 | name = "wasm-bindgen-macro-support"
3324 | version = "0.2.100"
3325 | source = "registry+https://github.com/rust-lang/crates.io-index"
3326 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
3327 | dependencies = [
3328 | "proc-macro2",
3329 | "quote",
3330 | "syn",
3331 | "wasm-bindgen-backend",
3332 | "wasm-bindgen-shared",
3333 | ]
3334 |
3335 | [[package]]
3336 | name = "wasm-bindgen-shared"
3337 | version = "0.2.100"
3338 | source = "registry+https://github.com/rust-lang/crates.io-index"
3339 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
3340 | dependencies = [
3341 | "unicode-ident",
3342 | ]
3343 |
3344 | [[package]]
3345 | name = "wasm-streams"
3346 | version = "0.4.2"
3347 | source = "registry+https://github.com/rust-lang/crates.io-index"
3348 | checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
3349 | dependencies = [
3350 | "futures-util",
3351 | "js-sys",
3352 | "wasm-bindgen",
3353 | "wasm-bindgen-futures",
3354 | "web-sys",
3355 | ]
3356 |
3357 | [[package]]
3358 | name = "web-sys"
3359 | version = "0.3.77"
3360 | source = "registry+https://github.com/rust-lang/crates.io-index"
3361 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
3362 | dependencies = [
3363 | "js-sys",
3364 | "wasm-bindgen",
3365 | ]
3366 |
3367 | [[package]]
3368 | name = "web-time"
3369 | version = "1.1.0"
3370 | source = "registry+https://github.com/rust-lang/crates.io-index"
3371 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
3372 | dependencies = [
3373 | "js-sys",
3374 | "wasm-bindgen",
3375 | ]
3376 |
3377 | [[package]]
3378 | name = "winapi"
3379 | version = "0.3.9"
3380 | source = "registry+https://github.com/rust-lang/crates.io-index"
3381 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
3382 | dependencies = [
3383 | "winapi-i686-pc-windows-gnu",
3384 | "winapi-x86_64-pc-windows-gnu",
3385 | ]
3386 |
3387 | [[package]]
3388 | name = "winapi-i686-pc-windows-gnu"
3389 | version = "0.4.0"
3390 | source = "registry+https://github.com/rust-lang/crates.io-index"
3391 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
3392 |
3393 | [[package]]
3394 | name = "winapi-util"
3395 | version = "0.1.9"
3396 | source = "registry+https://github.com/rust-lang/crates.io-index"
3397 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
3398 | dependencies = [
3399 | "windows-sys 0.59.0",
3400 | ]
3401 |
3402 | [[package]]
3403 | name = "winapi-x86_64-pc-windows-gnu"
3404 | version = "0.4.0"
3405 | source = "registry+https://github.com/rust-lang/crates.io-index"
3406 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
3407 |
3408 | [[package]]
3409 | name = "windows-core"
3410 | version = "0.52.0"
3411 | source = "registry+https://github.com/rust-lang/crates.io-index"
3412 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
3413 | dependencies = [
3414 | "windows-targets",
3415 | ]
3416 |
3417 | [[package]]
3418 | name = "windows-link"
3419 | version = "0.2.1"
3420 | source = "registry+https://github.com/rust-lang/crates.io-index"
3421 | checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
3422 |
3423 | [[package]]
3424 | name = "windows-sys"
3425 | version = "0.52.0"
3426 | source = "registry+https://github.com/rust-lang/crates.io-index"
3427 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
3428 | dependencies = [
3429 | "windows-targets",
3430 | ]
3431 |
3432 | [[package]]
3433 | name = "windows-sys"
3434 | version = "0.59.0"
3435 | source = "registry+https://github.com/rust-lang/crates.io-index"
3436 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
3437 | dependencies = [
3438 | "windows-targets",
3439 | ]
3440 |
3441 | [[package]]
3442 | name = "windows-targets"
3443 | version = "0.52.6"
3444 | source = "registry+https://github.com/rust-lang/crates.io-index"
3445 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
3446 | dependencies = [
3447 | "windows_aarch64_gnullvm",
3448 | "windows_aarch64_msvc",
3449 | "windows_i686_gnu",
3450 | "windows_i686_gnullvm",
3451 | "windows_i686_msvc",
3452 | "windows_x86_64_gnu",
3453 | "windows_x86_64_gnullvm",
3454 | "windows_x86_64_msvc",
3455 | ]
3456 |
3457 | [[package]]
3458 | name = "windows_aarch64_gnullvm"
3459 | version = "0.52.6"
3460 | source = "registry+https://github.com/rust-lang/crates.io-index"
3461 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
3462 |
3463 | [[package]]
3464 | name = "windows_aarch64_msvc"
3465 | version = "0.52.6"
3466 | source = "registry+https://github.com/rust-lang/crates.io-index"
3467 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
3468 |
3469 | [[package]]
3470 | name = "windows_i686_gnu"
3471 | version = "0.52.6"
3472 | source = "registry+https://github.com/rust-lang/crates.io-index"
3473 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
3474 |
3475 | [[package]]
3476 | name = "windows_i686_gnullvm"
3477 | version = "0.52.6"
3478 | source = "registry+https://github.com/rust-lang/crates.io-index"
3479 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
3480 |
3481 | [[package]]
3482 | name = "windows_i686_msvc"
3483 | version = "0.52.6"
3484 | source = "registry+https://github.com/rust-lang/crates.io-index"
3485 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
3486 |
3487 | [[package]]
3488 | name = "windows_x86_64_gnu"
3489 | version = "0.52.6"
3490 | source = "registry+https://github.com/rust-lang/crates.io-index"
3491 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
3492 |
3493 | [[package]]
3494 | name = "windows_x86_64_gnullvm"
3495 | version = "0.52.6"
3496 | source = "registry+https://github.com/rust-lang/crates.io-index"
3497 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
3498 |
3499 | [[package]]
3500 | name = "windows_x86_64_msvc"
3501 | version = "0.52.6"
3502 | source = "registry+https://github.com/rust-lang/crates.io-index"
3503 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
3504 |
3505 | [[package]]
3506 | name = "wit-bindgen-rt"
3507 | version = "0.39.0"
3508 | source = "registry+https://github.com/rust-lang/crates.io-index"
3509 | checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
3510 | dependencies = [
3511 | "bitflags",
3512 | ]
3513 |
3514 | [[package]]
3515 | name = "writeable"
3516 | version = "0.6.1"
3517 | source = "registry+https://github.com/rust-lang/crates.io-index"
3518 | checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
3519 |
3520 | [[package]]
3521 | name = "xxhash-rust"
3522 | version = "0.8.10"
3523 | source = "registry+https://github.com/rust-lang/crates.io-index"
3524 | checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03"
3525 |
3526 | [[package]]
3527 | name = "yoke"
3528 | version = "0.8.0"
3529 | source = "registry+https://github.com/rust-lang/crates.io-index"
3530 | checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
3531 | dependencies = [
3532 | "serde",
3533 | "stable_deref_trait",
3534 | "yoke-derive",
3535 | "zerofrom",
3536 | ]
3537 |
3538 | [[package]]
3539 | name = "yoke-derive"
3540 | version = "0.8.0"
3541 | source = "registry+https://github.com/rust-lang/crates.io-index"
3542 | checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
3543 | dependencies = [
3544 | "proc-macro2",
3545 | "quote",
3546 | "syn",
3547 | "synstructure",
3548 | ]
3549 |
3550 | [[package]]
3551 | name = "zerocopy"
3552 | version = "0.7.34"
3553 | source = "registry+https://github.com/rust-lang/crates.io-index"
3554 | checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087"
3555 | dependencies = [
3556 | "zerocopy-derive",
3557 | ]
3558 |
3559 | [[package]]
3560 | name = "zerocopy-derive"
3561 | version = "0.7.34"
3562 | source = "registry+https://github.com/rust-lang/crates.io-index"
3563 | checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
3564 | dependencies = [
3565 | "proc-macro2",
3566 | "quote",
3567 | "syn",
3568 | ]
3569 |
3570 | [[package]]
3571 | name = "zerofrom"
3572 | version = "0.1.6"
3573 | source = "registry+https://github.com/rust-lang/crates.io-index"
3574 | checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
3575 | dependencies = [
3576 | "zerofrom-derive",
3577 | ]
3578 |
3579 | [[package]]
3580 | name = "zerofrom-derive"
3581 | version = "0.1.6"
3582 | source = "registry+https://github.com/rust-lang/crates.io-index"
3583 | checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
3584 | dependencies = [
3585 | "proc-macro2",
3586 | "quote",
3587 | "syn",
3588 | "synstructure",
3589 | ]
3590 |
3591 | [[package]]
3592 | name = "zeroize"
3593 | version = "1.8.1"
3594 | source = "registry+https://github.com/rust-lang/crates.io-index"
3595 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
3596 |
3597 | [[package]]
3598 | name = "zerotrie"
3599 | version = "0.2.2"
3600 | source = "registry+https://github.com/rust-lang/crates.io-index"
3601 | checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
3602 | dependencies = [
3603 | "displaydoc",
3604 | "yoke",
3605 | "zerofrom",
3606 | ]
3607 |
3608 | [[package]]
3609 | name = "zerovec"
3610 | version = "0.11.2"
3611 | source = "registry+https://github.com/rust-lang/crates.io-index"
3612 | checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
3613 | dependencies = [
3614 | "yoke",
3615 | "zerofrom",
3616 | "zerovec-derive",
3617 | ]
3618 |
3619 | [[package]]
3620 | name = "zerovec-derive"
3621 | version = "0.11.1"
3622 | source = "registry+https://github.com/rust-lang/crates.io-index"
3623 | checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
3624 | dependencies = [
3625 | "proc-macro2",
3626 | "quote",
3627 | "syn",
3628 | ]
3629 |
3630 | [[package]]
3631 | name = "zstd"
3632 | version = "0.13.1"
3633 | source = "registry+https://github.com/rust-lang/crates.io-index"
3634 | checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a"
3635 | dependencies = [
3636 | "zstd-safe",
3637 | ]
3638 |
3639 | [[package]]
3640 | name = "zstd-safe"
3641 | version = "7.1.0"
3642 | source = "registry+https://github.com/rust-lang/crates.io-index"
3643 | checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a"
3644 | dependencies = [
3645 | "zstd-sys",
3646 | ]
3647 |
3648 | [[package]]
3649 | name = "zstd-sys"
3650 | version = "2.0.11+zstd.1.5.6"
3651 | source = "registry+https://github.com/rust-lang/crates.io-index"
3652 | checksum = "75652c55c0b6f3e6f12eb786fe1bc960396bf05a1eb3bf1f3691c3610ac2e6d4"
3653 | dependencies = [
3654 | "cc",
3655 | "pkg-config",
3656 | ]
3657 |
--------------------------------------------------------------------------------