Skip to content

feat(table): locale-aware CSV and TSV exports - #10661

Draft
kirangadhave wants to merge 10 commits into
mainfrom
kg/mo-7455-locale-table-export
Draft

feat(table): locale-aware CSV and TSV exports#10661
kirangadhave wants to merge 10 commits into
mainfrom
kg/mo-7455-locale-table-export

Conversation

@kirangadhave

@kirangadhave kirangadhave commented Aug 26, 2026

Copy link
Copy Markdown
Member

Summary

  • CSV and TSV table exports now use the resolved frontend locale for numeric decimal separators. File download and clipboard copy share one backend artifact.
  • JSON, Parquet, and Markdown stay locale-neutral. locale is optional so older clients keep today's comma/dot CSV. An explicit download_csv_separator still wins.
  • Comma-decimal locales (e.g. pt-BR) use ; as the default CSV field separator. No thousands grouping.

Closes #10658

kirangadhave and others added 5 commits August 25, 2026 16:17
CSV and TSV downloads need the browser decimal separator on the wire.
Keep locale optional so older clients can still send only format.

Co-authored-by: Cursor <cursoragent@cursor.com>
CSV and TSV need a shared field and decimal separator policy so adapters
can format numbers without rewriting completed text. Default-table
exports stay locale-neutral unless a dialect is provided.
Pandas and Polars already wrap Narwhals, so locale decimal formatting
belongs in one writer. Adapters only prepare index and nested columns.
Copilot AI lite review requested due to automatic review settings August 26, 2026 06:32
@vercel

vercel Bot commented Aug 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview Aug 27, 2026 6:14pm

Request Review

@github-actions github-actions Bot added the bash-focus Area to focus on during release bug bash label Aug 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds locale-aware numeric formatting for CSV/TSV table exports by passing a browser-resolved locale (specifically the decimal separator) from the frontend to the backend export pipeline, while keeping JSON/Parquet/Markdown locale-neutral and preserving legacy behavior when locale is omitted.

Changes:

  • Introduces a shared “delimited dialect” model (field + decimal separators) and uses it for both file downloads and clipboard copy requests.
  • Updates table manager implementations (default/pandas/polars/narwhals) plus the narwhals CSV utility to support locale-specific decimal separators (no thousands grouping; semicolon CSV for comma-decimal locales by default).
  • Adds backend + frontend test coverage for locale resolution, dialect selection, and export output parity across CSV/TSV vs locale-neutral formats.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/_utils/test_narwhals_utils.py Adds CSV export tests for comma and Unicode decimal separators.
tests/_plugins/ui/_impl/utils/test_dataframe_utils.py Adds download-as tests covering pt-BR CSV/TSV behavior, legacy behavior, and locale-neutral JSON.
tests/_plugins/ui/_impl/test_table.py Verifies locale is optional in args parsing and that table downloads honor locale for CSV/TSV only.
tests/_plugins/ui/_impl/tables/test_polars_table.py Adds to_delimited_str tests for polars manager across decimal/exponent/non-finite/unicode cases.
tests/_plugins/ui/_impl/tables/test_pandas_table.py Adds to_delimited_str tests for pandas manager across decimal/exponent/non-finite/unicode cases.
tests/_plugins/ui/_impl/tables/test_narwhals_table.py New tests for narwhals table manager delimited exports and locale neutrality of CSV.
tests/_plugins/ui/_impl/tables/test_delimited.py New tests for dialect resolution rules and locale validation.
tests/_plugins/ui/_impl/tables/test_default_table.py Adds default table delimited export tests (no grouping, quoting rules, unicode decimal, neutrality).
tests/_plugins/ui/_impl/dataframes/test_dataframe.py Adds dataframe UI element download tests ensuring locale-aware CSV/TSV and locale-neutral JSON/Parquet.
packages/openapi/src/api.ts Regenerates/moves OpenAPI component type ordering (no functional change).
packages/openapi/api.yaml Regenerates/moves OpenAPI component ordering (no functional change).
marimo/_utils/narwhals_utils.py Extends dataframe_to_csv with optional dialect support and decimal separator formatting path.
marimo/_plugins/ui/_impl/utils/dataframe.py Threads optional locale through download_as and unifies CSV/TSV export via delimited serialization.
marimo/_plugins/ui/_impl/tables/table_manager.py Adds to_delimited_str default API to TableManager interface.
marimo/_plugins/ui/_impl/tables/polars_table.py Routes delimited export through dataframe_to_csv with dialect and improves error handling for narwhals compute errors.
marimo/_plugins/ui/_impl/tables/pandas_table.py Routes delimited export through narwhals CSV utility, including index-as-columns handling.
marimo/_plugins/ui/_impl/tables/narwhals_table.py Implements to_delimited_str and updates CSV path to use dialect defaults.
marimo/_plugins/ui/_impl/tables/delimited.py New module defining locale/dialect types, dialect resolution, and numeric formatting helpers.
marimo/_plugins/ui/_impl/tables/default_table.py Implements delimited export with numeric decimal replacement using resolved dialect.
marimo/_plugins/ui/_impl/table.py Extends download args with optional locale and forwards it into export pipeline.
marimo/_plugins/ui/_impl/dataframes/dataframe.py Forwards optional locale into dataframe export pipeline.
frontend/src/components/data-table/schemas.ts Extends RPC schema/types to accept optional locale.
frontend/src/components/data-table/export-locale.ts New helper to resolve decimal separator from Intl.NumberFormat(...).formatToParts.
frontend/src/components/data-table/export-actions.tsx Uses useLocale() to attach locale to CSV/TSV download/copy requests and factors request-building helpers.
frontend/src/components/data-table/tests/export-locale.test.ts Adds tests for locale resolution and schema acceptance of optional locale.
frontend/src/components/data-table/tests/export-actions.test.tsx Adds tests ensuring parity between download and clipboard requests (locale included only for CSV/TSV).
frontend/plugins.openapi.yaml Updates generated frontend OpenAPI schema to include optional locale for download_as inputs.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread marimo/_utils/narwhals_utils.py Outdated
Comment thread marimo/_plugins/ui/_impl/tables/delimited.py Outdated
Comment thread marimo/_plugins/ui/_impl/dataframes/dataframe.py Outdated
Comment thread marimo/_plugins/ui/_impl/table.py Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread marimo/_plugins/ui/_impl/tables/polars_table.py Outdated
Comment thread tests/_plugins/ui/_impl/dataframes/test_dataframe.py
Comment thread marimo/_plugins/ui/_impl/tables/pandas_table.py Outdated
Comment thread marimo/_plugins/ui/_impl/utils/dataframe.py Outdated
Comment thread marimo/_plugins/ui/_impl/tables/delimited.py Outdated
Comment thread marimo/_utils/narwhals_utils.py Outdated
@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for ./frontend

