From fabcea6370cdca38068dec07a70386f0bf264570 Mon Sep 17 00:00:00 2001 From: David Beal Date: Thu, 24 Oct 2024 04:05:23 +0200 Subject: [PATCH] [ADD] polars_process: process polars dataframe from file or database --- polars_process/README.rst | 115 +++++ polars_process/__init__.py | 2 + polars_process/__manifest__.py | 34 ++ polars_process/data/action.xml | 10 + polars_process/data/demo.xml | 38 ++ polars_process/models/__init__.py | 4 + polars_process/models/dataframe.py | 81 ++++ polars_process/models/df_field.py | 29 ++ polars_process/models/df_source.py | 85 ++++ polars_process/models/ir_model_fields.py | 14 + polars_process/pyproject.toml | 3 + polars_process/readme/DESCRIPTION.md | 27 ++ polars_process/security/ir.model.access.xml | 41 ++ polars_process/static/description/icon.png | Bin 0 -> 2605 bytes polars_process/static/description/index.html | 453 ++++++++++++++++++ polars_process/tests/__init__.py | 1 + polars_process/tests/files/4_fields.xlsx | Bin 0 -> 5433 bytes .../tests/files/missing_required_column.xlsx | Bin 0 -> 5335 bytes polars_process/tests/files/wrong_date.xlsx | Bin 0 -> 5414 bytes polars_process/tests/test_module.py | 39 ++ polars_process/views/dataframe.xml | 65 +++ polars_process/views/df_field.xml | 24 + polars_process/views/df_source.xml | 24 + polars_process/views/menu.xml | 33 ++ polars_process/wizards/__init__.py | 1 + polars_process/wizards/df_process.py | 125 +++++ polars_process/wizards/df_process.xml | 48 ++ requirements.txt | 3 + 28 files changed, 1299 insertions(+) create mode 100644 polars_process/README.rst create mode 100644 polars_process/__init__.py create mode 100644 polars_process/__manifest__.py create mode 100644 polars_process/data/action.xml create mode 100644 polars_process/data/demo.xml create mode 100644 polars_process/models/__init__.py create mode 100644 polars_process/models/dataframe.py create mode 100644 polars_process/models/df_field.py create mode 100644 polars_process/models/df_source.py create mode 100644 polars_process/models/ir_model_fields.py create mode 100644 polars_process/pyproject.toml create mode 100644 polars_process/readme/DESCRIPTION.md create mode 100644 polars_process/security/ir.model.access.xml create mode 100644 polars_process/static/description/icon.png create mode 100644 polars_process/static/description/index.html create mode 100644 polars_process/tests/__init__.py create mode 100644 polars_process/tests/files/4_fields.xlsx create mode 100644 polars_process/tests/files/missing_required_column.xlsx create mode 100644 polars_process/tests/files/wrong_date.xlsx create mode 100644 polars_process/tests/test_module.py create mode 100644 polars_process/views/dataframe.xml create mode 100644 polars_process/views/df_field.xml create mode 100644 polars_process/views/df_source.xml create mode 100644 polars_process/views/menu.xml create mode 100644 polars_process/wizards/__init__.py create mode 100644 polars_process/wizards/df_process.py create mode 100644 polars_process/wizards/df_process.xml create mode 100644 requirements.txt diff --git a/polars_process/README.rst b/polars_process/README.rst new file mode 100644 index 0000000000..f3cf5c40f2 --- /dev/null +++ b/polars_process/README.rst @@ -0,0 +1,115 @@ +======================= +Sheet Dataframe Process +======================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:3fb8a401fe8c3d73e23b477915bbd9ff0b2bcb331711726a4fd5be280ad53d5d + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github + :target: https://github.com/OCA/reporting-engine/tree/18.0/polars_process + :alt: OCA/reporting-engine +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/reporting-engine-18-0/reporting-engine-18-0-polars_process + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/reporting-engine&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +From an imported spreadsheet (xlsx), this module allows to transform +file data in Polars dataframe and process them according to rules in +order to: + +- filter data and display +- obtain another dataframe with only the expected data to use in Odoo + +A such dataframe can help to prepare data in order to be used to +create/update or import + +Typical use case: + +You receive files from your vendors and these files have many difference +(column names, number of columns, dirty paging) but contains data +related to same concepts. Then you want apply them a common process to +automate things. For that you need to transform/arrange data to the same +way + +Why dataframe ? + +- a dataframe is a kind of in-memory dataset on which you can operate +- you can operates on your entire dataset a bit like with a database + but in memory: you don't need to iterate on each line to perform + operations +- the operations are powerful: filter, add column resulting from + calculation, select a subset of data + +Why Polars ? + +- performance: code in rust +- environment consideration +- dynamic project + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Akretion + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-bealdav| image:: https://github.com/bealdav.png?size=40px + :target: https://github.com/bealdav + :alt: bealdav + +Current `maintainer `__: + +|maintainer-bealdav| + +This module is part of the `OCA/reporting-engine `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/polars_process/__init__.py b/polars_process/__init__.py new file mode 100644 index 0000000000..aee8895e7a --- /dev/null +++ b/polars_process/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizards diff --git a/polars_process/__manifest__.py b/polars_process/__manifest__.py new file mode 100644 index 0000000000..bbdd05fe25 --- /dev/null +++ b/polars_process/__manifest__.py @@ -0,0 +1,34 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Polars Process", + "version": "18.0.1.0.0", + "summary": "Allow to create a Polars dataframe from file or db query and " + "process it according to rules", + "category": "Reporting", + "license": "AGPL-3", + "author": "Akretion, Odoo Community Association (OCA)", + "development_status": "Alpha", + "website": "https://github.com/OCA/reporting-engine", + "maintainers": ["bealdav"], + "depends": [ + "contacts", + ], + "external_dependencies": { + "python": [ + "polars", + "fastexcel", + ] + }, + "data": [ + "data/action.xml", + "data/demo.xml", + "security/ir.model.access.xml", + "wizards/df_process.xml", + "views/dataframe.xml", + "views/df_field.xml", + "views/df_source.xml", + "views/menu.xml", + ], + "installable": True, +} diff --git a/polars_process/data/action.xml b/polars_process/data/action.xml new file mode 100644 index 0000000000..dede8792e1 --- /dev/null +++ b/polars_process/data/action.xml @@ -0,0 +1,10 @@ + + + + 🐻‍❄️ Populate file polars example + + + code + env["df.source"]._populate() + + diff --git a/polars_process/data/demo.xml b/polars_process/data/demo.xml new file mode 100644 index 0000000000..de1fbf4665 --- /dev/null +++ b/polars_process/data/demo.xml @@ -0,0 +1,38 @@ + + + + stop + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/polars_process/models/__init__.py b/polars_process/models/__init__.py new file mode 100644 index 0000000000..96b8121bf9 --- /dev/null +++ b/polars_process/models/__init__.py @@ -0,0 +1,4 @@ +from . import dataframe +from . import df_field +from . import df_source +from . import ir_model_fields diff --git a/polars_process/models/dataframe.py b/polars_process/models/dataframe.py new file mode 100644 index 0000000000..4376b06f97 --- /dev/null +++ b/polars_process/models/dataframe.py @@ -0,0 +1,81 @@ +from odoo import Command, fields, models + +# Demo record +UISTRING = "polars_process.dataframe_contact" + + +class Dataframe(models.Model): + _name = "dataframe" + _inherit = "mail.thread" + _description = "File Configuration" + _rec_name = "model_id" + + model_id = fields.Many2one( + comodel_name="ir.model", + required=True, + copy=False, + ondelete="cascade", + tracking=True, + ) + code = fields.Char(help="Allow to browse between several identical models") + action = fields.Selection( + selection=[ + ("display", "Display"), + ("dataframe", "Dataframe"), + ], + default="display", + tracking=True, + help="Some other behaviors can be implemented", + ) + on_fail = fields.Selection( + selection=[("stop", "Stop"), ("skip", "Skip record (TODO)")], + default="stop", + tracking=True, + help="What should be the behavior in case of failure regarding constraint " + "fields (required, format, etc)\n\n" + " - Stop: stop the process by raising an exception\n" + " - Skip record: current line'll be ignored from the next process", + ) + partner_ids = fields.Many2many( + comodel_name="res.partner", + domain="[('active', 'in', (True, False))]", + tracking=True, + ) + field_ids = fields.One2many( + comodel_name="df.field", inverse_name="dataframe_id", copy=True + ) + + def populate_match_lines(self): + # TODO use api depends instead of ui button ? + self.ensure_one() + for partner in self.partner_ids: + ffields = self.field_match_ids.filtered( + lambda s, partner=partner: s.partner_id == partner + ).mapped("field_id") + line_ids = self.field_ids.filtered( + lambda s, ffields=ffields: s.field_id not in ffields + ).mapped("id") + self.field_match_ids = [ + Command.create({"partner_id": partner.id, "line_id": x}) + for x in line_ids + ] + self.field_match_ids.filtered( + lambda s: s.partner_id not in s.dataframe_id.partner_ids + ).unlink() + for rec in self: + if rec == self.env.ref(UISTRING): + rec._populate_demo_column_names() + + def _populate_match(self, mfield, mstring, uidstring): + record = self.field_match_ids.filtered( + lambda s, field=mfield, uidstring=uidstring: s.field_id.name == field + and s.partner_id == s.dataframe_id.partner_ids[0] + ) + if record: + record.matching_column = mstring + + def _populate_demo_column_names(self): + self.field_match_ids.matching_column = False + self._populate_match("street", "myStreet", UISTRING) + self._populate_match("street2", "Second street", UISTRING) + self._populate_match("country_code", "Country", UISTRING) diff --git a/polars_process/models/df_field.py b/polars_process/models/df_field.py new file mode 100644 index 0000000000..031c32fad4 --- /dev/null +++ b/polars_process/models/df_field.py @@ -0,0 +1,29 @@ +from odoo import fields, models + + +class FileField(models.Model): + _name = "df.field" + _inherit = ["mail.thread"] + _description = "Configuration de l'import de champ" + _order = "field_id ASC" + + dataframe_id = fields.Many2one( + comodel_name="dataframe", required=True, ondelete="cascade" + ) + field_id = fields.Many2one( + comodel_name="ir.model.fields", + ondelete="cascade", + required=True, + domain="[('model_id', '=', model_id)]", + ) + model_id = fields.Many2one( + comodel_name="ir.model", + related="dataframe_id.model_id", + readonly=True, + ) + required = fields.Boolean( + help="Prevent to import missing data if field is missing in some records", + ) + check_type = fields.Boolean( + help="Check data type is compatible", + ) diff --git a/polars_process/models/df_source.py b/polars_process/models/df_source.py new file mode 100644 index 0000000000..a9c771ace6 --- /dev/null +++ b/polars_process/models/df_source.py @@ -0,0 +1,85 @@ +import base64 +from pathlib import Path + +from odoo import fields, models +from odoo.modules.module import get_module_path + + +class DfSource(models.Model): + _name = "df.source" + _description = "Dataframe data source" + + dataframe_id = fields.Many2one( + comodel_name="dataframe", required=True, ondelete="cascade", readonly=True + ) + name = fields.Char() + template = fields.Binary(string="Fichier", attachment=False) + + def _populate(self): + def create_attach(myfile, addon, idstring, relative_path): + with open(myfile, "rb") as f: + vals = { + "dataframe_id": self.env.ref(idstring).id, + "name": f.name[f.name.find(addon) :], + } + self.env[self._name].sudo().create(vals) + + self.env[self._name].search([("template", "=", False)]).unlink() + paths = self._get_test_file_paths() + for addon, data in paths.items(): + relative_path = data["relative_path"] + idstring = f"{addon}.{data['xmlid']}" + if self.env.ref(idstring): + mpath = Path(get_module_path(addon)) / relative_path + for mfile in tuple(mpath.iterdir()): + create_attach(mfile, addon, idstring, relative_path) + action = self.env.ref( + "polars_process.df_source_action" + )._get_action_dict() + return action + + def start(self): + self.ensure_one() + transient = self.env["df.process.wiz"].create( + { + "filename": self.name, + "file": self._get_file(), + "dataframe_id": self.dataframe_id.id, + } + ) + action = self.env.ref( + "polars_process.df.process.wiz_action" + )._get_action_dict() + action["res_id"] = transient.id + return action + + def _get_file(self): + # TODO Clean + if self.template: + return self.template + module = self.name[: self.name.find("/")] + relative = self._get_test_file_paths().get(module) + relative = relative and relative.get("relative_path") + if relative: + path = Path(get_module_path(module)) + path = path / relative / self.name[self.name.rfind("/") + 1 :] + # myfile = path / self.name + with open(path, "rb") as f: + return base64.b64encode(f.read()) + + def _get_test_file_paths(self): + """ + You may override if you want populate files in your module + returns: + {"module_name": { + "relative_path": "tests/files", + "xmlid": "dataframe_xml_id"} + } + } + """ + return { + "polars_process": { + "relative_path": "tests/files", + "xmlid": "dataframe_contact", + } + } diff --git a/polars_process/models/ir_model_fields.py b/polars_process/models/ir_model_fields.py new file mode 100644 index 0000000000..14d2039c81 --- /dev/null +++ b/polars_process/models/ir_model_fields.py @@ -0,0 +1,14 @@ +from odoo import api, models + + +class IrModelFields(models.Model): + _inherit = "ir.model.fields" + + @api.depends("field_description", "model") + def _compute_display_name(self): + super()._compute_display_name() + if self.env.context.get("technical_name"): + for field in self: + if self.env.context.get("technical_name"): + field.display_name = field.name + return diff --git a/polars_process/pyproject.toml b/polars_process/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/polars_process/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/polars_process/readme/DESCRIPTION.md b/polars_process/readme/DESCRIPTION.md new file mode 100644 index 0000000000..b2eedffec0 --- /dev/null +++ b/polars_process/readme/DESCRIPTION.md @@ -0,0 +1,27 @@ +From an imported spreadsheet (xlsx), this module allows to transform file data in +Polars dataframe and process them according to rules in order to: + +- filter data and display +- obtain another dataframe with only the expected data to use in Odoo + +A such dataframe can help to prepare data in order to be used to create/update or import + +Typical use case: + +You receive files from your vendors and these files have many difference (column names, number of columns, dirty paging) but contains data related to same concepts. +Then you want apply them a common process to automate things. +For that you need to transform/arrange data to the same way + + +Why dataframe ? + +- a dataframe is a kind of in-memory dataset on which you can operate +- you can operates on your entire dataset a bit like with a database but in memory: you don't need to iterate on each line to perform operations +- the operations are powerful: filter, add column resulting from calculation, select a subset of data + + +Why Polars ? + +- performance: code in rust +- environment consideration +- dynamic project diff --git a/polars_process/security/ir.model.access.xml b/polars_process/security/ir.model.access.xml new file mode 100644 index 0000000000..7bb63a8d88 --- /dev/null +++ b/polars_process/security/ir.model.access.xml @@ -0,0 +1,41 @@ + + + Dataframe + + + + + + + + + + Df Field + + + + + + + + + + df.process.wiz + + + + + + + + + + df.source + + + + + + + + diff --git a/polars_process/static/description/icon.png b/polars_process/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d1d2b572970f1b1180a2fef75dc439bffb034de6 GIT binary patch literal 2605 zcmV+|3exq7P)^6 zrc5)2DbtK$$}~ea1ozl_)bf6v8Nl{M&h_PP``crr>kS+4>^^UL?T7`y`ZD+SN@ug1 z`o=|DGWf~4+z>oia!40tJI|P%esa1!ST)Y)2@=vp4@dYzgghq1!^`z{0eEtc{gzV) z;Oq-c0A4<1^>bJ?#j|>fr^82HYiA6!Fk@t}(?`B^(CP^iON)KgW$rgmWWQUR3E=Nf zIcALtr0I=hq=mAZowQ^-c_#kcxTeH^=#G%<@{>0@=p*$k0D{2kDW2-T=ALY10o1H< zcsb&W+Zg~{eyY06eWi_-?>lQ$pzQtpCbw>)l{@}?OKRUsLdqyR(ZJR=>PZ4?XSfA1 ze39b;V6rW|$|eqCx%F^ix7+0>XllS=E@EEm?`sIJJ z1K2pb>y^1(iBFO|Wt=1itUG|Cn>t?;pz}NQsBQq~MSflYNubomseF1? zVHZXwj*Y0`C$qZaj^PEoeKPBvQ&|AsSm@d?v-?Ur4WP|SwRxjI$<=lmKu?go(?tyt zWgBL8ZDxs? z8)eJ?Xs>P31L$wqFCMh+xnu;ee^sm1&?ihIi0DQ_PZo(Y`p5c>Zk;zo0J!K#bhDH0 zJju$PZqeHeyv>lj63|9jOT@)=`l16Txy#`pqbL)_K8@Ks^TQ)IH>lieQK9ekd9FZ+ zcxYS-_E6~&K3k&}KPHHwcK=GjBxg8c!a$2JJrLVr$v-0q5kRSplT`ZnoH){A+wtr( z&5X?`eDG+y%CIK4Zu6lWKZmELdRCTtqI%Op*+eV1xuOezeGp3cf`eK1i9Ns*KP+=^ zt8^;6`FobG+`|K6WIs6m3nM7>iN;0XYi;>myu4(8CU42BZd4nk}v4sDbv9eEZj%qj3ovOH>- z%TLb!FyHAX=a2F4UD=wF2UWo@zsjt+X#kLC;;T~O_)K)zjiF#f{_uY**PhQ9|-R)=@Z<}Dd-hdN{#u*c;Eh2tpKE0f9G7oy`5fi_UJgpi_dRmJiFfpV0)!=eI#=m6YI;}>&xW{MLd`k9KG{!=WQn~ zd5vZ_wQyG+fblupzkiULGS8mN#tRMx!1=pOl!P)dN!m+t7(~Ljuazkwi(ywkUG*)% zAbeS0E8FyW&f)qD06UkrMyV_1iC9=(ONX3Xy1XfwB zn7Aw-VrcVaPw%tc?4$u4e)ewEj@g^TQnX1@8X%7Z`X;j1&ghwx%LyV;o*w|PcSWmo zSZb6xR7WuKgaAk)=KRT550Zwqg&B-^q97l=WA^5-6m3C}2FN1;pwJR3wDczal?ox> z%*$sLdVeKNrT9}Z|B#;WkPw5i4F{}ud#Ef{-1S)7cuP23m@*=UrvLv$49fOhHA;<6 zAGxT|KTw8#R=!$_aquX#g!Ggc;0gI0(S3qA3$w08zx~TBAbgZi*_Fi#$|QtRV=8j< zK(gn{rrCoH8}Gz^=!C1~=|CLH&a^Pnp&h$PSUtt_v-z&;9WXAT5;ToB3mFTjYEh7co9g=o1Eq!?Z@dAQEMH z0an#9ZC&8}R|9LH#d%}=CmL9-)$$ZV8)Z9cGmq7?*{ty1k`DDlD3fzJAcnIS#Xjv_ z=S*AvnFCE%nsro?b<9#*u&T)C2@*?+eTY=m0O&|j`CwFfHiI~nEuG+% zlF^k#egJP)cAjq5XJ-i0MGcilxfB=WtuTenP&VK(M1O$P%M+& P00000NkvXXu0mjf2J`yU literal 0 HcmV?d00001 diff --git a/polars_process/static/description/index.html b/polars_process/static/description/index.html new file mode 100644 index 0000000000..86912e40ac --- /dev/null +++ b/polars_process/static/description/index.html @@ -0,0 +1,453 @@ + + + + + +Sheet Dataframe Process + + + +
+

