crabxl 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- crabxl-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +46 -0
- crabxl-0.1.0/.github/ISSUE_TEMPLATE/compatibility.yml +32 -0
- crabxl-0.1.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
- crabxl-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +16 -0
- crabxl-0.1.0/.github/actions/setup-supported-python/action.yml +42 -0
- crabxl-0.1.0/.github/pull_request_template.md +15 -0
- crabxl-0.1.0/.github/workflows/docs.yml +30 -0
- crabxl-0.1.0/.github/workflows/python.yml +62 -0
- crabxl-0.1.0/.github/workflows/release.yml +181 -0
- crabxl-0.1.0/.gitignore +10 -0
- crabxl-0.1.0/CHANGELOG.md +47 -0
- crabxl-0.1.0/CONTRIBUTING.md +146 -0
- crabxl-0.1.0/Cargo.lock +590 -0
- crabxl-0.1.0/Cargo.toml +33 -0
- crabxl-0.1.0/LICENSE +21 -0
- crabxl-0.1.0/PKG-INFO +153 -0
- crabxl-0.1.0/README.md +126 -0
- crabxl-0.1.0/SECURITY.md +30 -0
- crabxl-0.1.0/docs/changelog.md +7 -0
- crabxl-0.1.0/docs/compatibility.md +54 -0
- crabxl-0.1.0/docs/guide/charts/anchors.md +99 -0
- crabxl-0.1.0/docs/guide/charts/area.md +102 -0
- crabxl-0.1.0/docs/guide/charts/area.png +0 -0
- crabxl-0.1.0/docs/guide/charts/area3d.png +0 -0
- crabxl-0.1.0/docs/guide/charts/bar.md +123 -0
- crabxl-0.1.0/docs/guide/charts/bar.png +0 -0
- crabxl-0.1.0/docs/guide/charts/bar3d.png +0 -0
- crabxl-0.1.0/docs/guide/charts/bubble.md +62 -0
- crabxl-0.1.0/docs/guide/charts/bubble.png +0 -0
- crabxl-0.1.0/docs/guide/charts/chart-layout.md +139 -0
- crabxl-0.1.0/docs/guide/charts/chart-layout.png +0 -0
- crabxl-0.1.0/docs/guide/charts/chartsheet.md +46 -0
- crabxl-0.1.0/docs/guide/charts/chartsheet.png +0 -0
- crabxl-0.1.0/docs/guide/charts/doughnut.md +69 -0
- crabxl-0.1.0/docs/guide/charts/doughnut.png +0 -0
- crabxl-0.1.0/docs/guide/charts/gauge.md +73 -0
- crabxl-0.1.0/docs/guide/charts/gauge.png +0 -0
- crabxl-0.1.0/docs/guide/charts/graphical.md +87 -0
- crabxl-0.1.0/docs/guide/charts/highlighted.png +0 -0
- crabxl-0.1.0/docs/guide/charts/index.md +58 -0
- crabxl-0.1.0/docs/guide/charts/limits-and-scaling-log.png +0 -0
- crabxl-0.1.0/docs/guide/charts/limits-and-scaling-minmax.png +0 -0
- crabxl-0.1.0/docs/guide/charts/limits-and-scaling-orientation.png +0 -0
- crabxl-0.1.0/docs/guide/charts/limits-and-scaling.md +229 -0
- crabxl-0.1.0/docs/guide/charts/line.md +150 -0
- crabxl-0.1.0/docs/guide/charts/line.png +0 -0
- crabxl-0.1.0/docs/guide/charts/line3d.png +0 -0
- crabxl-0.1.0/docs/guide/charts/meta.json +24 -0
- crabxl-0.1.0/docs/guide/charts/pattern.md +57 -0
- crabxl-0.1.0/docs/guide/charts/pattern.png +0 -0
- crabxl-0.1.0/docs/guide/charts/pie-gradient.png +0 -0
- crabxl-0.1.0/docs/guide/charts/pie.md +192 -0
- crabxl-0.1.0/docs/guide/charts/pie.png +0 -0
- crabxl-0.1.0/docs/guide/charts/pie3d.png +0 -0
- crabxl-0.1.0/docs/guide/charts/projected-pie.png +0 -0
- crabxl-0.1.0/docs/guide/charts/radar.md +67 -0
- crabxl-0.1.0/docs/guide/charts/radar.png +0 -0
- crabxl-0.1.0/docs/guide/charts/scatter.md +60 -0
- crabxl-0.1.0/docs/guide/charts/scatter.png +0 -0
- crabxl-0.1.0/docs/guide/charts/secondary.md +58 -0
- crabxl-0.1.0/docs/guide/charts/secondary.png +0 -0
- crabxl-0.1.0/docs/guide/charts/stock.md +181 -0
- crabxl-0.1.0/docs/guide/charts/stock.png +0 -0
- crabxl-0.1.0/docs/guide/charts/surface.md +143 -0
- crabxl-0.1.0/docs/guide/charts/surface.png +0 -0
- crabxl-0.1.0/docs/guide/comments.md +93 -0
- crabxl-0.1.0/docs/guide/conditional-formatting.md +207 -0
- crabxl-0.1.0/docs/guide/dates.md +101 -0
- crabxl-0.1.0/docs/guide/defined-names.md +104 -0
- crabxl-0.1.0/docs/guide/document-properties.md +63 -0
- crabxl-0.1.0/docs/guide/editing-worksheets.md +81 -0
- crabxl-0.1.0/docs/guide/exercise-1-result.png +0 -0
- crabxl-0.1.0/docs/guide/filters.md +153 -0
- crabxl-0.1.0/docs/guide/filters.png +0 -0
- crabxl-0.1.0/docs/guide/formula-parsing.md +115 -0
- crabxl-0.1.0/docs/guide/formulas.md +65 -0
- crabxl-0.1.0/docs/guide/images.md +24 -0
- crabxl-0.1.0/docs/guide/memory.md +48 -0
- crabxl-0.1.0/docs/guide/meta.json +29 -0
- crabxl-0.1.0/docs/guide/optimized.md +122 -0
- crabxl-0.1.0/docs/guide/pandas.md +102 -0
- crabxl-0.1.0/docs/guide/pivot-tables.md +30 -0
- crabxl-0.1.0/docs/guide/print-settings.md +89 -0
- crabxl-0.1.0/docs/guide/protection.md +70 -0
- crabxl-0.1.0/docs/guide/rich-text.md +144 -0
- crabxl-0.1.0/docs/guide/simple-usage.md +84 -0
- crabxl-0.1.0/docs/guide/styles.md +355 -0
- crabxl-0.1.0/docs/guide/tables.md +142 -0
- crabxl-0.1.0/docs/guide/tutorial.md +388 -0
- crabxl-0.1.0/docs/guide/validation.md +131 -0
- crabxl-0.1.0/docs/guide/worksheet-properties.md +90 -0
- crabxl-0.1.0/docs/index.md +36 -0
- crabxl-0.1.0/docs/meta.json +4 -0
- crabxl-0.1.0/docs/migration.md +58 -0
- crabxl-0.1.0/docs/quick-start.md +51 -0
- crabxl-0.1.0/docs/support.md +33 -0
- crabxl-0.1.0/internal/STATUS.md +89 -0
- crabxl-0.1.0/internal/architecture.md +54 -0
- crabxl-0.1.0/internal/binding-contract.md +52 -0
- crabxl-0.1.0/internal/releases.md +94 -0
- crabxl-0.1.0/internal/roadmap.md +27 -0
- crabxl-0.1.0/pyproject.toml +84 -0
- crabxl-0.1.0/python/crabxl/__init__.py +66 -0
- crabxl-0.1.0/python/crabxl/_features.py +469 -0
- crabxl-0.1.0/python/crabxl/_values.py +142 -0
- crabxl-0.1.0/python/crabxl/cell/__init__.py +18 -0
- crabxl-0.1.0/python/crabxl/cell/cell.py +449 -0
- crabxl-0.1.0/python/crabxl/cell/read_only.py +5 -0
- crabxl-0.1.0/python/crabxl/cell/rich_text.py +298 -0
- crabxl-0.1.0/python/crabxl/cell/text.py +213 -0
- crabxl-0.1.0/python/crabxl/chart/_3d.py +106 -0
- crabxl-0.1.0/python/crabxl/chart/__init__.py +20 -0
- crabxl-0.1.0/python/crabxl/chart/_chart.py +212 -0
- crabxl-0.1.0/python/crabxl/chart/area_chart.py +107 -0
- crabxl-0.1.0/python/crabxl/chart/axis.py +402 -0
- crabxl-0.1.0/python/crabxl/chart/bar_chart.py +145 -0
- crabxl-0.1.0/python/crabxl/chart/bubble_chart.py +68 -0
- crabxl-0.1.0/python/crabxl/chart/chartspace.py +196 -0
- crabxl-0.1.0/python/crabxl/chart/data_source.py +247 -0
- crabxl-0.1.0/python/crabxl/chart/descriptors.py +44 -0
- crabxl-0.1.0/python/crabxl/chart/error_bar.py +63 -0
- crabxl-0.1.0/python/crabxl/chart/label.py +128 -0
- crabxl-0.1.0/python/crabxl/chart/layout.py +75 -0
- crabxl-0.1.0/python/crabxl/chart/legend.py +76 -0
- crabxl-0.1.0/python/crabxl/chart/line_chart.py +130 -0
- crabxl-0.1.0/python/crabxl/chart/marker.py +91 -0
- crabxl-0.1.0/python/crabxl/chart/picture.py +36 -0
- crabxl-0.1.0/python/crabxl/chart/pie_chart.py +186 -0
- crabxl-0.1.0/python/crabxl/chart/pivot.py +66 -0
- crabxl-0.1.0/python/crabxl/chart/plotarea.py +163 -0
- crabxl-0.1.0/python/crabxl/chart/print_settings.py +58 -0
- crabxl-0.1.0/python/crabxl/chart/radar_chart.py +56 -0
- crabxl-0.1.0/python/crabxl/chart/reader.py +33 -0
- crabxl-0.1.0/python/crabxl/chart/reference.py +125 -0
- crabxl-0.1.0/python/crabxl/chart/scatter_chart.py +54 -0
- crabxl-0.1.0/python/crabxl/chart/series.py +198 -0
- crabxl-0.1.0/python/crabxl/chart/series_factory.py +42 -0
- crabxl-0.1.0/python/crabxl/chart/shapes.py +90 -0
- crabxl-0.1.0/python/crabxl/chart/stock_chart.py +55 -0
- crabxl-0.1.0/python/crabxl/chart/surface_chart.py +120 -0
- crabxl-0.1.0/python/crabxl/chart/text.py +79 -0
- crabxl-0.1.0/python/crabxl/chart/title.py +77 -0
- crabxl-0.1.0/python/crabxl/chart/trendline.py +99 -0
- crabxl-0.1.0/python/crabxl/chart/updown_bars.py +32 -0
- crabxl-0.1.0/python/crabxl/chartsheet/__init__.py +3 -0
- crabxl-0.1.0/python/crabxl/chartsheet/chartsheet.py +251 -0
- crabxl-0.1.0/python/crabxl/chartsheet/custom.py +53 -0
- crabxl-0.1.0/python/crabxl/chartsheet/properties.py +25 -0
- crabxl-0.1.0/python/crabxl/chartsheet/protection.py +46 -0
- crabxl-0.1.0/python/crabxl/chartsheet/publish.py +69 -0
- crabxl-0.1.0/python/crabxl/chartsheet/relation.py +95 -0
- crabxl-0.1.0/python/crabxl/chartsheet/views.py +50 -0
- crabxl-0.1.0/python/crabxl/comments/__init__.py +4 -0
- crabxl-0.1.0/python/crabxl/comments/author.py +18 -0
- crabxl-0.1.0/python/crabxl/comments/comment_sheet.py +197 -0
- crabxl-0.1.0/python/crabxl/comments/comments.py +52 -0
- crabxl-0.1.0/python/crabxl/compat/__init__.py +55 -0
- crabxl-0.1.0/python/crabxl/compat/abc.py +9 -0
- crabxl-0.1.0/python/crabxl/compat/numbers.py +46 -0
- crabxl-0.1.0/python/crabxl/compat/product.py +18 -0
- crabxl-0.1.0/python/crabxl/compat/singleton.py +40 -0
- crabxl-0.1.0/python/crabxl/compat/strings.py +25 -0
- crabxl-0.1.0/python/crabxl/descriptors/__init__.py +55 -0
- crabxl-0.1.0/python/crabxl/descriptors/base.py +259 -0
- crabxl-0.1.0/python/crabxl/descriptors/container.py +37 -0
- crabxl-0.1.0/python/crabxl/descriptors/excel.py +108 -0
- crabxl-0.1.0/python/crabxl/descriptors/namespace.py +12 -0
- crabxl-0.1.0/python/crabxl/descriptors/nested.py +116 -0
- crabxl-0.1.0/python/crabxl/descriptors/sequence.py +129 -0
- crabxl-0.1.0/python/crabxl/descriptors/serialisable.py +233 -0
- crabxl-0.1.0/python/crabxl/descriptors/slots.py +18 -0
- crabxl-0.1.0/python/crabxl/drawing/__init__.py +3 -0
- crabxl-0.1.0/python/crabxl/drawing/colors.py +436 -0
- crabxl-0.1.0/python/crabxl/drawing/connector.py +151 -0
- crabxl-0.1.0/python/crabxl/drawing/drawing.py +84 -0
- crabxl-0.1.0/python/crabxl/drawing/effect.py +408 -0
- crabxl-0.1.0/python/crabxl/drawing/fill.py +426 -0
- crabxl-0.1.0/python/crabxl/drawing/geometry.py +585 -0
- crabxl-0.1.0/python/crabxl/drawing/graphic.py +177 -0
- crabxl-0.1.0/python/crabxl/drawing/image.py +78 -0
- crabxl-0.1.0/python/crabxl/drawing/line.py +145 -0
- crabxl-0.1.0/python/crabxl/drawing/picture.py +151 -0
- crabxl-0.1.0/python/crabxl/drawing/properties.py +190 -0
- crabxl-0.1.0/python/crabxl/drawing/relation.py +16 -0
- crabxl-0.1.0/python/crabxl/drawing/spreadsheet_drawing.py +130 -0
- crabxl-0.1.0/python/crabxl/drawing/text.py +718 -0
- crabxl-0.1.0/python/crabxl/drawing/xdr.py +30 -0
- crabxl-0.1.0/python/crabxl/formatting/__init__.py +3 -0
- crabxl-0.1.0/python/crabxl/formatting/formatting.py +103 -0
- crabxl-0.1.0/python/crabxl/formatting/rule.py +398 -0
- crabxl-0.1.0/python/crabxl/formula/__init__.py +5 -0
- crabxl-0.1.0/python/crabxl/formula/tokenizer.py +246 -0
- crabxl-0.1.0/python/crabxl/formula/translate.py +73 -0
- crabxl-0.1.0/python/crabxl/optimized.py +904 -0
- crabxl-0.1.0/python/crabxl/packaging/__init__.py +4 -0
- crabxl-0.1.0/python/crabxl/packaging/core.py +130 -0
- crabxl-0.1.0/python/crabxl/packaging/custom.py +254 -0
- crabxl-0.1.0/python/crabxl/packaging/extended.py +139 -0
- crabxl-0.1.0/python/crabxl/packaging/interface.py +48 -0
- crabxl-0.1.0/python/crabxl/packaging/manifest.py +170 -0
- crabxl-0.1.0/python/crabxl/packaging/relationship.py +137 -0
- crabxl-0.1.0/python/crabxl/packaging/workbook.py +196 -0
- crabxl-0.1.0/python/crabxl/pivot/__init__.py +32 -0
- crabxl-0.1.0/python/crabxl/pivot/_loaded.py +102 -0
- crabxl-0.1.0/python/crabxl/pivot/cache.py +977 -0
- crabxl-0.1.0/python/crabxl/pivot/fields.py +330 -0
- crabxl-0.1.0/python/crabxl/pivot/record.py +89 -0
- crabxl-0.1.0/python/crabxl/pivot/table.py +1375 -0
- crabxl-0.1.0/python/crabxl/reader/__init__.py +1 -0
- crabxl-0.1.0/python/crabxl/reader/excel.py +3 -0
- crabxl-0.1.0/python/crabxl/reader/strings.py +39 -0
- crabxl-0.1.0/python/crabxl/resources.py +149 -0
- crabxl-0.1.0/python/crabxl/styles/__init__.py +27 -0
- crabxl-0.1.0/python/crabxl/styles/_base.py +313 -0
- crabxl-0.1.0/python/crabxl/styles/_collections.py +92 -0
- crabxl-0.1.0/python/crabxl/styles/_x/__init__.py +10 -0
- crabxl-0.1.0/python/crabxl/styles/_x/alignment.py +85 -0
- crabxl-0.1.0/python/crabxl/styles/_x/borders.py +138 -0
- crabxl-0.1.0/python/crabxl/styles/_x/colors.py +227 -0
- crabxl-0.1.0/python/crabxl/styles/_x/fills.py +237 -0
- crabxl-0.1.0/python/crabxl/styles/_x/fonts.py +147 -0
- crabxl-0.1.0/python/crabxl/styles/_x/numbers.py +197 -0
- crabxl-0.1.0/python/crabxl/styles/_x/protection.py +17 -0
- crabxl-0.1.0/python/crabxl/styles/alignment.py +65 -0
- crabxl-0.1.0/python/crabxl/styles/borders.py +85 -0
- crabxl-0.1.0/python/crabxl/styles/builtins.py +1397 -0
- crabxl-0.1.0/python/crabxl/styles/cell_style.py +215 -0
- crabxl-0.1.0/python/crabxl/styles/colors.py +126 -0
- crabxl-0.1.0/python/crabxl/styles/differential.py +124 -0
- crabxl-0.1.0/python/crabxl/styles/fills.py +146 -0
- crabxl-0.1.0/python/crabxl/styles/fonts.py +87 -0
- crabxl-0.1.0/python/crabxl/styles/named_styles.py +394 -0
- crabxl-0.1.0/python/crabxl/styles/numbers.py +3 -0
- crabxl-0.1.0/python/crabxl/styles/protection.py +12 -0
- crabxl-0.1.0/python/crabxl/styles/proxy.py +5 -0
- crabxl-0.1.0/python/crabxl/styles/styleable.py +139 -0
- crabxl-0.1.0/python/crabxl/styles/stylesheet.py +201 -0
- crabxl-0.1.0/python/crabxl/styles/table.py +119 -0
- crabxl-0.1.0/python/crabxl/utils/__init__.py +15 -0
- crabxl-0.1.0/python/crabxl/utils/bound_dictionary.py +25 -0
- crabxl-0.1.0/python/crabxl/utils/cell.py +246 -0
- crabxl-0.1.0/python/crabxl/utils/dataframe.py +88 -0
- crabxl-0.1.0/python/crabxl/utils/datetime.py +147 -0
- crabxl-0.1.0/python/crabxl/utils/escape.py +42 -0
- crabxl-0.1.0/python/crabxl/utils/exceptions.py +29 -0
- crabxl-0.1.0/python/crabxl/utils/formulas.py +382 -0
- crabxl-0.1.0/python/crabxl/utils/indexed_list.py +49 -0
- crabxl-0.1.0/python/crabxl/utils/inference.py +67 -0
- crabxl-0.1.0/python/crabxl/utils/protection.py +22 -0
- crabxl-0.1.0/python/crabxl/utils/units.py +112 -0
- crabxl-0.1.0/python/crabxl/workbook/__init__.py +3 -0
- crabxl-0.1.0/python/crabxl/workbook/child.py +153 -0
- crabxl-0.1.0/python/crabxl/workbook/defined_name.py +188 -0
- crabxl-0.1.0/python/crabxl/workbook/external_link/__init__.py +3 -0
- crabxl-0.1.0/python/crabxl/workbook/external_link/external.py +186 -0
- crabxl-0.1.0/python/crabxl/workbook/external_reference.py +15 -0
- crabxl-0.1.0/python/crabxl/workbook/function_group.py +37 -0
- crabxl-0.1.0/python/crabxl/workbook/loader.py +109 -0
- crabxl-0.1.0/python/crabxl/workbook/properties.py +151 -0
- crabxl-0.1.0/python/crabxl/workbook/protection.py +180 -0
- crabxl-0.1.0/python/crabxl/workbook/smart_tags.py +57 -0
- crabxl-0.1.0/python/crabxl/workbook/views.py +155 -0
- crabxl-0.1.0/python/crabxl/workbook/web.py +112 -0
- crabxl-0.1.0/python/crabxl/workbook/workbook.py +721 -0
- crabxl-0.1.0/python/crabxl/worksheet/__init__.py +3 -0
- crabxl-0.1.0/python/crabxl/worksheet/_cell_cache.py +43 -0
- crabxl-0.1.0/python/crabxl/worksheet/cell_range.py +201 -0
- crabxl-0.1.0/python/crabxl/worksheet/cell_watch.py +35 -0
- crabxl-0.1.0/python/crabxl/worksheet/controls.py +108 -0
- crabxl-0.1.0/python/crabxl/worksheet/custom.py +35 -0
- crabxl-0.1.0/python/crabxl/worksheet/datavalidation.py +219 -0
- crabxl-0.1.0/python/crabxl/worksheet/dimensions.py +578 -0
- crabxl-0.1.0/python/crabxl/worksheet/drawing.py +15 -0
- crabxl-0.1.0/python/crabxl/worksheet/errors.py +93 -0
- crabxl-0.1.0/python/crabxl/worksheet/filters.py +576 -0
- crabxl-0.1.0/python/crabxl/worksheet/formula.py +70 -0
- crabxl-0.1.0/python/crabxl/worksheet/header_footer.py +277 -0
- crabxl-0.1.0/python/crabxl/worksheet/hyperlink.py +199 -0
- crabxl-0.1.0/python/crabxl/worksheet/merge.py +237 -0
- crabxl-0.1.0/python/crabxl/worksheet/multi_cell_range.py +90 -0
- crabxl-0.1.0/python/crabxl/worksheet/ole.py +134 -0
- crabxl-0.1.0/python/crabxl/worksheet/page.py +175 -0
- crabxl-0.1.0/python/crabxl/worksheet/pagebreak.py +89 -0
- crabxl-0.1.0/python/crabxl/worksheet/picture.py +9 -0
- crabxl-0.1.0/python/crabxl/worksheet/print_settings.py +175 -0
- crabxl-0.1.0/python/crabxl/worksheet/properties.py +94 -0
- crabxl-0.1.0/python/crabxl/worksheet/protection.py +149 -0
- crabxl-0.1.0/python/crabxl/worksheet/related.py +14 -0
- crabxl-0.1.0/python/crabxl/worksheet/scenario.py +103 -0
- crabxl-0.1.0/python/crabxl/worksheet/smart_tag.py +78 -0
- crabxl-0.1.0/python/crabxl/worksheet/table.py +385 -0
- crabxl-0.1.0/python/crabxl/worksheet/views.py +155 -0
- crabxl-0.1.0/python/crabxl/worksheet/worksheet.py +1319 -0
- crabxl-0.1.0/python/crabxl/xml/__init__.py +47 -0
- crabxl-0.1.0/python/crabxl/xml/_preserve.py +170 -0
- crabxl-0.1.0/python/crabxl/xml/constants.py +131 -0
- crabxl-0.1.0/python/crabxl/xml/functions.py +61 -0
- crabxl-0.1.0/rust-toolchain.toml +4 -0
- crabxl-0.1.0/src/dimensions.rs +183 -0
- crabxl-0.1.0/src/editor.rs +471 -0
- crabxl-0.1.0/src/features.rs +932 -0
- crabxl-0.1.0/src/functions.rs +268 -0
- crabxl-0.1.0/src/hyperlink_views.rs +199 -0
- crabxl-0.1.0/src/images.rs +117 -0
- crabxl-0.1.0/src/imports.rs +23 -0
- crabxl-0.1.0/src/lib.rs +98 -0
- crabxl-0.1.0/src/reader.rs +557 -0
- crabxl-0.1.0/src/resources.rs +177 -0
- crabxl-0.1.0/src/rich_text.rs +120 -0
- crabxl-0.1.0/src/streaming/writer.rs +887 -0
- crabxl-0.1.0/src/streaming.rs +280 -0
- crabxl-0.1.0/src/style_owners.rs +471 -0
- crabxl-0.1.0/src/styles.rs +440 -0
- crabxl-0.1.0/src/values.rs +452 -0
- crabxl-0.1.0/src/workbook.rs +247 -0
- crabxl-0.1.0/src/worksheet/hyperlinks.rs +116 -0
- crabxl-0.1.0/src/worksheet/rows.rs +84 -0
- crabxl-0.1.0/src/worksheet.rs +1197 -0
- crabxl-0.1.0/tests/conftest.py +53 -0
- crabxl-0.1.0/tests/test_a12_compat.py +309 -0
- crabxl-0.1.0/tests/test_alpha11_integration.py +284 -0
- crabxl-0.1.0/tests/test_charts.py +422 -0
- crabxl-0.1.0/tests/test_compression.py +70 -0
- crabxl-0.1.0/tests/test_dimensions.py +107 -0
- crabxl-0.1.0/tests/test_features.py +1387 -0
- crabxl-0.1.0/tests/test_hyperlinks.py +117 -0
- crabxl-0.1.0/tests/test_images.py +270 -0
- crabxl-0.1.0/tests/test_merges.py +201 -0
- crabxl-0.1.0/tests/test_nonfinite.py +60 -0
- crabxl-0.1.0/tests/test_optimized.py +644 -0
- crabxl-0.1.0/tests/test_parity.py +2335 -0
- crabxl-0.1.0/tests/test_plain_append.py +84 -0
- crabxl-0.1.0/tests/test_resources.py +375 -0
- crabxl-0.1.0/tests/test_rich_text.py +247 -0
- crabxl-0.1.0/tests/test_structured_formulas.py +426 -0
- crabxl-0.1.0/tests/test_tokenizer.py +110 -0
- crabxl-0.1.0/tests/test_upstream_translate.py +197 -0
- crabxl-0.1.0/tests/test_upstream_workbook.py +146 -0
- crabxl-0.1.0/tests/test_upstream_worksheet.py +299 -0
- crabxl-0.1.0/tests/test_xml_preserve.py +66 -0
- crabxl-0.1.0/third_party/README.md +31 -0
- crabxl-0.1.0/third_party/licenses/openpyxl-MIT.txt +23 -0
- crabxl-0.1.0/third_party/python-formula-tests.json +28 -0
- crabxl-0.1.0/third_party/python-tests.json +58 -0
- crabxl-0.1.0/third_party/python-workbook-tests.json +37 -0
- crabxl-0.1.0/tools/check_release_files.py +106 -0
- crabxl-0.1.0/tools/openpyxl_suite_expected.json +339 -0
- crabxl-0.1.0/tools/platform_wheels.py +80 -0
- crabxl-0.1.0/tools/release.py +89 -0
- crabxl-0.1.0/tools/release_tag.py +42 -0
- crabxl-0.1.0/tools/run_openpyxl_suite.py +216 -0
- crabxl-0.1.0/tools/test_distribution.py +32 -0
- crabxl-0.1.0/tools/verify_openpyxl_corpus.py +282 -0
- crabxl-0.1.0/tools/verify_python_test_provenance.py +61 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: CrabXL gives an incorrect result, an error or a crash.
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: input
|
|
6
|
+
id: version
|
|
7
|
+
attributes:
|
|
8
|
+
label: CrabXL version
|
|
9
|
+
description: Run `python -c "import crabxl; print(crabxl.__version__)"`.
|
|
10
|
+
placeholder: 0.1.0
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: input
|
|
14
|
+
id: environment
|
|
15
|
+
attributes:
|
|
16
|
+
label: Python version and platform
|
|
17
|
+
placeholder: CPython 3.13, Linux x86_64
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: problem
|
|
22
|
+
attributes:
|
|
23
|
+
label: Problem
|
|
24
|
+
description: What did CrabXL do? Include the full traceback.
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
- type: textarea
|
|
28
|
+
id: expected
|
|
29
|
+
attributes:
|
|
30
|
+
label: Expected result
|
|
31
|
+
description: What did you expect? If openpyxl gives a different result, tell us.
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
34
|
+
- type: textarea
|
|
35
|
+
id: reproduce
|
|
36
|
+
attributes:
|
|
37
|
+
label: Steps to reproduce
|
|
38
|
+
description: Give the smallest code that shows the problem.
|
|
39
|
+
render: python
|
|
40
|
+
validations:
|
|
41
|
+
required: true
|
|
42
|
+
- type: textarea
|
|
43
|
+
id: file
|
|
44
|
+
attributes:
|
|
45
|
+
label: Input file
|
|
46
|
+
description: Attach the smallest .xlsx file that shows the problem. Remove confidential data first.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Difference from openpyxl
|
|
2
|
+
description: Code that works with openpyxl 3.1.5 fails or gives a different result with CrabXL.
|
|
3
|
+
labels: [compatibility]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: code
|
|
7
|
+
attributes:
|
|
8
|
+
label: Code
|
|
9
|
+
description: Give the smallest code that shows the difference.
|
|
10
|
+
render: python
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: openpyxl
|
|
15
|
+
attributes:
|
|
16
|
+
label: openpyxl result
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: crabxl
|
|
21
|
+
attributes:
|
|
22
|
+
label: CrabXL result
|
|
23
|
+
description: For example, a NotImplementedError or a different value.
|
|
24
|
+
validations:
|
|
25
|
+
required: true
|
|
26
|
+
- type: input
|
|
27
|
+
id: version
|
|
28
|
+
attributes:
|
|
29
|
+
label: CrabXL version
|
|
30
|
+
placeholder: 0.1.0
|
|
31
|
+
validations:
|
|
32
|
+
required: true
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Rust core problem
|
|
4
|
+
url: https://github.com/crabxl/crabxl/issues/new/choose
|
|
5
|
+
about: Report problems with the Rust API in the crabxl repository.
|
|
6
|
+
- name: Security vulnerability
|
|
7
|
+
url: https://github.com/crabxl/crabxl-python/security/advisories/new
|
|
8
|
+
about: Report a vulnerability privately. Do not open a public issue.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest a new capability or an API improvement.
|
|
3
|
+
labels: [enhancement]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: need
|
|
7
|
+
attributes:
|
|
8
|
+
label: Need
|
|
9
|
+
description: What do you want to do? Why can you not do it now?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposal
|
|
16
|
+
description: How could the API look? Give example code if possible.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Set up supported CPython versions
|
|
2
|
+
description: Install all supported interpreters on one runner; leave Python 3.14 as the builder.
|
|
3
|
+
outputs:
|
|
4
|
+
python-311:
|
|
5
|
+
description: CPython 3.11 executable
|
|
6
|
+
value: ${{ steps.py311.outputs.python-path }}
|
|
7
|
+
python-312:
|
|
8
|
+
description: CPython 3.12 executable
|
|
9
|
+
value: ${{ steps.py312.outputs.python-path }}
|
|
10
|
+
python-313:
|
|
11
|
+
description: CPython 3.13 executable
|
|
12
|
+
value: ${{ steps.py313.outputs.python-path }}
|
|
13
|
+
python-314:
|
|
14
|
+
description: CPython 3.14 executable
|
|
15
|
+
value: ${{ steps.py314.outputs.python-path }}
|
|
16
|
+
python-315:
|
|
17
|
+
description: CPython 3.15 executable
|
|
18
|
+
value: ${{ steps.py315.outputs.python-path }}
|
|
19
|
+
runs:
|
|
20
|
+
using: composite
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/setup-python@v7
|
|
23
|
+
id: py311
|
|
24
|
+
with:
|
|
25
|
+
python-version: '3.11'
|
|
26
|
+
- uses: actions/setup-python@v7
|
|
27
|
+
id: py312
|
|
28
|
+
with:
|
|
29
|
+
python-version: '3.12'
|
|
30
|
+
- uses: actions/setup-python@v7
|
|
31
|
+
id: py313
|
|
32
|
+
with:
|
|
33
|
+
python-version: '3.13'
|
|
34
|
+
- uses: actions/setup-python@v7
|
|
35
|
+
id: py315
|
|
36
|
+
with:
|
|
37
|
+
python-version: '3.15'
|
|
38
|
+
allow-prereleases: true
|
|
39
|
+
- uses: actions/setup-python@v7
|
|
40
|
+
id: py314
|
|
41
|
+
with:
|
|
42
|
+
python-version: '3.14'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## Change
|
|
2
|
+
|
|
3
|
+
<!-- What does this pull request change, and why? -->
|
|
4
|
+
|
|
5
|
+
Closes #
|
|
6
|
+
|
|
7
|
+
## Checks
|
|
8
|
+
|
|
9
|
+
- [ ] `ruff format --check .` and `ruff check .`
|
|
10
|
+
- [ ] `cargo fmt -- --check` and `cargo clippy --all-targets --locked -- -D warnings`
|
|
11
|
+
- [ ] `python -m pytest tests -q`
|
|
12
|
+
- [ ] Behavior matches openpyxl 3.1.5, or the difference is an explicit error.
|
|
13
|
+
- [ ] Selected openpyxl test assertions are unchanged.
|
|
14
|
+
- [ ] User documentation in `docs/` is updated, if behavior changed.
|
|
15
|
+
- [ ] Performance claims include measurements.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Documentation
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths: [docs/**]
|
|
7
|
+
pull_request:
|
|
8
|
+
paths: [docs/**]
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
check:
|
|
15
|
+
uses: crabxl/crabxl-docs/.github/workflows/check-docs.yml@main
|
|
16
|
+
|
|
17
|
+
rebuild-site:
|
|
18
|
+
needs: check
|
|
19
|
+
if: github.event_name == 'push'
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- name: Start a rebuild of the documentation site
|
|
23
|
+
env:
|
|
24
|
+
HOOK: ${{ secrets.DOCS_DEPLOY_HOOK }}
|
|
25
|
+
run: |
|
|
26
|
+
if [ -z "$HOOK" ]; then
|
|
27
|
+
echo "::notice::DOCS_DEPLOY_HOOK is not set. The daily rebuild includes this change."
|
|
28
|
+
exit 0
|
|
29
|
+
fi
|
|
30
|
+
curl -fsS -X POST "$HOOK"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: Python compatibility
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
pull_request:
|
|
5
|
+
permissions:
|
|
6
|
+
contents: read
|
|
7
|
+
jobs:
|
|
8
|
+
quality:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v7
|
|
12
|
+
- uses: actions/setup-python@v7
|
|
13
|
+
with:
|
|
14
|
+
python-version: '3.14'
|
|
15
|
+
- run: python -m pip install 'ruff>=0.16.10,<0.17'
|
|
16
|
+
- run: ruff format --check .
|
|
17
|
+
- run: ruff check .
|
|
18
|
+
adapter:
|
|
19
|
+
needs: quality
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v7
|
|
23
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
24
|
+
with:
|
|
25
|
+
components: rustfmt, clippy
|
|
26
|
+
- uses: ./.github/actions/setup-supported-python
|
|
27
|
+
id: pythons
|
|
28
|
+
- run: cargo fmt -- --check
|
|
29
|
+
- run: cargo clippy --all-targets --locked -- -D warnings
|
|
30
|
+
- run: python -m pip install 'maturin>=1.15,<2'
|
|
31
|
+
- name: Build all five wheels with shared Rust dependencies
|
|
32
|
+
env:
|
|
33
|
+
PYTHON_PATHS: ${{ toJSON(steps.pythons.outputs) }}
|
|
34
|
+
run: python tools/platform_wheels.py build
|
|
35
|
+
- name: Test each wheel in its matching clean Python environment
|
|
36
|
+
env:
|
|
37
|
+
PYTHON_PATHS: ${{ toJSON(steps.pythons.outputs) }}
|
|
38
|
+
run: python tools/platform_wheels.py test
|
|
39
|
+
- run: maturin sdist --out dist
|
|
40
|
+
- uses: actions/upload-artifact@v7
|
|
41
|
+
with:
|
|
42
|
+
name: python-packages-linux-x86_64
|
|
43
|
+
path: dist/*
|
|
44
|
+
if-no-files-found: error
|
|
45
|
+
|
|
46
|
+
native-platforms:
|
|
47
|
+
needs: quality
|
|
48
|
+
strategy:
|
|
49
|
+
matrix:
|
|
50
|
+
os: [windows-latest, macos-latest]
|
|
51
|
+
runs-on: ${{ matrix.os }}
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v7
|
|
54
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
55
|
+
- uses: actions/setup-python@v7
|
|
56
|
+
with:
|
|
57
|
+
python-version: '3.14'
|
|
58
|
+
- run: python -m pip install maturin "pytest>=9.1.1,<10" "openpyxl==3.1.5" "Pillow>=12.3" "lxml>=6.1.3"
|
|
59
|
+
- run: maturin build --release --locked --out dist
|
|
60
|
+
- shell: bash
|
|
61
|
+
run: python -m pip install dist/*.whl
|
|
62
|
+
- run: python -m pytest tests -q
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
name: Release Python
|
|
2
|
+
|
|
3
|
+
# Push a version tag, for example 0.1.0, to release that commit.
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- '[0-9]+.[0-9]+.[0-9]+'
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: python-release
|
|
14
|
+
cancel-in-progress: false
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
validate:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
outputs:
|
|
20
|
+
version: ${{ steps.request.outputs.version }}
|
|
21
|
+
notes: ${{ steps.request.outputs.notes }}
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v7
|
|
24
|
+
with:
|
|
25
|
+
fetch-depth: 0
|
|
26
|
+
- uses: actions/setup-python@v7
|
|
27
|
+
with:
|
|
28
|
+
python-version: '3.14'
|
|
29
|
+
- run: python -m pip install 'ruff>=0.16.10,<0.17'
|
|
30
|
+
- run: ruff format --check .
|
|
31
|
+
- run: ruff check .
|
|
32
|
+
- name: Validate the tag, the committed version and the changelog
|
|
33
|
+
id: request
|
|
34
|
+
env:
|
|
35
|
+
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
|
|
36
|
+
run: python tools/release_tag.py
|
|
37
|
+
|
|
38
|
+
package:
|
|
39
|
+
needs: validate
|
|
40
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
41
|
+
strategy:
|
|
42
|
+
fail-fast: false
|
|
43
|
+
matrix:
|
|
44
|
+
platform:
|
|
45
|
+
- name: linux-x86_64
|
|
46
|
+
runner: ubuntu-24.04
|
|
47
|
+
target: x86_64-unknown-linux-gnu
|
|
48
|
+
- name: linux-aarch64
|
|
49
|
+
runner: ubuntu-24.04-arm
|
|
50
|
+
target: aarch64-unknown-linux-gnu
|
|
51
|
+
- name: windows-x86_64
|
|
52
|
+
runner: windows-latest
|
|
53
|
+
target: x86_64-pc-windows-msvc
|
|
54
|
+
- name: macos-x86_64
|
|
55
|
+
runner: macos-15-intel
|
|
56
|
+
target: x86_64-apple-darwin
|
|
57
|
+
- name: macos-arm64
|
|
58
|
+
runner: macos-15
|
|
59
|
+
target: aarch64-apple-darwin
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@v7
|
|
62
|
+
- uses: ./.github/actions/setup-supported-python
|
|
63
|
+
id: pythons
|
|
64
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
65
|
+
with:
|
|
66
|
+
components: rustfmt, clippy
|
|
67
|
+
- run: cargo fmt -- --check
|
|
68
|
+
- run: cargo clippy --all-targets --locked -- -D warnings
|
|
69
|
+
- name: Build portable Linux wheels
|
|
70
|
+
if: runner.os == 'Linux'
|
|
71
|
+
uses: PyO3/maturin-action@v1
|
|
72
|
+
with:
|
|
73
|
+
maturin-version: 'v1.15.0'
|
|
74
|
+
rust-toolchain: 'stable'
|
|
75
|
+
target: ${{ matrix.platform.target }}
|
|
76
|
+
manylinux: '2_28'
|
|
77
|
+
args: >-
|
|
78
|
+
--release --locked --out dist --interpreter
|
|
79
|
+
/opt/python/cp311-cp311/bin/python
|
|
80
|
+
/opt/python/cp312-cp312/bin/python
|
|
81
|
+
/opt/python/cp313-cp313/bin/python
|
|
82
|
+
/opt/python/cp314-cp314/bin/python
|
|
83
|
+
/opt/python/cp315-cp315/bin/python
|
|
84
|
+
- name: Install the native package builder
|
|
85
|
+
if: runner.os != 'Linux'
|
|
86
|
+
run: python -m pip install 'maturin>=1.15,<2'
|
|
87
|
+
- name: Build Windows and macOS wheels
|
|
88
|
+
if: runner.os != 'Linux'
|
|
89
|
+
env:
|
|
90
|
+
PYTHON_PATHS: ${{ toJSON(steps.pythons.outputs) }}
|
|
91
|
+
run: python tools/platform_wheels.py build --target ${{ matrix.platform.target }}
|
|
92
|
+
- name: Test all five installed CPython wheels
|
|
93
|
+
env:
|
|
94
|
+
PYTHON_PATHS: ${{ toJSON(steps.pythons.outputs) }}
|
|
95
|
+
run: python tools/platform_wheels.py test
|
|
96
|
+
- uses: actions/upload-artifact@v7
|
|
97
|
+
with:
|
|
98
|
+
name: release-wheel-${{ matrix.platform.name }}
|
|
99
|
+
path: dist/*.whl
|
|
100
|
+
if-no-files-found: error
|
|
101
|
+
|
|
102
|
+
source:
|
|
103
|
+
needs: validate
|
|
104
|
+
runs-on: ubuntu-latest
|
|
105
|
+
steps:
|
|
106
|
+
- uses: actions/checkout@v7
|
|
107
|
+
- uses: actions/setup-python@v7
|
|
108
|
+
with:
|
|
109
|
+
python-version: '3.14'
|
|
110
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
111
|
+
- run: python -m pip install 'maturin>=1.15,<2'
|
|
112
|
+
- run: maturin sdist --out dist
|
|
113
|
+
- name: Build and test from the source distribution
|
|
114
|
+
run: python tools/test_distribution.py '*.tar.gz'
|
|
115
|
+
- uses: actions/upload-artifact@v7
|
|
116
|
+
with:
|
|
117
|
+
name: release-source
|
|
118
|
+
path: dist/*.tar.gz
|
|
119
|
+
if-no-files-found: error
|
|
120
|
+
|
|
121
|
+
publish:
|
|
122
|
+
needs: [validate, package, source]
|
|
123
|
+
runs-on: ubuntu-latest
|
|
124
|
+
environment: pypi
|
|
125
|
+
permissions:
|
|
126
|
+
id-token: write
|
|
127
|
+
contents: read
|
|
128
|
+
steps:
|
|
129
|
+
- uses: actions/checkout@v7
|
|
130
|
+
with:
|
|
131
|
+
fetch-depth: 0
|
|
132
|
+
- uses: actions/setup-python@v7
|
|
133
|
+
with:
|
|
134
|
+
python-version: '3.14'
|
|
135
|
+
- uses: actions/download-artifact@v8
|
|
136
|
+
with:
|
|
137
|
+
pattern: release-*
|
|
138
|
+
path: dist
|
|
139
|
+
merge-multiple: true
|
|
140
|
+
- name: Verify artifact identities and safe retries
|
|
141
|
+
env:
|
|
142
|
+
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
|
|
143
|
+
run: python tools/check_release_files.py "$RELEASE_VERSION"
|
|
144
|
+
- name: Publish to PyPI using OIDC
|
|
145
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
146
|
+
with:
|
|
147
|
+
packages-dir: dist/
|
|
148
|
+
skip-existing: true
|
|
149
|
+
|
|
150
|
+
release:
|
|
151
|
+
needs: [validate, publish]
|
|
152
|
+
runs-on: ubuntu-latest
|
|
153
|
+
permissions:
|
|
154
|
+
contents: write
|
|
155
|
+
steps:
|
|
156
|
+
- uses: actions/checkout@v7
|
|
157
|
+
with:
|
|
158
|
+
fetch-depth: 0
|
|
159
|
+
- uses: actions/setup-python@v7
|
|
160
|
+
with:
|
|
161
|
+
python-version: '3.14'
|
|
162
|
+
- uses: actions/download-artifact@v8
|
|
163
|
+
with:
|
|
164
|
+
pattern: release-*
|
|
165
|
+
path: dist
|
|
166
|
+
merge-multiple: true
|
|
167
|
+
- name: Recheck the version and create the GitHub release
|
|
168
|
+
env:
|
|
169
|
+
GH_TOKEN: ${{ github.token }}
|
|
170
|
+
GH_REPO: ${{ github.repository }}
|
|
171
|
+
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
|
|
172
|
+
RELEASE_NOTES: ${{ needs.validate.outputs.notes }}
|
|
173
|
+
run: |
|
|
174
|
+
python tools/release.py check "$RELEASE_VERSION"
|
|
175
|
+
printf '%s\n' "$RELEASE_NOTES" > "$RUNNER_TEMP/release-notes.md"
|
|
176
|
+
if gh release view "$RELEASE_VERSION" > /dev/null 2>&1; then
|
|
177
|
+
gh release upload "$RELEASE_VERSION" dist/* --clobber
|
|
178
|
+
else
|
|
179
|
+
gh release create "$RELEASE_VERSION" dist/* --verify-tag \
|
|
180
|
+
--title "$RELEASE_VERSION" --notes-file "$RUNNER_TEMP/release-notes.md"
|
|
181
|
+
fi
|
crabxl-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
4
|
+
Before version 1.0, a minor version can change the API.
|
|
5
|
+
|
|
6
|
+
Each release uses a pinned revision of the Rust core. The core has its own
|
|
7
|
+
[changelog](https://github.com/crabxl/crabxl/blob/main/CHANGELOG.md).
|
|
8
|
+
|
|
9
|
+
## [0.1.0]
|
|
10
|
+
|
|
11
|
+
First release. It uses the Rust core 0.1.0.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `Workbook`, `load_workbook`, `Worksheet` and `Cell` with openpyxl call names,
|
|
16
|
+
in normal, `read_only` and `write_only` modes. Paths and file-like objects.
|
|
17
|
+
- Values, dates, formulas with cached results and rich text.
|
|
18
|
+
- Cell styles (`Font`, `PatternFill`, `GradientFill`, `Border`, `Alignment`,
|
|
19
|
+
`Protection`, number formats), named styles, themes, row and column styles,
|
|
20
|
+
`cell.quotePrefix` and `cell.pivotButton`.
|
|
21
|
+
- Merged cells, row and column dimensions, outline groups and hyperlinks,
|
|
22
|
+
including in `write_only` mode.
|
|
23
|
+
- Sheet create, copy, remove, rename and move; `append`, `insert_rows`,
|
|
24
|
+
`delete_rows`, `insert_cols`, `delete_cols` and `move_range`.
|
|
25
|
+
- Tables, auto filters, conditional formatting, data validation, comments,
|
|
26
|
+
sheet protection, headers and footers, print areas and titles, defined
|
|
27
|
+
names, scenarios, workbook protection and document properties.
|
|
28
|
+
- Images, charts, chartsheets, drawings, pivot tables, external links and
|
|
29
|
+
`wb.vba_archive`.
|
|
30
|
+
- `ws.sheet_properties` and `ws.sheet_format` in all modes.
|
|
31
|
+
- The openpyxl import paths, for example `crabxl.worksheet.table`,
|
|
32
|
+
`crabxl.formatting.rule` and `crabxl.comments`, and the deprecated openpyxl
|
|
33
|
+
3.1 calls such as `get_sheet_by_name`, which emit a `DeprecationWarning`.
|
|
34
|
+
- `max_memory_bytes`, `ResourceOptions`, `ResourceLimits`,
|
|
35
|
+
`SharedStringOptions` and `AutoMemory` to control memory, temporary storage
|
|
36
|
+
and shared strings.
|
|
37
|
+
- `save(path, compression_level=...)`. Level 0 stores without compression;
|
|
38
|
+
levels 1–9 use Deflate; the default is 6.
|
|
39
|
+
- Rows of plain values (`None`, `bool`, `int`, `float`, `str` and dates and
|
|
40
|
+
times) are converted in Rust when appended.
|
|
41
|
+
- `tools/run_openpyxl_suite.py` runs the unchanged openpyxl 3.1.5 test suite
|
|
42
|
+
against crabxl and checks the result against a tracked list of expected
|
|
43
|
+
failures. `--report` writes the compatibility page of the documentation.
|
|
44
|
+
- The user guide, adapted from the openpyxl documentation, and pages for
|
|
45
|
+
memory limits, migration, supported features and compatibility.
|
|
46
|
+
|
|
47
|
+
[0.1.0]: https://github.com/crabxl/crabxl-python/releases/tag/0.1.0
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Contributing to CrabXL for Python
|
|
2
|
+
|
|
3
|
+
## Ways to contribute
|
|
4
|
+
|
|
5
|
+
- **Report a bug.** Use the [issue forms](https://github.com/crabxl/crabxl-python/issues/new/choose).
|
|
6
|
+
Give the CrabXL version, the Python version and the smallest code or `.xlsx`
|
|
7
|
+
file that shows the problem. Remove confidential data first.
|
|
8
|
+
- **Report a difference from openpyxl.** CrabXL must behave like openpyxl
|
|
9
|
+
3.1.5. Give the code, the openpyxl result and the CrabXL result.
|
|
10
|
+
- **Improve the documentation.** User documentation is in [docs](docs). The
|
|
11
|
+
documentation site is built from it by
|
|
12
|
+
[crabxl-docs](https://github.com/crabxl/crabxl-docs).
|
|
13
|
+
- **Contribute code.** For a change that is larger than a small fix, open an
|
|
14
|
+
issue first. Agree on the design before you start the work.
|
|
15
|
+
|
|
16
|
+
Do not report security problems in public issues. Read [SECURITY.md](SECURITY.md).
|
|
17
|
+
|
|
18
|
+
## How this package works
|
|
19
|
+
|
|
20
|
+
This package does not implement spreadsheet features itself. The Rust core in
|
|
21
|
+
[crabxl](https://github.com/crabxl/crabxl) implements them. This package adapts
|
|
22
|
+
the core to the openpyxl API.
|
|
23
|
+
|
|
24
|
+
- If a feature is missing in the core, add it to the core first.
|
|
25
|
+
- `Cargo.toml` pins the core to an exact Git revision. A change that needs a
|
|
26
|
+
new core feature also updates this revision.
|
|
27
|
+
- An unsupported feature raises an explicit error, usually
|
|
28
|
+
`NotImplementedError`. The package never falls back to openpyxl.
|
|
29
|
+
|
|
30
|
+
## Repository layout
|
|
31
|
+
|
|
32
|
+
| Path | Contents |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `python/crabxl` | Public Python package. Its modules follow the openpyxl module layout. |
|
|
35
|
+
| `src/` | PyO3 bindings to the Rust core. |
|
|
36
|
+
| `tests/` | Tests. Files named `test_upstream_*.py` contain selected openpyxl tests. |
|
|
37
|
+
| `third_party/` | Provenance and licenses of the selected openpyxl tests. |
|
|
38
|
+
| `docs/` | Public user documentation. |
|
|
39
|
+
| `internal/` | Maintainer records: [status](internal/STATUS.md), roadmap, architecture, design decisions and release evidence. |
|
|
40
|
+
| `tools/` | Release, wheel and provenance scripts. |
|
|
41
|
+
|
|
42
|
+
## Development setup
|
|
43
|
+
|
|
44
|
+
You need:
|
|
45
|
+
|
|
46
|
+
- Python 3.11 or later.
|
|
47
|
+
- Rust 1.99 or later, installed with [rustup](https://rustup.rs/). The
|
|
48
|
+
repository uses the latest stable toolchain. If the build reports that it
|
|
49
|
+
requires a newer `rustc`, run `rustup update stable`.
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
git clone https://github.com/crabxl/crabxl-python.git
|
|
53
|
+
cd crabxl-python
|
|
54
|
+
python -m venv .venv
|
|
55
|
+
source .venv/bin/activate
|
|
56
|
+
python -m pip install "maturin>=1.15,<2"
|
|
57
|
+
python -m pip install -e ".[test,dev]"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The editable install builds the native extension. After you change Rust code in
|
|
61
|
+
`src/`, build it again:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
maturin develop --release
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Checks
|
|
68
|
+
|
|
69
|
+
CI runs these checks. Run them before you open a pull request:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
ruff format --check .
|
|
73
|
+
ruff check .
|
|
74
|
+
cargo fmt -- --check
|
|
75
|
+
cargo clippy --all-targets --locked -- -D warnings
|
|
76
|
+
python -m pytest tests -q
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
CI also builds and tests wheels for all supported Python versions on Linux,
|
|
80
|
+
Windows and macOS.
|
|
81
|
+
|
|
82
|
+
## Code rules
|
|
83
|
+
|
|
84
|
+
- **Match openpyxl.** Use the same call names, arguments, object access and
|
|
85
|
+
observable behavior as openpyxl 3.1.5. Extensions are permitted, but keep
|
|
86
|
+
them separate from compatible calls.
|
|
87
|
+
- **Fail explicitly.** If a feature is not supported, raise an error. Do not
|
|
88
|
+
accept a property that is lost on save.
|
|
89
|
+
- **Keep work in Rust.** Convert values in batches. Release the GIL during
|
|
90
|
+
native work.
|
|
91
|
+
- **Write in English** in code, comments, documentation and commit messages.
|
|
92
|
+
|
|
93
|
+
### Tests
|
|
94
|
+
|
|
95
|
+
- Add tests that compare the CrabXL result with the openpyxl result for the
|
|
96
|
+
same public calls.
|
|
97
|
+
- Do not change the assertions of the selected openpyxl tests. Their bodies are
|
|
98
|
+
recorded in `third_party/`. To verify them, run
|
|
99
|
+
`python tools/verify_python_test_provenance.py --reference-checkout <path>`
|
|
100
|
+
with a checkout of openpyxl 3.1.5.
|
|
101
|
+
- Mark expected failures explicitly. Do not count them as passes.
|
|
102
|
+
- Do not put timing limits in tests. Measure performance with [crabxl-benchmarks](https://github.com/crabxl/crabxl-benchmarks).
|
|
103
|
+
|
|
104
|
+
### Performance changes
|
|
105
|
+
|
|
106
|
+
If you claim a speed or memory improvement, include the measurements. Compare
|
|
107
|
+
the same mode and the same behavior in CrabXL and openpyxl. Give the time, peak
|
|
108
|
+
memory and the commands that you used.
|
|
109
|
+
|
|
110
|
+
### Code from other projects
|
|
111
|
+
|
|
112
|
+
You can copy code from another project, including openpyxl, if its license is
|
|
113
|
+
compatible with MIT. Keep the original copyright notice and add the project to
|
|
114
|
+
[third_party/](third_party).
|
|
115
|
+
|
|
116
|
+
### Design decisions
|
|
117
|
+
|
|
118
|
+
Explain large design changes in the pull request.
|
|
119
|
+
|
|
120
|
+
## Documentation style
|
|
121
|
+
|
|
122
|
+
Follow the [writing rules](https://github.com/crabxl/crabxl-docs/blob/main/WRITING.md)
|
|
123
|
+
and the [page format](https://github.com/crabxl/crabxl-docs/blob/main/CONTENT-SPEC.md).
|
|
124
|
+
CI checks them with Vale.
|
|
125
|
+
|
|
126
|
+
## Commits and pull requests
|
|
127
|
+
|
|
128
|
+
- Use [Conventional Commits](https://www.conventionalcommits.org/):
|
|
129
|
+
`<type>(<scope>): <description>`. For example:
|
|
130
|
+
`fix(worksheet): keep merged cells after a row insertion`. Common types are
|
|
131
|
+
`feat`, `fix`, `docs`, `refactor`, `perf`, `test`, `build`, `ci` and `chore`.
|
|
132
|
+
- Put one coherent change in each commit. Related code, tests and documentation
|
|
133
|
+
can be in the same commit. Put unrelated changes in separate commits.
|
|
134
|
+
- Describe the result, not the work process.
|
|
135
|
+
- Complete the pull request template. Link the related issue. Make sure that CI
|
|
136
|
+
passes.
|
|
137
|
+
|
|
138
|
+
## Releases
|
|
139
|
+
|
|
140
|
+
Maintainers make releases with the release workflow. You do not need to change
|
|
141
|
+
version numbers. [internal/releases.md](internal/releases.md) describes the
|
|
142
|
+
process.
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
You agree that your contributions are licensed under the [MIT License](LICENSE).
|