Status Category Percentage Covered / Total
🔵 Lines 56.19% 20972 / 37317
🔵 Statements 56.11% 21339 / 38027
🔵 Functions 49.07% 4703 / 9583
🔵 Branches 49.53% 10782 / 21765
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
frontend/src/components/data-table/export-actions.tsx 51.16% 35.71% 52.38% 51.19% 124, 170-177, 181-192, 204-207, 216, 221, 230-238, 242, 247-282, 333-369
frontend/src/components/data-table/export-locale.ts 87.5% 85.71% 100% 87.5% 24-26
frontend/src/components/data-table/schemas.ts 100% 100% 100% 100%
Generated in workflow #20840 for commit ef964c5 by the Vitest Coverage Report Action

Comment thread marimo/_plugins/ui/_impl/tables/table_manager.py Outdated
Locale-aware delimited serialization bypassed Polars normalization, changed pandas index headers and Windows line endings, and rejected empty configured separators.

Keep locale policy in the table layer while moving serialization primitives below it. Return structured locale validation errors without hiding unrelated export failures.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 16 files (changes from recent commits).

You’re at about 92% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread marimo/_plugins/ui/_impl/dataframes/dataframe.py
Comment thread marimo/_plugins/ui/_impl/tables/polars_table.py Outdated
Comment thread marimo/_utils/delimited.py Outdated
Structured export errors must stop file and clipboard actions before empty URLs reach the browser. Polars also needs a safe fallback for nested containers that cannot use its native string cast.

Preserve the fast scalar path, serialize complex nested cells as JSON, and expose numeric narrowing through a TypeGuard.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 6 files (changes from recent commits).

You’re at about 92% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread frontend/src/components/data-table/__tests__/export-actions.test.tsx Outdated
Download and clipboard rows exposed the same accessible name, which let the
download error regression test pass through either action. Give each action a
distinct name so assistive technology and tests can select it reliably.

Pandas-native CSV output also follows the platform line separator. Compare the
compatibility tests with pandas output so the Windows job does not assume LF.

@Light2Dark Light2Dark left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5.6 Sol on Codex

I found one pandas export regression to address.

The updated frontend sends a locale for every CSV and TSV request, including en-US. That means pandas exports now use PandasTableManager.to_delimited_str. For a dataframe with an unnamed, non-default index, this method calls with_index_as_columns(), which gives the index a synthetic name.

Before this PR, pandas produces:

,value
10,1.5

With this PR, the same export produces:

Index0,value
10,1.5

Unnamed MultiIndex levels similarly become Index0, Index1, and so on. This changes the exported column schema even though the feature should only change field and decimal separators.

Light2Dark
Light2Dark previously approved these changes Aug 27, 2026

@Light2Dark Light2Dark left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bash-focus Area to focus on during release bug bash bug Something isn't working team-draft

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Table export not following Locale

3 participants