Sheet Dataframe Process

+ + +

Alpha License: AGPL-3 OCA/reporting-engine Translate me on Weblate Try me on Runboat

+

From an imported spreadsheet (xlsx), this module allows to transform +file data in Polars dataframe and process them according to rules in +order to:

+
    +
  • filter data and display
  • +
  • obtain another dataframe with only the expected data to use in Odoo
  • +
+

A such dataframe can help to prepare data in order to be used to +create/update or import

+

Typical use case:

+

You receive files from your vendors and these files have many difference +(column names, number of columns, dirty paging) but contains data +related to same concepts. Then you want apply them a common process to +automate things. For that you need to transform/arrange data to the same +way

+

Why dataframe ?

+
    +
  • a dataframe is a kind of in-memory dataset on which you can operate
  • +
  • you can operates on your entire dataset a bit like with a database +but in memory: you don’t need to iterate on each line to perform +operations
  • +
  • the operations are powerful: filter, add column resulting from +calculation, select a subset of data
  • +
+

Why Polars ?

+
    +
  • performance: code in rust
  • +
  • environment consideration
  • +
  • dynamic project
  • +
+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Akretion
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

bealdav

+

This module is part of the OCA/reporting-engine project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/polars_process/tests/__init__.py b/polars_process/tests/__init__.py new file mode 100644 index 0000000000..d9b96c4fa5 --- /dev/null +++ b/polars_process/tests/__init__.py @@ -0,0 +1 @@ +from . import test_module diff --git a/polars_process/tests/files/4_fields.xlsx b/polars_process/tests/files/4_fields.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..66c858ae68c7570052603313347d1fe757920539 GIT binary patch literal 5433 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 literal 0 HcmV?d00001 diff --git a/polars_process/tests/files/missing_required_column.xlsx b/polars_process/tests/files/missing_required_column.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b1ce314ed6d6428407c07de6e27ae6ab146e911b GIT binary patch literal 5335 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 literal 0 HcmV?d00001 diff --git a/polars_process/tests/files/wrong_date.xlsx b/polars_process/tests/files/wrong_date.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..67808f7ee95fe62a2189a28afdd2eda611e1241b GIT binary patch literal 5414 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", "
") + return string diff --git a/polars_process/views/dataframe.xml b/polars_process/views/dataframe.xml new file mode 100644 index 0000000000..7e9ed30949 --- /dev/null +++ b/polars_process/views/dataframe.xml @@ -0,0 +1,65 @@ + + + dataframe + +
+ + + + + + + + + + + + + + +
+
+ + + dataframe + + + + + + + + + + + dataframe + + + + + + + + + + + + + + + Dataframe + dataframe + list,form + dataframe + +
diff --git a/polars_process/views/df_field.xml b/polars_process/views/df_field.xml new file mode 100644 index 0000000000..ba42155ee0 --- /dev/null +++ b/polars_process/views/df_field.xml @@ -0,0 +1,24 @@ + + + df.field + + + + + + + + + + + + Df Field + df.field + list + df-field + + diff --git a/polars_process/views/df_source.xml b/polars_process/views/df_source.xml new file mode 100644 index 0000000000..47b7eb452f --- /dev/null +++ b/polars_process/views/df_source.xml @@ -0,0 +1,24 @@ + + + df.source + + + +