Polars expression plugin for refkit citation and BibTeX workflows
Project description
polars-refkit
polars-refkit adds Rust-backed Polars expressions for BibTeX and BibLaTeX columns. It imports as polars_refkit.
Install
pip install polars-refkit
The supported Python versions, Polars dependency, native wheel ABI, and Pyodide target are declared in package metadata and release workflows.
Render And Inspect Rows
import polars as pl
import polars_refkit as prk
df = pl.DataFrame(
{
"bibtex": [
"""
@article{doe2024, title={Fast Citations}, year={2024}}
@book{roe2022, title={Batch References}, year={2022}}
""",
],
"key": ["doe2024"],
"keys": [["doe2024", "roe2022"]],
}
)
out = df.select(
citation=pl.col("bibtex").refkit.cite(pl.col("key")),
literal_citation=pl.col("bibtex").refkit.cite(pl.lit("doe2024")),
each_citation=pl.col("bibtex").refkit.cite_each(pl.col("keys")),
grouped_citation=pl.col("bibtex").refkit.cite_group(pl.col("keys")),
bibliography=pl.col("bibtex").refkit.full_bibliography_html(),
formatted=pl.col("bibtex").refkit.tidy_bibtex(sort_fields=True),
count=pl.col("bibtex").refkit.entry_count(),
keys=pl.col("bibtex").refkit.keys(),
entries=pl.col("bibtex").refkit.entries(),
)
Each row is one BibTeX or BibLaTeX source. The expressions run inside eager DataFrame.select and lazy LazyFrame.select(...).collect() plans. Row-level parse and formatting failures return null for value expressions. Use diagnostics, parse_report, or tidy_bibtex_report when a query needs row messages.
recovery="error" uses strict parsing. In a Polars expression, a strict row parse failure returns null for value expressions, False from can_parse, and a failed parse_report instead of aborting the query. recovery="report" keeps recoverable entries in that row and preserves parser diagnostics.
String arguments name columns. Use pl.lit(...) for literal BibTeX sources or citation keys:
keys = pl.DataFrame({"key": ["doe2024"]})
out = keys.select(citation=pl.lit(df["bibtex"][0]).refkit.cite(pl.col("key")))
Use cite_each when one row has an ordered list of citation keys and each key should render as a separate citation:
batch = pl.DataFrame({"keys": [["doe2024", "roe2022"]]})
out = batch.select(citations=pl.lit(df["bibtex"][0]).refkit.cite_each(pl.col("keys")))
Use cite_group when one row has an ordered list of citation keys and the list should render as one grouped citation:
batch = pl.DataFrame({"keys": [["doe2024", "roe2022"]]})
out = batch.select(citation=pl.lit(df["bibtex"][0]).refkit.cite_group(pl.col("keys")))
Use tidy_bibtex to format BibTeX rows in the same query plan:
out = df.select(
formatted=pl.col("bibtex").refkit.tidy_bibtex(sort_fields=True, wrap=88),
report=pl.col("bibtex").refkit.tidy_bibtex_report(sort_fields=True),
)
tidy_bibtex_report returns {ok, bibtex, count, warnings, error}. warnings is a list of {code, rule, message} structs. Invalid static option values raise during query construction or execution.
Top-level functions and namespace methods use stable default output names, so multiple expressions over the same bibtex column can be selected without manual aliases. Use alias or named select expressions when a result column needs a different name.
Capabilities
| Capability | Polars surface |
|---|---|
| Read normalized bibliography data | entry_count, can_parse, has_diagnostics, keys, entries, parse_report, diagnostics |
| Render citations | cite, cite_html, cite_rendered, cite_each, cite_group, and their HTML or struct variants |
| Render bibliographies | full_bibliography_text, full_bibliography_html, full_bibliography_rendered |
| Format BibTeX | tidy_bibtex, tidy_bibtex_report |
| Inspect entries | keys, entries, to_hayagriva_json |
| Process dataframe columns | eager DataFrame.select and lazy LazyFrame.select(...).collect() |
| Use expression namespace | pl.Expr.refkit methods with the same capability set |
Expressions
| Function | Return | Behavior |
|---|---|---|
cite(bibtex_col, key_col, style="apa", locale="en-US", recovery="error") |
String |
Renders one citation as text. Missing keys and row parse failures return null. |
cite_html(bibtex_col, key_col, style="apa", locale="en-US", recovery="error") |
String |
Renders one citation as escaped HTML. |
cite_rendered(bibtex_col, key_col, style="apa", locale="en-US", recovery="error") |
Struct[text, html] |
Renders one citation with both text and HTML fields. |
cite_each(bibtex_col, keys_col, style="apa", locale="en-US", recovery="error") |
List[String] |
Renders each key in a List[String] column as a separate citation. Missing keys and row parse failures return null for the row. |
cite_each_html(bibtex_col, keys_col, style="apa", locale="en-US", recovery="error") |
List[String] |
Renders each key as separate citation HTML. |
cite_each_rendered(bibtex_col, keys_col, style="apa", locale="en-US", recovery="error") |
List[Struct[text, html]] |
Renders each key as a separate citation struct. |
cite_group(bibtex_col, keys_col, style="apa", locale="en-US", recovery="error") |
String |
Renders one grouped citation from a List[String] key column. |
cite_group_html(bibtex_col, keys_col, style="apa", locale="en-US", recovery="error") |
String |
Renders one grouped citation as HTML. |
cite_group_rendered(bibtex_col, keys_col, style="apa", locale="en-US", recovery="error") |
Struct[text, html] |
Renders one grouped citation with both text and HTML fields. |
full_bibliography_html(bibtex_col, style="apa", locale="en-US", recovery="error") |
String |
Renders all entries in the row as an HTML bibliography. Row parse failures return null. |
full_bibliography_text(bibtex_col, style="apa", locale="en-US", recovery="error") |
String |
Renders all entries in the row as plain text. |
full_bibliography_rendered(bibtex_col, style="apa", locale="en-US", recovery="error") |
Struct[text, html] |
Renders all entries in the row with both bibliography formats. |
entry_count(bibtex_col, recovery="error") |
UInt32 |
Counts normalized entries in each BibTeX string. |
can_parse(bibtex_col, recovery="error") |
Boolean |
Returns whether the row can produce a normalized library. |
has_diagnostics(bibtex_col, recovery="error") |
Boolean |
Returns whether parsing produced diagnostics. |
keys(bibtex_col, recovery="error") |
List[String] |
Returns normalized entry keys in source order. |
entries(bibtex_col, fields=("key", "title", "doi", "volume"), recovery="error") |
List[Struct] |
Projects normalized entries into Polars-native rows. |
parse_report(bibtex_col, recovery="error") |
Struct[ok, entry_count, keys, diagnostics] |
Parses each row once and returns a summary struct. |
diagnostics(bibtex_col, recovery="error") |
List[String] |
Returns an empty list for valid rows and parse messages for invalid rows. |
to_hayagriva_json(bibtex_col, recovery="error") |
String |
Returns normalized Hayagriva entry JSON with id and key fields. |
tidy_bibtex(bibtex_col, sort_fields=False, wrap=False, ...) |
String |
Formats each BibTeX row. Row formatting failures return null. |
tidy_bibtex_report(bibtex_col, sort_fields=False, wrap=False, ...) |
Struct[ok, bibtex, count, warnings, error] |
Formats each row and reports formatter warnings or row errors. |
Expression Namespace
The same operations are available from pl.Expr.refkit.
out = df.select(
keys=pl.col("bibtex").refkit.keys(),
count=pl.col("bibtex").refkit.entry_count(),
citation=pl.col("bibtex").refkit.cite(pl.col("key")),
each_citation=pl.col("bibtex").refkit.cite_each(pl.col("keys")),
grouped_citation=pl.col("bibtex").refkit.cite_group(pl.col("keys")),
entries=pl.col("bibtex").refkit.entries(),
hayagriva_json=pl.col("bibtex").refkit.to_hayagriva_json(),
formatted=pl.col("bibtex").refkit.tidy_bibtex(sort_fields=True),
)
Top-level functions and namespace methods expose one name per capability. They return expressions with names that match the method, such as keys, entry_count, cite, to_hayagriva_json, and tidy_bibtex. Name outputs in select, with_columns, or alias when a call site needs a different column name.
Typed code can cast the namespace when the type checker does not know Polars plugin namespaces:
from typing import cast
namespace = cast(prk.RefkitExprNamespace, pl.col("bibtex").refkit)
out = df.select(citation=namespace.cite(pl.col("key")))
entries returns a list of structs. Explode and unnest it to query entries as rows:
entries = (
df.select(entries=pl.col("bibtex").refkit.entries())
.explode("entries")
.unnest("entries")
)
Scope
Use polars-refkit when BibTeX source lives in a dataframe and the result should stay in a Polars query plan. Use refkit.BibDocument when a workflow edits raw documents with comments, preambles, string definitions, failed blocks, ordering, and source spans.
Development
uv sync --all-packages --group dev
(cd packages/polars-refkit && uv run maturin develop)
uv run pytest packages/polars-refkit/tests --no-cov
License
polars-refkit is licensed under the Apache License, Version 2.0, available in LICENSE. See NOTICE for upstream citation and bibliography component acknowledgements.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file polars_refkit-0.0.4rc1.tar.gz.
File metadata
- Download URL: polars_refkit-0.0.4rc1.tar.gz
- Upload date:
- Size: 84.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3379bfd675ebee36e0466f2a1b6082d6bf5566cdb67aa997de4ba486da70efb1
|
|
| MD5 |
87b549e588ff8b3ce17190de13588b3e
|
|
| BLAKE2b-256 |
28b19ea922eec7d7805d3a735fb39c291e26714296b2b4124251cb5e636964c9
|
File details
Details for the file polars_refkit-0.0.4rc1-cp311-abi3-win_amd64.whl.
File metadata
- Download URL: polars_refkit-0.0.4rc1-cp311-abi3-win_amd64.whl
- Upload date:
- Size: 6.4 MB
- Tags: CPython 3.11+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3853d6317d674f1f5c3a2cac95d12aced762df31f3a863269d51b9ef7ab127fe
|
|
| MD5 |
ca5681dcbf21fc787405c1c593a8af01
|
|
| BLAKE2b-256 |
ab38f7cb74a41e95272d123094743b4ed710f6f703852818a0d8958995b0f3fd
|
File details
Details for the file polars_refkit-0.0.4rc1-cp311-abi3-pyemscripten_2026_0_wasm32.whl.
File metadata
- Download URL: polars_refkit-0.0.4rc1-cp311-abi3-pyemscripten_2026_0_wasm32.whl
- Upload date:
- Size: 3.7 MB
- Tags: CPython 3.11+, PyEmscripten 2026.0 wasm32
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00f818b2c7d285ce5fcf0de4b57a8ab4ca5e7d76b1b99b1622d8a9286321f3ff
|
|
| MD5 |
85fe6ae31908664a5114ce4c2caf6bbe
|
|
| BLAKE2b-256 |
0cfbfeeb275f05533062911b096b38d047c4faac65f865503f79a5e91e6e27b8
|
File details
Details for the file polars_refkit-0.0.4rc1-cp311-abi3-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: polars_refkit-0.0.4rc1-cp311-abi3-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 6.4 MB
- Tags: CPython 3.11+, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2f7f4f22deb08f7d13dda4a590ed8c8a15e0c3b5e1f72b36c9ec9b4dce25507
|
|
| MD5 |
fdb5935aaab0db364dac80e3f8a8118b
|
|
| BLAKE2b-256 |
89b15bb885005ef96de895a2a9b5d795ebd57362ac6f46d8c643e5e663d2da76
|
File details
Details for the file polars_refkit-0.0.4rc1-cp311-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: polars_refkit-0.0.4rc1-cp311-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 5.5 MB
- Tags: CPython 3.11+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f317381416de39594fda8e9c94db36fd65eaf898bdbd38dfc640c46ead02f4dc
|
|
| MD5 |
702799dab86efaa92b8d13773b12cf38
|
|
| BLAKE2b-256 |
becea11823e9dbc149d74899250d0d5a47da9c46451414ba7eaa1d7289014052
|