diff --git a/.bumpversion.cfg b/.bumpversion.cfg new file mode 100644 index 000000000..ffcd695b9 --- /dev/null +++ b/.bumpversion.cfg @@ -0,0 +1,12 @@ +[bumpversion] +current_version = 0.6.3 +commit = True +tag = True + +[bumpversion:file:pyproject.toml] + +[bumpversion:file:package.json] + +[bumpversion:file:buckaroo/_version.py] + +[bumpversion:file:docs/source/conf.py] diff --git a/.coveragerc b/.coveragerc index 0a40787fb..423e15976 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,2 +1,2 @@ [run] -omit = dcef/tests/* +omit = buckaroo/tests/* diff --git a/.eslintignore b/.eslintignore index e8a22210a..ec65eed30 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,4 +2,6 @@ node_modules dist coverage **/*.d.ts -tests \ No newline at end of file +tests +js/vendor/RechartTooltip.tsx +js/baked_data/colorMap.ts \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 9fb27ea5b..ee4a89d8d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -7,15 +7,24 @@ module.exports = { ], parser: '@typescript-eslint/parser', parserOptions: { - project: 'tsconfig.eslint.json', + project: "tsconfig.json", sourceType: 'module' }, - plugins: ['@typescript-eslint'], + plugins: ['@typescript-eslint', + 'prettier' + ], rules: { '@typescript-eslint/no-unused-vars': ['warn', { args: 'none' }], '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-namespace': 'off', '@typescript-eslint/no-use-before-define': 'off', + "@typescript-eslint/no-unused-vars": "off", + + //necessary for js/version.ts... otherwise the python build fails + "@typescript-eslint/no-var-requires": "off", + + + "@typescript-eslint/explicit-function-return-type": "off", '@typescript-eslint/quotes': [ 'error', 'single', @@ -24,5 +33,9 @@ module.exports = { curly: ['error', 'all'], eqeqeq: 'error', 'prefer-arrow-callback': 'error' - } -}; \ No newline at end of file + }, + "ignorePatterns": [ + "webpack.config.ts", + "jest.config.js" + ] +}; diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000..c099b1745 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,88 @@ +name: '🐞 Bug report - Python' +description: Report an issue with Buckaroo. +labels: [bug] + +body: + - type: checkboxes + id: checks + attributes: + label: Checks + options: + - label: > + I have checked that this issue has not already been reported. + required: true + - label: > + I have confirmed this bug exists on the + [latest version](https://github.com/paddymul/buckaroo) of Buckaroo. + required: true + + - type: dropdown + id: Notebook-system + attributes: + label: What type of jupyter notebook were you using (VSCode notebook, google colab, Jupyter Lab, Jupyter notebook). Select multiple if you can reproduce this in multiple environments. If other, please add to description. + multiple: true + options: + - VS Code + - Jupyter Lab + - Google Colab + - Jupyter Notebook + - Other (please describe in Issue Description) + validations: + required: true + + - type: textarea + id: example + attributes: + label: Reproducible example + description: > + Please follow [this guide](https://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports) on how to + provide a minimal, copy-pastable example. [Infinity displays as blank](https://github.com/paddymul/buckaroo/issues/122) is an excellent buckaroo example. Include the (wrong) output if applicable. + value: | + ```python + + ``` + validations: + required: true + + - type: textarea + id: problem + attributes: + label: Issue description + description: > + Provide any additional information you think might be relevant. If this is a visual bug, provide a screenshot of the input dataframe and the top couple of lines of buckaroo output. + validations: + required: true + + - type: textarea + id: expected-behavior + attributes: + label: Expected behavior + description: > + Describe or show a code example of the expected behavior. + validations: + required: true + + - type: textarea + id: version + attributes: + label: Installed versions + description: > + Paste the output of ``buckaroo.debug_packages()`` + value: | +
+ ``` + Replace this line with the output of buckaroo.debug_packages(). Leave the backticks in place. + ``` +
+ validations: + required: true + + - type: textarea + id: logs + attributes: + label: Jupyter Log output + description: > + If the buckaroo widget completely didn't display, check the Jupyter Log Console. Also check the javascript console of the browser to see if any obvious JS errors occurred. This is optional + Paste the output of the logs here. + render: shell + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..7c3c16708 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 000000000..5d0029ec4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,58 @@ +name: 'Enhancement Request' +description: Request an enhancement to Buckaroo. +labels: [enhancement] + +body: + - type: checkboxes + id: checks + attributes: + label: Checks + options: + - label: > + I have checked that this enhancement has not already been requested + required: true + + - type: dropdown + id: Subsystem + attributes: + label: How would you categorize this request. You can select multiple if not sure + multiple: true + options: + - Display (is this related to visual display of a value) + - Documentation + - Summary stats + - Developer ergonomics (defaults, error messages) + - Auto Cleaning + - Performance + - Developer Experience/CI (feature to make it easier to devlop on Buckaroo) + - Low Code UI + - Other (please describe in Issue Description) + validations: + required: true + + - type: textarea + id: problem + attributes: + label: Enhancement Description + description: > + How would you like Buckaroo to function? Write a description of what you want buckaroo to do. + validations: + required: true + + - type: textarea + id: pseudo-code-implementation + attributes: + label: Pseudo Code Implementation + description: > + If applicable, write simple python code that shows an input dataframe, the code to transform it to the output dataframe you are looking for, and the output dataframe. + validations: + required: false + + - type: textarea + id: prior-art + attributes: + label: Prior Art + description: > + Link to other tools that function in the way you want. Describe how that tool solves this problem. Videos are welcome too + validations: + required: true diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dfab4e374..d54de743a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,33 +12,85 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - python-version: ["3.7", "3.10"] + #os: [ubuntu-latest, windows-latest, macos-latest] + os: [ubuntu-latest] + python-version: ["3.9"] steps: - name: Checkout - uses: actions/checkout@v2 - + uses: actions/checkout@v4 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - uses: actions/setup-node@v4 + with: + node-version: "20.x" + cache: yarn - name: Install dependencies run: | python -m pip install -U codecov npm install -g codecov + + - name: Check docs can be build + links + if: ${{ matrix.os == 'ubuntu-latest' }} + working-directory: docs + run: | + sudo apt install -y pandoc graphviz + pip install sphinx==7.1.2 pytest-check-links graphviz==0.20.1 + make html + python -m pytest --check-links + - name: Test the extension run: | python -m pip install --upgrade -v -e ".[test, examples, docs]" - python -m pytest + python -m pytest tests/unit yarn run test - name: Linting if: ${{ matrix.os == 'ubuntu-latest' }} run: | yarn run lint:check + pip install ruff + ruff check . - - name: Check docs can be build + links - if: ${{ matrix.os == 'ubuntu-latest' }} - working-directory: docs + - name: Package run: | - sudo apt install -y pandoc - make html - python -m pytest --check-links + python -m pip install build + python -m build . + + - name: Upload builds + uses: actions/upload-artifact@v4 + with: + name: buckaroo-dist-${{ github.run_number }} + path: | + ./dist + ./js/*.tgz + + + ui-test: + needs: [build] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: buckaroo-dist-${{ github.run_number }} + + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: 3.9 + + - name: Setup buckaroo ui test + run: pip install `echo dist/*.whl`[ui-test] -r requirements-ui-test.txt + + - name: Install playwright browsers + run: playwright install chromium + + - name: Run ui-tests + run: SOLARA_TEST_RUNNERS=jupyter_lab pytest tests/ui/ --video=retain-on-failure + + - name: Upload Test artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: buckaroo-test-results-${{ github.run_number }} + path: test-results diff --git a/.gitignore b/.gitignore index 979639bd4..781209f0f 100644 --- a/.gitignore +++ b/.gitignore @@ -156,5 +156,9 @@ myproject/labextension ipydatagrid/labextension/* ipydatagrid/nbextension/* -dcf/nbextension/* -dcf/labextension/* \ No newline at end of file +buckaroo/nbextension/* +buckaroo/labextension/* +docs/*.js +docs/*.js.map +docs/*js* +docs/source/_static/*woff* \ No newline at end of file diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 000000000..ebaa0b9a9 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,24 @@ +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.11" + nodejs: "20" + apt_packages: + - graphviz + - npm + - git + jobs: + post_build: + - echo "Command run at 'post_build' step" + - echo `date` + - echo "$READTHEDOCS_OUTPUT/html" + - pwd + - git rev-parse HEAD + - node --version + - npm install -g yarn@1.22.19 + - yarn --version + - yarn install + - yarn run build:examples + - cp -r docs/build/html/examples "$READTHEDOCS_OUTPUT/html" \ No newline at end of file diff --git a/README.md b/README.md index 5e1135e11..873c2ea73 100644 --- a/README.md +++ b/README.md @@ -1,216 +1,112 @@ -# DCEF - Data Cleaning Exploration Framework -We all know how awkward it is to clean data in jupyter notebooks. Multiple cells of exploratory work, trying different transforms, looking up different transforms, adhoc functions that work in one notebook and have to be either copied/pasta-ed to the next notebook, or rewritten from scratch. Data Cleaning Explorationg Framework (DCEF) makes all of that better by providing a visual UI for common cleaning operations AND emitting python code that performs the transformation. Specifically, the DCEF is a tool built to interactively explore, clean, and transform pandas dataframes. +# Buckaroo - The Data Table for Jupyter -![Data Cleaning Exploration Framework Screenshot](static/images/dcf-jupyter.png) +Buckaroo is a modern data table for Jupyter that expedites the most common exploratory data analysis tasks. The most basic data analysis task - looking at the raw data, is cumbersome with the existing pandas tooling. Buckaroo starts with a modern performant data table that displays up to 10k rows, is sortable, has value formatting, and scrolls. On top of the core table experience extra features like summary stats, histograms, smart sampling, auto-cleaning, and a low code UI are added. All of the functionality has sensible defaults that can be overridden to customize the experience for your workflow. +Polars-Buckaroo -## Installation -If using JupyterLab, `dcef` requires JupyterLab version 3 or higher. +## Try it today -You can install `dcef` using `pip` +* [Buckaroo full tour](https://github.com/paddymul/buckaroo/blob/main/example-notebooks/Full-tour.ipynb)[![Open In Colab](https://camo.githubusercontent.com/52feade06f2fecbf006889a904d221e6a730c194/68747470733a2f2f636f6c61622e72657365617263682e676f6f676c652e636f6d2f6173736574732f636f6c61622d62616467652e737667)](https://colab.research.google.com/github/paddymul/buckaroo/blob/main/example-notebooks/Full-tour.ipynb) Notebook -Using `pip`: +## Quick start + +run `pip install buckaroo` +in a notebook execute the following to see Buckaroo -```bash -pip install dcef ``` +import pandas as pd +import buckaroo +pd.DataFrame({'a':[1, 2, 10, 30, 50, 60, 50], 'b': ['foo', 'foo', 'bar', pd.NA, pd.NA, pd.NA, pd. NA]}) -## Caveats -DCEF is in beta form. At this point, it is based on from Bloomberg's [ipydatagrid](https://github.com/bloomberg/ipydatagrid) for the basis of the widget build. +``` -If you install ipydatagrid with dcef at this point, expect errors. +When you run `import buckaroo` in a Jupyter notebook, Buckaroo becomes the default display method for Pandas and Polars DataFrames +## Compatibility -# Using DCEF +Buckaroo works in the following notebook environments -in a jupylter notebook just add the following to a cell +- `jupyter lab` (version >=3.6.0) +- `jupyter notebook` (version >=7.0) +- `VS Code notebooks` (with extra install) +- `Google colab` (with special initiation code) -```python -from dcef.dcef_widget import DCEFWidget -DCEFWidget(df=df) #df being the dataframe you want to explore -``` -and you will see the UI for DCEF +Buckaroo works with the following DataFrame libraries +- `pandas` (version >=1.3.5) +- `polars` optional +- `geopandas` optional -## Using commands +# Learn More -At the core DCEF commands operate on columns. You must first click on a cell (not a header) in the top pane to select a column. +Buckaroo has extensive docs and tests, the best way to learn about the system is from feature example videos on youtube -Next you must click on a command like `dropcol`, `fillna`, or `groupby` to create a new command -After creating a new command, you will see that command in the commands list, now you must edit the details of a command. Select the command by clicking on the bottom cell. +## Videos +- [Extending Buckaroo](https://www.youtube.com/watch?v=GPl6_9n31NE) +- [Styling Buckaroo](https://www.youtube.com/watch?v=cbwJyo_PzKY) +- [GeoPandas Support](https://youtu.be/8WBhoNjDJsA) -At this point you can either delete the command by clicking the `X` button or change command parameters. +## Example Notebooks -## Writing your own commands +The following notebooks must executed in an environemnt with Buckaroo installed. +- [Full Tour](https://github.com/paddymul/buckaroo/blob/main/example-notebooks/Full-tour.ipynb) Start here. This gives a broad overview of Buckaroo's features. +- [Histogram Demo](https://github.com/paddymul/buckaroo/blob/main/example-notebooks/Histograms-demo.ipynb) Explantion of the embedded histograms of Buckaroo. +- [Styling Gallery](https://github.com/paddymul/buckaroo/blob/main/example-notebooks/styling-gallery.ipynb) Examples of all of the different formatters and styling available for the table +- [Extending Buckaroo](http://localhost:8888/lab/workspaces/auto-p/tree/Extending.ipynb) Broad overview of how to add post processing methods and custom styling methods to Buckaroo +- [Styling Howto](https://github.com/paddymul/buckaroo/blob/main/example-notebooks/styling-howto.ipynb) In depth explanation of how to write custom styling methods +- [Pluggable Analysis Framework](https://github.com/paddymul/buckaroo/blob/main/example-notebooks/Pluggable-Analysis-Framework.ipynb) How to add new summary stats to Buckaroo +- [Solara Buckaroo](https://github.com/paddymul/buckaroo/blob/main/example-notebooks/Solara-Buckaroo.ipynb) Using Buckaroo with Solara +- [GeoPandas with Bucakroo](https://github.com/paddymul/buckaroo/blob/main/example-notebooks/GeoPandas.ipynb) -Builtin commands are found in [all_transforms.py](dcef/all_transforms.py) +# Features -### Simple example -Here is a simple example command -```python -class DropCol(Transform): - command_default = [s('dropcol'), s('df'), "col"] - command_pattern = [None] +## High performance table +The core data grid of buckaroo is based on [AG-Grid](https://www.ag-grid.com/). This loads 1000s of cells in less than a second, with highly customizable display, formatting and scrolling. You no longer have to use `df.head()` to poke at portions of your data. - @staticmethod - def transform(df, col): - df.drop(col, axis=1, inplace=True) - return df +## Fixed width formatting by default - @staticmethod - def transform_to_py(df, col): - return " df.drop('%s', axis=1, inplace=True)" % col -``` -`command_default` is the base configuration of the command when first added, `s('dropcol')` is a special notation for the function name. `s('df')` is a symbol notation for the dataframe argument (see LISP section for details). `"col"` is a placeholder for the selected column. +By default numeric columns are formatted to use a fixed width font and commas are added. This allows quick visual confirmation of magnitudes in a column. -since `dropcol` does not take any extra arguments, `command_pattern` is `[None]` -```python - def transform(df, col): - df.drop(col, axis=1, inplace=True) - return df -``` -This `transform` is the function that manipulates the dataframe. For `dropcol` we take two arguments, the dataframe, and the column name. +## Histograms -```python - def transform_to_py(df, col): - return " df.drop('%s', axis=1, inplace=True)" % col -``` -`transform_to_py` emits equivalent python code for this transform. Code is indented 4 space for use in a function. - -### Complex example -```python -class GroupBy(Transform): - command_default = [s("groupby"), s('df'), 'col', {}] - command_pattern = [[3, 'colMap', 'colEnum', ['null', 'sum', 'mean', 'median', 'count']]] - @staticmethod - def transform(df, col, col_spec): - grps = df.groupby(col) - df_contents = {} - for k, v in col_spec.items(): - if v == "sum": - df_contents[k] = grps[k].apply(lambda x: x.sum()) - elif v == "mean": - df_contents[k] = grps[k].apply(lambda x: x.mean()) - elif v == "median": - df_contents[k] = grps[k].apply(lambda x: x.median()) - elif v == "count": - df_contents[k] = grps[k].apply(lambda x: x.count()) - return pd.DataFrame(df_contents) -``` -The `GroupBy` command is complex. it takes a 3rd argument of `col_spec`. `col_spec` is an argument of type `colEnum`. A `colEnum` argument tells the UI to display a table with all column names, and a drop down box of enum options. - -In this case each column can have an operation of either `sum`, `mean`, `median`, or `count` applied to it. - -Note also the leading `3` in the `command_pattern`. That is telling the UI that these are the specs for the 3rd element of the command. Eventually commands will be able to have multiple configured arguments. - -### Argument types -Arguments can currently be configured as - -* `integer` - allowing an integer input -* `enum` - allowing a strict set of options, returned as a string to the transform -* `colEnum` - allowing a strict set of options per column, returned as a dictionary keyed on column with values of enum options - - -## Order of Operations for data cleaning -The ideal order of operations is as follows - -* Column level fixes - * drop (remove this column) - * fillna (fill NaN/None with a value) - * safe int (convert a colum to integers where possible, and nan everywhere else) - * OneHotEncoding ( create multiple boolean columns from the possible values of this column ) - * MakeCategorical ( change the values of string to a Categorical Data type) - * Quantize -* DataFrame transformations -these transforms largely keep the shape of the data the same - - * Resample - * ManyColdDecoding (the opposite of OneHotEncoding, take multiple boolean columns and transform into a single categorical - * Index shift (add a column with the value from previous row's column) -* Dataframe transformations 2 -These result in a single new dataframe with a vastly different shape - * Stack/Unstack columns - * GroupBy (with UI for sellect group by function for each column) -* DataFrame transformations 2 -These transforms emit multiple DataFrames - * Relational extract (extract one or more columns into a second dataframe that can be joined back to a foreign key column) - * Split on column (emit separate dataframes for each value of a categorical, no shape editting) -* DataFrame combination - * concat (concatenate multiple dataframes, with UI affordances to assure a similar shape) - * join (join two dataframes on a key, with UI affordances) - -DCEF can only work on a single input dataframe shape at a time. Any newly created columns are visible on output, but not available for manipulation in the same DCEF Cell. - - -# Components -* a rich table widget that is embeddable into applications and in the jupyter notebook. -* A UI for selecting and trying transforms interactively -* An output table widget showing the transformed dataframe - - -# What works now, what's coming - -## Exists now - * React frontend app - * Displays a datatframe - * Simple UI for column level functions - * Shows generated python code - * Shows transformed data frame - * DCEF server - * Serves up dataframes for use by frontend - * responds to dcef commands - * shows generated python code - * Developer User experience - * define DCEF commands in python onloy - * DCEF Intepreter - * Based on Peter Norvig's lispy.py, a simple syntax that is easy for the frontend to generate (no parens, just JSON arrays) - * DCEF core (actual transforms supported) - * dropcol - * fillna - * one hot - * safe int - * GroupBy - -## Next major features - * Jupyter Notebook widget - * embed the same UI from the frontend into a jupyter notebook shell - * No need to fire up a separate server, commands sent via ipywidgets.comms - * Add a "send generated python to next cell" function - * React frontend app - * Styling - * Server only, some UI for DataFrame selection - * Pre filtering concept (only operate on first 1000 rows, some sample of all rows) - * DataFrame joining UI - * Summary statistics tab for incoming dataframe - * Multi index columns - * DateTimeIndex support - * DCEF core - * MakeCategorical - * Quantize - * Resample - * ManyColdDecoding - * IndexShift - * Computed - * Stack/Unstack - * RelationalExtract - * Split - * concat - * join - +[Histograms](https://buckaroo-data.readthedocs.io/en/latest/articles/histograms.html) for every column give you a very quick overview of the distribution of values, including uniques and N/A. + +## Summary stats +The summary stats view can be toggled by clicking on the `0` below the `Σ` icon. Summary stats are similar to `df.describe` and extensible. + +## Inteligent sampling + +Buckaroo will display entire DataFrames up to 10k rows. Displaying more than that would run into performance problems that would make display too slow. When a DataFrame has more than 10k rows, Buckaroo samples a random set of 10k rows, and also adds in the rwos with the 5 most extreme values for each column. + +## Sorting + +All of the data visible in the table (rows shown), is sortable by clicking on a column name, further clicks change sort direction then disable sort for that column. Because extreme values are included with sample rows, you can see outlier values too. + +## Extensibility at the core + +Buckaroo summary stats are built on the [Pluggable Analysis Framework](https://buckaroo-data.readthedocs.io/en/latest/articles/pluggable.html) that allows individual summary stats to be overridden, and new summary stats to be built in terms of existing summary stats. Care is taken to prevent errors in summary stats from preventing display of a dataframe. + +## Lowcode UI (beta) +Buckaroo has a simple low code UI with python code gen. This view can be toggled by clicking on the `0` below the ` λ ` icon. +## Auto cleaning (beta) + +Buckaroo can [automatically clean](https://buckaroo-data.readthedocs.io/en/latest/articles/auto_clean.html) dataframes to remove common data errors (a single string in a column of ints, recognizing date times...). This feature is in beta. You can access it by invoking buckaroo as `BuckarooWidget(df, auto_clean=True)` ## Development installation For a development installation: ```bash -git clone https://github.com/paddymul/dcef.git -cd dcef -conda install ipywidgets=8 jupyterlab +git clone https://github.com/paddymul/buckaroo.git +cd buckaroo +#we need to build against 3.6.5, jupyterlab 4.0 has different JS typing that conflicts +# the installable still works in JL4 +pip install build twine pytest sphinx polars mypy jupyterlab==3.6.5 pandas-stubs geopolars pyarrow pip install -ve . ``` @@ -225,33 +121,24 @@ jupyter labextension develop . --overwrite Note for developers: the `--symlink` argument on Linux or OS X allows one to modify the JavaScript code in-place. This feature is not available with Windows. ` +### Developing the JS side -## Contributions - -We :heart: contributions. - -Have you had a good experience with this project? Why not share some love and contribute code, or just let us know about any issues you had with it? - -We welcome issue reports [here](../../issues); be sure to choose the proper issue template for your issue, so that we can be sure you're providing the necessary information. +There are a series of examples of the components in [examples/ex](./examples/ex). -Before sending a [Pull Request](../../pulls), please make sure you read our -[Contribution Guidelines](https://github.com/bloomberg/.github/blob/master/CONTRIBUTING.md). -## License -Please read the [LICENSE](LICENSE.txt) file. +Instructions +```bash +npm install +npm run dev +``` -## Code of Conduct -This project has adopted a [Code of Conduct](https://github.com/bloomberg/.github/blob/master/CODE_OF_CONDUCT.md). -If you have any concerns about the Code, or behavior which you have experienced in the project, please -contact us at opensource@bloomberg.net. +## Contributions -## Security Vulnerability Reporting +We :heart: contributions. -If you believe you have identified a security vulnerability in this project, please send email to the project -team at opensource@bloomberg.net, detailing the suspected issue and any methods you've found to reproduce it. +Have you had a good experience with this project? Why not share some love and contribute code, or just let us know about any issues you had with it? -Please do NOT open an issue in the GitHub repository, as we'd prefer to keep vulnerability reports private until -we've had an opportunity to review and address them. +We welcome issue reports [here](../../issues); be sure to choose the proper issue template for your issue, so that we can be sure you're providing the necessary information. diff --git a/buckaroo.json b/buckaroo.json new file mode 100644 index 000000000..2e0ad579b --- /dev/null +++ b/buckaroo.json @@ -0,0 +1,5 @@ +{ + "load_extensions": { + "buckaroo/extension":true + } +} diff --git a/buckaroo/__init__.py b/buckaroo/__init__.py new file mode 100644 index 000000000..ffbd7eb0f --- /dev/null +++ b/buckaroo/__init__.py @@ -0,0 +1,124 @@ +# -*- coding: utf-8 -*- +from ._version import __version__ +from .buckaroo_widget import BuckarooWidget +from .dataflow.widget_extension_utils import DFViewer +from .widget_utils import is_in_ipython, enable, disable, determine_jupter_env + + +def _jupyter_nbextension_paths(): + """Called by Jupyter Notebook Server to detect if it is a valid nbextension and + to install the widget + Returns + ======= + section: The section of the Jupyter Notebook Server to change. + Must be 'notebook' for widget extensions + src: Source directory name to copy files from. Webpack outputs generated files + into this directory and Jupyter Notebook copies from this directory during + widget installation + dest: Destination directory name to install widget files to. Jupyter Notebook copies + from `src` directory into /nbextensions/ directory + during widget installation + require: Path to importable AMD Javascript module inside the + /nbextensions/ directory + """ + return [{ + 'section': 'notebook', + 'src': 'nbextension', + 'dest': "buckaroo", + 'require': 'buckaroo/extension' + }] + + +def _jupyter_labextension_paths(): + """Called by Jupyter Lab Server to detect if it is a valid labextension and + to install the widget + Returns + ======= + src: Source directory name to copy files from. Webpack outputs generated files + into this directory and Jupyter Lab copies from this directory during + widget installation + dest: Destination directory name to install widget files to. Jupyter Lab copies + from `src` directory into /labextensions/ directory + during widget installation + """ + return [{ + 'src': 'labextension', + 'dest': "buckaroo" + }] + + + + +def is_notebook_compatible(): + jupyter_env = determine_jupter_env() + if jupyter_env == "jupyter-notebook": + try: + import notebook + return notebook.version_info[0] >= 7 + except: + pass + return False + else: + return True + +def warn_on_incompatible(): + if not is_notebook_compatible(): + import notebook + print("Buckaroo is compatible with jupyter notebook > 7, or jupyterlab >3.6.0") + print("You seem to be executing this in jupyter notebook version %r" % str(notebook.__version__)) + print("You can upgrade to notebook 7 by running 'pip install --upgrade notebook'") + print("Or you can try running jupyter lab with 'jupyter lab'") + + + +def debug_packages(): + print("Selected Jupyter core packages...") + jupyter_env = determine_jupter_env() + print("executing in %s " % jupyter_env) + packages = [ + "buckaroo", + "jupyterlab", + "notebook", + "ipywidgets", + "traitlets", + "jupyter_core", + "pandas", + "numpy", + "IPython", + "ipykernel", + "jupyter_client", + "jupyter_server", + "nbclient", + "nbconvert", + "nbformat", + "qtconsole", + ] + + for package in packages: + try: + mod = __import__(package) + version = mod.__version__ + except ImportError: + version = "not installed" + print(f"{package:<17}:", version) + for package in packages: + try: + mod = __import__(package) + path = mod.__file__ + except ImportError: + path = "not installed" + print(f"{package:<17}:", path) + +try: + if is_in_ipython(): + enable() + print("Buckaroo has been enabled as the default DataFrame viewer. To return to default dataframe visualization use `from buckaroo import disable; disable()`") + else: + print("must be running inside ipython to enable default display via enable()") + + + warn_on_incompatible() +except: + print("error enabling buckaroo as default display formatter for dataframes (ignore message during testing/builds") + + diff --git a/ipydatagrid/_frontend.py b/buckaroo/_frontend.py similarity index 88% rename from ipydatagrid/_frontend.py rename to buckaroo/_frontend.py index 67eec5522..5ed8a32ff 100644 --- a/ipydatagrid/_frontend.py +++ b/buckaroo/_frontend.py @@ -7,5 +7,5 @@ from ._version import __version__ -module_name = "ipydatagrid" +module_name = "buckaroo" module_version = f"^{__version__}" diff --git a/buckaroo/_version.py b/buckaroo/_version.py new file mode 100644 index 000000000..f35a5b937 --- /dev/null +++ b/buckaroo/_version.py @@ -0,0 +1,10 @@ +# Copyright (c) Paddy Mullen. +# Distributed under the terms of the Modified BSD License. + +import pkg_resources + +try: + __version__ = pkg_resources.get_distribution('buckaroo').version +except Exception: + import json + __version__ = json.loads(open("../package.json").read())['version'] diff --git a/buckaroo/auto_clean/auto_clean.py b/buckaroo/auto_clean/auto_clean.py new file mode 100644 index 000000000..408511960 --- /dev/null +++ b/buckaroo/auto_clean/auto_clean.py @@ -0,0 +1,214 @@ +import math +import warnings + +from collections import defaultdict + +import pandas as pd +import numpy as np + + +#adapted from https://docs.python.org/3/library/warnings.html + +# this is needed to see if a series that we think should be datetime +# would throw a warning indicating a slow coercion this saves a huge +# (100x) slowdown + +def check_for_datetime_warnings(ser): + "return 1 if to_datetime throws errors for the series" + with warnings.catch_warnings(record=True) as w: + pd.to_datetime(ser, errors='coerce') + if len(w) == 0: + return 0 + if "Could not infer format" in str(w[-1].message): + return 1 + else: + #not sure how we'd get here + return 1 + +default_type_dict = { + 'datetime':0, 'datetime_error':0, + 'int':0, 'int_error':0, + 'float':0, 'float_error':0, + 'bool':0, 'bool_error':0} + + +#pandas parses ints and floats as datetimes in ns, you end up with a +# lot of values around 1970 Unix epoch we use 1971 as a cutoff, a bit +# of a hack, but pragmatic +SEVENTY_ONE_CUTOFF = pd.to_datetime('1971-01-01') + +def get_object_typing_metadata(ser): + # this function should just return percentages, to separate + # introspection from action. This way we can pass in a different + # decision weighting. As is this function is complex enough + counts = defaultdict(lambda: 0) + counts.update(default_type_dict) # we always want these keys present + assert pd.api.types.is_object_dtype(ser.dtype) + #this is slow because it goes through python as opposed to vectorized C code + for v in ser.values: + try: + dt = pd.to_datetime(v) + if dt > SEVENTY_ONE_CUTOFF: + counts['datetime'] += 1 + else: + counts['datetime_error'] += 1 + except (pd.core.tools.datetimes.DateParseError, ValueError, TypeError): + counts['datetime_error'] += 1 + + if isinstance(v, bool): + counts['bool'] += 1 + else: + counts['bool_error'] += 1 + if isinstance(v, str): + try: + int(v) + counts['int'] += 1 + except ValueError: + counts['int_error'] += 1 + try: + float(v) + counts['float'] += 1 + except ValueError: + counts['float_error'] += 1 + elif isinstance(v, float) or isinstance(v, int): + int(v) + counts['int'] += 1 + float(v) + counts['float'] += 1 + + + + if len(ser) == 0: + return counts + ret_dict = dict([[k, v/len(ser)] for k,v in counts.items()]) + + #this is an ugly hack, but it really speeds things up if there are + #abberant kind of datetime columns + if ret_dict['datetime_error'] < .5: + if check_for_datetime_warnings(ser): + ret_dict['datetime_error'] = 1.0 + if ret_dict['int_error'] < .5: + float_remainder = (pd.to_numeric(ser, errors='coerce').abs() % 1).sum() + if float_remainder > 0.0001: + ret_dict['int_error'] = 1 + return ret_dict + +def get_typing_metadata(ser): + td = default_type_dict.copy() #type_dict + dt = ser.dtype + if not pd.api.types.is_object_dtype(dt): + td['exact_type'] = str(dt) + if pd.api.types.is_datetime64_any_dtype(dt): + #general_type is used as a pass through + td['general_type'] = 'datetime' + elif pd.api.types.is_bool_dtype(dt): + td['general_type'] = 'bool' + elif pd.api.types.is_categorical_dtype(dt): + pass #not sure how to handle this yet, it will end up being handled as an object/string + elif pd.api.types.is_float_dtype(dt): + #could still be a float that includes only ints + td['general_type'] = 'float' + td['float'], td['float_error'] = 1, 0 + elif pd.api.types.is_integer_dtype(dt): + td['general_type'] = 'int' + td['int'], td['int_error'] = 1, 0 + return td + else: + return get_object_typing_metadata(ser.dropna()) + +def recommend_type(type_dict): + if type_dict.get('general_type', None) is not None: + return type_dict['general_type'] + if type_dict['datetime_error'] < 0.5: + return 'datetime' + if type_dict['bool_error'] < 0.5: + #bool ends up being stricter than int or float + return 'bool' + if type_dict['float_error'] < 0.5 or type_dict['int_error'] < 0.5: + #numeric type, figure out if float or int float will parse for + # everything that also parses as int + if math.isclose(type_dict['float'], type_dict['int']) or type_dict['int'] > type_dict['float']: + return 'int' + else: + return 'float' + return 'string' + +def smart_to_int(ser): + + if pd.api.types.is_numeric_dtype(ser): + working_ser = ser + lower, upper = ser.min(), ser.max() + else: + working_ser = pd.to_numeric(ser, errors='coerce') + lower, upper = working_ser.min(), working_ser.max() + + + if lower < 0: + if upper < np.iinfo(np.int8).max: + new_type = 'Int8' + elif upper < np.iinfo(np.int16).max: + new_type = 'Int16' + elif upper < np.iinfo(np.int32).max: + new_type = 'Int32' + else: + new_type = 'Int64' + else: + if upper < np.iinfo(np.uint8).max: + new_type = 'UInt8' + elif upper < np.iinfo(np.uint16).max: + new_type = 'UInt16' + elif upper < np.iinfo(np.uint32).max: + new_type = 'UInt32' + else: + new_type = 'UInt64' + base_ser = pd.to_numeric(ser, errors='coerce').dropna() + return base_ser.astype(new_type).reindex(ser.index) + +def coerce_series(ser, new_type): + if new_type == 'bool': + #dropna is key here, otherwise Nan's and errors are treated as true + return pd.to_numeric(ser, errors='coerce').dropna().astype('boolean').reindex(ser.index) + elif new_type == 'datetime': + return pd.to_datetime(ser, errors='coerce').reindex(ser.index) + elif new_type == 'int': + # try: + return smart_to_int(ser) + # except: + # #just let pandas figure it out, we recommended the wrong type + # return pd.to_numeric(ser, errors='coerce') + + elif new_type == 'float': + return pd.to_numeric(ser, errors='coerce').dropna().astype('float').reindex(ser.index) + elif new_type == 'string': + if int(pd.__version__[0]) < 2: + return ser.fillna(value="").astype('string').reindex(ser.index) + return ser.fillna(value="").astype('string').replace("", None).reindex(ser.index) + else: + raise Exception("Unkown type of %s" % new_type) + +def emit_command(col_name, new_type): + # I need a "no-op" new_type that doesn't change a column at all + # also possible meta tags about commands taht will change data, vs just re-typing + return [{"symbol":"to_%s" % new_type , "meta":{"precleaning":True}},{"symbol":"df"}, col_name] + +def auto_type_df(df): + #this is much faster because we only run the slow function on a maximum of 200 rows. + #That's a good size for an estimate + sample_size = min(len(df), 200) + recommended_types = {} + new_data = {} + for c in df.columns: + recommended_types[c] = recommend_type(get_typing_metadata(df[c].sample(sample_size))) + new_data[c] = coerce_series(df[c], recommended_types[c]) + return pd.DataFrame(new_data) + +def get_auto_type_operations(df, metadata_f, recommend_f): + #this is much faster because we only run the slow function on a maximum of 200 rows. + #That's a good size for an estimate + sample_size = min(len(df), 200) + cleaning_commands = [] + for c in df.columns: + metadata = metadata_f(df[c].sample(sample_size)) + new_type = recommend_f(metadata) + cleaning_commands.append(emit_command(c, new_type)) + return cleaning_commands diff --git a/buckaroo/auto_clean/cleaning_commands.py b/buckaroo/auto_clean/cleaning_commands.py new file mode 100644 index 000000000..1daa0f4df --- /dev/null +++ b/buckaroo/auto_clean/cleaning_commands.py @@ -0,0 +1,104 @@ +from ..jlisp.lispy import s +from ..jlisp.configure_utils import configure_buckaroo +from .auto_clean import smart_to_int, get_auto_type_operations +import pandas as pd + +class Command(object): + pass + +class to_bool(Command): + #argument_names = ["df", "col"] + command_default = [s('to_bool'), s('df'), "col"] + command_pattern = [None] + + @staticmethod + def transform(df, col): + ser = df[col] + df[col] = pd.to_numeric(ser, errors='coerce').dropna().astype('boolean').reindex(ser.index) + return df + + @staticmethod + def transform_to_py(df, col): + return " df['%s'] = pd.to_numeric(df['%s'], errors='coerce').dropna().astype('boolean').reindex(df['%s'].index)" % (col, col, col) + +class to_datetime(Command): + #argument_names = ["df", "col"] + command_default = [s('to_datetime'), s('df'), "col"] + command_pattern = [None] + + @staticmethod + def transform(df, col): + ser = df[col] + df[col] = pd.to_datetime(ser, errors='coerce').reindex(ser.index) + return df + + @staticmethod + def transform_to_py(df, col): + return " df['%s'] = pd.to_datetime(df['%s'], errors='coerce').reindex(df['%s'].index)" % (col, col, col) + +class to_int(Command): + #argument_names = ["df", "col"] + command_default = [s('to_int'), s('df'), "col"] + command_pattern = [None] + + @staticmethod + def transform(df, col): + ser = df[col] + try: + df[col] = smart_to_int(ser) + except Exception: + #just let pandas figure it out, we recommended the wrong type + df[col] = pd.to_numeric(ser, errors='coerce') + + return df + + @staticmethod + def transform_to_py(df, col): + return " df['%s'] = smart_to_int(df['%s'])" % (col, col) + +class to_float(Command): + #argument_names = ["df", "col"] + command_default = [s('to_float'), s('df'), "col"] + command_pattern = [None] + + @staticmethod + def transform(df, col): + ser = df[col] + df[col] = pd.to_numeric(ser, errors='coerce').dropna().astype('float').reindex(ser.index) + return df + + @staticmethod + def transform_to_py(df, col): + return " df['%s'] = pd.to_numeric(df['%s'], errors='coerce')" % (col, col) + +class to_string(Command): + #argument_names = ["df", "col"] + command_default = [s('to_string'), s('df'), "col"] + command_pattern = [None] + + @staticmethod + def transform(df, col): + ser = df[col] + if int(pd.__version__[0]) < 2: + df[col] = ser.fillna(value="").astype('string').reindex(ser.index) + return df + df[col] = ser.fillna(value="").astype('string').replace("", None).reindex(ser.index) + return df + + @staticmethod + def transform_to_py(df, col): + return " df['%s'] = df['%s'].fillna(value='').astype('string').replace('', None)" % (col, col) + + + +cleaning_classes = [to_bool, to_datetime, to_int, to_float, to_string,] + +def auto_type_df2(df): + _command_defaults, _command_patterns, transform, buckaroo_to_py_core = configure_buckaroo( + cleaning_classes) + + cleaning_operations = get_auto_type_operations(df) + + full_ops = [{'symbol': 'begin'}] + full_ops.extend(cleaning_operations) + return transform(full_ops, df) diff --git a/buckaroo/buckaroo_widget.py b/buckaroo/buckaroo_widget.py new file mode 100644 index 000000000..ea12d67e1 --- /dev/null +++ b/buckaroo/buckaroo_widget.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python +# coding: utf-8 + +# Copyright (c) Paddy Mullen. +# Distributed under the terms of the Modified BSD License. + +""" +TODO: Add module docstring +""" + +from ipywidgets import DOMWidget +from traitlets import Unicode, List, Dict, observe + +from ._frontend import module_name, module_version +from .customizations.all_transforms import DefaultCommandKlsList + + +from .customizations.analysis import (TypingStats, ComputedDefaultSummaryStats, DefaultSummaryStats) +from .customizations.histogram import (Histogram) +from .customizations.styling import (DefaultSummaryStatsStyling, DefaultMainStyling) +from .pluggable_analysis_framework.analysis_management import DfStats +from .pluggable_analysis_framework.pluggable_analysis_framework import ColAnalysis + +from .serialization_utils import EMPTY_DF_WHOLE +from .dataflow.dataflow import CustomizableDataflow, StylingAnalysis, exception_protect +from .dataflow.dataflow_extras import (Sampling) + +class BuckarooProjectWidget(DOMWidget): + """ + Repetitious code needed to make Jupyter communicate properly with any BuckarooWidget in this package + + """ + _model_module = Unicode(module_name).tag(sync=True) + _view_module = Unicode(module_name).tag(sync=True) + + _model_module_version = Unicode(module_version).tag(sync=True) + _view_module_version = Unicode(module_version).tag(sync=True) + + + +class PdSampling(Sampling): + #pre_limit = 500_000 + pre_limit = False + +class BuckarooWidget(CustomizableDataflow, BuckarooProjectWidget): + """Extends CustomizableDataFlow and DOMWIdget + + Replaces generic options in CustomizableDataFlow with Pandas implementations + Also adds buckaroo_state object and communication to simpler CustomizableDataFlow implementations + + """ + + #### DOMWidget Boilerplate + _model_name = Unicode('DCEFWidgetModel').tag(sync=True) + _view_name = Unicode('DCEFWidgetView').tag(sync=True) + #END DOMWidget Boilerplate + + sampling_klass = PdSampling + + operations = List().tag(sync=True) + operation_results = Dict( + {'transformed_df': EMPTY_DF_WHOLE, 'generated_py_code':'# instantiation, unused'} + ).tag(sync=True) + + df_meta = Dict({ + 'columns': 5, + 'rows_shown': 20, + 'total_rows': 877}).tag(sync=True) + + + buckaroo_state = Dict({ + 'auto_clean': 'conservative', + 'post_processing': '', + 'sampled': False, + 'show_commands': False, + 'df_display': 'main', + 'search_string': '', + }).tag(sync=True) + + + @observe('buckaroo_state') + @exception_protect('buckaroo_state-protector') + def _buckaroo_state(self, change): + #how to control ordering of column_config??? + # dfviewer_config = self._get_dfviewer_config(self.merged_sd, self.style_method) + # self.widget_args_tuple = [self.processed_df, self.merged_sd, dfviewer_config] + old, new = change['old'], change['new'] + if not old['post_processing'] == new['post_processing']: + self.post_processing_method = new['post_processing'] + + + + #widget config. Change these via inheritance to alter core behaviors of buckaroo + command_klasses = DefaultCommandKlsList + analysis_klasses = [TypingStats, DefaultSummaryStats, + Histogram, + ComputedDefaultSummaryStats, + StylingAnalysis, + DefaultSummaryStats, + DefaultSummaryStatsStyling, DefaultMainStyling] + + + DFStatsClass = DfStats + + + def add_analysis(self, analysis_klass): + """ + same as get_summary_sd, call whatever to set summary_sd and trigger further comps + """ + + stats = self.DFStatsClass( + self.processed_df, + self.analysis_klasses, + self.df_name, debug=self.debug) + stats.add_analysis(analysis_klass) + self.analysis_klasses = stats.ap.ordered_a_objs + self.setup_options_from_analysis() + self.summary_sd = stats.sdf + + def add_processing(self, df_processing_func): + proc_func_name = df_processing_func.__name__ + class DecoratedProcessing(ColAnalysis): + provides_defaults = {} + @classmethod + def post_process_df(kls, df): + new_df = df_processing_func(df) + return [new_df, {}] + post_processing_method = proc_func_name + self.add_analysis(DecoratedProcessing) + temp_buckaroo_state = self.buckaroo_state.copy() + temp_buckaroo_state['post_processing'] = proc_func_name + self.buckaroo_state = temp_buckaroo_state + + +class RawDFViewerWidget(BuckarooProjectWidget): + """ + + A very raw way of instaniating just the DFViewer, not meant for use by enduers + + instead use DFViewer, or PolarsDFViewer which have better convience methods + """ + + #### DOMWidget Boilerplate + _model_name = Unicode('DFViewerModel').tag(sync=True) + _view_name = Unicode('DFViewerView').tag(sync=True) + #END DOMWidget Boilerplate + + + + df_data = List([ + {'a': 5 , 'b':20, 'c': 'Paddy'}, + {'a': 58.2, 'b': 9, 'c': 'Margaret'}]).tag(sync=True) + + df_viewer_config = Dict({ + 'column_config': [ + { 'col_name': 'a', + 'displayer_args': { 'displayer': 'float', 'min_fraction_digits': 2, 'max_fraction_digits': 8 }}, + { 'col_name': 'b', + 'displayer_args': { 'displayer': 'integer', 'min_digits': 3, 'max_digits': 5 }}, + { 'col_name': 'c', + 'displayer_args': { 'displayer': 'string', 'min_digits': 3, 'max_digits': 5 }}], + 'pinned_rows': [ + { 'primary_key_val': 'dtype', 'displayer_args': { 'displayer': 'obj' }}, + { 'primary_key_val': 'mean', 'displayer_args': { 'displayer': 'integer', 'min_digits': 3, 'max_digits': 5 }}]} + ).tag(sync=True) + + summary_stats_data = List([ + { 'index': 'mean', 'a': 28, 'b': 14, 'c': 'Padarget' }, + { 'index': 'dtype', 'a': 'float64', 'b': 'int64', 'c': 'object' }]).tag(sync=True) + + diff --git a/dcef/channeldata.json b/buckaroo/channeldata.json similarity index 100% rename from dcef/channeldata.json rename to buckaroo/channeldata.json diff --git a/dcef/all_transforms.py b/buckaroo/customizations/all_transforms.py similarity index 73% rename from dcef/all_transforms.py rename to buckaroo/customizations/all_transforms.py index e267aa363..a41f38d5e 100644 --- a/dcef/all_transforms.py +++ b/buckaroo/customizations/all_transforms.py @@ -1,8 +1,10 @@ -from .lispy import s -from .configure_utils import configure_dcef import pandas as pd import numpy as np +from ..jlisp.lispy import s +from ..jlisp.configure_utils import configure_buckaroo +from ..auto_clean.cleaning_commands import (to_bool, to_datetime, to_int, to_float, to_string) + class Command(object): pass @@ -48,7 +50,7 @@ def transform(df, col): def transform_to_py(df, col): commands = [ " one_hot = pd.get_dummies(df['%s'])" % (col), - " df.drop('%s', inplace=True)" % (col), + " df.drop('%s', axis=1, inplace=True)" % (col), " df = df.join(one_hot)"] return "\n".join(commands) @@ -122,8 +124,39 @@ def transform_to_py(df, col, col_spec): - +class ato_datetime(Command): + #argument_names = ["df", "col"] + command_default = [s('to_datetime'), s('df'), "col"] + command_pattern = [None] + + @staticmethod + def transform(df, col): + df[col] = pd.to_datetime(df[col]) + return df + + @staticmethod + def transform_to_py(df, col): + return " df['%s'] = pd.to_datetime(df['%s'])" % (col, col) + +class reindex(Command): + command_default = [s('reindex'), s('df'), "col"] + command_pattern = [None] + + @staticmethod + def transform(df, col): + old_col = df[col] + df.drop(col, axis=1, inplace=True) + df.index = old_col.values + return df -DefaultCommandKlsList = [FillNA, DropCol, OneHot, GroupBy] -command_defaults, command_patterns, dcef_transform, dcef_to_py_core = configure_dcef(DefaultCommandKlsList) + @staticmethod + def transform_to_py(df, col): + return "\n".join( + [" old_col = df['%s']" % col, + " df.drop('%s', axis=1, inplace=True)" % col, + " df.index = old_col.values"]) + +DefaultCommandKlsList = [DropCol, SafeInt, FillNA, reindex, OneHot, GroupBy, + to_bool, to_datetime, to_int, to_float, to_string] +command_defaults, command_patterns, buckaroo_transform, buckaroo_to_py_core = configure_buckaroo(DefaultCommandKlsList) diff --git a/buckaroo/customizations/analysis.py b/buckaroo/customizations/analysis.py new file mode 100644 index 000000000..20c7d1316 --- /dev/null +++ b/buckaroo/customizations/analysis.py @@ -0,0 +1,138 @@ +import pandas as pd +import numpy as np +from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import ColAnalysis +import warnings + +def probable_datetime(ser): + #turning off warnings in this single function is a bit of a hack. + #Understandable since this is explicitly abusing pd.to_datetime + #which throws warnings. + + warnings.filterwarnings('ignore') + s_ser = ser.sample(np.min([len(ser), 500])) + try: + dt_ser = pd.to_datetime(s_ser) + #pd.to_datetime(1_00_000_000_000_000_000) == pd.to_datetime('1973-01-01') + warnings.filterwarnings('default') + if dt_ser.max() < pd.to_datetime('1973-01-01'): + return False + return True + + except Exception: + warnings.filterwarnings('default') + return False + +def get_mode(ser): + try: + mode_raw = ser.mode() + if len(mode_raw) == 0: + return np.nan + else: + return mode_raw.values[0] + except Exception: + return np.nan + + +""" +to best take advantage of the DAG and pluggable_analysis_framework, structure your code as follows +a single ColAnalysis can return multiple facts, but those facts shouldn't be interdepedent +That way individual facts can be overridden via the DAG machinery, and other facts that depend on them will +get the proper value + +Overtime codebases will probably trend towards many classes with single facts, but it doesn't have to be that way. Code what comes naturally to you + + +""" + +class TypingStats(ColAnalysis): + + provides_defaults = { + 'dtype':'asdf', 'is_numeric':False, 'is_integer':False, + 'is_datetime':False, 'is_bool':False, 'is_float':False, '_type':'asdf'} + + @staticmethod + def series_summary(sampled_ser, ser): + return dict( + dtype=str(ser.dtype), + is_numeric=pd.api.types.is_numeric_dtype(ser), + is_integer=pd.api.types.is_integer_dtype(ser), + is_datetime=probable_datetime(ser), + is_bool=pd.api.types.is_bool_dtype(ser), + is_float=pd.api.types.is_float_dtype(ser), + is_string=pd.api.types.is_string_dtype(ser), + memory_usage=ser.memory_usage()) + + @staticmethod + def computed_summary(summary_dict): + _type = "obj" + if summary_dict['is_bool']: + _type = "boolean" + elif summary_dict['is_numeric']: + if summary_dict['is_float']: + _type = "float" + else: + _type = "integer" + #elif pd.api.types.is_datetime64_any_dtype(ser): + elif summary_dict['is_datetime']: + _type = 'datetime' + elif summary_dict['is_string']: + _type = "string" + return dict(_type=_type) + +class DefaultSummaryStats(ColAnalysis): + provides_defaults = { + 'length':0, 'min':0, 'max':0, 'mean':0, 'nan_count':0, + 'value_counts':0, 'mode':0} + @staticmethod + def series_summary(sampled_ser, ser): + l = len(ser) + value_counts = ser.value_counts() + nan_count = l - len(ser.dropna()) + is_numeric = pd.api.types.is_numeric_dtype(ser) + is_bool = pd.api.types.is_bool_dtype(ser) + + base_d = dict( + length=l, + nan_count=nan_count, + value_counts=value_counts, + mode=get_mode(ser), + min=np.nan, + max=np.nan) + if is_numeric and not is_bool: + base_d.update({ + 'mean': ser.mean(), + 'min': ser.dropna().min(), + 'max': ser.dropna().max()}) + return base_d + +class ComputedDefaultSummaryStats(ColAnalysis): + + + requires_summary = ['length', 'nan_count', + 'value_counts'] + + provides_defaults = { + 'distinct_per':0, 'empty_per':0, 'unique_per':0, 'nan_per':0, + 'unique_count':0, 'empty_count':0, 'distinct_count':0} + + + @staticmethod + def computed_summary(summary_dict): + l = summary_dict['length'] + value_counts = summary_dict['value_counts'] + try: + empty_count = value_counts.get('', 0) + except: + empty_count = 0 + distinct_count=len(value_counts) + unique_count = len(value_counts[value_counts==1]) + + return dict( + unique_count=unique_count, + empty_count=empty_count, + distinct_count=distinct_count, + distinct_per=distinct_count/l, + empty_per=empty_count/l, + unique_per=unique_count/l, + nan_per=summary_dict['nan_count']/l) + diff --git a/buckaroo/customizations/analysis_utils.py b/buckaroo/customizations/analysis_utils.py new file mode 100644 index 000000000..446b5b27c --- /dev/null +++ b/buckaroo/customizations/analysis_utils.py @@ -0,0 +1,14 @@ +import numpy as np +import pandas as pd + + +def int_digits(n): + if pd.isna(n): + return 1 + if np.isnan(n): + return 1 + if n == 0: + return 1 + if np.sign(n) == -1: + return int(np.floor(np.log10(np.abs(n)))) + 2 + return int(np.floor(np.log10(n)+1)) \ No newline at end of file diff --git a/buckaroo/customizations/down_sample.py b/buckaroo/customizations/down_sample.py new file mode 100644 index 000000000..e5db9084a --- /dev/null +++ b/buckaroo/customizations/down_sample.py @@ -0,0 +1,40 @@ +import pandas as pd +import numpy as np + + +def get_outlier_idxs(ser): + if not pd.api.types.is_numeric_dtype(ser.dtype): + return [] + outlier_idxs = [] + outlier_idxs.extend(ser.nlargest(5).index) + outlier_idxs.extend(ser.nsmallest(5).index) + return outlier_idxs + + +def polars_sample(df, sample_size=500, include_outliers=False): + return df.sample(min(len(df), sample_size)) + +def sample(df, sample_size=500, include_outliers=False): + include_outliers = False + if len(df) <= sample_size: + return df + + try: + import polars + if isinstance(df, polars.DataFrame): + return polars_sample(df, sample_size, include_outliers) + except ImportError: + pass + sdf = df.sample(np.min([sample_size, len(df)])) + if True: + return sdf + #non_unique indexes are very slow + if include_outliers and sdf.index.is_unique: + outlier_idxs = [] + for col in df.columns: + outlier_idxs.extend(get_outlier_idxs(df[col]) ) + outlier_idxs.extend(sdf.index) + uniq_idx = np.unique(outlier_idxs) + return df.loc[uniq_idx] + return sdf + diff --git a/buckaroo/customizations/histogram.py b/buckaroo/customizations/histogram.py new file mode 100644 index 000000000..cd5a7b6f5 --- /dev/null +++ b/buckaroo/customizations/histogram.py @@ -0,0 +1,138 @@ +import pandas as pd +import numpy as np +from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import ColAnalysis + + +def numeric_histogram_labels(endpoints): + left = endpoints[0] + labels = [] + for edge in endpoints[1:]: + labels.append("{:.0f}-{:.0f}".format(left, edge)) + left = edge + return labels + +def categorical_dict(len_, val_counts, top_n_positions=7): + top = min(len(val_counts), top_n_positions) + top_vals = val_counts.iloc[:top] + + rest_vals = val_counts.iloc[top:] + try: + histogram = top_vals.to_dict() + except TypeError: + top_vals.index = top_vals.index.map(str) + histogram = top_vals.to_dict() + + full_long_tail = rest_vals.sum() + unique_count = sum(val_counts == 1) + long_tail = full_long_tail - unique_count + if unique_count > 0: + histogram['unique'] = np.round( (unique_count/len_)* 100, 0) + if long_tail > 0: + histogram['longtail'] = np.round((long_tail/len_) * 100,0) + return histogram + + +def categorical_histogram(length:int, val_counts, nan_per:float, top_n_positions=7): + nan_observation = {'name':'NA', 'NA':np.round(nan_per*100, 0)} + cd = categorical_dict(length, val_counts, top_n_positions) + + histogram = [] + longtail_obs = {'name': 'longtail'} + for k,v in cd.items(): + if k in ["longtail", "unique"]: + longtail_obs[k] = v + continue + histogram.append({'name':k, 'cat_pop': np.round((v/length)*100,0) }) + if len(longtail_obs) > 1: + histogram.append(longtail_obs) + if nan_per > 0.0: + histogram.append(nan_observation) + return histogram + +# histogram_args = TypedDict('histogram_args', { +# 'meat_histogram': Tuple[npt.NDArray[np.intp], npt.NDArray[Any]], +# 'low_tail': float, 'high_tail':float}) + +# class Histogram_Args(TypedDict): +# meat_histogram: Tuple[List[int], List[float]] +# normalized_populations:List[float] +# low_tail: float +# high_tail: float + +#def numeric_histogram(histogram_args: Histogram_Args , min_, max_, nan_per): +def numeric_histogram(histogram_args, min_, max_, nan_per): + low_tail, high_tail = histogram_args['low_tail'], histogram_args['high_tail'] + ret_histo = [] + nan_observation = {'name':'NA', 'NA':np.round(nan_per*100, 0)} + if nan_per == 1.0: + return [nan_observation] + + populations, endpoints = histogram_args['meat_histogram'] + + labels = numeric_histogram_labels(endpoints) + #normalized_pop = populations / populations.sum() + normalized_pop = histogram_args['normalized_populations'] + low_label = "%r - %r" % (min_, low_tail) + + ret_histo.append({'name': low_label, 'tail':1}) + for label, pop in zip(labels, normalized_pop): + ret_histo.append({'name': label, 'population':np.round(pop * 100, 0)}) + high_label = "%r - %r" % (high_tail, max_) + ret_histo.append({'name': high_label, 'tail':1}) + if nan_per > 0.0: + ret_histo.append(nan_observation) + return ret_histo + + +class Histogram(ColAnalysis): + provides_defaults = dict( + histogram= [[],[]], histogram_args=[], histogram_bins=[]) + + @staticmethod + def series_summary(sampled_ser, ser): + """ + https://stackoverflow.com/questions/11882393/matplotlib-disregard-outliers-when-plotting + """ + if not pd.api.types.is_numeric_dtype(ser): + return dict(histogram_args={}) + if pd.api.types.is_bool_dtype(ser): + return dict(histogram_args={}) + vals = ser.dropna() + if len(vals) == 0: + return dict(histogram_args={}) + low_tail = np.quantile(vals, 0.01) + high_tail = np.quantile(vals, 0.99) + low_pass = ser > low_tail + high_pass = ser < high_tail + meat = vals[low_pass & high_pass] + if len(meat) == 0: + return dict(histogram_args={}) + + meat_histogram=np.histogram(meat, 10) + populations, _ = meat_histogram + return dict( + histogram_bins = meat_histogram[1], + histogram_args=dict( + meat_histogram=meat_histogram, + normalized_populations=(populations/populations.sum()).tolist(), + low_tail=low_tail, + high_tail=high_tail)) + + requires_summary = ['value_counts', 'nan_per', 'is_numeric', 'length', + 'min', 'max',] + + + @staticmethod + def computed_summary(summary_dict): + is_numeric = summary_dict['is_numeric'] + value_counts = summary_dict['value_counts'] + nan_per = summary_dict['nan_per'] + if is_numeric and len(value_counts) > 5 and summary_dict['histogram_args']: + histogram_args = summary_dict['histogram_args'] + min_, max_ = summary_dict['min'], summary_dict['max'] + temp_histo = numeric_histogram(histogram_args, min_, max_, nan_per) + if len(temp_histo) > 5: + #if we had basically a categorical variable encoded into an integer.. don't return it + return {'histogram': temp_histo} + length = summary_dict['length'] + return {'histogram':categorical_histogram(length, value_counts, nan_per)} diff --git a/buckaroo/customizations/order_columns.py b/buckaroo/customizations/order_columns.py new file mode 100644 index 000000000..b75e88447 --- /dev/null +++ b/buckaroo/customizations/order_columns.py @@ -0,0 +1,95 @@ +import pandas as pd +import numpy as np + + +def make_num_categorical(ser): + return ser.dropna().astype('category', errors='ignore').cat.codes + +def get_cor_pair_dict(df, sdf): + + corrable_cols = sdf.columns[ + (sdf.loc['distinct_count'] > 1) & + ((sdf.loc['distinct_per'] < .3) | + (sdf.loc['distinct_count'] < 50))] + + num_df = pd.DataFrame({col:make_num_categorical(df[col]) for col in corrable_cols}) + + corr_df = num_df.corr() + high_corr_df = corr_df[corr_df > 0.6] + + #print(high_corr_df) + + cor_dict = {} + for col in high_corr_df.columns: + #columns with high correlation that aren't the column itself + other_cor_cols = high_corr_df[col].dropna().drop(col) + cor_cols = other_cor_cols.index.values + if len(cor_cols) > 0: + cor_dict[col] = cor_cols.tolist() + return cor_dict + +def set_when(df, cond_row_name, target_row_name, true_val, false_val): + true_row = df.loc[cond_row_name] + df.loc[target_row_name] = false_val + df.loc[target_row_name, true_row[true_row==True].index.values] = true_val + return df + +def without(arr, search_keys): + new_arr = [] + for v in arr: + if v not in search_keys: + new_arr.append(v) + return new_arr + +def find_groupings(corr_pairs): + all_groupings = [] + for key, other_key_list in corr_pairs.items(): + ab = other_key_list.copy() + ab.append(key) + all_groupings.append(set(ab)) + return np.unique(all_groupings) + +def order_groupings(grps, ranked_cols): + first_cols, rest_cols = [], [] + for col in ranked_cols: + for grp in grps: + if col in grp: + first_cols.append(col) + rest_cols.extend(list(without(grp, [col]))) + grps = without(grps, [grp]) + return list(set(first_cols)), list(set(rest_cols)) + +def order_columns(sdf, corr_pair_dict): + grouping_col_scores = sdf.loc[['grouping_score_integer', 'grouping_score_numeric']].sum() + duplicate_col_rankings = grouping_col_scores.sort_values().index[::-1].values + + groupings = find_groupings(corr_pair_dict) + #print("groupings", groupings) + first_cols, duplicate_cols = order_groupings(groupings, duplicate_col_rankings) + + #print("duplicate_cols", duplicate_cols) + sdf.loc['first_col':, first_cols] = 5 + sdf.loc['is_duplicate':, duplicate_cols] = -5 + #print(sdf.index) + col_scores = sdf.loc[['one_distinct', 'first_col', 'datetime_score', 'is_duplicate']].sum() + return col_scores.sort_values().index.values[::-1] + +def reorder_columns(df): + tdf_stats = summarize_df(df) + cpd = get_cor_pair_dict(df, tdf_stats) + # try: + col_order = order_columns(tdf_stats, cpd) + return df[col_order] + +def add_col_rankings(df, sdf): + sdf.loc['one_distinct'] = 0 + + only_ones = (sdf.loc['distinct_count'] <= 1) + sdf.loc['one_distinct', only_ones[only_ones==True].index.values] = -20 + + sdf.loc['first_col'] = 0 + sdf.loc['is_duplicate'] = 0 + set_when(sdf, 'is_datetime', 'datetime_score', 11, 0) + + set_when(sdf, 'is_integer', 'grouping_score_integer', -3, 0) + set_when(sdf, 'is_numeric', 'grouping_score_numeric', -3, 5) diff --git a/buckaroo/customizations/polars_analysis.py b/buckaroo/customizations/polars_analysis.py new file mode 100644 index 000000000..54c90c137 --- /dev/null +++ b/buckaroo/customizations/polars_analysis.py @@ -0,0 +1,254 @@ +import polars as pl +import numpy as np +import polars.selectors as cs +from polars import functions as F +from polars import datatypes as pdt + +from buckaroo.pluggable_analysis_framework.polars_analysis_management import PolarsAnalysis +from buckaroo.pluggable_analysis_framework.polars_utils import NUMERIC_POLARS_DTYPES +from buckaroo.pluggable_analysis_framework.utils import json_postfix +from buckaroo.customizations.histogram import numeric_histogram +from typing import Dict + +def get_mode(ser): + mode_raw = ser.mode() + if len(mode_raw) == 0: + return np.nan + else: + return mode_raw.values[0] + +""" +to best take advantage of the DAG and pluggable_analysis_framework, structure your code as follows +a single ColAnalysis can return multiple facts, but those facts shouldn't be interdepedent +That way individual facts can be overridden via the DAG machinery, and other facts that depend on them will +get the proper value + +Overtime codebases will probably trend towards many classes with single facts, but it doesn't have to be that way. Code what comes naturally to you + + +""" + + + + +class ComputedDefaultSummaryStats(PolarsAnalysis): + requires_summary = ['length', 'nan_count', + 'unique_count', 'empty_count', 'distinct_count'] + provides_defaults = dict( + distinct_per=0, empty_per=0, unique_per=0, nan_per=0) + + + @staticmethod + def computed_summary(summary_dict): + len_ = summary_dict['length'] + return dict( + distinct_per=summary_dict['distinct_count']/len_, + empty_per=summary_dict.get('empty_count',0)/len_, + unique_per=summary_dict['unique_count']/len_, + nan_per=summary_dict['nan_count']/len_) + + + +PROBABLY_STRUCTS = (~cs.numeric() & ~cs.string() & ~cs.temporal() & + ~cs.boolean()) +NOT_STRUCTS = (~PROBABLY_STRUCTS) + +class VCAnalysis(PolarsAnalysis): + provides_defaults = dict( + value_counts=pl.Series( + "", + [{'a': 'error', 'count': 1}], dtype=pl.Struct({'a': pl.String, 'count': pl.UInt32}))) + + select_clauses = [ + NOT_STRUCTS.exclude("count").value_counts(sort=True) + .implode().name.map(json_postfix('value_counts')), + (NOT_STRUCTS & pl.selectors.matches("^count$")) + .alias("not_counts") + .value_counts(sort=True) + .implode() + .alias("count").name.map(json_postfix('value_counts'))] + + +DUMMY_VALUE_COUNTS = pl.Series( + [{'a': 3, 'count': 1}, {'a': 4, 'count': 1}, {'a': 5, 'count': 1}]) +class BasicAnalysis(PolarsAnalysis): + + + provides_defaults = dict(length=0, nan_count=0, min=0, max=0, mode=0, + mean=0, unique_count=0, empty_count=0, distinct_count=0) + + requires_summary = ['value_counts'] + select_clauses = [ + F.all().len().name.map(json_postfix('length')), + F.all().null_count().name.map(json_postfix('nan_count')), + NOT_STRUCTS.min().name.map(json_postfix('min')), + NOT_STRUCTS.max().name.map(json_postfix('max')), + NOT_STRUCTS.mean().name.map(json_postfix('mean')), + F.col(pl.Utf8).str.count_matches("^$").sum().name.map(json_postfix('empty_count')), + (NOT_STRUCTS.len() - NOT_STRUCTS.is_duplicated().sum()).name.map(json_postfix('unique_count')) + ] + + @staticmethod + def computed_summary(summary_dict): + + if 'value_counts' in summary_dict: + temp_df = pl.DataFrame({'vc': summary_dict['value_counts'].explode()}).unnest('vc') + regular_col_vc_df = temp_df.select(pl.all().exclude('count').alias('key'), pl.col('count')) + return dict(mode=regular_col_vc_df[0]['key'][0], distinct_count=len(temp_df)) + else: + + return dict(mode=None, value_counts=DUMMY_VALUE_COUNTS, distinct_count=0, + mean=0, unique_count=0) + + +class PlTyping(PolarsAnalysis): + column_ops = {'dtype': ("all", lambda col_series: col_series.dtype)} + provides_defaults = dict(dtype='unknown', _type='unknown', is_numeric=False, is_integer=False) + + @staticmethod + def computed_summary(summary_dict): + dt = summary_dict['dtype'] + + res = {'is_numeric': False, 'is_integer': False} + + if dt in pdt.INTEGER_DTYPES: + t = 'integer' + elif dt in pdt.DATETIME_DTYPES: + t = 'datetime' + elif dt in pdt.FLOAT_DTYPES: + t = 'float' + elif dt in pl.datatypes.TEMPORAL_DTYPES: + #feels like a hack + t = 'temporal' + elif dt == pdt.Utf8: + t = 'string' + elif dt == pdt.Boolean: + t = 'boolean' + else: + t = 'unknown' + if t in ('integer', 'float'): + res['is_numeric'] = True + if t == 'integer': + res['is_integer'] = True + res['_type'] = t + return res + +def normalize_polars_histogram_ser(ser): + df = pl.DataFrame({'named_col':ser}) + + C = pl.col('named_col') + small_q, large_q = C.quantile(.01).alias('small'), C.quantile(.99).alias('large') + smallest, largest = df.select(small_q, large_q).to_numpy()[0] + + meat_df = df.lazy().filter( + (small_q < C) & (C < large_q) + ).select(C).collect()['named_col'] + if len(meat_df) == 0: + return { 'low_tail': smallest, 'high_tail':largest, + 'meat_histogram': [[],[]], 'normalized_populations': []} + raw_hist = meat_df.hist(bin_count=10, include_breakpoint=True) + hist_df = raw_hist.select(pl.col("break_point"), pl.selectors.ends_with("count").alias("count")) + edges = hist_df['break_point'].to_list() + edges[0], edges[-1] = smallest, largest + counts = hist_df['count'][1:] + norm_counts = counts/counts.sum() + return { 'low_tail': smallest, 'high_tail':largest, + 'meat_histogram': (counts.to_list(), edges), + 'normalized_populations': norm_counts.to_list()} + + +def categorical_dict_from_vc(vc_ser, top_n_positions=7) -> Dict[str, int]: + temp_df = pl.DataFrame({'vc': vc_ser.explode()}).unnest('vc') + regular_col_vc_df = temp_df.select(pl.all().exclude('count').alias('key'), pl.col('count')) + length = regular_col_vc_df['count'].sum() + normalized_counts = regular_col_vc_df['count'] / length + nml_df = pl.DataFrame({'key':regular_col_vc_df['key'], 'normalized_count':normalized_counts}) + + #filter out small categories + significant_categories_df = nml_df.filter(pl.col('normalized_count') > .05) + relevant_length = min(len(significant_categories_df), top_n_positions) + cat_df = significant_categories_df[:relevant_length] + + #everything that isn't a named category. relevant_length still applies + full_long_tail = regular_col_vc_df['count'][relevant_length:].sum() + unique_count = regular_col_vc_df['count'].eq(1).cum_sum()[-1] + + actual_long_tail = full_long_tail - unique_count + + categorical_histogram = dict(zip(cat_df['key'].to_list(), cat_df['normalized_count'].to_list())) + categorical_histogram['longtail'] = actual_long_tail/length + categorical_histogram['unique'] = unique_count/length + return categorical_histogram + + +def categorical_histogram_from_cd(cd, nan_per): + histogram = [] + longtail_obs = {'name': 'longtail'} + unique_obs = {'name': 'unique'} + for k,v in cd.items(): + if k == "longtail": + longtail_obs['longtail'] = np.round((v)*100,0) + continue + elif k == "unique": + unique_obs['unique'] = np.round((v)*100,0) + continue + histogram.append({'name':k, 'cat_pop': np.round((v)*100,0) }) + if longtail_obs['longtail'] > 0: + histogram.append(longtail_obs) + if unique_obs['unique'] > 0: + histogram.append(unique_obs) + nan_observation = {'name':'NA', 'NA':np.round(nan_per*100, 0)} + if nan_per > 0.0: + histogram.append(nan_observation) + return histogram + +class HistogramAnalysis(PolarsAnalysis): + + column_ops = { + 'histogram_args': (NUMERIC_POLARS_DTYPES, normalize_polars_histogram_ser)} + + requires_summary = ['min', 'max', 'value_counts', 'length', 'unique_count', 'is_numeric', 'nan_per'] + provides_defaults = dict(categorical_histogram=[], histogram=[], histogram_bins=[]) + + @staticmethod + def computed_summary(summary_dict): + if len(summary_dict.keys()) == 0: + return {} + + vc = summary_dict['value_counts'] + cd = categorical_dict_from_vc(vc) + is_numeric = summary_dict.get('is_numeric', False) + nan_per = summary_dict['nan_per'] + if is_numeric and len(vc.explode()) > 5: + histogram_args = summary_dict['histogram_args'] + min_, max_, nan_per = summary_dict['min'], summary_dict['max'], summary_dict['nan_per'] + temp_histo = numeric_histogram(histogram_args, min_, max_, nan_per) + if len(temp_histo) > 5: + #if we had basically a categorical variable encoded into an integer.. don't return it + return {'histogram': temp_histo, + 'histogram_bins': summary_dict['histogram_args']['meat_histogram'][1] + } + return {'categorical_histogram': cd, 'histogram' : categorical_histogram_from_cd(cd, nan_per), + 'histogram_bins': ['faked'] + } + +class PLCleaningStats(PolarsAnalysis): + requires_summary = ['value_counts', 'length'] + provides_defaults = {'int_parse_fail': 0.0, 'int_parse':0.0} + + @staticmethod + def computed_summary(column_metadata): + vc_ser, len_ = column_metadata['value_counts'], column_metadata['length'] + vc_df = pl.DataFrame({'vc': vc_ser.explode()}).unnest('vc') + regular_col_vc_df = vc_df.select(pl.all().exclude('count').alias('key'), pl.col('count')) + int_parse = pl.col('key').cast(pl.Int64, strict=False).is_null() + per_df = regular_col_vc_df.select( + int_parse.replace({True:1, False:0}).mul(pl.col('count')).sum().alias('int_parse_fail'), + int_parse.replace({True:0, False:1}).mul(pl.col('count')).sum().alias('int_parse')) / len_ + return per_df.to_dicts()[0] + + +PL_Analysis_Klasses = [VCAnalysis, BasicAnalysis, PlTyping, + HistogramAnalysis, ComputedDefaultSummaryStats] + + diff --git a/buckaroo/customizations/polars_commands.py b/buckaroo/customizations/polars_commands.py new file mode 100644 index 000000000..ea911fa0c --- /dev/null +++ b/buckaroo/customizations/polars_commands.py @@ -0,0 +1,123 @@ +import polars as pl +#import numpy as np + +from ..jlisp.lispy import s +#from ..jlisp.configure_utils import configure_buckaroo +#from ..auto_clean.cleaning_commands import (to_bool, to_datetime, to_int, to_float, to_string) + +class Command(object): + @staticmethod + def transform(df, col, val): + return df.with_columns(pl.col(col).fill_null(val)) + return df + + @staticmethod + def transform_to_py(df, col, val): + return " df = df.with_columns(pl.col('%s').fill_null(%r))" % (col, val) + +class FillNA(Command): + #argument_names = ["df", "col", "fill_val"] + command_default = [s('fillna'), s('df'), "col", 8] + command_pattern = [[3, 'fillVal', 'type', 'integer']] + + @staticmethod + def transform(df, col, val): + return df.with_columns(pl.col(col).fill_null(val)) + return df + + @staticmethod + def transform_to_py(df, col, val): + return " df = df.with_columns(pl.col('%s').fill_null(%r))" % (col, val) + +class NoOp(Command): + #used for testing command stuff + command_default = [s('noop'), s('df'), "col"] + command_pattern = [None] + + @staticmethod + def transform(df, col): + return df + + @staticmethod + def transform_to_py(df, col): + return " #noop" + +class PlSafeInt(Command): + command_default = [s('safe_int'), s('df'), "col"] + command_pattern = [None] + + @staticmethod + def transform(df, col): + return df.with_columns(pl.col(col).cast(pl.Int64, strict=False)) + return df + + @staticmethod + def transform_to_py(df, col): + return " df = df.with_columns(pl.col('%s').cast(pl.Int64, strict=False))" % (col) + +class DropCol(Command): + #argument_names = ["df", "col"] + command_default = [s('dropcol'), s('df'), "col"] + command_pattern = [None] + + @staticmethod + def transform(df, col): + return df.drop(col) + return df + + @staticmethod + def transform_to_py(df, col): + return " df.drop_in_place('%s')" % col + + +class GroupBy(Command): + command_default = [s("groupby"), s('df'), 'col', {}] + command_pattern = [[3, 'colMap', 'colEnum', ['null', 'sum', 'mean', 'median', 'count']]] + @staticmethod + def transform(df, col, col_spec): + agg_clauses = [] + for k, v in col_spec.items(): + if v == "sum": + agg_clauses.append(pl.col(k).sum().alias("%s(sum)" % k)) + elif v == "mean": + agg_clauses.append(pl.col(k).mean().alias("%s(mean)" % k)) + elif v == "median": + agg_clauses.append(pl.col(k).median.alias("%s(median)" % k)) + elif v == "count": + agg_clauses.append(pl.col(k).drop_nulls().count().alias("%s(count)" % k)) + + q = ( + df + .lazy() + .group_by(by=col) + .agg(*agg_clauses) + .sort(col, descending=True) + ) + return q.collect() + + + + @staticmethod + def transform_to_py(df, col, col_spec): + agg_clauses = [] + for k, v in col_spec.items(): + if v == "sum": + agg_clauses.append(" pl.col('%s').sum().alias('%s(sum)')" % (k, k)) + elif v == "mean": + agg_clauses.append(" pl.col('%s').mean().alias('%s(mean)')" % (k, k)) + elif v == "median": + agg_clauses.append(" pl.col('%s').median().alias('%s(median)')" % (k, k)) + elif v == "count": + agg_clauses.append(" pl.col('%s').drop_nulls().count().alias('%s(count)')" % (k, k)) + full_agg_text = ",\n".join(agg_clauses) + command_template = """ + q = ( + df + .lazy() + .group_by(by='%s') + .agg(%s) + .sort('%s', descending=True) + ) + df = q.collect() + """ + return command_template % (col, full_agg_text, col) diff --git a/buckaroo/customizations/styling.py b/buckaroo/customizations/styling.py new file mode 100644 index 000000000..830263fb1 --- /dev/null +++ b/buckaroo/customizations/styling.py @@ -0,0 +1,53 @@ +from buckaroo.dataflow.dataflow import StylingAnalysis +from typing import Any + +def obj_(pkey): + return {'primary_key_val': pkey, 'displayer_args': { 'displayer': 'obj' } } + +def float_(pkey, digits=3): + return {'primary_key_val': pkey, + 'displayer_args': { + 'displayer': 'float', 'min_fraction_digits':digits, 'max_fraction_digits':digits}} + + +class DefaultMainStyling(StylingAnalysis): + requires_summary = ["histogram", "is_numeric", "dtype", "_type"] + pinned_rows = [ + obj_('dtype'), + {'primary_key_val': 'histogram', 'displayer_args': {'displayer': 'histogram'}}] + + @classmethod + def style_column(kls, col:str, column_metadata: Any) -> Any: + #print(col, list(sd.keys())) + if len(column_metadata.keys()) == 0: + #I'm still having problems with index and polars + return {'col_name':str(col), 'displayer_args': {'displayer': 'obj'}} + + digits = 3 + t = column_metadata['_type'] + if t == 'integer': + disp = {'displayer': 'float', 'min_fraction_digits':0, 'max_fraction_digits':0} + elif t == 'float': + disp = {'displayer': 'float', 'min_fraction_digits':digits, 'max_fraction_digits':digits} + elif t == 'temporal': + disp = {'displayer': 'datetimeLocaleString','locale': 'en-US', 'args': {}} + elif t == 'string': + disp = {'displayer': 'string', 'max_length': 35} + else: + disp = {'displayer': 'obj'} + return {'col_name':str(col), 'displayer_args': disp } + + +class DefaultSummaryStatsStyling(StylingAnalysis): + pinned_rows = [ + obj_('dtype'), + float_('min'), + float_('mean'), + float_('max'), + float_('unique_count', 0), + float_('distinct_count', 0), + float_('empty_count', 0)] + + df_display_name = "summary" + data_key = "empty" + summary_stats_key= 'all_stats' diff --git a/dcef/tests/__init__.py b/buckaroo/dataflow/__init__.py similarity index 100% rename from dcef/tests/__init__.py rename to buckaroo/dataflow/__init__.py diff --git a/buckaroo/dataflow/autocleaning.py b/buckaroo/dataflow/autocleaning.py new file mode 100644 index 000000000..2d8959cea --- /dev/null +++ b/buckaroo/dataflow/autocleaning.py @@ -0,0 +1,153 @@ +import pandas as pd +from buckaroo.jlisp.lisp_utils import split_operations +#from buckaroo.pluggable_analysis_framework.polars_analysis_management import PlDfStats +from buckaroo.pluggable_analysis_framework.analysis_management import DfStats +from ..customizations.all_transforms import configure_buckaroo, DefaultCommandKlsList + + +''' + + + def handle_ops_and_clean_orig(self, df, cleaning_method, existing_operations): + if self.sampled_df is None: + return None + cleaning_operations, cleaning_sd = self._run_cleaning(df, cleaning_method) + merged_operations = merge_ops(existing_operations, cleaning_operations) + cleaned_df = self._run_df_interpreter(df, merged_operations) + generated_code = self._run_code_generator(merged_operations) + self.cleaned [cleaned_df, cleaning_sd, generated_code, merged_operations] + + +''' +def dumb_merge_ops(existing_ops, cleaning_ops): + """ strip cleaning_ops from existing_ops, reinsert cleaning_ops at the beginning """ + a = existing_ops.copy() + a.extend(cleaning_ops) + return a + +SENTINEL_DF_1 = pd.DataFrame({'foo' :[10, 20], 'bar' : ["asdf", "iii"]}) +SENTINEL_DF_2 = pd.DataFrame({'col1' :[55, 55], 'col2': ["pppp", "333"]}) +SENTINEL_DF_3 = pd.DataFrame({'pp' :[99, 33], 'ee': [ 6, 9]}) +SENTINEL_DF_4 = pd.DataFrame({'vvv' :[12, 49], 'oo': [ 'ccc', 'www']}) + +class SentinelAutocleaning: + + def handle_ops_and_clean(self, df, cleaning_method, existing_operations): + cleaning_ops = [] + generated_code = "" + if cleaning_method == "one op": + cleaning_ops = [""] + generated_code = "codegen 1" + generated_code = "codegen 2" + elif cleaning_method == "two op": + cleaning_ops = ["", ""] + + merged_operations = dumb_merge_ops(existing_operations, cleaning_ops) + + if len(merged_operations) == 1: + cleaned_df = SENTINEL_DF_1 + elif len(merged_operations) == 2: + cleaned_df = SENTINEL_DF_2 + else: + cleaned_df = df + return [cleaned_df, {}, generated_code, merged_operations] + +def merge_ops(existing_ops, cleaning_ops): + """ strip cleaning_ops from existing_ops, reinsert cleaning_ops at the beginning """ + old_cleaning_ops, user_gen_ops = split_operations(existing_ops) + merged = cleaning_ops.copy() + merged.extend(user_gen_ops) + return merged + + + +def format_ops(column_meta): + ret_ops = [] + for k,v in column_meta.items(): + ops = v['cleaning_ops'] + if len(ops) > 0: + temp_ops = ops.copy() + temp_ops.insert(2, k) + ret_ops.append(temp_ops) + return ret_ops + +def make_origs(raw_df, cleaned_df): + clauses = [] + for col in raw_df.columns: + clauses.append(cleaned_df[col]) + clauses.append(raw_df[col].alias(col+"_orig")) + # clauses.append( + # pl.when((raw_df[col] - cleaned_df[col]).eq(0)).then(None).otherwise(raw_df[col]).alias(col+"_orig")) + ret_df = cleaned_df.select(clauses) + return ret_df + + +class AutocleaningConfig: + command_klasses = [DefaultCommandKlsList] + autocleaning_analysis_klasses = [] + + name = 'default' + + +class Autocleaning: + # def add_command(self, incomingCommandKls): + # without_incoming = [x for x in self.command_classes if not x.__name__ == incomingCommandKls.__name__] + # without_incoming.append(incomingCommandKls) + # self.command_klasses = without_incoming + # self.setup_from_command_kls_list() + + DFStatsKlass = DfStats + def __init__(self, ac_configs): + + self.config_dict = {} + for conf in ac_configs: + self.config_dict[conf.name] = conf + + ### start code interpreter block + def _setup_from_command_kls_list(self, name): + #used to initially setup the interpreter, and when a command + #is added interactively + if name not in self.config_dict: + options = list(self.config_dict.keys()) + raise Exception( + "Unknown autocleaning conf of %s, available options are %r" % (name, options)) + conf = self.config_dict[name] + c_klasses, self.autocleaning_analysis_klasses = conf.command_klasses, conf.autocleaning_analysis_klasses + + c_defaults, c_patterns, df_interpreter, gencode_interpreter = configure_buckaroo(c_klasses) + self.df_interpreter, self.gencode_interpreter = df_interpreter, gencode_interpreter + self.commandConfig = dict(argspecs=c_patterns, defaultArgs=c_defaults) + + + def _run_df_interpreter(self, df, operations): + full_ops = [{'symbol': 'begin'}] + full_ops.extend(operations) + print("*"*80) + print(full_ops) + print("*"*80) + if len(full_ops) == 1: + return df + return self.df_interpreter(full_ops , df) + + def _run_code_generator(self, operations): + if len(operations) == 0: + return 'no operations' + return self.gencode_interpreter(operations) + + def _run_cleaning(self, df, cleaning_method): + dfs = self.DFStatsKlass(df, self.autocleaning_analysis_klasses, debug=True) + gen_ops = format_ops(dfs.sdf) + + cleaning_sd = {} + return gen_ops, cleaning_sd + + def handle_ops_and_clean(self, df, cleaning_method, existing_operations): + if df is None: + return None + self._setup_from_command_kls_list(cleaning_method) + cleaning_operations, cleaning_sd = self._run_cleaning(df, cleaning_method) + merged_operations = merge_ops(existing_operations, cleaning_operations) + cleaned_df = self._run_df_interpreter(df, merged_operations) + merged_cleaned_df = make_origs(df, cleaned_df) + generated_code = self._run_code_generator(merged_operations) + return [merged_cleaned_df, cleaning_sd, generated_code, merged_operations] diff --git a/buckaroo/dataflow/dataflow.py b/buckaroo/dataflow/dataflow.py new file mode 100644 index 000000000..3e0db01d4 --- /dev/null +++ b/buckaroo/dataflow/dataflow.py @@ -0,0 +1,380 @@ +import six +import warnings +import pandas as pd +from traitlets import Unicode, Any, observe, HasTraits, Dict +from ..serialization_utils import pd_to_obj +from buckaroo.pluggable_analysis_framework.utils import (filter_analysis) +from buckaroo.pluggable_analysis_framework.analysis_management import DfStats +from .autocleaning import SentinelAutocleaning +from .dataflow_extras import ( + EMPTY_DF_DISPLAY_ARG, merge_sds, merge_column_config, + style_columns, exception_protect, StylingAnalysis, + Sampling) + + +class DataFlow(HasTraits): + """This class is meant to only represent the dataflow through + buckaroo with no accomodation for widget particulars + + It generally has stub methods for implementations that enable basic testing of the 'data flow' . + It is meant to be extended by Customizable DataFlow that can specify multiple different options + + CustomizableDataflow is meant to be extended by BuckarooWidget whcih connects frontend values to the following properties + + sample_method + cleaning_method + existing_operations + style_method ... became df_display_args + + all of this results in values for df_dict being updated + + """ + def __init__(self, raw_df): + self.exception = None + super().__init__() + self.summary_sd = {} + self.existing_operations = [] + self.ac_obj = self.autocleaning_klass() + try: + self.raw_df = raw_df + except Exception: + six.reraise(self.exception[0], self.exception[1], self.exception[2]) + + autocleaning_klass = SentinelAutocleaning + + raw_df = Any('') + sample_method = Unicode('default') + sampled_df = Any('') + + cleaning_method = Unicode('') + cleaning_operations = Any() + + existing_operations = Any([]) + merged_operations = Any() + + cleaned = Any().tag(default=None) + + lowcode_operations = Any() + + post_processing_method = Unicode('').tag(default='') + processed_result = Any().tag(default=None) + + analysis_klasses = None + summary_sd = Any() + + merged_sd = Any() + + style_method = Unicode('simple') + column_config = Any() + + column_config_overrides = {} + + merged_column_config = Any() + + widget_args_tuple = Any() + + + + def _compute_sampled_df(self, raw_df, sample_method): + if sample_method == "first": + return raw_df[:1] + return raw_df + + + @observe('raw_df', 'sample_method') + @exception_protect('sampled_df-protector') + def _sampled_df(self, change): + self.sampled_df = self._compute_sampled_df(self.raw_df, self.sample_method) + + @observe('sampled_df', 'cleaning_method', 'existing_operations') + @exception_protect('operation_result-protector') + def _operation_result(self, change): + result = self.ac_obj.handle_ops_and_clean( + self.sampled_df, self.cleaning_method, self.existing_operations) + if result is None: + return + else: + self.cleaned = result + @property + def cleaned_df(self): + if self.cleaned is not None: + return self.cleaned[0] + + @property + def cleaned_sd(self): + if self.cleaned is not None: + return self.cleaned[1] + return {} + + @property + def generated_code(self): + if self.cleaned is not None: + return self.cleaned[2] + + @property + def merged_operations(self): + if self.cleaned is not None: + return self.cleaned[3] + + def _compute_processed_result(self, cleaned_df, post_processing_method): + return [cleaned_df, {}] + + @observe('cleaned', 'post_processing_method') + @exception_protect('processed_result-protector') + def _processed_result(self, change): + #for now this is a no-op because I don't have a post_processing_function or mechanism + self.processed_result = self._compute_processed_result(self.cleaned_df, self.post_processing_method) + + @property + def processed_df(self): + if self.processed_result is not None: + return self.processed_result[0] + return None + + @property + def processed_sd(self): + if self.processed_result is not None: + return self.processed_result[1] + return {} + + def _get_summary_sd(self, df): + analysis_klasses = self.analysis_klasses + if analysis_klasses == "foo": + return {'some-col': {'foo':8}} + if analysis_klasses == "bar": + return {'other-col': {'bar':10}} + index_name = df.index.name or "index" + ret_summary = {index_name: {}} + for col in df.columns: + ret_summary[col] = {} + return ret_summary + + @observe('processed_result', 'analysis_klasses') + @exception_protect('summary_sd-protector') + def _summary_sd(self, change): + result_summary_sd = self._get_summary_sd(self.processed_df) + self.summary_sd = result_summary_sd + + @observe('summary_sd') + @exception_protect('merged_sd-protector') + def _merged_sd(self, change): + #slightly inconsitent that processed_sd gets priority over + #summary_sd, given that processed_df is computed first. My + #thinking was that processed_sd has greater total knowledge + #and should supersede summary_sd. + self.merged_sd = merge_sds(self.cleaned_sd, self.summary_sd, self.processed_sd) + + def _get_dfviewer_config(self, sd, style_method): + dfviewer_config = style_columns(style_method, sd) + base_column_config = dfviewer_config['column_config'] + dfviewer_config['column_config'] = merge_column_config( + base_column_config, self.column_config_overrides) + return dfviewer_config + + @observe('merged_sd', 'style_method') + @exception_protect('widget_config-protector') + def _widget_config(self, change): + #how to control ordering of column_config??? + # dfviewer_config = self._get_dfviewer_config(self.merged_sd, self.style_method) + # self.widget_args_tuple = [self.processed_df, self.merged_sd, dfviewer_config] + self.widget_args_tuple = (id(self.processed_df), self.processed_df, self.merged_sd) + + +class CustomizableDataflow(DataFlow): + """ + This allows targetd extension and customization of DataFlow + """ + analysis_klasses = [StylingAnalysis] + commandConfig = Dict({}).tag(sync=True) + DFStatsClass = DfStats + sampling_klass = Sampling + df_display_klasses = {} + + + def __init__(self, df, debug=False, + column_config_overrides=None, + pinned_rows=None, extra_grid_config=None, + component_config=None): + if column_config_overrides is None: + column_config_overrides = {} + self.column_config_overrides = column_config_overrides + self.pinned_rows = pinned_rows + self.extra_grid_config = extra_grid_config + self.component_config = component_config + if not debug: + warnings.filterwarnings('ignore') + + self.debug = debug + #self.df_name = get_df_name(df) + self.df_name = "placeholder" + self.df_display_args = {} + self.setup_options_from_analysis() + super().__init__(self.sampling_klass.pre_stats_sample(df)) + + self.populate_df_meta() + #self.raw_df = df + warnings.filterwarnings('default') + + def populate_df_meta(self): + self.df_meta = { + 'columns': len(self.raw_df.columns), + # I need to recompute this when sampling changes + 'rows_shown': len(self.sampled_df), + 'total_rows': len(self.raw_df)} + + buckaroo_options = Dict({ + 'sampled': ['random'], + 'auto_clean': ['aggressive', 'conservative'], + 'post_processing': [], + 'df_display': ['main', 'summary'], + 'show_commands': ['on'], + 'summary_stats': ['all'], + }).tag(sync=True) + + def setup_options_from_analysis(self): + self.df_display_klasses = filter_analysis(self.analysis_klasses, "df_display_name") + #add a check to verify that there aren't multiple classes offering the same df_display_name + + empty_df_display_args = {} + for k, kls in self.df_display_klasses.items(): + empty_df_display_args[kls.df_display_name] = EMPTY_DF_DISPLAY_ARG + + + self.DFStatsClass.verify_analysis_objects(self.analysis_klasses) + + self.post_processing_klasses = filter_analysis(self.analysis_klasses, "post_processing_method") + + new_buckaroo_options = self.buckaroo_options.copy() + new_buckaroo_options['df_display'] = list(self.df_display_klasses.keys()) + post_processing_methods = [''] + post_processing_methods.extend(list(self.post_processing_klasses.keys())) + new_buckaroo_options['post_processing'] = post_processing_methods + #important that we open up the possibilities first before we add them as options in the UI + self.df_display_args = empty_df_display_args + self.buckaroo_options = new_buckaroo_options + + df_display_args = Any({'main':EMPTY_DF_DISPLAY_ARG}).tag(sync=True) + #empty needs to always be present, it enables startup + df_data_dict = Any({'empty':[]}).tag(sync=True) + + + ### start code interpreter block + def add_command(self, incomingCommandKls): + return self.ac_obj.add_command(incomingCommandKls) + + def _run_df_interpreter(self, df, operations): + self.ac_obj._run_df_interpreter(df, operations) + + def run_code_generator(self, operations): + self.ac_obj.run_code_generator(operations) + ### end code interpeter block + + def _compute_processed_result(self, cleaned_df, post_processing_method): + if post_processing_method == '': + return [cleaned_df, {}] + else: + post_analysis = self.post_processing_klasses[post_processing_method] + try: + ret_df, sd = post_analysis.post_process_df(cleaned_df) + return (ret_df, sd) + except Exception as e: + return (self._build_error_dataframe(e), {}) + + def _build_error_dataframe(self, e): + return pd.DataFrame({'err': [str(e)]}) + + + ### start summary stats block + + def _get_summary_sd(self, processed_df): + stats = self.DFStatsClass( + processed_df, + self.analysis_klasses, + self.df_name, debug=self.debug) + sdf = stats.sdf + if stats.errs: + if self.debug: + raise Exception("Error executing analysis") + else: + return {} + else: + return sdf + + + # ### end summary stats block + + def _sd_to_jsondf(self, sd): + """exists so this can be overriden for polars """ + temp_sd = sd.copy() + #FIXME add actual test around weird index behavior + if 'index' in temp_sd: + del temp_sd['index'] + return self._df_to_obj(pd.DataFrame(temp_sd)) + + def _df_to_obj(self, df:pd.DataFrame): + return pd_to_obj(self.sampling_klass.serialize_sample(df)) + + + #final processing block + @observe('widget_args_tuple') + def _handle_widget_change(self, change): + """ + put together df_dict for consumption by the frontend + """ + _unused, processed_df, merged_sd = self.widget_args_tuple + if processed_df is None: + return + + # df_data_dict is still hardcoded for now + # eventually processed_df will be able to add or alter values of df_data_dict + # correlation would be added, filtered would probably be altered + + # to expedite processing maybe future provided dfs from + # postprcoessing could default to empty until that is + # selected, optionally + + self.df_data_dict = {'main': self._df_to_obj(processed_df), + 'all_stats': self._sd_to_jsondf(merged_sd), + 'empty': []} + + temp_display_args = {} + for display_name, A_Klass in self.df_display_klasses.items(): + df_viewer_config = A_Klass.style_columns(merged_sd) + base_column_config = df_viewer_config['column_config'] + df_viewer_config['column_config'] = merge_column_config( + base_column_config, self.column_config_overrides) + disp_arg = {'data_key': A_Klass.data_key, + #'df_viewer_config': json.loads(json.dumps(df_viewer_config)), + 'df_viewer_config': df_viewer_config, + 'summary_stats_key': A_Klass.summary_stats_key} + temp_display_args[display_name] = disp_arg + + if self.pinned_rows is not None: + temp_display_args['main']['df_viewer_config']['pinned_rows'] = self.pinned_rows + if self.extra_grid_config: + temp_display_args['main']['df_viewer_config']['extra_grid_config'] = self.extra_grid_config + if self.component_config: + temp_display_args['main']['df_viewer_config']['component_config'] = self.component_config + + self.df_display_args = temp_display_args + +""" +Instantiation +df_data_dict starts with only 'empty' +first populate df_display_args, make all data point to 'empty', make all df_viewer_configs EMPTY_DFVIEWER_CONFIG + +then populate buckaroo_options['df_display'] from gathered classes + +Next add 'all_stats' to 'df_data_dict' +add 'main' to 'df_data_dict' + + +all of the above steps might trigger redisplays, but they will be cheap because df_viewer_config will be empty, pointing at empty data + +finally iterate through all 'df_display' analysis_klasses and update df_display_args + + + + + +""" diff --git a/buckaroo/dataflow/dataflow_extras.py b/buckaroo/dataflow/dataflow_extras.py new file mode 100644 index 000000000..786e70007 --- /dev/null +++ b/buckaroo/dataflow/dataflow_extras.py @@ -0,0 +1,175 @@ +import sys +import pandas as pd +from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import (ColAnalysis) + +EMPTY_DFVIEWER_CONFIG = { + 'pinned_rows': [], + 'column_config': []} +EMPTY_DF_DISPLAY_ARG = {'data_key': 'empty', 'df_viewer_config': EMPTY_DFVIEWER_CONFIG, + 'summary_stats_key': 'empty'} + + +SENTINEL_DF_1 = pd.DataFrame({'foo' :[10, 20], 'bar' : ["asdf", "iii"]}) +SENTINEL_DF_2 = pd.DataFrame({'col1' :[55, 55], 'col2': ["pppp", "333"]}) + +SENTINEL_COLUMN_CONFIG_1 = "ASDF" +SENTINEL_COLUMN_CONFIG_2 = "FOO-BAR" + + + +def merge_ops(existing_ops, cleaning_ops): + """ strip cleaning_ops from existing_ops, reinsert cleaning_ops at the beginning """ + a = existing_ops.copy() + a.extend(cleaning_ops) + return a + +def merge_sds(*sds): + """merge sds with later args taking precedence + + sub-merging of "overide_config"?? + """ + base_sd = {} + for sd in sds: + for column in sd.keys(): + base_sd[column] = merge_column(base_sd.get(column, {}), sd[column]) + return base_sd + + +def merge_column(base, new): + """ + merge individual column dictionaries, with special handling for column_config_override + """ + ret = base.copy() + ret.update(new) + + base_override = base.get('column_config_override', {}).copy() + new_override = new.get('column_config_override', {}).copy() + base_override.update(new_override) + + if len(base_override) > 0: + ret['column_config_override'] = base_override + return ret + + +def merge_column_config(styled_column_config, overide_column_configs): + existing_column_config = styled_column_config.copy() + ret_column_config = [] + for row in existing_column_config: + col = row['col_name'] + if col in overide_column_configs: + row.update(overide_column_configs[col]) + if row.get('merge_rule', 'blank') == 'hidden': + continue + ret_column_config.append(row) + return ret_column_config + +def style_columns(style_method:str, sd): + if style_method == "foo": + return SENTINEL_COLUMN_CONFIG_2 + else: + ret_col_config = [] + for col in sd.keys(): + ret_col_config.append( + {'col_name':col, 'displayer_args': {'displayer': 'obj'}}) + return { + 'pinned_rows': [ + # {'primary_key_val': 'dtype', 'displayer_args': {'displayer': 'obj'}} + ], + 'column_config': ret_col_config} + + +def exception_protect(protect_name=None): + """ + used to make sure that an exception from any part of DataFlow derived classes has the minimum amount of traitlets observer stuff in the stack trace. + + Requires that a a class has `self.exception` + + protect_name occurs in the printed exception handler to narrow down the call stack + + """ + def wrapped_decorator(func): + def wrapped(self, *args, **kwargs): + try: + func(self, *args, **kwargs) + except Exception: + #sometimes useful for debugging tricky call order stuff + # if protect_name: + # print("protect handler", protect_name, self.exception) + if self.exception is None: + self.exception = sys.exc_info() + raise + return wrapped + return wrapped_decorator + + + + +class Sampling: + + max_columns = 250 + pre_limit = 100_000 + serialize_limit = 10_000 + + @classmethod + def pre_stats_sample(kls, df): + if len(df.columns) > kls.max_columns: + print("Removing excess columns, found %d columns" % len(df.columns)) + df = df[df.columns[:kls.max_columns]] + if kls.pre_limit and len(df) > kls.pre_limit: + sampled = df.sample(kls.pre_limit) + if isinstance(sampled, pd.DataFrame): + return sampled.sort_index() + return sampled + return df + + + @classmethod + def serialize_sample(kls, df): + if kls.serialize_limit and len(df) > kls.serialize_limit: + sampled = df.sample(kls.serialize_limit) + if isinstance(sampled, pd.DataFrame): + return sampled.sort_index() + return sampled + return df + + +class StylingAnalysis(ColAnalysis): + provides_defaults = {} + pinned_rows = [] + + extra_grid_config = {} + component_config = {} + + #the type should be + #def style_column(col:str, column_metadata: SingleColumnMetadata) -> ColumnConfig: + @classmethod + def style_column(kls, col, column_metadata): + return {'col_name':str(col), 'displayer_args': {'displayer': 'obj'}} + + #what is the key for this in the df_display_args_dictionary + df_display_name = "main" + data_key = "main" + summary_stats_key= 'all_stats' + + @classmethod + def style_columns(kls, sd): + ret_col_config = [] + + #this is necessary for polars to add an index column, which is + #required so that summary_stats makes sense + if 'index' not in sd: + ret_col_config.append({'col_name': 'index', 'displayer_args': {'displayer': 'obj'}}) + + for col in sd.keys(): + col_meta = sd[col] + base_style = kls.style_column(col, col_meta) + if 'column_config_override' in col_meta: + base_style.update(col_meta['column_config_override']) + ret_col_config.append(base_style) + + return { + 'pinned_rows': kls.pinned_rows, + 'column_config': ret_col_config, + 'extra_grid_config': kls.extra_grid_config, + 'component_config': kls.component_config + } diff --git a/buckaroo/dataflow/widget_extension_utils.py b/buckaroo/dataflow/widget_extension_utils.py new file mode 100644 index 000000000..b1534c67b --- /dev/null +++ b/buckaroo/dataflow/widget_extension_utils.py @@ -0,0 +1,117 @@ +from buckaroo.customizations.styling import (DefaultMainStyling) +from buckaroo.buckaroo_widget import RawDFViewerWidget, BuckarooWidget + +def find_most_specific_styling(klasses, df_display_name='main'): + """if we have multiple styling klasses, all of which extend StylingAnalysis keyed to df_display_name='main' + we want a deterministic result for which one is the called class to provide styling for that key + + if B extends A, B is more specific. + + Since most class extension for styling will work by extending + DefaultMainStyling, try to follow the user's intent by making sure + the most specific class is chosen + + https://stackoverflow.com/questions/23660447/how-can-i-sort-a-list-of-python-classes-by-inheritance-depth + """ + styling_klasses = filter(lambda x: issubclass(x, DefaultMainStyling), klasses) + klasses_by_depth = sorted(styling_klasses, key=lambda x: len(x.__mro__)) + return klasses_by_depth[-1] + +class InvalidArgumentException(Exception): + pass +def analysis_extend( + BaseBuckarooKls, + extra_analysis_klasses=None, analysis_klasses=None): + + # In this case we are going to extend PolarsBuckarooWidget so we + # can take this combination with us + base_a_klasses = BaseBuckarooKls.analysis_klasses.copy() + if extra_analysis_klasses: + if analysis_klasses is not None: + raise InvalidArgumentException( + "Must specify either extra_analysis_klasses or analysis_klasses, not both") + base_a_klasses.extend(extra_analysis_klasses) + elif analysis_klasses: + base_a_klasses = analysis_klasses + return base_a_klasses + +def get_styling_analysis( + BaseStylingKlass, + extra_pinned_rows=None, pinned_rows=None): + + base_pinned_rows = BaseStylingKlass.pinned_rows.copy() + if extra_pinned_rows: + if pinned_rows is not None: + raise InvalidArgumentException( + "Must specify either extra_pinned_rows or pinned_rows, not both") + base_pinned_rows.extend(extra_pinned_rows) + elif pinned_rows is not None: # is not None accomodates empty list + base_pinned_rows = pinned_rows + + class SyntheticStyling(BaseStylingKlass): + pinned_rows = base_pinned_rows + df_display_name = "dfviewer_special" + + return SyntheticStyling + + +def configure_buckaroo( + BaseBuckarooKls, + extra_pinned_rows=None, pinned_rows=None, + extra_analysis_klasses=None, analysis_klasses=None): + """Used to instantiate a synthetic Buckaroo class with easier extension methods. + + It seemed more straight forward to write this as a completely + separate function vs a classmethod so that things are clear vs + inheritance + """ + + + a_klasses = analysis_extend( + BaseBuckarooKls, + extra_analysis_klasses, analysis_klasses) + + #there could possibly be another way of picking off the styling + #klass vs just knowing that it's default BaseStylingKls + #BaseStylingKls = DefaultMainStyling + BaseStylingKls = find_most_specific_styling(a_klasses) + + special_styling_analysis_klass = get_styling_analysis( + BaseStylingKls, extra_pinned_rows, pinned_rows) + + a_klasses.append(special_styling_analysis_klass) + + class TempBuckarooWidget(BaseBuckarooKls): + analysis_klasses = a_klasses + return TempBuckarooWidget + + + +def DFViewer(df, + column_config_overrides=None, + extra_pinned_rows=None, pinned_rows=None, + extra_analysis_klasses=None, analysis_klasses=None): + """ + Display a DataFrame with buckaroo styling and analysis, no extra UI pieces + + column_config_overrides allows targetted specific overriding of styling + + extra_pinned_rows adds pinned_rows of summary stats + pinned_rows replaces the default pinned rows + + extra_analysis_klasses adds an analysis_klass + analysis_klasses replaces default analysis_klass + """ + BuckarooKls = configure_buckaroo( + BuckarooWidget, + extra_pinned_rows=extra_pinned_rows, pinned_rows=pinned_rows, + extra_analysis_klasses=extra_analysis_klasses, analysis_klasses=analysis_klasses) + + bw = BuckarooKls(df, column_config_overrides=column_config_overrides) + dfv_config = bw.df_display_args['dfviewer_special']['df_viewer_config'] + df_data = bw.df_data_dict['main'] + summary_stats_data = bw.df_data_dict['all_stats'] + return RawDFViewerWidget( + df_data=df_data, df_viewer_config=dfv_config, summary_stats_data=summary_stats_data) + + diff --git a/buckaroo/geopandas_buckaroo.py b/buckaroo/geopandas_buckaroo.py new file mode 100644 index 000000000..d5501feb1 --- /dev/null +++ b/buckaroo/geopandas_buckaroo.py @@ -0,0 +1,90 @@ +import pandas as pd +import buckaroo + +from buckaroo.customizations.styling import DefaultMainStyling, StylingAnalysis +from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import ColAnalysis +from .dataflow.dataflow_extras import (Sampling) +from buckaroo.serialization_utils import pd_to_obj +from buckaroo.customizations.analysis import (TypingStats) +import geopandas + + +class SvgReprPostProcessing(ColAnalysis): + @classmethod + def post_process_df(kls, gdf): + geo_columns = [] + svg_columns = [] + svg_ser_dict = {} + for col in gdf.columns: + ser = gdf[col] + if isinstance(ser.dtype, geopandas.array.GeometryDtype): + svg_col_name = col+"_svg" + geo_columns.append(col) + svg_columns.append(svg_col_name) + svg_ser_dict[svg_col_name] = ser.apply(lambda x: x._repr_svg_()) + svg_df = pd.DataFrame(svg_ser_dict) + merged_df = pd.concat([svg_df, gdf], axis=1) + + extra_conf = {} + for col in svg_columns: + extra_conf[col] = {'column_config_override': {'displayer_args': {'displayer': 'SVGDisplayer'}}} + return merged_df, extra_conf + post_processing_method = "svg_geo" + +class GeoStyling(StylingAnalysis): #DefaultMainStyling): + requires_summary = [#"histogram", + "is_numeric", "dtype", "_type"] + @classmethod + def style_column(kls, col:str, column_metadata): + t = column_metadata['_type'] + if t == 'obj': + return {'col_name':col, 'displayer_args': {'displayer': 'string', 'max_length': 50}} + else: + return DefaultMainStyling.style_column(col, column_metadata) + pinned_rows = [ + #obj_('dtype'), obj_('_type') + ] + + extra_grid_config = {'rowHeight':105} + +class GeoPdSampling(Sampling): + #pre_limit = 500_000 + #no point in a larger limit until summary stats work for Geopandas + pre_limit = 2_000 + + + +class GeopandasBase(buckaroo.BuckarooWidget): + + def _df_to_obj(self, df): + pd_df = pd.DataFrame(dict(zip(df.columns, df.to_numpy().T))) + return pd_to_obj(self.sampling_klass.serialize_sample(pd_df)) + + def _sd_to_jsondf(self, sd): + """exists so this can be overriden for polars """ + temp_sd = sd.copy() + #FIXME add actual test around weird index behavior + if 'index' in temp_sd: + del temp_sd['index'] + # we need this to go through the regular pandas path, not our + # special serialization the special serialization gives + # numeric indexes, when summary stats needs string indexes of + # the stats name + return pd_to_obj(pd.DataFrame(temp_sd)) + +class GeopandasBuckarooWidget(GeopandasBase): + pass + +class GeopandasSVGBuckarooWidget(GeopandasBase): + analysis_klasses = [ + TypingStats, + GeoStyling, + SvgReprPostProcessing] + + sampling_klass = GeoPdSampling + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + t_state = self.buckaroo_state.copy() + t_state['post_processing'] = 'svg_geo' + self.buckaroo_state = t_state diff --git a/buckaroo/jlisp/__init__.py b/buckaroo/jlisp/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/dcef/configure_utils.py b/buckaroo/jlisp/configure_utils.py similarity index 64% rename from dcef/configure_utils.py rename to buckaroo/jlisp/configure_utils.py index eca6ee330..4a9490d08 100644 --- a/dcef/configure_utils.py +++ b/buckaroo/jlisp/configure_utils.py @@ -1,5 +1,6 @@ +import pandas as pd from .lispy import make_interpreter -def configure_dcef(transforms): +def configure_buckaroo(transforms): command_defaults = {} command_patterns = {} @@ -13,23 +14,24 @@ def configure_dcef(transforms): transform_lisp_primitives[transform_name] = T.transform to_py_lisp_primitives[transform_name] = T.transform_to_py - dcef_eval, raw_parse = make_interpreter(transform_lisp_primitives) - def dcef_transform(instructions, df): - df_copy = df.copy() - ret_val = dcef_eval(instructions, {'df':df_copy}) - #print(ret_val) + buckaroo_eval, raw_parse = make_interpreter(transform_lisp_primitives) + + def buckaroo_transform(instructions, df): + if isinstance(df, pd.DataFrame): + df_copy = df.copy() + else: # hack we know it's polars here... just getting something working for now + df_copy = df.clone() + ret_val = buckaroo_eval(instructions, {'df':df_copy}) return ret_val convert_to_python, __unused = make_interpreter(to_py_lisp_primitives) - def dcef_to_py(instructions): + def buckaroo_to_py(instructions): #I would prefer to implement this with a macro named something #like 'clean' that is implemented for the _convert_to_python #interpreter to return a string code block, and for the real DCF #interpreter as 'begin'... that way the exact same instructions #could be sent to either interpreter. For now, this will do individual_instructions = [x for x in map(lambda x:convert_to_python(x, {'df':5}), instructions)] - #print("individual_instructions", individual_instructions) code_block = '\n'.join(individual_instructions) - - return "def clean(df):\n" + code_block - return command_defaults, command_patterns, dcef_transform, dcef_to_py + return "def clean(df):\n" + code_block + "\n return df" + return command_defaults, command_patterns, buckaroo_transform, buckaroo_to_py diff --git a/buckaroo/jlisp/lisp_utils.py b/buckaroo/jlisp/lisp_utils.py new file mode 100644 index 000000000..08a0b6584 --- /dev/null +++ b/buckaroo/jlisp/lisp_utils.py @@ -0,0 +1,46 @@ +""" +It would be awesome to have cleaning and verification commands that add new columns with related names + +The new columns are null accept for errored values. + +Could use this to show original values that were removed/cleaned. Combined with conditional styling in the UI + +sick. And still ahve high perfromance properly typed columns + + + +""" + +def is_symbol(obj): + return isinstance(obj, dict) and "symbol" in obj + +def is_generated_symbol(obj): + return is_symbol(obj) and obj.get("meta", False) + +def split_operations(full_operations): + """ + utitlity to split a combined set of operations with machine generated commands and user entered commands into two lists, machine_generated and user_generated + + machine_generated commands have function calls with the symbol token also having a meta key with a value of {"precleaning":True} + """ + + machine_generated, user_entered = [], [] + for command in full_operations: + assert isinstance(command, list) + sym_atom = command[0] + if is_symbol(sym_atom): + if is_generated_symbol(sym_atom): + machine_generated.append(command) + else: + user_entered.append(command) + continue + raise Exception("Unexpected token %r" % command) + return machine_generated, user_entered + +def lists_match(l1, l2): + #https://note.nkmk.me/en/python-list-compare/#checking-the-exact-match-of-lists + if len(l1) != len(l2): + return False + return all(x == y and type(x) == type(y) for x, y in zip(l1, l2)) + + diff --git a/dcef/lispy.py b/buckaroo/jlisp/lispy.py similarity index 94% rename from dcef/lispy.py rename to buckaroo/jlisp/lispy.py index 27d58939d..b5e740c56 100644 --- a/dcef/lispy.py +++ b/buckaroo/jlisp/lispy.py @@ -186,7 +186,6 @@ def eval(x, env=global_env): eval(exp, env) x = x[-1] else: # (proc exp*) - print("exp", x) exps = [eval(exp, env) for exp in x] proc = exps.pop(0) if isa(proc, Procedure): @@ -197,6 +196,22 @@ def eval(x, env=global_env): return proc(*exps) + def is_unparsed_atom_a_symbol(obj): + if isinstance(obj, dict): + if obj.get('symbol', False): + if len(obj) == 1: + return True + elif len(obj) == 2 and obj.get('meta', False) is not False: + #our symbols can have a meta key too + return True + return False + + def is_unparsed_atom_a_quote(obj): + if isinstance(obj, dict) and len(obj) == 1: + if obj.get('quote', False) is not False: + return True + return False + def list_parse(lst): ret_list = [] if isinstance(lst, list) == False: @@ -207,15 +222,12 @@ def list_parse(lst): while True: if isinstance(x, list): ret_list.append(list_parse(x)) - elif isinstance(x, dict) and len(x) == 1: #hack to make the aprser easier - if x.get('symbol', False): - ret_list.append(Sym(x['symbol'])) - elif x.get('quote', False): - quote_char = x.get('quote') - quote_func = quotes[quote_char] - ret_list.append([quote_func, list_parse(next(lst))]) - else: - ret_list.append(x) + elif is_unparsed_atom_a_symbol(x): + ret_list.append(Sym(x['symbol'])) + elif is_unparsed_atom_a_quote(x): + quote_char = x.get('quote') + quote_func = quotes[quote_char] + ret_list.append([quote_func, list_parse(next(lst))]) elif isinstance(x, dict): print("x was a dict", x) ret_list.append(x) diff --git a/dcef/nbextension/extension.js b/buckaroo/nbextension/extension.js similarity index 85% rename from dcef/nbextension/extension.js rename to buckaroo/nbextension/extension.js index 569692de6..8373518e1 100644 --- a/dcef/nbextension/extension.js +++ b/buckaroo/nbextension/extension.js @@ -6,7 +6,7 @@ define(function() { window['requirejs'].config({ map: { '*': { - 'dcf': 'nbextensions/dcf/index', + 'buckaroo': 'nbextensions/buckaroo/index', }, } }); diff --git a/dcef/noarch/current_repodata.json b/buckaroo/noarch/current_repodata.json similarity index 100% rename from dcef/noarch/current_repodata.json rename to buckaroo/noarch/current_repodata.json diff --git a/dcef/noarch/current_repodata.json.bz2 b/buckaroo/noarch/current_repodata.json.bz2 similarity index 100% rename from dcef/noarch/current_repodata.json.bz2 rename to buckaroo/noarch/current_repodata.json.bz2 diff --git a/dcef/noarch/index.html b/buckaroo/noarch/index.html similarity index 100% rename from dcef/noarch/index.html rename to buckaroo/noarch/index.html diff --git a/dcef/noarch/repodata.json b/buckaroo/noarch/repodata.json similarity index 100% rename from dcef/noarch/repodata.json rename to buckaroo/noarch/repodata.json diff --git a/dcef/noarch/repodata.json.bz2 b/buckaroo/noarch/repodata.json.bz2 similarity index 100% rename from dcef/noarch/repodata.json.bz2 rename to buckaroo/noarch/repodata.json.bz2 diff --git a/dcef/noarch/repodata_from_packages.json b/buckaroo/noarch/repodata_from_packages.json similarity index 100% rename from dcef/noarch/repodata_from_packages.json rename to buckaroo/noarch/repodata_from_packages.json diff --git a/dcef/noarch/repodata_from_packages.json.bz2 b/buckaroo/noarch/repodata_from_packages.json.bz2 similarity index 100% rename from dcef/noarch/repodata_from_packages.json.bz2 rename to buckaroo/noarch/repodata_from_packages.json.bz2 diff --git a/buckaroo/pluggable_analysis_framework/analysis_management.py b/buckaroo/pluggable_analysis_framework/analysis_management.py new file mode 100644 index 000000000..acd65df9b --- /dev/null +++ b/buckaroo/pluggable_analysis_framework/analysis_management.py @@ -0,0 +1,236 @@ +from collections import defaultdict +import traceback +import warnings + +import numpy as np +from buckaroo.pluggable_analysis_framework.safe_summary_df import output_full_reproduce, output_reproduce_preamble + +from buckaroo.pluggable_analysis_framework.utils import FAST_SUMMARY_WHEN_GREATER, PERVERSE_DF +from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import ( + order_analysis, check_solvable) + +def produce_series_df(df, ordered_objs, df_name='test_df', debug=False): + """ just executes the series methods + + """ + errs = {} + series_stats = defaultdict(lambda: {}) + + cols = [] + if hasattr(df, "index"): + #hack around polars not having indexes" + cols.append("index") + cols.extend(df.columns) + for possib_ser_name in cols: + if possib_ser_name == "index": + ser_name = df.index.name or "index" + ser = df.index.to_series() + else: + ser_name = possib_ser_name + ser = df[ser_name] + #FIXME: actually sample the series. waiting until I have time + #to proeprly benchmark + sampled_ser = ser + for a_kls in ordered_objs: + col_stat_dict = a_kls.provides_defaults.copy() + try: + if a_kls.quiet or a_kls.quiet_warnings: + if debug is False: + warnings.filterwarnings('ignore') + + col_stat_dict.update(a_kls.series_summary(sampled_ser, ser)) + warnings.filterwarnings('default') + else: + col_stat_dict.update(a_kls.series_summary(sampled_ser, ser)) + + series_stats[ser_name].update(col_stat_dict) + except Exception as e: + if not a_kls.quiet: + errs[(ser_name, "series_summary")] = e, a_kls + if debug: + traceback.print_exc() + continue + return series_stats, errs + + + +def produce_summary_df(df, series_stats, ordered_objs, df_name='test_df', debug=False): + """ + takes a dataframe and a list of analyses that have been ordered by a graph sort, + then it produces a summary dataframe + """ + errs = {} + summary_col_dict = {} + cols = [] + if hasattr(df, "index"): + #hack around polars not having indexes" + cols.append("index") + cols.extend(df.columns) + for possib_ser_name in cols: + if possib_ser_name == "index": + ser_name = df.index.name or "index" + else: + ser_name = possib_ser_name + #figure out how to add in "index"... but just for table_hints + #for ser_name in df.columns: + #base_summary_dict = series_stats[ser_name] + base_summary_dict = series_stats.get(ser_name, {}) + for a_kls in ordered_objs: + try: + if a_kls.quiet or a_kls.quiet_warnings: + if debug is False: + warnings.filterwarnings('ignore') + summary_res = a_kls.computed_summary(base_summary_dict) + warnings.filterwarnings('default') + else: + summary_res = a_kls.computed_summary(base_summary_dict) + for k,v in summary_res.items(): + base_summary_dict.update(summary_res) + except Exception as e: + if not a_kls.quiet: + errs[(ser_name, "computed_summary")] = e, a_kls + if debug: + traceback.print_exc() + continue + summary_col_dict[ser_name] = base_summary_dict + return summary_col_dict, errs + + +#TODO Figure out how to do proper typing with AnalysisPipeline and the polars subclasses +# We want a TypeVar for DFType and AT. But the main function, process_df whild still return 3 dicts +#DFT = TypeVar("DFT") #DF Type +#AT = TypeVar("AT") #Analysis Type +class AnalysisPipeline(object): + """ + manage the ordering of a set of col_analysis objects + allow for computing summary_stats (and other oberservation sets) based on col_analysis objects + allow col_anlysis objects to be added + """ + + #this is only a list to prevent it from being interpretted as an instance method + #full_produce_func: List[Callable[[DFT, List[AT], str, bool], Any]] = + + @staticmethod + def full_produce_summary_df(df, ordered_objs, df_name='test_df', debug=False): + if len(df) == 0: + return {}, {} + + series_stat_dict, series_errs = produce_series_df(df, ordered_objs, df_name, debug) + summary_df, summary_errs = produce_summary_df( + df, series_stat_dict, ordered_objs, df_name, debug) + series_errs.update(summary_errs) + return summary_df, series_errs + + style_method = None + + def __init__(self, analysis_objects, unit_test_objs=True): + + #self.produce_func = self.full_produce_func[0] + self.summary_stats_display = "all" + self.unit_test_objs = unit_test_objs + self.verify_analysis_objects(analysis_objects) + + def process_summary_facts_set(self): + all_provided = [] + for a_obj in self.ordered_a_objs: + all_provided.extend(list(a_obj.provides_defaults.keys())) + + self.provided_summary_facts_set = set(all_provided) + + + def verify_analysis_objects(self, analysis_objects): + self.ordered_a_objs = order_analysis(analysis_objects) + check_solvable(self.ordered_a_objs) + self.process_summary_facts_set() + + def unit_test(self): + """test a single, or each col_analysis object with a set of commonly difficult series. + not implemented yet. + + This helps interactive development by doing a smoke test on + each new iteration of summary stats function. + + """ + try: + output_df, errs = self.full_produce_summary_df(PERVERSE_DF, self.ordered_a_objs) + if len(errs) == 0: + return True, [] + else: + return False, errs + except KeyError: + pass + + + def process_df(self, input_df, debug=False): + output_df, errs = self.full_produce_summary_df(input_df, self.ordered_a_objs, debug=debug) + return output_df, errs + + def add_analysis(self, new_aobj): + new_cname = new_aobj.cname() + new_aobj_set = [] + for aobj in self.ordered_a_objs: + if aobj.cname() == new_cname: + continue + new_aobj_set.append(aobj) + new_aobj_set.append(new_aobj) + self.verify_analysis_objects(new_aobj_set) + passed_unit_test, errs = self.unit_test() + if passed_unit_test is False: + return False, errs + return True, [] + + +class DfStats(object): + ''' + DfStats exists to handle inteligent downampling and applying the ColAnalysis functions + ''' + + ap_class = AnalysisPipeline + + @classmethod + def verify_analysis_objects(kls, col_analysis_objs): + kls.ap_class(col_analysis_objs) + + def __init__(self, df_stats_df, col_analysis_objs, operating_df_name=None, debug=False): + self.df = self.get_operating_df(df_stats_df, force_full_eval=False) + self.col_order = self.df.columns + self.ap = self.ap_class(col_analysis_objs) + self.operating_df_name = operating_df_name + self.debug = debug + + self.sdf, self.errs = self.ap.process_df(self.df, self.debug) + if self.errs: + output_full_reproduce(self.errs, self.sdf, operating_df_name) + + def get_operating_df(self, df, force_full_eval): + rows = len(df) + cols = len(df.columns) + item_count = rows * cols + + if item_count > FAST_SUMMARY_WHEN_GREATER: + return df.sample(np.min([50_000, len(df)])) + else: + return df + + @property + def presentation_sdf(self): + raise Exception("deprecated") + + def add_analysis(self, a_obj): + passed_unit_tests, ut_errs = self.ap.add_analysis(a_obj) + #if you're adding analysis interactively, of course you want debug info... I think + self.sdf, errs = self.ap.process_df(self.df, debug=True) + if passed_unit_tests is False: + print("Unit tests failed") + if errs: + print("Errors on original dataframe") + + if ut_errs or errs: + output_reproduce_preamble() + if ut_errs: + # setting debug=False here because we're already printing reproduce instructions, let the users produce their own stacktrace.. I think + ut_summary_df, ut_errs2 = produce_summary_df( + PERVERSE_DF, {}, self.ap.ordered_a_objs, debug=False) + output_full_reproduce(ut_errs, ut_summary_df, "PERVERSE_DF") + if errs: + output_full_reproduce(errs, self.sdf, self.operating_df_name) diff --git a/buckaroo/pluggable_analysis_framework/pluggable_analysis_framework.py b/buckaroo/pluggable_analysis_framework/pluggable_analysis_framework.py new file mode 100644 index 000000000..67f29d36d --- /dev/null +++ b/buckaroo/pluggable_analysis_framework/pluggable_analysis_framework.py @@ -0,0 +1,109 @@ +import graphlib +from collections import OrderedDict +from typing import List, Union, Any, Mapping, Tuple, Callable + +class ColAnalysis: + """ + Col Analysis runs on a single column + + this is the pandas based implementation + """ + requires_summary:List[str] = [] # What summary stats does this analysis provide + + #provides_series_stats:List[str] = [] # what does this provide at a series level + provides_defaults:Mapping[str, any] = {} + + + @classmethod + @property + def provides_summary(kls): + return list(kls.provides_defaults.keys()) + + + @classmethod + def full_provides(kls): + if not isinstance(kls.provides_defaults, dict): + raise Exception("no provides Defaults for %r" %kls) + + #a = kls.provides_series_stats.copy() + return list(kls.provides_defaults.keys()) + + summary_stats_display:Union[List[str], None] = None + quiet = False + quiet_warnings = False + + @staticmethod + def series_summary(sampled_ser, ser): + return {} + + @staticmethod + def computed_summary(summary_dict): + return {} + + @classmethod + def cname(kls): + return kls.__qualname__ + + #polars methods + select_clauses:List[Any] = [] + column_ops: Mapping[str, Tuple[List[Any], Callable[[Any], Any]]] = {} + + +class NotProvidedException(Exception): + pass + +def check_solvable(a_objs): + """ + checks that all of the required inputs are provided by another analysis object. + """ + provides = [] + required = [] + for ao in a_objs: + rest = ao.full_provides() + provides.extend(rest) + + required.extend(ao.requires_summary) + all_provides = set(provides) + all_required = set(required) + if not all_required.issubset(all_provides): + missing = all_required - all_provides + raise NotProvidedException("Missing provided analysis for %r" % missing) + +def remove_duplicates(lst): + return list(OrderedDict.fromkeys(lst)) + +def clean_list(full_class_list): + only_kls_lst = [kls for kls in full_class_list if kls is not None] + #note I also want someway to detect that classes don't alternate + # ['a', 'a', 'b', 'c', 'c'] # fine + # ['a', 'a', 'b', 'a', 'c'] # something went wrong with the graph algo + return remove_duplicates(only_kls_lst) + + +def order_analysis(a_objs): + """order a set of col analysis objects such that the dag of their + provides_summary and requires_summary is ordered for computation + """ + + graph = {} + key_class_objs = {} + for ao in a_objs: + fp = ao.full_provides() + if len(fp) == 0: + temp_provided = "__no_provided_keys__" + else: + temp_provided = fp[0] + first_mid_key = mid_key = ao.__name__ + "###" + temp_provided + for k in ao.full_provides()[1:]: + next_mid_key = ao.__name__ + "###" + k + graph[mid_key] = set([next_mid_key]) + key_class_objs[mid_key] = ao + mid_key = next_mid_key + graph[mid_key] = set(ao.requires_summary) + key_class_objs[mid_key] = ao + for j in ao.full_provides(): + graph[j] = set([first_mid_key]) + ts = graphlib.TopologicalSorter(graph) + seq = tuple(ts.static_order()) + full_class_list = [key_class_objs.get(k, None) for k in seq] + return clean_list(full_class_list) diff --git a/buckaroo/pluggable_analysis_framework/polars_analysis_management.py b/buckaroo/pluggable_analysis_framework/polars_analysis_management.py new file mode 100644 index 000000000..bc471ce1e --- /dev/null +++ b/buckaroo/pluggable_analysis_framework/polars_analysis_management.py @@ -0,0 +1,108 @@ +import traceback + +import polars as pl + +from buckaroo.pluggable_analysis_framework.polars_utils import split_to_dicts + + +from .pluggable_analysis_framework import ColAnalysis +from .analysis_management import (produce_summary_df, AnalysisPipeline, DfStats) +from buckaroo.pluggable_analysis_framework.safe_summary_df import safe_summary_df +from typing import Mapping, Any, Callable, Tuple, List, MutableMapping + + + +class PolarsAnalysis(ColAnalysis): + select_clauses:List[pl.Expr] = [] + column_ops: Mapping[str, Tuple[List[pl.PolarsDataType], Callable[[pl.Series], Any]]] = {} + + + +def polars_produce_series_df(df:pl.DataFrame, + unordered_objs:List[PolarsAnalysis], + df_name:str='test_df', debug:bool=False): + """ just executes the series methods + + """ + errs: MutableMapping[str, str] = {} + all_clauses = [] + for obj in unordered_objs: + all_clauses.extend(obj.select_clauses) + try: + result_df = df.lazy().select(all_clauses).collect() + except Exception: + if debug: + df.write_parquet('error.parq') + traceback.print_exc() + return dict([[k, {}] for k in df.columns]), {} + + summary_dict = {} + for col in df.columns: + summary_dict[col] = {} + for a_klass in unordered_objs: + summary_dict[col].update(a_klass.provides_defaults) + first_run_dict = split_to_dicts(result_df) + + for col, measures in first_run_dict.items(): + summary_dict[col].update(measures) + + for pa in unordered_objs: + for measure_name, action_tuple in pa.column_ops.items(): + col_selector, func = action_tuple + if col_selector == "all": + sub_df = df.select(pl.all()) + else: + sub_df = df.select(pl.col(col_selector)) + for col in sub_df.columns: + summary_dict[col][measure_name] = func(df[col]) + pass + return summary_dict, errs + + +class PolarsAnalysisPipeline(AnalysisPipeline): + """ + manage the ordering of a set of col_analysis objects + allow for computing summary_stats (and other oberservation sets) based on col_analysis objects + allow col_anlysis objects to be added + """ + + @staticmethod + def full_produce_summary_df( + df:pl.DataFrame, ordered_objs:List[PolarsAnalysis], + df_name:str='test_df', debug:bool=False): + series_stat_dict, series_errs = polars_produce_series_df(df, ordered_objs, df_name, debug) + summary_dict, summary_errs = produce_summary_df( + df, series_stat_dict, ordered_objs, df_name, debug) + series_errs.update(summary_errs) + return summary_dict, series_errs + + + + def add_analysis(self, new_aobj): + new_cname = new_aobj.cname() + new_aobj_set = [] + for aobj in self.ordered_a_objs: + if aobj.cname() == new_cname: + continue + new_aobj_set.append(aobj) + new_aobj_set.append(new_aobj) + self.verify_analysis_objects(new_aobj_set) + + # passed_unit_test, errs = self.unit_test() + # if passed_unit_test is False: + # return False, errs + return True, [] + + +class PlDfStats(DfStats): + ''' + DfStats exists to handle inteligent downampling and applying the ColAnalysis functions + ''' + ap_class = PolarsAnalysisPipeline + + @property + def presentation_sdf(self): + import pandas as pd + if self.ap.summary_stats_display == "all": + return pd.DataFrame(self.sdf) + return safe_summary_df(self.sdf, self.ap.summary_stats_display) diff --git a/buckaroo/pluggable_analysis_framework/polars_utils.py b/buckaroo/pluggable_analysis_framework/polars_utils.py new file mode 100644 index 000000000..519107641 --- /dev/null +++ b/buckaroo/pluggable_analysis_framework/polars_utils.py @@ -0,0 +1,19 @@ +import polars as pl + +import json +from collections import defaultdict +from typing import Any, Mapping, MutableMapping, List + + +def split_to_dicts(stat_df:pl.DataFrame) -> Mapping[str, MutableMapping[str, Any]]: + summary: MutableMapping[str, MutableMapping[str, Any]] = defaultdict(lambda : {}) + for col in stat_df.columns: + orig_col, measure = json.loads(col) + summary[orig_col][measure] = stat_df[col][0] + return summary + + +NUMERIC_POLARS_DTYPES:List[pl.PolarsDataType] = [ + pl.Int8, pl.Int16, pl.Int32, pl.Int64, + pl.UInt8, pl.UInt16, pl.UInt32, pl.UInt64, + pl.Float32, pl.Float64] \ No newline at end of file diff --git a/buckaroo/pluggable_analysis_framework/safe_summary_df.py b/buckaroo/pluggable_analysis_framework/safe_summary_df.py new file mode 100644 index 000000000..574c357c1 --- /dev/null +++ b/buckaroo/pluggable_analysis_framework/safe_summary_df.py @@ -0,0 +1,102 @@ +import pandas as pd +import numpy as np +import sys +import traceback +from buckaroo.serialization_utils import pick + + +class UnquotedString(str): + pass + +def val_replace(dct, replacements): + ret_dict = {} + for k, v in dct.items(): + if isinstance(v, pd.Series): + ret_dict[k] = UnquotedString('pd.Series()') + #hack, but trying to get away from conditional imports + elif repr(v.__class__) == "": + ret_dict[k] = UnquotedString('pl.Series()') + elif v in replacements: + ret_dict[k] = replacements[v] + else: + ret_dict[k] = v + return ret_dict + + +def dict_repr(dct): + ret_str = "{" + for k, v in dct.items(): + ret_str += "'%s': " % k + if type(v) == UnquotedString: + ret_str += "%s, " % v + else: + ret_str += "%r, " % v + ret_str += "}" + return ret_str + + +def pd_py_serialize(dct): + """ + This is used to output an exact string that is valid python code. + """ + cleaned_dct = val_replace(dct, + {pd.NA: UnquotedString("pd.NA"), + np.nan: UnquotedString("np.nan")}) + return dict_repr(cleaned_dct) + +def get_df_name(df, level=0): + """ looks up the call stack until it finds the variable with this name""" + if level == 0: + _globals = globals() + elif level < 60: + try: + call_frame = sys._getframe(level) + _globals = call_frame.f_globals + except ValueError: + return None #we went to far up the stacktrace to a non-existent frame + else: + return None + + name_possibs = [x for x in _globals.keys() if _globals[x] is df] + if name_possibs: + return name_possibs[0] + else: + #+2 because the function is recursive, and we need to skip over this frame + return get_df_name(df, level + 2) + +def safe_summary_df(base_summary_df, index_list): + #there are instances where not all indexes of the summary_df will + #be available, because there was no valid data to produce those + #indexes. This fixes them and explicitly. Empty rows will have NaN + return pd.DataFrame(base_summary_df, index_list) + +def reproduce_summary(ser_name_qualifier, kls, summary_df, err, operating_df_name): + #print("ser_name_qualifier", ser_name_qualifier) + #ser_name, method_name = ser_name_qualifier.split(':') + ser_name, method_name = ser_name_qualifier + ssdf = safe_summary_df(summary_df, kls.requires_summary) + summary_ser = ssdf[ser_name] + minimal_summary_dict = pick(summary_ser, kls.requires_summary) + sum_ser_repr = "pd.Series(%s)" % pd_py_serialize(minimal_summary_dict) + + f = "{kls}.summary({df_name}['{ser_name}'], {summary_ser_repr}, {df_name}['{ser_name}']) # {err_msg}" + print(f.format( + kls=kls.cname(), df_name=operating_df_name, ser_name=ser_name, + summary_ser_repr=sum_ser_repr, err_msg=err)) + +def output_reproduce_preamble(): + print("#Reproduction code") + print("#" + "-" * 80) + print("from buckaroo.pluggable_analysis_framework.analysis_management import PERVERSE_DF") + +def output_full_reproduce(errs, summary_df, df_name): + if len(errs) == 0: + raise Exception("output_full_reproduce called with 0 len errs") + + try: + for ser_name, err_kls in errs.items(): + err, kls = err_kls + reproduce_summary(ser_name, kls, summary_df, err, df_name) + except Exception: + #this is tricky stuff that shouldn't error, I want these stack traces to escape being caught + traceback.print_exc() diff --git a/buckaroo/pluggable_analysis_framework/utils.py b/buckaroo/pluggable_analysis_framework/utils.py new file mode 100644 index 000000000..a972eca76 --- /dev/null +++ b/buckaroo/pluggable_analysis_framework/utils.py @@ -0,0 +1,91 @@ +import json +import sys +import pandas as pd +import numpy as np + + +BASE_COL_HINT = { + 'type':'string', + 'is_numeric': False, + 'is_integer': None, + 'min_digits':None, + 'max_digits':None, + 'formatter':None, + 'histogram': []} + +FAST_SUMMARY_WHEN_GREATER = 1_000_000 + +PERVERSE_DF = pd.DataFrame({ + 'all_nan': [np.nan] * 10, + 'all_false': [False] * 10, + 'all_True': [True] * 10, + 'mixed_bool': np.concatenate([[True]*5, [False]*5]), + 'mixed_float': np.concatenate([[0.5, np.nan, None], [6]*7]), + 'float': [0.5]*10, + 'int': [8] *10, + 'negative': [-1]*10, + 'UInt32': pd.Series([5]*10, dtype='UInt32'), + 'UInt8None':pd.Series([None] * 10, dtype='UInt8') + }) + + +class NonExistentSummaryRowException(Exception): + pass + +def get_df_name(df, level=0): + """ looks up the call stack until it finds the variable with this name""" + if level == 0: + _globals = globals() + elif level < 60: + try: + call_frame = sys._getframe(level) + _globals = call_frame.f_globals + except ValueError: + return None #we went to far up the stacktrace to a non-existent frame + else: + return None + + name_possibs = [x for x in _globals.keys() if _globals[x] is df] + if name_possibs: + return name_possibs[0] + else: + #+2 because the function is recursive, and we need to skip over this frame + return get_df_name(df, level + 2) + + +def safe_isnan(v): + try: + return np.isnan(v) + except Exception: + return False + +def replace_in_dict(input_dict, replace_tuples): + ret_dict = {} + for k,v in input_dict.items(): + if isinstance(v, dict): + ret_dict[k] = replace_in_dict(v, replace_tuples) + elif safe_isnan(v): + ret_dict[k] = None + else: + for old, new in replace_tuples: + if v is old: + ret_dict[k] = new + break + elif v == old: + ret_dict[k] = new + break + ret_dict[k] = v + return ret_dict + + +def json_postfix(postfix): + return lambda nm: json.dumps([nm, postfix]) + + +def filter_analysis(klasses, attr): + ret_klses = {} + for k in klasses: + attr_val = getattr(k, attr, None) + if attr_val is not None: + ret_klses[attr_val] = k + return ret_klses diff --git a/buckaroo/polars_buckaroo.py b/buckaroo/polars_buckaroo.py new file mode 100644 index 000000000..ad07b3c36 --- /dev/null +++ b/buckaroo/polars_buckaroo.py @@ -0,0 +1,82 @@ +import polars as pl +from buckaroo.buckaroo_widget import BuckarooWidget, RawDFViewerWidget +from .customizations.polars_analysis import PL_Analysis_Klasses +from .pluggable_analysis_framework.polars_analysis_management import ( + PlDfStats) +from .serialization_utils import pd_to_obj +from buckaroo.customizations.polars_commands import ( + DropCol, FillNA, GroupBy #, OneHot, GroupBy, reindex +) +from .customizations.styling import DefaultSummaryStatsStyling, DefaultMainStyling +from .dataflow.dataflow import Sampling +from .dataflow.autocleaning import Autocleaning +from .dataflow.widget_extension_utils import configure_buckaroo + +class PLSampling(Sampling): + pre_limit = False + +local_analysis_klasses = PL_Analysis_Klasses.copy() +local_analysis_klasses.extend( + [DefaultSummaryStatsStyling, DefaultMainStyling]) + + +class PolarsAutocleaning(Autocleaning): + DFStatsKlass = PlDfStats + + +class PolarsBuckarooWidget(BuckarooWidget): + """TODO: Add docstring here + """ + command_classes = [DropCol, FillNA, GroupBy] + analysis_klasses = local_analysis_klasses + DFStatsClass = PlDfStats + sampling_klass = PLSampling + + def _sd_to_jsondf(self, sd): + """exists so this can be overriden for polars """ + import pandas as pd + temp_sd = sd.copy() + + #FIXME add actual test around weird index behavior + # if 'index' in temp_sd: + # del temp_sd['index'] + return pd_to_obj(pd.DataFrame(temp_sd)) + + def _build_error_dataframe(self, e): + return pl.DataFrame({'err': [str(e)]}) + + def _df_to_obj(self, df): + # I want to this, but then row numbers are lost + #return pd_to_obj(self.sampling_klass.serialize_sample(df).to_pandas()) + return pd_to_obj(self.sampling_klass.serialize_sample(df.to_pandas())) + +def PolarsDFViewer(df, + column_config_overrides=None, + extra_pinned_rows=None, pinned_rows=None, + extra_analysis_klasses=None, analysis_klasses=None, + ): + """ + Display a Polars DataFrame with buckaroo styling and analysis, no extra UI pieces + + column_config_overrides allows targetted specific overriding of styling + + extra_pinned_rows adds pinned_rows of summary stats + pinned_rows replaces the default pinned rows + + extra_analysis_klasses adds an analysis_klass + analysis_klasses replaces default analysis_klass + """ + BuckarooKls = configure_buckaroo( + PolarsBuckarooWidget, + extra_pinned_rows=extra_pinned_rows, pinned_rows=pinned_rows, + extra_analysis_klasses=extra_analysis_klasses, analysis_klasses=analysis_klasses) + + bw = BuckarooKls(df, column_config_overrides=column_config_overrides) + dfv_config = bw.df_display_args['dfviewer_special']['df_viewer_config'] + df_data = bw.df_data_dict['main'] + summary_stats_data = bw.df_data_dict['all_stats'] + return RawDFViewerWidget( + df_data=df_data, df_viewer_config=dfv_config, summary_stats_data=summary_stats_data) + + + diff --git a/buckaroo/serialization_utils.py b/buckaroo/serialization_utils.py new file mode 100644 index 000000000..c35bda01c --- /dev/null +++ b/buckaroo/serialization_utils.py @@ -0,0 +1,99 @@ +import json +import pandas as pd +from typing import Union, Any + + +EMPTY_DF_WHOLE = { + 'pinned_rows':[], + 'column_config': [], + 'data': [] +} + +def d_update(d1, d2): + ret_dict = d1.copy() + ret_dict.update(d2) + return ret_dict + +def pick(dct, keys): + new_dict = {} + for k in keys: + new_dict[k] = dct[k] + return new_dict + + +def val_replace(dct, replacements): + ret_dict = {} + for k, v in dct.items(): + if isinstance(v, pd.Series): + ret_dict[k] = UnquotedString('pd.Series()') + elif v in replacements: + ret_dict[k] = replacements[v] + else: + ret_dict[k] = v + return ret_dict + +class UnquotedString(str): + pass + +def dict_repr(dct): + ret_str = "{" + for k, v in dct.items(): + ret_str += "'%s': " % k + if type(v) == UnquotedString: + ret_str += "%s, " % v + else: + ret_str += "%r, " % v + ret_str += "}" + return ret_str + + +#def force_to_pandas(df_pd_or_pl:Union[pd.DataFrame, pl.DataFrame]) -> pd.DataFrame: +def force_to_pandas(df_pd_or_pl) -> pd.DataFrame: + if isinstance(df_pd_or_pl, pd.DataFrame): + return df_pd_or_pl + + import polars as pl + #hack for now so everything else flows through + + if isinstance(df_pd_or_pl, pl.DataFrame): + return df_pd_or_pl.to_pandas() + else: + raise Exception("unexpected type for dataframe, got %r" % (type(df_pd_or_pl))) + +#def generate_column_config(df:pd.DataFrame, summary_dict) -> List[ColumnConfig]: +def generate_column_config(df:pd.DataFrame, summary_dict): + ret_conf = [] + index_name = df.index.name or "index" + ret_conf.append({'col_name':index_name, 'displayer_args' : { 'displayer':'obj'}}) + for col in df.columns: + ret_conf.append({'col_name': col, 'displayer_args' : { 'displayer':'obj'} }) + return ret_conf + + +#def df_to_obj(unknown_df:Union[pd.DataFrame, Any], summary_dict:Any) -> DFWhole: +def df_to_obj(unknown_df:Union[pd.DataFrame, Any], summary_dict:Any): + df = force_to_pandas(unknown_df) + data = pd_to_obj(df) + #dfviewer_config:DFViewerConfig = { + dfviewer_config = { + 'pinned_rows' : [], + 'column_config' : generate_column_config(df, summary_dict) + } + return {'data':data, 'dfviewer_config': dfviewer_config} + + +def pd_to_obj(df:pd.DataFrame): + obj = json.loads(df.to_json(orient='table', indent=2, default_handler=str)) + + if isinstance(df.index, pd.MultiIndex): + old_index = df.index + temp_index = pd.Index(df.index.to_list(), tupleize_cols=False) + df.index = temp_index + obj = json.loads(df.to_json(orient='table', indent=2, default_handler=str)) + df.index = old_index + else: + obj = json.loads(df.to_json(orient='table', indent=2, default_handler=str)) + return obj['data'] + + + diff --git a/buckaroo/solara/__init__.py b/buckaroo/solara/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/buckaroo/solara/__init__.py @@ -0,0 +1 @@ + diff --git a/buckaroo/solara_buckaroo.py b/buckaroo/solara_buckaroo.py new file mode 100644 index 000000000..24a1318b3 --- /dev/null +++ b/buckaroo/solara_buckaroo.py @@ -0,0 +1,69 @@ +from buckaroo import BuckarooWidget +from buckaroo.buckaroo_widget import RawDFViewerWidget +from buckaroo.dataflow.widget_extension_utils import configure_buckaroo + +def SolaraDFViewer(df, column_config_overrides=None, + extra_pinned_rows=None, pinned_rows=None, + extra_analysis_klasses=None, analysis_klasses=None): + import reacton + BuckarooKls = configure_buckaroo( + BuckarooWidget, + extra_pinned_rows=extra_pinned_rows, pinned_rows=pinned_rows, + extra_analysis_klasses=extra_analysis_klasses, analysis_klasses=analysis_klasses) + + bw = BuckarooKls(df, column_config_overrides=column_config_overrides) + dfv_config = bw.df_display_args['dfviewer_special']['df_viewer_config'] + df_data = bw.df_data_dict['main'] + summary_stats_data = bw.df_data_dict['all_stats'] + + comp = reacton.core.ComponentWidget(widget=RawDFViewerWidget) + + element_kwargs = dict(df_data=df_data, df_viewer_config=dfv_config, summary_stats_data=summary_stats_data) + + return reacton.core.Element(comp, kwargs=element_kwargs) + +def SolaraBuckarooWidget(df, column_config_overrides=None, + extra_pinned_rows=None, pinned_rows=None, + extra_analysis_klasses=None, analysis_klasses=None): + import reacton + BuckarooKls = configure_buckaroo( + BuckarooWidget, + extra_pinned_rows=extra_pinned_rows, pinned_rows=pinned_rows, + extra_analysis_klasses=extra_analysis_klasses, analysis_klasses=analysis_klasses) + + comp = reacton.core.ComponentWidget(widget=BuckarooKls) + return reacton.core.Element(comp, df=df, column_config_overrides=column_config_overrides) + +def SolaraPolarsDFViewer(df, column_config_overrides=None, + extra_pinned_rows=None, pinned_rows=None, + extra_analysis_klasses=None, analysis_klasses=None): + import reacton + from buckaroo.polars_buckaroo import PolarsBuckarooWidget + BuckarooKls = configure_buckaroo( + PolarsBuckarooWidget, + extra_pinned_rows=extra_pinned_rows, pinned_rows=pinned_rows, + extra_analysis_klasses=extra_analysis_klasses, analysis_klasses=analysis_klasses) + + bw = BuckarooKls(df, column_config_overrides=column_config_overrides) + dfv_config = bw.df_display_args['dfviewer_special']['df_viewer_config'] + df_data = bw.df_data_dict['main'] + summary_stats_data = bw.df_data_dict['all_stats'] + + comp = reacton.core.ComponentWidget(widget=RawDFViewerWidget) + + element_kwargs = dict(df_data=df_data, df_viewer_config=dfv_config, summary_stats_data=summary_stats_data) + + return reacton.core.Element(comp, kwargs=element_kwargs) + +def SolaraPolarsBuckarooWidget(df, column_config_overrides=None, + extra_pinned_rows=None, pinned_rows=None, + extra_analysis_klasses=None, analysis_klasses=None): + import reacton + from buckaroo.polars_buckaroo import PolarsBuckarooWidget + BuckarooKls = configure_buckaroo( + PolarsBuckarooWidget, + extra_pinned_rows=extra_pinned_rows, pinned_rows=pinned_rows, + extra_analysis_klasses=extra_analysis_klasses, analysis_klasses=analysis_klasses) + + comp = reacton.core.ComponentWidget(widget=BuckarooKls) + return reacton.core.Element(comp, df=df, column_config_overrides=column_config_overrides) diff --git a/buckaroo/trait_utils.py b/buckaroo/trait_utils.py new file mode 100644 index 000000000..2f1f10696 --- /dev/null +++ b/buckaroo/trait_utils.py @@ -0,0 +1,50 @@ +import typing as t +from traitlets import Sentinel, EventHandler, All, ObserveHandler, HasTraits, Int, Unicode + +def my_observe(*names: t.Union[Sentinel, str], type: str = "change") -> "ObserveHandler": + """A decorator which can be used to observe Traits on a class. + + The handler passed to the decorator will be called with one ``change`` + dict argument. The change dictionary at least holds a 'type' key and a + 'name' key, corresponding respectively to the type of notification and the + name of the attribute that triggered the notification. + + Other keys may be passed depending on the value of 'type'. In the case + where type is 'change', we also have the following keys: + * ``owner`` : the HasTraits instance + * ``old`` : the old value of the modified trait attribute + * ``new`` : the new value of the modified trait attribute + * ``name`` : the name of the modified trait attribute. + + Parameters + ---------- + *names + The str names of the Traits to observe on the object. + type : str, kwarg-only + The type of event to observe (e.g. 'change') + """ + if not names: + raise TypeError("Please specify at least one trait name to observe.") + for name in names: + if name is not All and not isinstance(name, str): + raise TypeError("trait names to observe must be strings or All, not %r" % name) + return MyObserveHandler(names, type=type) + +class MyObserveHandler(EventHandler): + def __init__(self, names, type): + self.trait_names = names + self.type = type + + def instance_init(self, inst): + print("instance init called", inst) + + inst.observe(self, self.trait_names, type=self.type) + +class Foo(HasTraits): + bar = Int() + baz = Unicode() + + @my_observe("bar") + def _observe_bar(self, change): + print(change["old"]) + print(change["new"]) diff --git a/buckaroo/widget_utils.py b/buckaroo/widget_utils.py new file mode 100644 index 000000000..6329a920d --- /dev/null +++ b/buckaroo/widget_utils.py @@ -0,0 +1,151 @@ +import traceback +from .buckaroo_widget import BuckarooWidget +import pandas as pd +from datetime import datetime as dtdt +import os +import psutil + + +def is_in_ipython(): + + try: + from IPython.core.getipython import get_ipython + except ImportError: + raise ImportError('This feature requires IPython 1.0+') + + ip = get_ipython() + if ip is None: + #print("must be running inside ipython to enable default display via enable()") + return False + return ip + + +def enable(sampled=True, + summaryStats=False, + reorderdColumns=False, + showCommands=False, + auto_clean=False, + postProcessingF=None, + debug=False + ): + """ + Automatically use buckaroo to display all DataFrames + instances in the notebook. + + """ + + ip = is_in_ipython() + + parent_process = psutil.Process().parent() + server_start_time = dtdt.fromtimestamp(parent_process.create_time()) + + buckaroo_mtime = dtdt.fromtimestamp(os.path.getmtime(__file__)) + + jupyter_env = determine_jupter_env() + if jupyter_env in ["jupyter-lab", "jupyter-notebook"] and buckaroo_mtime > server_start_time: + print("It looks like you installed Buckaroo after you started this notebook server.") + print("""If you see a messages like""") + print(""""Failed to load model class 'DCEFWidgetModel' from module 'buckaroo'" """) + print("""restart the jupyter server and try again.""") + print("""If you have furter errors, please file a bug report at https://github.com/paddymul/buckaroo""") + print("-"*80) + print("buckaroo_mtime", buckaroo_mtime, "server_start_time", server_start_time) + #note we don't throw an exception here because this is a + #warning. I think this usecase specifically works on google + #colab + + + + def _display_as_buckaroo(df): + from IPython.display import display + try: + bw = BuckarooWidget(df, debug=debug) + return display(bw) + except: + if debug: + traceback.print_exc() + return + # returning NotImplementedError causes IPython to find the + # next registered formatter for the type + raise NotImplementedError + + def _display_polars_as_buckaroo(polars_df): + from IPython.display import display + from buckaroo.polars_buckaroo import PolarsBuckarooWidget + + try: + return display(PolarsBuckarooWidget(polars_df)) + except: + if debug: + traceback.print_exc() + return + raise NotImplementedError + + def _display_geopandas_as_buckaroo(gdf): + from IPython.display import display + from buckaroo.geopandas_buckaroo import GeopandasBuckarooWidget + + try: + return display(GeopandasBuckarooWidget(gdf)) + except: + if debug: + traceback.print_exc() + return + raise NotImplementedError + + + ip_formatter = ip.display_formatter.ipython_display_formatter + ip_formatter.for_type(pd.DataFrame, _display_as_buckaroo) + + try: + import polars as pl + ip_formatter.for_type(pl.DataFrame, _display_polars_as_buckaroo) + except ImportError: + pass + + try: + import geopandas + ip_formatter.for_type(geopandas.geodataframe.GeoDataFrame, _display_geopandas_as_buckaroo) + except ImportError: + pass + + + return True + +def disable(): + """ + disable bucakroo as the default display method for DataFrames + + """ + + ip = is_in_ipython() + + ip_formatter = ip.display_formatter.ipython_display_formatter + ip_formatter.type_printers.pop(pd.DataFrame, None) + + try: + import polars as pl + ip_formatter.type_printers.pop(pl.DataFrame, None) + except ImportError: + pass + print("The default DataFrame displayers have been restored. To re-enable Buckaroo use `from buckaroo import enable; enable()`") + +def determine_jupter_env(): + import psutil + parent_process = psutil.Process().parent().cmdline()[-1] + + if 'jupyter-lab' in parent_process: + return "jupyter-lab" + elif 'jupyter-notebook' in parent_process: + return "jupyter-notebook" + elif '__vsc_ipynb_file__' in globals(): + return "vscode" + else: + try: + from IPython.core import getipython + if 'google.colab' in str(getipython.get_ipython()): + return "google-colab" + except: + pass + return "unknown" + diff --git a/dcef/__init__.py b/dcef/__init__.py deleted file mode 100644 index faaaf799c..000000000 --- a/dcef/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding: utf-8 -*- - - diff --git a/dcef/_frontend.py b/dcef/_frontend.py deleted file mode 100644 index 67eec5522..000000000 --- a/dcef/_frontend.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) Bloomberg. -# Distributed under the terms of the Modified BSD License. - -""" -Information about the frontend package of the widgets. -""" - -from ._version import __version__ - -module_name = "ipydatagrid" -module_version = f"^{__version__}" diff --git a/dcef/_version.py b/dcef/_version.py deleted file mode 100644 index e7eef18bc..000000000 --- a/dcef/_version.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) Bloomberg. -# Distributed under the terms of the Modified BSD License. - -__version__ = "1.1.15" diff --git a/dcef/dcef_widget.py b/dcef/dcef_widget.py deleted file mode 100644 index 8627894c6..000000000 --- a/dcef/dcef_widget.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python -# coding: utf-8 - -# Copyright (c) Paddy Mullen. -# Distributed under the terms of the Modified BSD License. - -""" -TODO: Add module docstring -""" - -from ipywidgets import DOMWidget -from traitlets import Unicode, List, Dict, observe -from ._frontend import module_name, module_version -from .all_transforms import configure_dcef, DefaultCommandKlsList -import json - - -class DCEFWidget(DOMWidget): - """TODO: Add docstring here - """ - _model_name = Unicode('DCFWidgetModel').tag(sync=True) - _model_module = Unicode(module_name).tag(sync=True) - _model_module_version = Unicode(module_version).tag(sync=True) - _view_name = Unicode('DCFWidgetView').tag(sync=True) - _view_module = Unicode(module_name).tag(sync=True) - _view_module_version = Unicode(module_version).tag(sync=True) - - value = Unicode('Hello World').tag(sync=True) - command_config = Dict({}).tag(sync=True) - - commands = List().tag(sync=True) - - command_classes = DefaultCommandKlsList - - js_df = Dict({}).tag(sync=True) - - # transformed_df = Dict({}).tag(sync=True) - # transform_error = Unicode('').tag(sync=True) - - # generated_py_code = Unicode('').tag(sync=True) - # generated_py_error = Unicode('').tag(sync=True) - - - operation_results = Dict({}).tag(sync=True) - - def __init__(self, df): - super().__init__() - self.df = df - self.js_df = json.loads(df.to_json(orient='table', indent=2)) - self.operation_results = { - 'transformed_df':self.js_df, - 'generated_py_code':'#from py widget init'} - self.setup_from_command_kls_list() - - @observe('commands') - def interpret_operations(self, change): - print("interpret_operations") - try: - operations = change['new'] - print("interpret_operations", operations) - results = {} - if len(operations) == 1: - - results['transformed_df'] = self.js_df - results['generated_py_code'] = 'no operations' - print('exiting early') - return - - transformed_df = self.dcef_transform(operations, self.df) - results['transformed_df'] = json.loads(transformed_df.to_json(orient='table', indent=2)) - - results['generated_py_code'] = self.dcef_to_py_core(operations[1:]) - self.operation_results = results - print("operations_results", results.keys()) - except Exception as e: - print("error_setting", e) - self.transform_error = str(e) - raise - - def setup_from_command_kls_list(self): - command_defaults, command_patterns, self.dcef_transform, self.dcef_to_py_core = configure_dcef( - self.command_classes) - self.command_config = dict( - argspecs=command_patterns, defaultArgs=command_defaults) - - - def add_command(self, incomingCommandKls): - without_incoming = [x for x in self.command_classes if not x.__name__ == incomingCommandKls.__name__] - without_incoming.append(incomingCommandKls) - self.command_classes = without_incoming - self.setup_from_command_kls_list() - - - - - - diff --git a/dcef/dcf_transform.py b/dcef/dcf_transform.py deleted file mode 100644 index 8076b94d0..000000000 --- a/dcef/dcf_transform.py +++ /dev/null @@ -1,185 +0,0 @@ -import pandas as pd -import numpy as np -from .lispy import make_interpreter, s -import json - -def dropcol(df, col): - df.drop(col, axis=1, inplace=True) - return df - -def fillna(df, col, val): - df.fillna({col:val}, inplace=True) - return df - - -sample_df = pd.DataFrame({'a':[2,None], 'b':['3', 'a'], 'c':[5, None]}) - -def test_dropcol(): - dropped_df = dropcol(sample_df.copy(), 'b') - assert dropped_df is not sample_df - #I want to make sure we haven't modified df - assert len(dropped_df.columns) != len(sample_df.columns) - assert 'b' not in dropped_df.columns - - -def test_fillna(): - filled_df = fillna(sample_df.copy(), 'a', 13) - - assert filled_df is not sample_df - assert np.isnan(sample_df.iloc[1]['a']) - assert np.isnan(sample_df.iloc[1]['c']) - assert np.isnan(filled_df.iloc[1]['c']) - assert filled_df.iloc[1]['a'] == 13 - - -_eval, raw_parse = make_interpreter({'dropcol':dropcol, 'fillna':fillna}) -def dcf_transform(instructions, df): - df_copy = df.copy() - return _eval(instructions, {'df':df_copy}) - -def test_interpret_fillna(): - # I would like to have symbol:df be implicit, I can do that later - filled_df = dcf_transform( - [s('fillna'), s('df'), 'a', 13], sample_df) - assert filled_df is not sample_df - assert np.isnan(sample_df.iloc[1]['a']) - assert np.isnan(sample_df.iloc[1]['c']) - assert np.isnan(filled_df.iloc[1]['c']) - assert filled_df.iloc[1]['a'] == 13 - - -def test_interpret_dropcol(): - # I would like to have symbol:df be implicit, I can do that later - dropped_df = dcf_transform( - [s('dropcol'), s('df'), 'b'], sample_df) - assert dropped_df is not sample_df - #I want to make sure we haven't modified df - assert len(dropped_df.columns) != len(sample_df.columns) - assert 'b' not in dropped_df.columns - -def test_interpret_multiple_dropcol(): - # I would like to have symbol:df be implicit, I can do that later - dropped_df = dcf_transform([ - s('begin'), - [s('dropcol'), s('df'), 'b'], - [s('dropcol'), s('df'), 'c']], - sample_df) - - - # [ - # {"symbol":"begin"},[[{"symbol":"dropcol"},{"symbol":"df"},"tripduration"]]] - assert dropped_df is not sample_df - #I want to make sure we haven't modified df - assert len(dropped_df.columns) != len(sample_df.columns) - assert 'b' not in dropped_df.columns - assert 'c' not in dropped_df.columns - - -print(json.dumps([s('dropcol'), s('df'), 'b'])) - - -def dropcol_py(df, col): - return " df.drop('%s', axis=1, inplace=True)" % col - -def fillna_py(df, col, val): - return " df.fillna({'%s':%r}, inplace=True)" % (col, val) - - -_convert_to_python, _convert_to_py_lisp = make_interpreter({'dropcol':dropcol_py, 'fillna':fillna_py}) - -def dcf_to_py(instructions): - #I would prefer to implement this with a macro named something - #like 'clean' that is implemented for the _convert_to_python - #interpreter to return a string code block, and for the real DCF - #interpreter as 'begin'... that way the exact same instructions - #could be sent to either interpreter. For now, this will do - individual_instructions = [x for x in map(lambda x:_convert_to_python(x, {'df':5}), instructions)] - code_block = '\n'.join(individual_instructions) - - return "def clean(df):\n" + code_block - -expected_py_output = """def clean(df): - df.drop('b', axis=1, inplace=True) - df.drop('c', axis=1, inplace=True)""" - -def test_to_py(): - assert dcf_to_py([[s('dropcol'), s('df'), 'b'], - [s('dropcol'), s('df'), 'c']]) == expected_py_output - assert dcf_to_py( - [ - [{'symbol': 'dropcol'}, {'symbol': 'df'}, 'starttime'], - [{'symbol': 'dropcol'}, {'symbol': 'df'}, 'stoptime']])== "asdf" - - - -def fillna(df, col, val): - df.fillna({col:val}, inplace=True) - return df - -def fillna_py(df, col, val): - return " df.fillna({'%s':%r}, inplace=True)" % (col, val) - - -class Arguments(object): - - df = "df" - column_name = "column_name" - of_type = "of_type" - -class TransformType(object): - - column = "column" - multi_column = "multi_column" - shape_change = "shape_change" - -class Transform(object): - - t_type = TransformType.column - transform = fillna - transform_to_py = fillna_py - - argument_types = [Arguments.df, Arguments.column_name, Arguments.of_type] - argument_names = ["df", "col", "val"] - command_template = [s('fillna'), s('df'), "col", "val"] - - -class FillNA(Transform): - t_type = TransformType.column - - @staticmethod - def transform(df, col, val): - df.fillna({col:val}, inplace=True) - return df - - @staticmethod - def transform_to_py(df, col, val): - return " df.fillna({'%s':%r}, inplace=True)" % (col, val) - - arguments = [Arguments.df, Arguments.column_name, Arguments.of_type] - argument_names = ["df", "col", "val"] - command_template = [s('fillna'), s('df'), "col", "val"] - - -class OneHot(Transform): - t_type = TransformType.column - - @staticmethod - def transform(df, col, val): - one_hot = pd.get_dummies(df[col]) - df = df.drop(col, axis=1, inplace=True) - #how to make this inplace? - return df.join(one_hot) - - - @staticmethod - def transform_to_py(df, col, val): - commands = [ - " one_hot = pd.get_dummies(df['%s'])" % (col), - " df.drop('%s', inplace=True)" % (col), - " df = df.join(one_hot)"] - return "\n".join(commands) - - arguments = [Arguments.df, Arguments.column_name, Arguments.of_type] - - - diff --git a/dcef/df_methods.py b/dcef/df_methods.py deleted file mode 100644 index 51a42d3e3..000000000 --- a/dcef/df_methods.py +++ /dev/null @@ -1,442 +0,0 @@ - - - -['T', - '_AXIS_LEN', - '_AXIS_ORDERS', - '_AXIS_TO_AXIS_NUMBER', - '_HANDLED_TYPES', - '__abs__', - '__add__', - '__and__', - '__annotations__', - '__array__', - '__array_priority__', - '__array_ufunc__', - '__array_wrap__', - '__bool__', - '__class__', - '__contains__', - '__copy__', - '__dataframe__', - '__deepcopy__', - '__delattr__', - '__delitem__', - '__dict__', - '__dir__', - '__divmod__', - '__doc__', - '__eq__', - '__finalize__', - '__floordiv__', - '__format__', - '__ge__', - '__getattr__', - '__getattribute__', - '__getitem__', - '__getstate__', - '__gt__', - '__hash__', - '__iadd__', - '__iand__', - '__ifloordiv__', - '__imod__', - '__imul__', - '__init__', - '__init_subclass__', - '__invert__', - '__ior__', - '__ipow__', - '__isub__', - '__iter__', - '__itruediv__', - '__ixor__', - '__le__', - '__len__', - '__lt__', - '__matmul__', - '__mod__', - '__module__', - '__mul__', - '__ne__', - '__neg__', - '__new__', - '__nonzero__', - '__or__', - '__pos__', - '__pow__', - '__radd__', - '__rand__', - '__rdivmod__', - '__reduce__', - '__reduce_ex__', - '__repr__', - '__rfloordiv__', - '__rmatmul__', - '__rmod__', - '__rmul__', - '__ror__', - '__round__', - '__rpow__', - '__rsub__', - '__rtruediv__', - '__rxor__', - '__setattr__', - '__setitem__', - '__setstate__', - '__sizeof__', - '__str__', - '__sub__', - '__subclasshook__', - '__truediv__', - '__weakref__', - '__xor__', - '_accessors', - '_accum_func', - '_add_numeric_operations', - '_agg_by_level', - '_agg_examples_doc', - '_agg_summary_and_see_also_doc', - '_align_frame', - '_align_series', - '_append', - '_arith_method', - '_as_manager', - '_attrs', - '_box_col_values', - '_can_fast_transpose', - '_check_inplace_and_allows_duplicate_labels', - '_check_inplace_setting', - '_check_is_chained_assignment_possible', - '_check_label_or_level_ambiguity', - '_check_setitem_copy', - '_clear_item_cache', - '_clip_with_one_bound', - '_clip_with_scalar', - '_cmp_method', - '_combine_frame', - '_consolidate', - '_consolidate_inplace', - '_construct_axes_dict', - '_construct_axes_from_arguments', - '_construct_result', - '_constructor', - '_constructor_sliced', - '_convert', - '_count_level', - '_data', - '_dir_additions', - '_dir_deletions', - '_dispatch_frame_op', - '_drop_axis', - '_drop_labels_or_levels', - '_ensure_valid_index', - '_find_valid_index', - '_flags', - '_from_arrays', - '_get_agg_axis', - '_get_axis', - '_get_axis_name', - '_get_axis_number', - '_get_axis_resolvers', - '_get_block_manager_axis', - '_get_bool_data', - '_get_cleaned_column_resolvers', - '_get_column_array', - '_get_index_resolvers', - '_get_item_cache', - '_get_label_or_level_values', - '_get_numeric_data', - '_get_value', - '_getitem_bool_array', - '_getitem_multilevel', - '_gotitem', - '_hidden_attrs', - '_indexed_same', - '_info_axis', - '_info_axis_name', - '_info_axis_number', - '_info_repr', - '_init_mgr', - '_inplace_method', - '_internal_names', - '_internal_names_set', - '_is_copy', - '_is_homogeneous_type', - '_is_label_or_level_reference', - '_is_label_reference', - '_is_level_reference', - '_is_mixed_type', - '_is_view', - '_iset_item', - '_iset_item_mgr', - '_iset_not_inplace', - '_item_cache', - '_iter_column_arrays', - '_ixs', - '_join_compat', - '_logical_func', - '_logical_method', - '_maybe_cache_changed', - '_maybe_update_cacher', - '_metadata', - '_mgr', - '_min_count_stat_function', - '_needs_reindex_multi', - '_protect_consolidate', - '_reduce', - '_reduce_axis1', - '_reindex_axes', - '_reindex_columns', - '_reindex_index', - '_reindex_multi', - '_reindex_with_indexers', - '_rename', - '_replace_columnwise', - '_repr_data_resource_', - '_repr_fits_horizontal_', - '_repr_fits_vertical_', - '_repr_html_', - '_repr_latex_', - '_reset_cache', - '_reset_cacher', - '_sanitize_column', - '_series', - '_set_axis', - '_set_axis_name', - '_set_axis_nocheck', - '_set_is_copy', - '_set_item', - '_set_item_frame_value', - '_set_item_mgr', - '_set_value', - '_setitem_array', - '_setitem_frame', - '_setitem_slice', - '_slice', - '_stat_axis', - '_stat_axis_name', - '_stat_axis_number', - '_stat_function', - '_stat_function_ddof', - '_take', - '_take_with_is_copy', - '_to_dict_of_blocks', - '_typ', - '_update_inplace', - '_validate_dtype', - '_values', - '_where', - 'abs', - 'add', - 'add_prefix', - 'add_suffix', - 'agg', - 'aggregate', - 'align', - 'all', - 'any', - 'append', - 'apply', - 'applymap', - 'asfreq', - 'asof', - 'assign', - 'astype', - 'at', - 'at_time', - 'attrs', - 'axes', - 'backfill', - 'between_time', - 'bfill', - 'bool', - 'boxplot', - 'clip', - 'columns', - 'combine', - 'combine_first', - 'compare', - 'convert_dtypes', - 'copy', - 'corr', - 'corrwith', - 'count', - 'cov', - 'cummax', - 'cummin', - 'cumprod', - 'cumsum', - 'describe', - 'diff', - 'div', - 'divide', - 'dot', - 'drop', - 'drop_duplicates', - 'droplevel', - 'dropna', - 'dtypes', - 'duplicated', - 'empty', - 'eq', - 'equals', - 'eval', - 'ewm', - 'expanding', - 'explode', - 'ffill', - 'fillna', - 'filter', - 'first', - 'first_valid_index', - 'flags', - 'floordiv', - 'from_dict', - 'from_records', - 'ge', - 'get', - 'groupby', - 'gt', - 'head', - 'hist', - 'iat', - 'idxmax', - 'idxmin', - 'iloc', - 'index', - 'infer_objects', - 'info', - 'insert', - 'interpolate', - 'isetitem', - 'isin', - 'isna', - 'isnull', - 'items', - 'iteritems', - 'iterrows', - 'itertuples', - 'join', - 'keys', - 'kurt', - 'kurtosis', - 'last', - 'last_valid_index', - 'le', - 'loc', - 'lookup', - 'lt', - 'mad', - 'mask', - 'max', - 'mean', - 'median', - 'melt', - 'memory_usage', - 'merge', - 'min', - 'mod', - 'mode', - 'mul', - 'multiply', - 'ndim', - 'ne', - 'nlargest', - 'notna', - 'notnull', - 'nsmallest', - 'nunique', - 'pad', - 'pct_change', - 'pipe', - 'pivot', - 'pivot_table', - 'plot', - 'pop', - 'pow', - 'prod', - 'product', - 'quantile', - 'query', - 'radd', - 'rank', - 'rdiv', - 'reindex', - 'reindex_like', - 'rename', - 'rename_axis', - 'reorder_levels', - 'replace', - 'resample', - 'reset_index', - 'rfloordiv', - 'rmod', - 'rmul', - 'rolling', - 'round', - 'rpow', - 'rsub', - 'rtruediv', - 'sample', - 'select_dtypes', - 'sem', - 'set_axis', - 'set_flags', - 'set_index', - 'shape', - 'shift', - 'size', - 'skew', - 'slice_shift', - 'sort_index', - 'sort_values', - 'squeeze', - 'stack', - 'std', - 'sub', - 'subtract', - 'sum', - 'swapaxes', - 'swaplevel', - 'tail', - 'take', - 'transform', - 'transpose', - 'truncate', - 'unstack', - 'update', - 'where', - 'xs'] - - # 'style', - # 'value_counts', - # 'values', - # 'var', - # 'tz_convert', - # 'tz_localize', - # 'truediv', - - # 'to_clipboard', - # 'to_csv', - # 'to_dict', - # 'to_excel', - # 'to_feather', - # 'to_gbq', - # 'to_hdf', - # 'to_html', - # 'to_json', - # 'to_latex', - # 'to_markdown', - # 'to_numpy', - # 'to_orc', - # 'to_parquet', - # 'to_period', - # 'to_pickle', - # 'to_records', - # 'to_sql', - # 'to_stata', - # 'to_string', - # 'to_timestamp', - # 'to_xarray', - # 'to_xml', diff --git a/dcef/index.html b/dcef/index.html deleted file mode 100644 index 90041ef54..000000000 --- a/dcef/index.html +++ /dev/null @@ -1,83 +0,0 @@ - - - dcf - - - -

dcf

-

RSS Feed   channeldata.json

-noarch    - - - - - - - - -
PackageLatest VersionDocDevLicensenoarch Summary
-
Updated: 2023-03-21 17:59:44 +0000 - Files: 0
- - \ No newline at end of file diff --git a/dcef/tests/conftest.py b/dcef/tests/conftest.py deleted file mode 100644 index 5448bba6a..000000000 --- a/dcef/tests/conftest.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -# coding: utf-8 - -# Copyright (c) Paddy Mullen. -# Distributed under the terms of the Modified BSD License. - -import pytest - -from ipykernel.comm import Comm -from ipywidgets import Widget - -class MockComm(Comm): - """A mock Comm object. - - Can be used to inspect calls to Comm's open/send/close methods. - """ - comm_id = 'a-b-c-d' - kernel = 'Truthy' - - def __init__(self, *args, **kwargs): - self.log_open = [] - self.log_send = [] - self.log_close = [] - super(MockComm, self).__init__(*args, **kwargs) - - def open(self, *args, **kwargs): - self.log_open.append((args, kwargs)) - - def send(self, *args, **kwargs): - self.log_send.append((args, kwargs)) - - def close(self, *args, **kwargs): - self.log_close.append((args, kwargs)) - -_widget_attrs = {} -undefined = object() - - -@pytest.fixture -def mock_comm(): - _widget_attrs['_comm_default'] = getattr(Widget, '_comm_default', undefined) - Widget._comm_default = lambda self: MockComm() - _widget_attrs['_ipython_display_'] = Widget._ipython_display_ - def raise_not_implemented(*args, **kwargs): - raise NotImplementedError() - Widget._ipython_display_ = raise_not_implemented - - yield MockComm() - - for attr, value in _widget_attrs.items(): - if value is undefined: - delattr(Widget, attr) - else: - setattr(Widget, attr, value) diff --git a/dcef/tests/test_example.py b/dcef/tests/test_example.py deleted file mode 100644 index 176d615ca..000000000 --- a/dcef/tests/test_example.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python -# coding: utf-8 - -# Copyright (c) Paddy Mullen. -# Distributed under the terms of the Modified BSD License. - -import pytest - -from ..example import ExampleWidget - - -def test_example_creation_blank(): - w = ExampleWidget() - assert w.value == 'Hello World' diff --git a/dcef/tests/test_nbextension_path.py b/dcef/tests/test_nbextension_path.py deleted file mode 100644 index ff845cfc7..000000000 --- a/dcef/tests/test_nbextension_path.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python -# coding: utf-8 - -# Copyright (c) Paddy Mullen. -# Distributed under the terms of the Modified BSD License. - - -def test_nbextension_path(): - # Check that magic function can be imported from package root: - from dcf import _jupyter_nbextension_paths - # Ensure that it can be called without incident: - path = _jupyter_nbextension_paths() - # Some sanity checks: - assert len(path) == 1 - assert isinstance(path[0], dict) diff --git a/dcef/views.py b/dcef/views.py deleted file mode 100644 index 00f96323b..000000000 --- a/dcef/views.py +++ /dev/null @@ -1,83 +0,0 @@ -# -*- coding: utf-8 -*- -import os -import pandas as pd -from flask import Blueprint, jsonify, request -from flask_login import login_required, current_user -from flask_cors import cross_origin -from ..extensions import db -import json -#from .dcf_transform import dcf_transform, s, dcf_to_py as dcf_to_py_core -from .lispy import s -from .all_transforms import dcf_transform, dcf_to_py_core, command_patterns, command_defaults -#from lispy import s -dcf_views = Blueprint('dcf', __name__, url_prefix='/dcf') - - -#make an @serve_df decorator that deals with query params and converting the df - -DEFAULT_CSV_PATH = './sample_data/2014-01-citibike-tripdata.csv' -#DEFAULT_CSV_PATH = './sample_data/problem.csv' -csv_path = os.getenv('DCF_CSV', DEFAULT_CSV_PATH) - -@dcf_views.route('/df/', methods=['GET']) -@cross_origin() -def read_df(id): - - df = pd.read_csv(csv_path) - slice_start = int(request.args.get('slice_start', 0)) - slice_end = request.args.get('slice_end', False) - if slice_end is not False: - df = df[slice_start:int(slice_end)] - return json.loads(df.to_json(orient='table', indent=2)) - - -@dcf_views.route('/transform_df/', methods=['GET']) -@cross_origin() -def transform_df(id): - df = pd.read_csv(csv_path) - instructions = json.loads(request.args.get('instructions', None)) - - #slice before or after??? probably after, otherwise run a dcf command - df = dcf_transform(instructions, df) - - slice_start = int(request.args.get('slice_start', 0)) - slice_end = request.args.get('slice_end', False) - - if slice_end is not False: - df = df.iloc[slice_start:int(slice_end)] - return json.loads(df.to_json(orient='table', indent=2)) - - -@dcf_views.route('/dcf_to_py/', methods=['GET']) -@cross_origin() -def dcf_to_py(id): - instructions = json.loads(request.args.get('instructions', None)) - #return dcf_to_py(instructions) - try: - py_string = dcf_to_py_core(instructions) - return dict(py=py_string) - except Exception as e: - print("e", e) - return "error" - - - -@dcf_views.route('/command-config', methods=['GET']) -@cross_origin() -def command_config(): - sym = s - - commandPatterns = { - "dropcol":[None], - "fillna":[[3, 'fillVal', 'type', 'integer']], - "groupby":[[3, 'colMap', 'colEnum', ['null', 'sum', 'mean', 'count']]] - } - commandDefaults = { - "dropcol": [sym("dropcol"), sym("df"), "col"], - "fillna": [sym("fillna"), sym("df"), "col", 8], - "groupby": [sym("resample"), sym('df'), 'col', {}] - } - #return dict(commandPatterns=commandPatterns, commandDefaults=commandDefaults) - return dict(commandPatterns=command_patterns, commandDefaults=command_defaults) - - diff --git a/docs/examples/App.tsx b/docs/examples/App.tsx new file mode 100644 index 000000000..01eea628c --- /dev/null +++ b/docs/examples/App.tsx @@ -0,0 +1,108 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import 'bootstrap/dist/css/bootstrap.min.css'; +import React from 'react'; +import {HashRouter as Router, Route, Link} from 'react-router-dom'; +import {Button} from 'react-bootstrap'; + +import './app.css'; + + +const examples = { + WidgetDCFCellEx: {title: 'WigetDCFCell', file: 'WidgetDCFCellEx'}, + ColumnsEditorEx: {title: 'ColumnsEditor', file: 'ColumnsEditorEx'}, + CommandViewerEx: {title: 'CommandViewer', file: 'CommandViewerEx'}, + DFViewerEx: {title: 'DFViewer', file: 'DFViewerEx'}, + DFViewerEx_string_index: {title: 'DFViewer string index', file: 'DFViewerEx_string_index'}, + DFViewerEx_large: {title: 'DFViewer large', file: 'DFViewerEx_large'}, + DFViewerEx_real_summary: {title: 'DFViewer summary', file: 'DFViewerEx_real_summary'}, + DFViewerEx_short_data: {title: 'DFViewer short_data', file: 'DFViewerEx_short_data'}, + + StatusBarEx: {title: 'StatusBar', file: 'StatusBarEx'}, + HistogramEx: {title: 'Histogram', file: 'HistogramEx'} +}; + + +// The examples use a code-loading technique that I have described in +// https://mmomtchev.medium.com/making-examples-displaying-code-along-its-output-with-webpack-a28dcf5439c6 + +const ReadmeBlock = React.lazy(() => import(/* webpackPrefetch: true */ './ReadmeBlock')); +const CodeBlock = React.lazy(() => import(/* webpackPrefetch: true */ './CodeBlock')); + +for (const ex of Object.keys(examples)) { + examples[ex].comp = React.lazy( + () => import(/* webpackPrefetch: true */ `./ex/${examples[ex].file}.tsx`) + ); + examples[ex].code = import( + /* webpackPrefetch: true */ `!!html-loader?{"minimize":false}!./jsx-loader.ts!./ex/${examples[ex].file}.tsx` + ).then((code) => code.default); + examples[ex].text = import( + /* webpackPrefetch: true */ `!!raw-loader!./ex/${examples[ex].file}.tsx` + ).then((text) => text.default); +} + +const LeftMenuItem = (props): JSX.Element => ( + + + +); + +// eslint-disable-next-line no-var +//declare var VERSION: string = "handwritten"; + +const App = (): JSX.Element => { + const [jsText, setJSText] = React.useState(''); + + return ( + +

+ Buckaroo JS Frontend Examples +

+
+
+ + {Object.keys(examples).map((e) => ( + + ))} +
+
+
+ +
+ Loading...
}> + + +
+ + {Object.keys(examples).map((e) => ( + +
+
+ Loading component...
}> +
+

Component example

+ {React.createElement(examples[e].comp)} +
+ +
+
+ Parsing code...
}> + + +
+
+ + ))} + + + +
+ ); +}; + +export default App; diff --git a/docs/examples/CodeBlock.tsx b/docs/examples/CodeBlock.tsx new file mode 100644 index 000000000..47853fea0 --- /dev/null +++ b/docs/examples/CodeBlock.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import CodePenButton from './CodePenButton'; +import 'prism-themes/themes/prism-vsc-dark-plus.css'; + +// This is expensive to render +const CodeBlock = React.memo(function _CodeBlock(props: { + title: string; + code: Promise; + text: Promise; +}) { + const [code, setCode] = React.useState('loading()'); + React.useEffect(() => { + props.code.then((r) => setCode(r)); + }, [props.code, props.text]); + return ( +
+ +
+
+                    
+                
+
+
+ ); +}); + +export default CodeBlock; diff --git a/docs/examples/CodePenButton.tsx b/docs/examples/CodePenButton.tsx new file mode 100644 index 000000000..cae1f9493 --- /dev/null +++ b/docs/examples/CodePenButton.tsx @@ -0,0 +1,77 @@ +import * as React from 'react'; + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import exampleCss from '!!raw-loader!./example.css'; + +const CodePenButton = React.memo(function _CodePenButton(props: { + text: Promise; + title: string; +}) { + const [text, setText] = React.useState('loading()'); + React.useEffect(() => { + props.text.then((r) => { + r = r.replace( + /import (.*) from '(.*)'/g, + (match, g1, g2) => `import ${g1} from "https://cdn.skypack.dev/${g2}"` + ); + r = r.replace(/import '.*';\n/g, ''); + r = r.replace(/export default function (.*)/, 'function Comp() {'); + r = 'import * as ReactDOM from "https://cdn.skypack.dev/react-dom";\n' + r; + r += '\nReactDOM.render(, document.getElementById("root"));\n'; + setText(r); + }); + }, [props.text]); + + const ref = React.useRef(); + + return ( +
+ ', + js: text, + js_pre_processor: 'typescript', + css: exampleCss, + js_external: + 'https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js', + css_external: + 'https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css;' + + 'https://unpkg.com/react-day-picker/dist/style.css' + })} + /> + +
+ ); +}); + +export default CodePenButton; diff --git a/docs/examples/ReadmeBlock.tsx b/docs/examples/ReadmeBlock.tsx new file mode 100644 index 000000000..9360cbd0e --- /dev/null +++ b/docs/examples/ReadmeBlock.tsx @@ -0,0 +1,12 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import React from 'react'; +// @ts-ignore +import READMEmd from '../../README.md'; +//const READMEmd = "

paddy readme

" + +// This is expensive to render +const ReadmeBlock = React.memo(function _README() { + return
; +}); + +export default ReadmeBlock; diff --git a/docs/examples/app.css b/docs/examples/app.css new file mode 100644 index 000000000..bfc3bb42e --- /dev/null +++ b/docs/examples/app.css @@ -0,0 +1,193 @@ +.left-menu button { + text-align: left; + font-weight: bold; + color: #333333; +} + +.left-menu a:hover { + text-decoration: none; +} + +.left-menu { + width: 105; + min-width: 15em; + max-width: 15em; + overflow:hidden +} + +.codeblock { + max-height: 90vh; + overflow-y: scroll; + text-align: left; +} + +.codeblock > pre { + margin-top: 0 !important; +} + +.codeblock > pre > code { + font-size: 0.9rem !important; + line-height: 1.1 !important; +} + + + +:root +{ + --color-example: #fff; +} + +.fluid-container { + min-width:950px +} + +html,body +{ + font-family: "Roboto", sans-serif; + display: flex; + flex-grow: 1; + width: 100%; + height: 100%; + min-height: 100vh; + font-size: 16px; + text-align: center; + /*color: var(--color-example); */ + color:black; + margin: 0; +} +#fullscreen { + width:100% + +} + + +#app +{ + background-color: #4158D0; + background-image: linear-gradient(43deg, #4158D0 0%, #C850C0 46%, #FFCC70 100%); + color: var(--color-example); + + justify-content: center; + display: flex; + flex-grow: 1; + flex-direction:column; + align-items: center; + font-size: 2rem; + outline:4px solid pink; +} + +.histogram { + color:black; +} + +.component-example { + border:1px solid black; + table { + th { + border: 2px solid black; + } + td { + border:1px solid black; + } + } +} + +.customHeaderRenderer { + height:100%; +} +.customHeaderLabel { + padding:0; +} + + +.histogram-ex { + +} + +.histogram-ex .histogram-wrap {border: 1px solid gray; clear:both} +.histogram-ex span {color:black; width:200px; float:left; text-align:left; } +.histogram-ex .histogram-component {width:105px; float:left} +.patterns { + width: 100vw; + height: 100vw; +} + + +.small-bar { + height:30px; width:10px; +} + +.med-bar { + height:100px; width:100px; +} + +/* +from https://www.magicpattern.design/tools/css-backgrounds +*/ +.pt1 { +background-color: #e5e5f7; +opacity: 0.8; +background-image: repeating-linear-gradient(45deg, #444cf7 25%, transparent 25%, transparent 75%, #444cf7 75%, #444cf7), repeating-linear-gradient(45deg, #444cf7 25%, #e5e5f7 25%, #e5e5f7 75%, #444cf7 75%, #444cf7); +background-position: 0 0, 2px 2px; +background-size: 4px 4px; + +} +.pt4 { + background-color: #e5e5f7; + opacity: 0.8; + background: repeating-linear-gradient( 45deg, #444cf7, #444cf7 3px, #e5e5f7 3px, #e5e5f7 6px ); +} + +.pt5 { +background-color: #e5e5f7; +opacity: 0.8; +background-image: linear-gradient(135deg, #444cf7 25%, transparent 25%), linear-gradient(225deg, #444cf7 25%, transparent 25%), linear-gradient(45deg, #444cf7 25%, transparent 25%), linear-gradient(315deg, #444cf7 25%, #e5e5f7 25%); +background-position: 3px 0, 3px 0, 0 0, 0 0; +background-size: 6px 6px; +background-repeat: repeat; +} + +.pt6 { +background-color: #e5e5f7; +opacity: 0.8; +background-image: radial-gradient(#444cf7 1.2px, #e5e5f7 1.2px); +background-size: 4px 4px; +} + +.pt7 { +background-color: #e5e5f7; +opacity: 0.8; +background-image: radial-gradient( ellipse farthest-corner at 4px 4px , #444cf7, #444cf7 50%, #e5e5f7 50%); +background-size: 4px 4px; + +} +/* +body { + + margin: 0; + min-height: 100vh; +} + +html { + background: #fff; +} + +special values + +true +false +n/a +long tail +completely unique + + +*/ + + +.ag-column-hover: { + overflow: visible +} +.histogram-ex { background:#181d1f} +.histogram-ex span { color : white } + + diff --git a/examples/data/2014-01-citibike-tripdata.csv b/docs/examples/data/2014-01-citibike-tripdata.csv similarity index 100% rename from examples/data/2014-01-citibike-tripdata.csv rename to docs/examples/data/2014-01-citibike-tripdata.csv diff --git a/examples/data/yellow_tripdata_2021-02.csv b/docs/examples/data/yellow_tripdata_2021-02.csv similarity index 100% rename from examples/data/yellow_tripdata_2021-02.csv rename to docs/examples/data/yellow_tripdata_2021-02.csv diff --git a/docs/examples/ex/ColumnsEditorEx.tsx b/docs/examples/ex/ColumnsEditorEx.tsx new file mode 100644 index 000000000..b9a3c6402 --- /dev/null +++ b/docs/examples/ex/ColumnsEditorEx.tsx @@ -0,0 +1,5 @@ +import { extraComponents } from 'buckaroo'; +import 'ag-grid-community/styles/ag-grid.css'; +import 'ag-grid-community/styles/ag-theme-alpine.css'; + +export default extraComponents.ColumnsEditorEx; diff --git a/docs/examples/ex/CommandViewerEx.tsx b/docs/examples/ex/CommandViewerEx.tsx new file mode 100644 index 000000000..4b1a62dfc --- /dev/null +++ b/docs/examples/ex/CommandViewerEx.tsx @@ -0,0 +1,20 @@ +import * as React from 'react'; + +//import {bakedOperations, bakedCommandConfig } from '../../../js/baked_data/staticData'; +import { bakedData } from 'buckaroo'; +import { extraComponents } from 'buckaroo'; + + +export default function Simple() { + return ( + { + console.log('setCommands sent', foo); + }} + activeColumn={'foo-column'} + allColumns={['foo-col', 'bar-col', 'baz-col']} + commandConfig={bakedData.bakedCommandConfig} + /> + ); +} diff --git a/docs/examples/ex/DFViewerEx.tsx b/docs/examples/ex/DFViewerEx.tsx new file mode 100644 index 000000000..410ea2411 --- /dev/null +++ b/docs/examples/ex/DFViewerEx.tsx @@ -0,0 +1,3 @@ +import { extraComponents } from 'buckaroo'; + +export default extraComponents.DFViewerEx; diff --git a/docs/examples/ex/DFViewerEx_large.tsx b/docs/examples/ex/DFViewerEx_large.tsx new file mode 100644 index 000000000..3fde2d756 --- /dev/null +++ b/docs/examples/ex/DFViewerEx_large.tsx @@ -0,0 +1,266 @@ +import React, { useState} from 'react'; +import _ from 'lodash'; + +import { extraComponents } from 'buckaroo'; +//import { DFData, DFViewerConfig } from 'buckaroo'; + +const data = [ + { + "index": 0, + "a": 5, + "b": 2.8571428571 + }, + { + "index": 1, + "a": 28, + "b": 12.8571428571 + }, + +] + +const summary_stats_data =[ + { + "index": "dtype", + "a": "int64", + "b": "float64" + }, + { + "index": "is_numeric", + "a": true, + "b": true + }, + { + "index": "_type", + "a": "integer", + "b": "float" + }, + { + "index": "histogram", + "a": [ + { + "name": "1 - 1.0", + "tail": 1 + }, + { + "name": "2-7", + "population": 16 + }, + { + "name": "7-11", + "population": 11 + }, + { + "name": "11-16", + "population": 6 + }, + { + "name": "16-20", + "population": 11 + }, + { + "name": "20-25", + "population": 5 + }, + { + "name": "25-30", + "population": 14 + }, + { + "name": "30-34", + "population": 9 + }, + { + "name": "34-39", + "population": 9 + }, + { + "name": "39-43", + "population": 11 + }, + { + "name": "43-48", + "population": 10 + }, + { + "name": "49.0 - 49", + "tail": 1 + } + ], + "b": [ + { + "name": "1.4285714285714286 - 1.4285714285714286", + "tail": 1 + }, + { + "name": "3-7", + "population": 12 + }, + { + "name": "7-10", + "population": 16 + }, + { + "name": "10-14", + "population": 9 + }, + { + "name": "14-18", + "population": 9 + }, + { + "name": "18-21", + "population": 9 + }, + { + "name": "21-25", + "population": 12 + }, + { + "name": "25-29", + "population": 14 + }, + { + "name": "29-33", + "population": 6 + }, + { + "name": "33-36", + "population": 7 + }, + { + "name": "36-40", + "population": 6 + }, + { + "name": "41.42857142857143 - 41.42857142857143", + "tail": 1 + } + ] + } + ]; + + function genInt(len, min, max) { + const a = new Array(len); + return _.map(a, a => _.random(min, max)) + } + + function genString(items:number, minLen:number, maxLen:number) : string[] { + + const a = new Array(items); + const randStrings = _.map(a, () => { + const strLen = _.random(minLen, maxLen); + const b = new Array(strLen) + const randLenStr = _.map(b, () => { return String.fromCharCode(_.random(65, 90)) }).join('') + return randLenStr + }) + return randStrings + } + +const dictOfListsToListOfDicts = (a: Record) : Record[] => { + const firstKey = _.keys(a)[0]; + const data : Record[] = _.map(a[firstKey], (_val, idx):Record => { + const pairs: [string, any][] = _.map(a, (arr, key) => { + return [key, arr[idx]] + }) + const row:Record = _.fromPairs(pairs); + return row; + }) + return data +} + + export default function DFViewerExString() { + const [activeCol, setActiveCol] = useState('tripduration'); + const samples= 1_000; + const data = dictOfListsToListOfDicts({ + 'a':genInt(samples, 2, 30), + 'b':genInt(samples, 10, 8), + 'c':genString(samples, 3, 10), + 'd':genInt(samples, 100, 999), + 'e':genInt(samples, -30_000, 55_123_123), + 'f':genString(samples, 3, 70), + 'g':genInt(samples, -3, 55), + }) + //const current: {'df':DFData, 'df_viewer_config':DFViewerConfig, 'summary_stats_data':DFData} = { + const current: {'df':any, 'df_viewer_config': any, 'summary_stats_data': any} = { + + "df": data, + "df_viewer_config": { + "pinned_rows": [ + { + "primary_key_val": "dtype", + "displayer_args": { + "displayer": "obj" + } + }, + { + "primary_key_val": "histogram", + "displayer_args": { + "displayer": "histogram" + } + } + ], + component_config: {height_fraction:1.15}, + + "column_config": [ + { + "col_name": "index", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "a", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "b", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "c", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "d", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "e", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "f", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "g", + "displayer_args": { + "displayer": "obj" + } + }, + + + ] + }, + "summary_stats_data": summary_stats_data + } + + + return ; + } + diff --git a/docs/examples/ex/DFViewerEx_real_summary.tsx b/docs/examples/ex/DFViewerEx_real_summary.tsx new file mode 100644 index 000000000..4f2673b08 --- /dev/null +++ b/docs/examples/ex/DFViewerEx_real_summary.tsx @@ -0,0 +1,20 @@ +import React, { useState} from 'react'; +import { extraComponents, bakedData } from 'buckaroo'; + +//import { realSummaryConfig, realSummaryTableData } from '../../../js/baked_data/staticData'; +//import { realSummaryConfig, realSummaryTableData } from 'buckaroo'; + + + export default function DFViewerExString() { + const [activeCol, setActiveCol] = useState('tripduration'); + + const current = { + 'df': bakedData.realSummaryTableData, 'df_viewer_config': bakedData.realSummaryConfig, + 'summary_stats_data': bakedData.realSummaryTableData }; + + return ; + } + diff --git a/docs/examples/ex/DFViewerEx_short_data.tsx b/docs/examples/ex/DFViewerEx_short_data.tsx new file mode 100644 index 000000000..cc95a3ac7 --- /dev/null +++ b/docs/examples/ex/DFViewerEx_short_data.tsx @@ -0,0 +1,22 @@ +import React, { useState} from 'react'; +import { bakedData, extraComponents } from 'buckaroo'; + + + + export default function DFViewerExString() { + const [activeCol, setActiveCol] = useState('tripduration'); +// const dfv_config:DFViewerConfig = { + const dfv_config:any = { + column_config: bakedData.realSummaryConfig.column_config, + pinned_rows: []} + + const current = { + 'df':bakedData.realSummaryTableData, 'df_viewer_config': bakedData.realSummaryConfig, + 'summary_stats_data': bakedData.realSummaryTableData }; + + return ; + } + diff --git a/docs/examples/ex/DFViewerEx_string_index.tsx b/docs/examples/ex/DFViewerEx_string_index.tsx new file mode 100644 index 000000000..c43207d39 --- /dev/null +++ b/docs/examples/ex/DFViewerEx_string_index.tsx @@ -0,0 +1,1012 @@ +import React, { useState} from 'react'; +import { extraComponents } from 'buckaroo'; +//import { DFData, DFViewerConfig } from 'buckaroo'; + + +const data = [ + { + "index": 0, + "a": 5, + "b": 2.8571428571 + }, + { + "index": 1, + "a": 28, + "b": 12.8571428571 + }, + { + "index": 2, + "a": 47, + "b": 2.8571428571 + }, + { + "index": 3, + "a": 4, + "b": 32.8571428571 + }, + { + "index": 4, + "a": 29, + "b": 30 + }, + { + "index": 5, + "a": 26, + "b": 38.5714285714 + }, + { + "index": 6, + "a": 29, + "b": 12.8571428571 + }, + { + "index": 7, + "a": 49, + "b": 18.5714285714 + }, + { + "index": 8, + "a": 22, + "b": 4.2857142857 + }, + { + "index": 9, + "a": 32, + "b": 35.7142857143 + }, + { + "index": 10, + "a": 19, + "b": 8.5714285714 + }, + { + "index": 11, + "a": 32, + "b": 27.1428571429 + }, + { + "index": 12, + "a": 44, + "b": 24.2857142857 + } +] + +const summary_stats_data =[ + { + "index": "dtype", + "a": "int64", + "b": "float64" + }, + { + "index": "is_numeric", + "a": true, + "b": true + }, + { + "index": "is_integer", + "a": true, + "b": false + }, + { + "index": "is_datetime", + "a": false, + "b": false + }, + { + "index": "is_bool", + "a": false, + "b": false + }, + { + "index": "is_float", + "a": false, + "b": true + }, + { + "index": "is_string", + "a": false, + "b": false + }, + { + "index": "memory_usage", + "a": 1732, + "b": 1732 + }, + { + "index": "length", + "a": 200, + "b": 200 + }, + { + "index": "nan_count", + "a": 0, + "b": 0 + }, + { + "index": "value_counts", + "a": [ + 7, + 7, + 7, + 7, + 7, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 1, + 1, + 1 + ], + "b": [ + 12, + 11, + 10, + 10, + 10, + 10, + 9, + 9, + 8, + 8, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 6, + 6, + 5, + 5, + 5, + 4, + 4, + 3, + 3, + 3, + 3 + ] + }, + { + "index": "mode", + "a": 2, + "b": 7.1428571429 + }, + { + "index": "min", + "a": 1, + "b": 1.4285714286 + }, + { + "index": "max", + "a": 49, + "b": 41.4285714286 + }, + { + "index": "mean", + "a": 24.275, + "b": 19.4571428571 + }, + { + "index": "histogram_args", + "a": { + "meat_histogram": [ + [ + 29, + 20, + 11, + 20, + 10, + 26, + 16, + 17, + 20, + 18 + ], + [ + 2, + 6.6, + 11.2, + 15.8, + 20.4, + 25, + 29.6, + 34.2, + 38.8, + 43.4, + 48 + ] + ], + "normalized_populations": [ + 0.1550802139, + 0.1069518717, + 0.0588235294, + 0.1069518717, + 0.0534759358, + 0.1390374332, + 0.0855614973, + 0.0909090909, + 0.1069518717, + 0.0962566845 + ], + "low_tail": 1, + "high_tail": 49 + }, + "b": { + "meat_histogram": [ + [ + 22, + 30, + 17, + 17, + 16, + 22, + 26, + 11, + 13, + 12 + ], + [ + 2.8571428571, + 6.5714285714, + 10.2857142857, + 14, + 17.7142857143, + 21.4285714286, + 25.1428571429, + 28.8571428571, + 32.5714285714, + 36.2857142857, + 40 + ] + ], + "normalized_populations": [ + 0.1182795699, + 0.1612903226, + 0.0913978495, + 0.0913978495, + 0.0860215054, + 0.1182795699, + 0.1397849462, + 0.0591397849, + 0.0698924731, + 0.064516129 + ], + "low_tail": 1.4285714286, + "high_tail": 41.4285714286 + } + }, + { + "index": "_type", + "a": "integer", + "b": "float" + }, + { + "index": "type", + "a": "integer", + "b": "float" + }, + { + "index": "min_digits", + "a": 1, + "b": 1 + }, + { + "index": "max_digits", + "a": 2, + "b": 2 + }, + { + "index": "unique_count", + "a": 3, + "b": 0 + }, + { + "index": "empty_count", + "a": 0, + "b": 0 + }, + { + "index": "distinct_count", + "a": 49, + "b": 29 + }, + { + "index": "distinct_per", + "a": 0.245, + "b": 0.145 + }, + { + "index": "empty_per", + "a": 0, + "b": 0 + }, + { + "index": "unique_per", + "a": 0.015, + "b": 0 + }, + { + "index": "nan_per", + "a": 0, + "b": 0 + }, + { + "index": "histogram", + "a": [ + { + "name": "1 - 1.0", + "tail": 1 + }, + { + "name": "2-7", + "population": 16 + }, + { + "name": "7-11", + "population": 11 + }, + { + "name": "11-16", + "population": 6 + }, + { + "name": "16-20", + "population": 11 + }, + { + "name": "20-25", + "population": 5 + }, + { + "name": "25-30", + "population": 14 + }, + { + "name": "30-34", + "population": 9 + }, + { + "name": "34-39", + "population": 9 + }, + { + "name": "39-43", + "population": 11 + }, + { + "name": "43-48", + "population": 10 + }, + { + "name": "49.0 - 49", + "tail": 1 + } + ], + "b": [ + { + "name": "1.4285714285714286 - 1.4285714285714286", + "tail": 1 + }, + { + "name": "3-7", + "population": 12 + }, + { + "name": "7-10", + "population": 16 + }, + { + "name": "10-14", + "population": 9 + }, + { + "name": "14-18", + "population": 9 + }, + { + "name": "18-21", + "population": 9 + }, + { + "name": "21-25", + "population": 12 + }, + { + "name": "25-29", + "population": 14 + }, + { + "name": "29-33", + "population": 6 + }, + { + "name": "33-36", + "population": 7 + }, + { + "name": "36-40", + "population": 6 + }, + { + "name": "41.42857142857143 - 41.42857142857143", + "tail": 1 + } + ] + } + ]; + + export default function DFViewerExString() { + const [activeCol, setActiveCol] = useState('tripduration'); + + //const dfvConfig:DFViewerConfig = { + + const dfvConfig:any = { + "pinned_rows": [ + { + "primary_key_val": "dtype", + "displayer_args": { + "displayer": "obj" + } + }, + { + "primary_key_val": "histogram", + "displayer_args": { + "displayer": "histogram" + } + } + ], + "column_config": [ + { + "col_name": "index", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "a", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "b", + "displayer_args": { + "displayer": "obj" + } + } + ] +} + + // { + // "pinned_rows": [ + // { + // "primary_key_val": "dtype", + // "displayer_args": { + // "displayer": "obj" + // } + // }, + // { + // "primary_key_val": "histogram", + // "displayer_args": { + // "displayer": "histogram" + // } + // } + // ], + // "column_config": [ + // { + // "col_name": "index", + // "displayer_args": { + // "displayer": "obj" + // } + // }, + // { + // "col_name": "a", + // "displayer_args": { + // "displayer": "obj" + // } + // }, + // { + // "col_name": "b", + // "displayer_args": { + // "displayer": "obj" + // } + // } + // ] + // } + //const current: {'df':DFData, 'df_viewer_config':DFViewerConfig, 'summary_stats_data':DFData} = { + + const current: {'df':any, 'df_viewer_config':any, 'summary_stats_data':any} = { + "df": [], + "df_viewer_config": { + "pinned_rows": [ + { + "primary_key_val": "dtype", + "displayer_args": { + "displayer": "obj" + } + }, + { + "primary_key_val": "histogram", + "displayer_args": { + "displayer": "histogram" + } + } + ], + "column_config": [ + { + "col_name": "index", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "a", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "b", + "displayer_args": { + "displayer": "obj" + } + } + ] + }, + "summary_stats_data": [ + { + "index": "dtype", + "a": "int64", + "b": "float64" + }, + { + "index": "is_numeric", + "a": true, + "b": true + }, + { + "index": "is_integer", + "a": true, + "b": false + }, + { + "index": "is_datetime", + "a": false, + "b": false + }, + { + "index": "is_bool", + "a": false, + "b": false + }, + { + "index": "is_float", + "a": false, + "b": true + }, + { + "index": "is_string", + "a": false, + "b": false + }, + { + "index": "memory_usage", + "a": 1732, + "b": 1732 + }, + { + "index": "length", + "a": 200, + "b": 200 + }, + { + "index": "nan_count", + "a": 0, + "b": 0 + }, + { + "index": "value_counts", + "a": [ + 12, + 9, + 8, + 7, + 7, + 7, + 7, + 7, + 6, + 6, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 1, + 1, + 1, + 1, + 1 + ], + "b": [ + 11, + 11, + 11, + 9, + 9, + 9, + 9, + 8, + 8, + 8, + 8, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 6, + 6, + 5, + 5, + 5, + 5, + 4, + 4, + 4, + 4, + 2 + ] + }, + { + "index": "mode", + "a": 6, + "b": 1.4285714286 + }, + { + "index": "min", + "a": 1, + "b": 1.4285714286 + }, + { + "index": "max", + "a": 49, + "b": 41.4285714286 + }, + { + "index": "mean", + "a": 23.375, + "b": 21.5285714286 + }, + { + "index": "histogram_args", + "a": { + "meat_histogram": [ + [ + 33, + 18, + 13, + 22, + 11, + 18, + 20, + 15, + 17, + 23 + ], + [ + 2, + 6.6, + 11.2, + 15.8, + 20.4, + 25, + 29.6, + 34.2, + 38.8, + 43.4, + 48 + ] + ], + "normalized_populations": [ + 0.1736842105, + 0.0947368421, + 0.0684210526, + 0.1157894737, + 0.0578947368, + 0.0947368421, + 0.1052631579, + 0.0789473684, + 0.0894736842, + 0.1210526316 + ], + "low_tail": 1, + "high_tail": 48.01 + }, + "b": { + "meat_histogram": [ + [ + 13, + 23, + 12, + 23, + 15, + 22, + 23, + 10, + 21, + 16 + ], + [ + 2.8571428571, + 6.5714285714, + 10.2857142857, + 14, + 17.7142857143, + 21.4285714286, + 25.1428571429, + 28.8571428571, + 32.5714285714, + 36.2857142857, + 40 + ] + ], + "normalized_populations": [ + 0.0730337079, + 0.1292134831, + 0.0674157303, + 0.1292134831, + 0.0842696629, + 0.1235955056, + 0.1292134831, + 0.0561797753, + 0.1179775281, + 0.0898876404 + ], + "low_tail": 1.4285714286, + "high_tail": 41.4285714286 + } + }, + { + "index": "_type", + "a": "integer", + "b": "float" + }, + { + "index": "type", + "a": "integer", + "b": "float" + }, + { + "index": "min_digits", + "a": 1, + "b": 1 + }, + { + "index": "max_digits", + "a": 2, + "b": 2 + }, + { + "index": "unique_count", + "a": 5, + "b": 0 + }, + { + "index": "empty_count", + "a": 0, + "b": 0 + }, + { + "index": "distinct_count", + "a": 49, + "b": 29 + }, + { + "index": "distinct_per", + "a": 0.245, + "b": 0.145 + }, + { + "index": "empty_per", + "a": 0, + "b": 0 + }, + { + "index": "unique_per", + "a": 0.025, + "b": 0 + }, + { + "index": "nan_per", + "a": 0, + "b": 0 + }, + { + "index": "histogram", + "a": [ + { + "name": "1 - 1.0", + "tail": 1 + }, + { + "name": "2-7", + "population": 17 + }, + { + "name": "7-11", + "population": 9 + }, + { + "name": "11-16", + "population": 7 + }, + { + "name": "16-20", + "population": 12 + }, + { + "name": "20-25", + "population": 6 + }, + { + "name": "25-30", + "population": 9 + }, + { + "name": "30-34", + "population": 11 + }, + { + "name": "34-39", + "population": 8 + }, + { + "name": "39-43", + "population": 9 + }, + { + "name": "43-48", + "population": 12 + }, + { + "name": "48.00999999999999 - 49", + "tail": 1 + } + ], + "b": [ + { + "name": "1.4285714285714286 - 1.4285714285714286", + "tail": 1 + }, + { + "name": "3-7", + "population": 7 + }, + { + "name": "7-10", + "population": 13 + }, + { + "name": "10-14", + "population": 7 + }, + { + "name": "14-18", + "population": 13 + }, + { + "name": "18-21", + "population": 8 + }, + { + "name": "21-25", + "population": 12 + }, + { + "name": "25-29", + "population": 13 + }, + { + "name": "29-33", + "population": 6 + }, + { + "name": "33-36", + "population": 12 + }, + { + "name": "36-40", + "population": 9 + }, + { + "name": "41.42857142857143 - 41.42857142857143", + "tail": 1 + } + ] + } + ] + } + + //const working = {'df':data, 'df_viewer_config': dfvConfig, 'summary_stats_data':summary_stats_data}; + const working = {'df':data, 'df_viewer_config': dfvConfig, 'summary_stats_data':summary_stats_data}; + + + return ; + } + diff --git a/docs/examples/ex/HistogramEx.tsx b/docs/examples/ex/HistogramEx.tsx new file mode 100644 index 000000000..6e1310250 --- /dev/null +++ b/docs/examples/ex/HistogramEx.tsx @@ -0,0 +1,67 @@ +import React from 'react'; +//import { histograms } from '../../js/baked_data/staticData'; +//import { HistogramCell } from '../../js/components/DFViewerParts/HistogramCell'; +import { extraComponents, bakedData } from 'buckaroo'; + + + +export default function Simple() { + const { + num_histo, bool_histo, NA_Only, simple_catgeorical, categorical_histo, + categorical_histo_lt, all_unique, unique_na, unique_continuous, + unique_continuous_scaled, unique_continuous_scaled_50, + start_station_categorical} = bakedData.histograms; + + return
+
+ Numeric + +
+
+ Boolean with NA + +
+
+ NA Only + +
+
+ Simple Categorical + +
+ +
+ Categorical unique NA + +
+
+ Categorical_longtail + +
+ +
+ Categorical All unique + +
+ +
+ Categorical Unique with NA + +
+ +
+ Numeric all Unique + +
+
+ start station categorical + +
+ + +
+ Numeric 50% unique + +
+
+} diff --git a/docs/examples/ex/StatusBarEx.tsx b/docs/examples/ex/StatusBarEx.tsx new file mode 100644 index 000000000..7fa15299e --- /dev/null +++ b/docs/examples/ex/StatusBarEx.tsx @@ -0,0 +1,6 @@ +import { extraComponents } from 'buckaroo'; + +export default extraComponents.StatusBarEx; +// export default function Simple() { +// return ; +// } diff --git a/docs/examples/ex/WidgetDCFCellEx.tsx b/docs/examples/ex/WidgetDCFCellEx.tsx new file mode 100644 index 000000000..05909a988 --- /dev/null +++ b/docs/examples/ex/WidgetDCFCellEx.tsx @@ -0,0 +1,6 @@ +import * as React from 'react'; +import {extraComponents} from 'buckaroo'; + +export default function Simple() { + return ; +} diff --git a/docs/examples/example.css b/docs/examples/example.css new file mode 100644 index 000000000..8841db871 --- /dev/null +++ b/docs/examples/example.css @@ -0,0 +1,20 @@ +.table-fixed { + table-layout: fixed; +} + +.btn-width { + width: 3rem; + text-align: end; +} + +.table-rounded td { + border-bottom-width: 0; +} + +.table-rounded td:first-child { + border-radius: 10px 0 0 10px; +} + +.table-rounded td:last-child { + border-radius: 0 10px 10px 0; +} diff --git a/docs/examples/index-iframe.hnottml b/docs/examples/index-iframe.hnottml new file mode 100644 index 000000000..ec751fb20 --- /dev/null +++ b/docs/examples/index-iframe.hnottml @@ -0,0 +1,24 @@ + + + + + + + + + iframe wrapper index + + + + + +

index iframe

+
+ + + + diff --git a/docs/examples/index-react18.tsx b/docs/examples/index-react18.tsx new file mode 100644 index 000000000..c20065879 --- /dev/null +++ b/docs/examples/index-react18.tsx @@ -0,0 +1,8 @@ +import React from 'react'; +import ReactDOMClient from 'react-dom/client'; + +import App from './App'; + +// eslint-disable-next-line no-console +console.debug('React 18 mode'); +ReactDOMClient.createRoot(document.getElementById('root')).render(); diff --git a/docs/examples/index.html b/docs/examples/index.html new file mode 100644 index 000000000..f73572bcf --- /dev/null +++ b/docs/examples/index.html @@ -0,0 +1,20 @@ + + + + + + + + + Buckaroo - JS Examples + + + +
+
+ <%= require('../../README.md').default %> +
+
+ + + diff --git a/docs/examples/index.tsx b/docs/examples/index.tsx new file mode 100644 index 000000000..eb10fb594 --- /dev/null +++ b/docs/examples/index.tsx @@ -0,0 +1,7 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; + +import App from './App'; + +// eslint-disable-next-line no-console +ReactDOM.render(, document.getElementById('root')); diff --git a/docs/examples/jsx-loader.ts b/docs/examples/jsx-loader.ts new file mode 100644 index 000000000..ff701c212 --- /dev/null +++ b/docs/examples/jsx-loader.ts @@ -0,0 +1,22 @@ +//import prettier from 'prettier/standalone'; +const prettier = require('prettier/standalone') + +//import parserTypescript from 'prettier/parser-typescript'; +const parserTypescript = require('prettier/parser-typescript'); +//import Prism from 'prismjs'; +const Prism = require('prismjs'); + + +import loadLanguages from 'prismjs/components/'; +//const loadLanguages = require('prismjs/components'); +loadLanguages(['tsx', 'jsx', 'typescript']); + +export default function tsx_loader(content: string, map: unknown, meta: unknown): void { + const formatted = prettier.format(content, { + parser: 'typescript', + plugins: [parserTypescript] + }); + const html = Prism.highlight(formatted, Prism.languages.tsx, 'tsx'); + this.callback(null, html, map, meta); + return; +} diff --git a/docs/examples_tsconfig.json b/docs/examples_tsconfig.json new file mode 100644 index 000000000..991c4ad59 --- /dev/null +++ b/docs/examples_tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "sourceMap": true, + "noImplicitAny": false, + "module": "esnext", + "target": "es2018", + "lib": [ + "esnext", + "dom", + "dom.iterable" + ], + "declaration": true, + "declarationMap": true, + "removeComments": false, + "allowSyntheticDefaultImports": true, + "jsx": "react", + "allowJs": true, + "baseUrl": "./", + "esModuleInterop": true, + "resolveJsonModule": true, + "moduleResolution": "node", + "downlevelIteration": true, + "paths": { + "paddy-react-edit-list": ["../js"] + } + }, + "include": [ + ".", + "../js" + ] +} diff --git a/docs/source/FAQ.rst b/docs/source/FAQ.rst index c5fb64a88..b75877317 100644 --- a/docs/source/FAQ.rst +++ b/docs/source/FAQ.rst @@ -1,23 +1,49 @@ -.. DCEF documentation master file, created by +.. Buckaroo documentation master file, created by sphinx-quickstart on Wed Apr 19 14:07:15 2023. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -DCEF - FAQ +Buckaroo - FAQ ========================================== +* **Does Buckaroo work in Visual Studio Code** + + As of 0.3.6 Buckaroo works properly in Visual Studio Code. You must install the `Visual Studio Code Jupyter Extension `_ and the `Jupyter Renderer extension `_. Then install buckaroo from pip and everything should work. + +* **Does Buckaroo work with Google Colab** + +Yes Buckaroo has been tested to work with Google Colab. + +* **Does Buckaroo work with Jupyter Notebook** + +Right now, buckaroo only works with the latest release - NB7. The recommended way to run buckaroo is with "jupyter lab". It could be possible to make buckaroo work with the older notebook versions, but this takes significant packaging work. File a bug, when support for previous versions of Notebook becomes a serious barier to buckaroo adoption, it will be addressed. + +* **Are there any similar projects to Buckaroo?** + +There are a couple of projects like Buckaroo that aim to provide a better table widget and pandas editing experience. `Complete article `_ about the many related projects. + + +* **Is Buckaroo meant to repalce knowledge of python/pandas** + + No, Buckaroo helps experienced pandas devs quickly build and try the transformations they already know. Transformation names stay very close to the underlying pandas names. Buckaroo makes different transforms more discoverable than reading obscure blogposts and half working stackoverflow submissions. Different transformations can be quickly tried without a lot of reading and tinkering to see if it is the transform you want. Finally, all transformations are emitted as python code. That python code can be a starting point. + + +* **How well does Buckaroo perform on large dataframes** + + If Buckaroo is configured to send the entire dataframe to the frontend table widget, performance can be slow. But because Buckaroo is built to seamlessly present summary statistics and use sampling. You can operate on just a representative subset of the data, this is much more performant. Manually scanning through more than 500 rows makes it way to easy to miss data anomalies. Furthermore, Buckaroo separates the intent of a transform from the implementation. Python code gen that does the same transform can be improved. It also makes it quick to generate more complex code that is faster than a shorter implementation. If you are coding yourself, you're more likely to write the short version vs painstakingly reproducing a fast implementation. + * **Why did you use LISP?** This is a problem domain that required a DSL and intermediate language. I could have written my own or chosen an existing language. I chose LISP because it is simple to interpret and generate, additionally it is well understood. Yes LISP is obscure, but it is less obscure than a custom language I would write myself. I didn't want to expose an entire progrmaming language with all the attendant security risks, I wanted a small safe strict subset of programming features that I explicitly exposed. LISP is easier to manipulate as an AST than any language in PL history. I am not yet using any symbolic manipulation facilities of LISP, and will probably only use them in limited ways. -* **Do I need to know LISP to use DCF?** +* **Do I need to know LISP to use Buckaroo?** - No. Users of DCF will never need to know that LISP is at the core of the system. + No. Users of Bucakroo will never need to know that LISP is at the core of the system. -* **Do I need to know LISP to contribute to DCF?** +* **Do I need to know LISP to contribute to Buckaroo?** - Not really. Commands are added to the dcf interpreter via the Command class. Commands are very simple and straight forward. Here are the two functions that make `fillna` work. + Not really. Commands are added to the buckaroo interpreter via the Command class. Commands are very simple and straight forward. Here are the two functions that make `fillna` work. .. code-block:: python @@ -41,9 +67,3 @@ If you want to work on code transformations, then a knowledge of lisp and partic Alternatively, you could write a command that instead of subtractively reducing a dataframe, builds up a new dataframe from an explicit list of columns. That is also a type of transform that could be written. -* **Is DCF meant to repalce knowledge of python/pandas** - - No, DCF helps experienced pandas devs quickly build and try the transformations they already know. Transformation names stay very close to the underlying pandas names. DCF makes different transforms more discoverable than reading obscure blogposts and half working stackoverflow submissions. Different transformations can be quickly tried without a lot of reading and tinkering to see if it is the transform you want. Finally, all transformations are emitted as python code. That python code can be a starting point. - - - diff --git a/docs/source/_static/Buckaroo-labled.png b/docs/source/_static/Buckaroo-labled.png new file mode 100644 index 000000000..c3f28f616 Binary files /dev/null and b/docs/source/_static/Buckaroo-labled.png differ diff --git a/docs/source/_static/Statusbar.png b/docs/source/_static/Statusbar.png new file mode 100644 index 000000000..2b4e3b9f5 Binary files /dev/null and b/docs/source/_static/Statusbar.png differ diff --git a/docs/source/_static/embed-bundle.js.LICENSE.txt b/docs/source/_static/embed-bundle.js.LICENSE.txt index 73838b328..b62af749c 100644 --- a/docs/source/_static/embed-bundle.js.LICENSE.txt +++ b/docs/source/_static/embed-bundle.js.LICENSE.txt @@ -1,15 +1,4 @@ -/** - * @ag-grid-community/all-modules - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue * @version v29.2.0 - * @link https://www.ag-grid.com/ - * @license MIT - */ - -/** - * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue - * @version v29.2.0 - * @link https://www.ag-grid.com/ - * @license MIT - */ +/*! decimal.js-light v2.5.1 https://github.com/MikeMcl/decimal.js-light/LICENCE */ /** * @license @@ -69,3 +58,12 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ + +/** @license React v16.13.1 + * react-is.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ diff --git a/docs/source/_static/histograms-categorical-1.png b/docs/source/_static/histograms-categorical-1.png new file mode 100644 index 000000000..b9e9e42d2 Binary files /dev/null and b/docs/source/_static/histograms-categorical-1.png differ diff --git a/docs/source/_static/histograms-common.png b/docs/source/_static/histograms-common.png new file mode 100644 index 000000000..4278f77ad Binary files /dev/null and b/docs/source/_static/histograms-common.png differ diff --git a/docs/source/_static/histograms-numeric.png b/docs/source/_static/histograms-numeric.png new file mode 100644 index 000000000..143d99f3d Binary files /dev/null and b/docs/source/_static/histograms-numeric.png differ diff --git a/docs/source/articles/auto_clean.rst b/docs/source/articles/auto_clean.rst new file mode 100644 index 000000000..2a0876f69 --- /dev/null +++ b/docs/source/articles/auto_clean.rst @@ -0,0 +1,67 @@ +.. _using: + +============= +Auto Cleaning +============= + +By default buckaroo aggresively tries to type data and clean it up. + +Better typing +------------- +What do I mean by cleaning types? By default if an integer column contains a single missing value, pandas will use the ``float64`` dtype to represent that value as a NaN. The autotyping functionality instead casts that as ``Int64`` a new type in pandas that allows ``NA`` values in Int columns. Work is also done to constrain types to their narrowest, so if an int value is between 0 and 255, autotyping will cast that to `UInt8` using a single byte instead of 8 for a float64 or int64. + + +Heuristic cleaning +------------------ +The autocleaning tool also heursitically removes errant mistyped values from column. If a column is primarily Ints with a single string, that string is stripped so the column can be treated as numeric. + + + +Using Autocleaning +================== + +Changing individual coercions +---------------------------- + +Autotyping operations are added to the lowcode UI by default, open up the lowcode UI with the λ menu, then click on operations and delete them with the X. + + +Turning off auto cleaning +------------------------- + +Buckaroo's auto cleaning is aggressive and sometimes not wanted to use Buckaroo without autotyping, invoke it this way +.. code-block:: python + +from buckaroo import BuckarooWidget +BuckarooWidget(df, autoType=False) + + + + + +How Autotyping Works +==================== + +There are three steps to auto_cleaning + +First frequency metadata is collected with ``get_typing_metadata``, this is a dictionary with ``0`` - ``1`` ranges for the proportion of values that could be ``int``, ``float``, ``bool``, ``datetime``. + +Next ``recommend_type`` takes the typing metadata and returns ``bool``, ``datetime``, ``int``, ``float``, or ``string`` + +Finally ``emit_command`` returns a JLisp operation that will perform the conversion. + + +Why three functions? +-------------------- + +Splitting this into three distinct phases makes it much easier to customize behavior. It also allows improvements to accrue without requiring complete rewrites of the auto-typing functionality. My guess is that ``recommend_type`` is the easiest to override, and will be the most frequently. + + +How do I add special replacement functionality? +----------------------------------------------- + +What if you commonly deal with a dataset that treats ``y`` as ``True`` and ``n`` as ``False``, how would you recognize those types of values and convert them to boolean? + +Code coming soon. + + diff --git a/docs/source/articles/data_flow.rst b/docs/source/articles/data_flow.rst new file mode 100644 index 000000000..44895fd74 --- /dev/null +++ b/docs/source/articles/data_flow.rst @@ -0,0 +1,208 @@ +.. _data_flow: + +Data Flow through Buckaroo +=========================== + + +Buckaroo is extensible. The architecture of Buckaroo is crafted to allow specific points of composable extensibility in an opinionated manner. It was designed this way based on experience from writing many adhoc analysis pipelines. Previous "simpler" attempts at extensibility ran into bugs that couldn't be cleanly accomodated. The following will be addressed below: + +Buckaroo aims to allow highly opionated configurations to be toggled by users. With buckaroo, you can add a cleaning_method of "interpret int as milliseconds from unix epoch", and it will look at a column of ints, and decide that values map to datetimes in the past year (as opposed to centered around 1970) and we should treat this column as a datetime. That is a highly opinionated view of your data, the cost for that highly opinonated view is less when multiple opinions can be quickly cycled through. + +This approach is different than most tools which aim to be a generic tool that is customizable with bespoke configuration. It would be a bad thing if a generic table tool displayed integers as dates because it assumes that those integers are milliseconds from the unix epoch. Normally this would require custom code to be written and called based on manual inspection of the data. + +This document describes the multiple ways of extending bucakroo to add your own toggable opinons. + + + + + + +#. understand the dataflow through Buckaroo +#. quick start to extending buckaroo +#. description of extension points + + +Customization points of Buckaroo +-------------------------------- + + +#. Sample_method + Used to specify conditions for downsampling dataframe and method of sampling. Example alternatives include sampling in chunks, only showing first and last row, random sampling, and limiting number of columns. Returns sampled df +#. Cleaning_method + recieves sampled_dataframe Used to control how dataframes are cleaned before summary stats are run. Examples include special parsing rules for unique date formats, removing strings from primarily numeric columns. Returns cleaned_df and cleaned_summary_dict +#. Post_processing_method + recieves entire cleaned dataframe. Used to perform multi-column operations, like adding a running_diff column, or combining a latitude and longitude column into a single lat/long column. returns processed_df and processed_summary_dict +#. Analysis_klasses + recieves individual columns from processed_df. Individual column level analysis klasses used to fill out summary_stats. examples include mean, median, min, max, and complex results like histograms. Each class returns a summary_dict about a single column +#. style-method + recieves col_name, col_summary_dict, default_config. Takes a column_summary_dict and returns the column_config for that column. Examples include formatting a datetime as time only if the min/max are within a single day, conditionally turning on tooltips and color_maps based on other info in summary_dict + + + +.. raw:: html + + + + +.. role:: dataflow-result +.. role:: dataflow-arg +.. role:: class-state +.. role:: ui-variable +.. role:: tuple-param +.. role:: tuple-result + + +Full Flow +--------- + +Starting with ``raw_df`` data flows through buckaroo as follows. If one of the values on the right side of equals changes, all steps below that are executed + +The final result of `widget` is what is displayed to the user. + + + ++----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+ +|Destination |args | ++==============================================+=============================================================================================================================+ +|:dataflow-result:`sampled_df` |:class-state:`raw_df`, :ui-variable:`sample_method` | ++----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+ +|:dataflow-result:`cleaned` |:dataflow-arg:`sampled_df`, :ui-variable:`sample_method`, :ui-variable:`cleaning_method`, :ui-variable:`lowcode_ops` | ++----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+ +| |:tuple-result:`cleaned_df`, :tuple-result:`cleaned_sd`, :tuple-result:`generated_code` | ++----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+ +|:dataflow-result:`processed` |:dataflow-arg:`cleaned_df`, :ui-variable:`post_processing_method` | ++----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+ +| |:tuple-result:`processed_df`, :tuple-result:`processed_sd` | ++----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+ +|:dataflow-result:`summary_sd` |:dataflow-arg:`processed_df`, :class-state:`analysis_klasses` | ++----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+ +|:dataflow-result:`merged_sd` |:tuple-param:`cleaned_sd`, :dataflow-arg:`summary_sd`, :tuple-param:`processed_sd` | ++----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+ +|:dataflow-result:`widget` |:tuple-param:`processed_df`, :dataflow-arg:`merged_sd`, :ui-variable:`style_method`, :tuple-param:`generated_code` | ++----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+ + +.. graphviz:: dataflow.dot + + + +Glossary +........ + +#. :dataflow-result:`dataflow-result` are the result of a step. updates to this variable trigger steps that watch the variable as a dataflow arg +#. :dataflow-arg:`dataflow-arg` a dataflow-result used as a function argument. updates to this cause the current step to execute +#. :ui-variable:`UI-Variable` are specified in the UI, and can be changed interactively. updates to this cause the current step to execute +#. :class-state:`class-state` are defined at class instantiation time, these can be customized, but not interactively +#. :tuple-result:`named-tuple-result` Some results return as a tuple, the tuple is what is watched, the sub parts of the tuple can be referenced later +#. :tuple-param:`tuple-param` read this from the a named-tuple-result. do not watch this vriable (setting this named-tuple-result will not trigger this step) + + +.. graphviz:: glossary.dot + + +Quick Start to extending Buckaroo +--------------------------------- + +In this exercise we are going add a custom coloring method to Buckaroo. We will take an OHLCV dataframecolor and Volume based on the change from the previous day. + +First we need to craft the column config that will enable this conditonal coloring. + +We want to use `ColorFromColumn`, we want the config for the volume column to look like + +.. code-block:: python + + volume_config_override = { + 'color_map_config' : { + 'color_rule': 'color_from_column', + 'col_name': 'Volume_colors'}} + + +Using this in Buckaroo will look like this + +.. code-block:: python + + df = get_ohlcv("IBM") + df['Volume_colors'] = 'red' + BuckarooWidget(df, override_column_config={'Volume': volume_config_override}) + +This is a nice start. But now our analysis depends on remembering and typing specific config lines each time we want this display. + + +Buckaroo provides built in ways of handling this. + +First we want to use a `post_processing_function` to add the `volume_colors` column all of the time. And to make it condtional on change. we need to use `post_processing_function` because we specifically need to operate on the whole dataframe, not just a single column. + + +.. code-block:: python + + def volume_post(df): + if 'Volume' not in df.columns: + return [df, {}] + df['Volume_colors'] = 'red' # replace with actual red/green based on diff + extra_summary_dict = { + 'Volume' : { + 'column_config_override': { + 'color_map_config' : + {'color_rule': 'color_from_column', + 'col_name': 'Volume_colors'}}}, + 'Volume_colors' : { + 'column_config_override': { + 'displayer': 'hidden'}}} + return [df, extra_summary_dict] + + class OHLVCBuckarooWidget(BuckarooWidget): + post_processing_function=volume_post + OHLVCBuckarooWidget(get_ohlcv("IBM")) + + +Now when you instantiate `OHLVCBuckarooWidget` there will be a UI toggable function of `volume_post` so you can turn on and turn off this feature interactively. `OHLVCBuckarooWidget` has your own opinions baked in, that the user can turn on or off. + +What if we want to switch between red/green colors map and a color map based on size of diff to previous day? In this case we want to add two "style_methods" which are togglable in the UI. style_method takes a summary_dict and returns the column config. + + +.. code-block:: python + + def volume_post(df): + if 'Volume' not in df.columns: + return [df, {}] + df['Volume_colors'] = 'red' # replace with actual red/green based on diff + df['Volume_diff'] = df['Volume'].diff() + extra_summary_dict = { + 'Volume_colors' : { 'column_config_override': { 'displayer': 'hidden'}}, + 'Volume_diff' : { 'column_config_override': { 'displayer': 'hidden'}}} + return [df, extra_summary_dict] + + def volume_style_red_green(col_name, col_summary_dict, default_config): + if col_name == 'Volume': + return {'override': { + 'color_map_config' : {'color_rule': 'color_from_column', 'col_name': 'Volume_colors'}}} + return {} + + def volume_style_color_map(col_name, col_summary_dict, default_config): + if col_name == 'Volume': + return {'override': { + 'color_map_config' : {'color_rule': 'color_map', 'map_name': 'BLUE_TO_YELLOW', + 'val_column': 'Volume_diff'}}} + return {} + + class OHLVCBuckarooWidget(BuckarooWidget): + post_processing_function=volume_post + style_methods=[volume_style_red_green, volume_style_color_map] + OHLVCBuckarooWidget(get_ohlcv("IBM")) + + +With this implementation, the frontend can cycle through three style_methods `volume_style_red_green`, `volume_style_color_map` and `default` + + + + + + + diff --git a/docs/source/articles/dataflow.dot b/docs/source/articles/dataflow.dot new file mode 100644 index 000000000..7608928a2 --- /dev/null +++ b/docs/source/articles/dataflow.dot @@ -0,0 +1,145 @@ +digraph g { + compound=true; + newrank=true; + node [style=filled; ]; + +//define nodes or cluster then links to the next level +//level raw_df +raw_df [color="green"; shape="house" height=1.2] +sample_method [color="orange"]; + +{ + rank = same; + // Here you enforce the desired order with "invisible" edges and arrowheads + edge[ style=invis]; + raw_df -> sample_method; + rankdir = LR; +} + + raw_df -> sampled_df [weight=20]; + sample_method -> sampled_df; + +//sampled_df level +sampled_df [color="lightblue"; shape="house" height=1.2]; +cleaning_method [color="orange"]; +lowcode_ops [color="orange" ]; + +{ + rank = same; + edge[ style=invis]; + sampled_df -> cleaning_method -> lowcode_ops; + rankdir = LR; +} + cleaning_method -> cleaned_df [lhead=cluster_cleaned] + lowcode_ops -> cleaned_sd [lhead=cluster_cleaned] + +//cluster cleaned level + +subgraph cluster_cleaned { + label="cleaned"; + fillcolor="red"; + style=filled; + + cleaned_df [shape="house" height=1.2; ]; + cleaned_sd [shape="invtrapezium" height=1 width=.5 group="sd"]; + { + rank = same; + edge[ style=invis]; + cleaned_df -> cleaned_sd -> generated_code ; + rankdir = LR; + } +} + +//forces post_processing_method onto a separate line +cleaned_df -> post_processing_method[style=invis]; +post_processing_method [color="orange"]; + + +{ + rank = same; + edge[ style=invis]; + //foo -> post_processing_method; + //foo[style=invis] + rankdir = LR; +} + + sampled_df -> cleaned_df [lhead=cluster_cleaned; color="blueviolet"; + penwidth = 5; weight=60] + + post_processing_method -> processed_sd[headport="e" tailport="w" + lhead=cluster_processed]; + +//cluster_processed level +subgraph cluster_processed { + label="processed"; + fillcolor="red"; + style=filled; + processed_df [shape="house" height=1.2 group="summary"]; + processed_sd [shape="invtrapezium" height=1 width=.5 group="sd"]; + { + rank = same; + edge[ style=invis]; + processed_df -> processed_sd; + rankdir = LR; + } +} + + cleaned_df -> processed_df[ + lhead=cluster_processed; color="blueviolet"; weight=100; penwidth = 5; ]; + + + processed_df -> summary_sd [ color="blueviolet"; penwidth = 5; weight=6; + tailport="sw" weight=50] ; + + { + rank=same; + analysis_klasses [color="orange" group="summary"]; + summary_sd; + summary_sd -> analysis_klasses [style=invis;] + } + analysis_klasses -> summary_sd ; + + +summary_sd [color="lightblue" shape="invtrapezium" height=1 width=.5 group="summary"]; +//analysis_klasses [color="green"]; + + summary_sd -> merged_sd [color="blueviolet"; penwidth = 5; headport="nw" weight=60]; + processed_sd -> merged_sd [style="dashed" headport="ne" weight=40 penwidth=2.5]; + + cleaned_sd -> merged_sd [style="dashed" tailport="s" headport="e" weight=10 penwidth=2.5]; + +merged_sd [color="lightblue"; shape="invtrapezium" height=1 width=.5 group="sd"] +style_method [color="orange"]; + {rank=same; + node [style="invis"] + edge [style="invis" headport="s" tailport="s"] + merged_sd -> style_method; + + } + style_method -> widget ; + + processed_df -> widget [style="dashed" weight=2.8 tailport="w" penwidth=2.5]; + merged_sd -> widget [color="blueviolet"; penwidth = 5; ]; + + //merged_sd -> style_method[style=invis]; //forces style_method onto a separate rank + generated_code -> widget [style="dashed" penwidth=2.5; tailport="s" headport="e" samehead="right"]; + generated_code [shape="component"; ]; + + +widget [color="lightblue"]; + + + +// sampled_df -> widget [ style="dotted" penwidth=3 color="red" constraint=false ] +// cleaned_df -> widget [ style="dotted" penwidth=3 color="red" constraint=false ltail=cluster_cleaned ] +// processed_df -> widget [ style="dotted" penwidth=3 color="red" constraint=false ltail=cluster_processed ] +// summary_sd -> widget [ style="dotted" penwidth=3 color="red" constraint=false ] +// merged_sd -> widget [ style="dotted" penwidth=3 color="red" constraint=false ] + + + + +} + + + diff --git a/docs/source/articles/dev-notes.rst b/docs/source/articles/dev-notes.rst new file mode 100644 index 000000000..471fd96ee --- /dev/null +++ b/docs/source/articles/dev-notes.rst @@ -0,0 +1,12 @@ + + +The version of the js module in package.json must be greater than the pyproject.toml version. + +Otherwise you will see "Widget model not found errors" + + +use +``` +time npm run build:labextension:dev +``` +when developing, it enables source-maps and is much faster diff --git a/docs/source/articles/dont-use-df-head-buckaroo-instead.rst b/docs/source/articles/dont-use-df-head-buckaroo-instead.rst new file mode 100644 index 000000000..62be76b2d --- /dev/null +++ b/docs/source/articles/dont-use-df-head-buckaroo-instead.rst @@ -0,0 +1,44 @@ +.. Buckaroo documentation master file, created by + sphinx-quickstart on Wed Apr 19 14:07:15 2023. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Don't use df.head(), try buckaroo instead +========================================= + +* **Why using df.head() is an anti-pattern** + +In tutorials and common use, whenever we inspect a new dataset with pandas and jupyter, the first command is inevitably ``df.head()``. The next commands and cells dig into the contents of the dataframe. In a *more perfect world* we would just be typing ``df`` and seeing a rendered dataframe. Pandas has sensible defaults for its builtin table html rendering system that limits the number of rows and columns displayed in the interest of performance and visual compactness. Soon you find yourself playing with ``pd.options.display.(width|max_rows)`` and looking up sorting and filtering commands. Some might remember these commands off the top of their head, but even so, typing them repeatedly is slow and litters the notebook with temp work. Next you'll look up ``df.info()`` and ``df.describe()`` + + + +.. image:: https://raw.githubusercontent.com/paddymul/buckaroo-assets/main/quick-buckaroo.gif + :alt: df.head() vs buckaroo annotated walkthrough + :align: right + + + +* **Buckaroo fixes this intuitively** + + +With the new release of buckaroo, we can stop using ``df.head()``. I have worked to make Buckaroo usable as the default table visualization for pandas dataframes. It does this through sensible defaults and down sampling. All columns are shown, if there are less than 10,000 rows, all rows are shown. If there are more than 10,000 rows, sampling is turned on. But not just any sampling, sampling that also includes the 5 largest and smallest values of each column. At this point you will have around 10k rows in the interactive widget, which can be sorted by any column. Summary stats are a toggle away. + +Buckaroo is already the fastest table widget (comparison coming from my testing) for the jupyter notebook. Being fast isn't just a bragging rights matter. To be usable as the default dataframe display method, some performance guarantees are necessary. Having your kernel lock up for 30 seconds or longer is unacceptable. So the system has to make some decisions for you. this is why sampling is automatically turned on for larger datasets. + +* **Common manipulations are also quickly available** + +Finally the Buckaroo command UI is available with a single click. The command interface allows you to iterate through normal data cleaning operations with a GUI… while generating python code to perform the operations in a function. Want to drop a column, click the column then the "dropcol" button. + +* **What this means for your workflows** + +When I worked with a trading desk at a hedge fund, every time I would show analysts a model the first thing they wanted to do was look at the raw and intermediate data. I would say "well obviously because of this command, the column will have these values”, the response would come "SHOW ME THE DATA". Many times the analyst was right. This key part of any analysis workflow is made unnecessarily difficult, partly because of tooling, partly because of calluses built up from the pain of tooling that doesn't support the workflow. + +When working with data we are constantly doing exploratory data analysis, when you transform a dataframe with code, you should explore the resulting dataframe. Our tools should help that process, buckaroo does. You can just visualize data frames and all of their important attributes with a single command. This encourages you to look at the data instead of making assumptions about it. This also leads to less cluttered notebooks. + +* **Planned developments for the default table experience** + +The biggest feature in this area is making the summary stats and column reordering algorithms pluggable. This will speed up my own development of features. I also want to to experiment with running the initial analysis in a separate thread, dynamically sizing the sample size, this way I can ensure that the table always loads in a reasonable and tunable timeframe. I will also be adding unit tests and integrating it with the pluggable stats algorithms (run a series of tests over user supplied summary stats to check for exceptions). There are also performance improvements, histograms, automatic column grouping, column reordering, and group colors coming. + +* **Try Buckaroo** + +Install buckaroo with ``pip install buckaroo`` then import it into your notebook with ``import buckaroo``. Buckaroo becomes the default dataframe viewer. Give it a try and reach out about what you think. diff --git a/docs/source/articles/glossary.dot b/docs/source/articles/glossary.dot new file mode 100644 index 000000000..a04c1433e --- /dev/null +++ b/docs/source/articles/glossary.dot @@ -0,0 +1,57 @@ +digraph g { + compound=true; + ratio = fill; + k=.8 + node [style=filled]; + +subgraph cluster_variables { + label="Variable types"; + instance_var [color="green";] + dataflow_variable [color="lightblue"] + ui_variable [color="orange"]; + } + instance_var -> dataframe [fconstraint=false style="invis" weight=10] + + +subgraph cluster_types { + label="Types"; + dataframe [shape="house" height=1 width=.5]; + summary_dict [shape="invtrapezium" height=1 width=.5]; +} + +summary_dict -> foo [fconstraint=false style="invis"] + +subgraph cluster_blah { + label="Named Tuple"; + fillcolor="red"; + style=filled; + foo + bar + baz + } + + foo -> c [ style="invis"] + + +subgraph cluster_edges { + landscape=true + packmode=10 + label="Edges"; + c -> d [penwidth = 5; color="blueviolet"; + label=" data-flow changes trigger recomputation" ]; + + e -> f [ constraint=false + label=" changes to ui-variables trigger recomputation too" ] + + a -> b [ style="dashed" penwidth=2.5 weight=10 + label=" read-only,\n does not trigger recompute"]; + + function -> widget [ + style="dotted" penwidth=3 color="red" + label="error-flow \n data-flow steps skipped" ] + e [color="orange"]; + c [color="lightblue"] + } + +} + diff --git a/docs/source/articles/histograms.rst b/docs/source/articles/histograms.rst new file mode 100644 index 000000000..1edf602f4 --- /dev/null +++ b/docs/source/articles/histograms.rst @@ -0,0 +1,79 @@ +.. _using: + +========== +Histograms +========== + +Buckaroo uses histograms to convey the general shape of a colum in the minimum amount of screen real estate. Like the rest of buckaroo, this is an opionated feature that can be overridden with your own preferences. + + +Interpreting Buckaroo histograms by example +============================== +Histograms in buckaroo are designed to give you a rough understanding of the distribution of values in a column at a glance. This can tell you important things like "is this an ID column?" "is this a categorical column". The following pictures give some context. + + +Common patterns +--------------- + +.. image:: ../_static/histograms-common.png + :alt: Most common histograms +This picture shows 5 common column types. + + +* ``normal`` shows a numerical column with random (unordered) values from the standard distribution +* ``exponential`` shows a numerical column with random unorderd values from the exponential distribution +* ``increasing`` shows all numbers from 1 to 2000 ordered. +* ``one`` shows a column where every value is "1". This is displayed in pink with a pattern because the histogram treats it as a categorical histogram even though it is a numerical column +* ``all_unique_cat`` shows the histogram for a string column where each value is different. This is a categorical histogram + + +Categorical patterns +-------------------- + +Buckaroo has special colors and patterns for categorical type columns. Categoricals are always displayed in decreasing order with the most frequent value on the left. There are other special columns. Unique and longtail are stacked. Longtail is the sum of occurences of every value that is not unique, and is not one of the 7 most frequent categories. Unique is the bar for values that occur only once. + + +.. image:: ../_static/histograms-categorical-1.png + :alt: Most common histograms + + +Numeric columns with less than 5 values are treated as categoricals. The thinking was that a limited number of values in a numeric column probably represented some type of flag field, and not a true measurement. + +* ``all_NA`` has only NA/NaN values. The red cross hatch takes up the entire histogram area +* ``half_NA`` has half NA values and the other half is filled with ``1``. +* ``longtail`` has 80% longtail values and 20% NA +* ``longtail_unique`` has half longtail values and half unique values. Note that the bars are stacked + + +Numeric patterns +---------------- + + +Numeric histograms work mostly as expected. One thing to note, there is a separate bar for the 1st and last percentile of values. This filters out extreme values and gives much more resolution to the middle 98% of data. With such a small area, this seemed like the best approach. + + +.. image:: ../_static/histograms-numeric.png + :alt: Most common histograms + +* ``bimodal`` shows a bimodal distribution +* ``Exp`` shows an exponential distribution +* ``geometric`` shows a geometric distribution. Note that this is very difficult to decipher from an exponential distribution, probably due to outlier filters and limited resolution. + + + + +Other research +============== + +https://edwinth.github.io/blog/outlier-bin/ + + +references + + Boris Iglewicz and David Hoaglin (1993), "Volume 16: How to Detect and + Handle Outliers", The ASQC Basic References in Quality Control: + Statistical Techniques, Edward F. Mykytka, Ph.D., Editor. + + + + diff --git a/docs/source/articles/index.rst b/docs/source/articles/index.rst new file mode 100644 index 000000000..2264a168a --- /dev/null +++ b/docs/source/articles/index.rst @@ -0,0 +1,22 @@ +.. Buckaroo documentation master file, created by + sphinx-quickstart on Wed Apr 19 14:07:15 2023. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Articles +======== +Articles about Buckaroo can be found here. It was more expedient to use Read The Docs for a common blog task than dealing with medium paywalls or yet another devops struggle. + + +.. toctree:: + :glob: + + .//* + + + + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` +* `Buckaroo on github `_ diff --git a/docs/source/articles/pluggable.rst b/docs/source/articles/pluggable.rst new file mode 100644 index 000000000..23b43ec23 --- /dev/null +++ b/docs/source/articles/pluggable.rst @@ -0,0 +1,70 @@ +.. _using: + +============================ +Pluggable analysis framework +============================ + + +The pluggable analysis framework is built to make it easy to add custom analysis to table applications built with Buckaroo. It powers summary stats and styling for buckaroo. + +Why +--- +when writing analysis code, I frequently wrote code that iterated over columns and built a resulting summary dataframe. This is initially simple. First you write transformations inline, then you probably iterate over functions that operate on each column. Eventually this type of code becomes difficult to maintain. A single error is hard to track down because it will be in the middle of nested for loops. For pandas in particular you face the problem of either repeating expenesive analyses over and over (value counts) or depending on state in an adhoc way. Your simple functions become complex and dependent on order of execution. + + +How +--- + +The pluggable analysis framework improves these problems by + +#. Writing analysis into classes that extend `ColAnalysis` +#. Requiring each analysis class to recieve previously computed values, specify which keys it depends on, and specify keys it provides along with defaults +#. Ordering analysis classes into a DAG so users don't have to manually order dependent classes. If the DAG contains cycles or the required keys aren't provided, an error is thrown before execution with a more understandable message. +#. If an error occurs during excution, sensible error messages are displayed along with explicit steps to reproduce. No more navigating through nested for loop stack traces and wondering what the state passed into functions was. + +There are 3 main areas that the pluggable analysis framework is responsible for powering + +#. Summary stats. A dictionary of measures about each column. These can be independently computed on a per column basis. +#. Column styling. This is a function that takes the "required" measures about an individual column and returns a column_config. Once again this can be computed indepently per column. Styling also can generally be agnostic to pandas vs polars, as long as the other analysis classes provide similar measures +#. Transform functions. Transform functions operate on the entire dataframe, and return extra summary_stats. This is the only place you can operate on related columns. + +Methods to override +=================== + +* Pandas / Polars specific methods to produce raw facts (covered separately) +* ``style_column`` return a column_config given column_metadata +* ``post_process_df`` modify the entire dataframe + +Properties to override +====================== + +* ``post_processing_method`` name of the post_processing function for display in the UI +* ``pinned_rows`` Ordered list of pinned_row configs that will be show before any main data +* ``df_display_name`` Name of the display view that is visible in the UI +* ``data_key`` Which key to read the non_pinned rows from, use "main" or "empty" + +Shared Summary stats properties +=============================== + +* ``requires_summary`` a list of keys that must be provided for this analysis to compute +* ``provides_defaults`` a dictionary from measure_key to measure of defaults that this analysis provides +* ``computed_summary`` passed the dictionary of measures, returns extra measures computed off of these, will include any measures computed by series_summary + +Pandas specific methods +======================= +1. ``series_summary`` Passed the series and sampled series, returns a dictionary of measures +The `extending-pandas `_ notebook shows all of these methods being used + +Polars specific methods +======================= +1. ``select_clauses`` A list of polars expressions to be called on the dataframe. Try to use this as much as possible, select queries are optimized heavily by polars. +2. ``column_ops`` a dictionary from measure_key to tuple of polars selector, and a function to apply to the polars series object of each matching series. There are some polars operations that only can be called on series and not executed as a select query. + +The `extending-polars `_ notebook shows all of these methods being used + + +Future Improvements +=================== + +1. Future releases of Buckaroo should include pydantic for better typing of summary stats methods +2. Better error messages. The error messages in pluggable analysis framework seek to give you a one line reproduction fo the error found. through some refactorings, the method names have changed. diff --git a/docs/source/articles/related_projects.rst b/docs/source/articles/related_projects.rst new file mode 100644 index 000000000..d501a001b --- /dev/null +++ b/docs/source/articles/related_projects.rst @@ -0,0 +1,51 @@ +.. _using: + +Related projects +================ + +Other jupyter widgets +--------------------- + +There are a couple of projects like Buckaroo that aim to provide a better table widget and pandas editing experience. + +#. `Mito `_. Source Available table/code editing widget for Jupyter. More aimed at easing transition to pandas from excel users. GNU Affero licensed +#. `Microsoft DataWrangler `_ . Closed source, provides a very similar experience inside of VSCode's notebook experience. Only works inside of VSCode by the `VS Marketplace Terms of Use `_ +#. `IpyDatagrid `_. Open source. Bloomberg's Jupyter table widget. I used the ipydatagrid repo structure as the basis for buckaroo (js build setup only) +#. `IPyAgGrid `_ . Open source. Wraps `AG Grid `_ in a jupyter widget. Buckaroo also uses AG Grid. +#. `Bamboolib `_ An originally open source tool aimed at building a similar experience, more aimed as a low-code tool for beginners. The parent company 8080labs was acquired by Databricks. Code no longer available. +#. `QGrid `_. Open source, unmaintained. A slick table widget built by Quantopian, no code gen or data manipulation features + + +To be clear, I had the idea for building Buckaroo like this before I saw any of the other projects... But they are all open source and we can learn from each other. If Buckaroo doesn't quite do what you want, check out one of the others. + + +Other exploratory data analysis tools +-------------------------------------- + +These tools are aimed at doing more comprehensive stastical analysis of data + +#. `Dtale `_ +#. `YData profiling `_ + + +Other data tables +----------------- + +#. `ITables `_ focusses on well styled static tables for Pandas/Jupyter +#. `PrettyTables.jl `_ A terminal/text only table for julia. Wildly ambitious for pushing the limits on terminal UI. + +Other js data tables +-------------------- + +JS Table widgets. These are the core interactive tables that modern table expereinces are built around. A lot of engineering goes into making a web browser handle large scrolling tables performantly + +#. `AG-Grid `_ The most popular high performance JS data table in use. Buckaroo is built on top of the open source version of AG-Grid. The closed source version offers additional features. +#. `Finos Perspective table `_ The highest performance JS Table that I have seen. Works via a complete rendering engine that writes pixels to a canvas. Open source. +#. `Glide Data grid `_ Relatively new. Claims to be doing canvas rendering. Looks impressive and fast, less features than AG-Grid. Developed as a side project from a VC funded pre-revenue company, longterm future isn't certain. + + +Why list potential competitors +------------------------------ + +Software is complex, picking open source packages is difficult, even understanding the landscape of possible solutions is difficult. If you landed on this page, and Buckaroo doesn't suit your needs, hopefully ony of these great other projects will. + diff --git a/docs/source/articles/roadmap.rst b/docs/source/articles/roadmap.rst new file mode 100644 index 000000000..bae2ccf00 --- /dev/null +++ b/docs/source/articles/roadmap.rst @@ -0,0 +1,132 @@ +.. _using: + +======= +Roadmap +======= + +Buckaroo is maturing and I decided to write a roadmap + + +Priorities +========== + +Buckaroo is still for the most part, pre-users. It is maturing though, and feedback gathered can map some reasonable principles + +* Function as a reliable replacement for the default display of dataframes + + * Exceptions in the basic display of a dataframe are a P1 error. + * Dataframes that don't display are a P1 error. + * Taking more than a second to display a dataframe with less than 1M values is a P2 error + +* Buckaroo should do the least surprising thing. + + * autocleaning should be turned off by default. + +* Bug/feature request priorities + + * This is the roadmap and I'll stick with it. + * If a user has a feature/bug request, and that is preventing them from using Buckaroo, that gets priority. + + +Release Plans +============= + + +0.4 Series +---------- + + +#. Documentation + + * Readme refresh + * How to create a formatter + * Pluggable analysis framework refresh + * Customizing autocleaning + * Customizing enable/instantiation + * Order of operations Dataflow doc +#. Promotion +#. Devops improvements (CI, testing, end to end testing, packaging) + + * CI passing - Done + * CI testing - Done + * End to End testing - Done + * CI version Bump - needed + * Ruff python linter - needed +#. Jupyter notebook compatability + + * Google colab - Done + * VSCode - Done + * Warning message on notebook < 7 - Done + * Notebook 6.0 compatability ??? +#. Code cleanup + + * Typescript passes linter - Done + * snake_case camelCase normalization + * better naming + * sub module organization +#. Python Repr bugs + + * List + * Tuple + * Nested list and tuple across python types (int, float, boolean) + * Dictionary? +#. Formatters + + * DateTime formatter + * Float formatter with specificity +#. Frontend + + * Autoclean toggle + + +0.5 series +---------- +I'm a bit fuzzy on this one, it's either going to be a backend port to polars or filtering. I'll write it as filtering for now + +#. Filtering + + * any field text search + * Should work with codegen + * Per column exact filtering +#. Additional sampling techniques + + * Chunks (50 contiguous rows) + * Outliers - extent percentile for each colum all in a single view + * Straight random sample +#. UI cycling + + * Everything that is now binary (summary stats on or off), is actually a single choice of multiple possible choices. Allow multiple clicks to cycle through different options. + * Enable cycling for summary_stats and sample method +#. Low code UI + + * Add Commands for filtering + +0.6 series +---------- +Polars backend + +All of the same tests should pass. + +#. Lowcode UI Commands in polars + + * Gives auto cleaning and filtering at much higher performance. Nice way to dip my feet into polars. + * Testing that verifies ``eval(_to_py) == transform(df)`` and ``pl.transform(df) == pd.transform(df)`` + * pandas and polars equivalence is key to code gen continuing to be useful +#. Serialization in polars + + * 2x speed bump + * straight forward +#. Pluggable analysis framework - for polars + + * Same pluggable analysis framework, now lazy + * Summary stats run on whole dataframe - up to 1Gig + +0.7 series +---------- + +#. serialization speedup + + * integrate parquest_wasm in the frontend + * parquet serialization on the backend + * maintain json serialization + diff --git a/docs/source/conf.py b/docs/source/conf.py index b1a397471..9a3181956 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -5,11 +5,13 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +import json -project = 'DCEF' -copyright = '2023, Paddy Mullen' +project = 'Buckaroo' +copyright = '2023-2024, Paddy Mullen' author = 'Paddy Mullen' -release = '0.2' +release = json.loads(open("../../package.json").read())['version'] + # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration @@ -26,3 +28,10 @@ html_theme = 'alabaster' html_static_path = ['_static'] + + +extensions = [ + # … + 'sphinx.ext.graphviz', +] +graphviz_output_format = 'svg' diff --git a/docs/source/contributing.rst b/docs/source/contributing.rst new file mode 100644 index 000000000..508509ef3 --- /dev/null +++ b/docs/source/contributing.rst @@ -0,0 +1,99 @@ +.. _Contributing: + +======================== +Contributing to Buckaroo +======================== + +Buckaroo is actively looking for contributors. All forms of participation are welcome, from bug reports, to suggestions, to code contributions. + + +Developing in the Jupyter Lab environment +========================================= + +The easiest way to develop and contribute to Buckaroo is to add ``Commands``. When I use Buckaroo to clean and explore a new dataset, I firt try to use the built in Buckaroo commands in the UI. When I want to perform a manipulation that doesn't yet exist in Buckaroo, I first drop down to raw pandas/python like I would before Buckaroo... Then I figure out how to expose that functionality as a ``Command``. While working with manatee data, I recognized that a column was probably date times, but a ``to_datetime`` ``Command`` didn't exist. So I wrote one. + +.. code-block:: python + + pd.to_datetime(df['REPDATE']).head() + #outputs -> + #0 1974-04-03 00:00:00+00:00 + #1 1974-06-27 00:00:00+00:00 + #Name: REPDATE, dtype: datetime64[ns, UTC] + + #pd.to_datetime is the transform I want... so I write it as a Command + #and add it to the w widget with the @w.add_command decorator + @w.add_command + class to_datetime(Command): + command_default = [s('to_datetime'), s('df'), "col"] + command_pattern = [None] + + @staticmethod + def transform(df, col): + df[col] = pd.to_datetime(df[col]) + return df + + @staticmethod + def transform_to_py(df, col): + return " df['%s'] = pd.to_datetime(df['%s'])" % (col, col) + + +When you use the ``add_command`` decorator, the command is instantly added to the UI of the corresponding widget. Subsequent re-evalutations of the same cell, will replace a ``Command`` in the widget with the same name. This allows you to iteratively develop commands. + +Once you have developed a ``Command`` you can either continue to use it internally as with the ``add_command`` decorator or you can open a PR and add it to the builtin commands for Buckaroo `all_transforms.py `_. + +The upside of just using the @add_command decorator is that you don't have to setup a development environment. + +Setting up a development environment +==================================== + +First, you need to fork the project. Then setup your environment: + +.. code-block:: bash + + # create a new conda environment + conda create -n buckaroo-dev jupyterlab pandas nodejs yarn pip + conda activate buckaroo-dev + pip install build twine + + # download buckaroo from your GitHub fork + git clone https://github.com//buckaroo.git + # or start by cloning the main repo + git clone https://github.com/paddymul/buckaroo.git + + # install JS dependencies and build js assets + cd buckaroo + yarn install + + # install Buckaroo in editable mode + python -m pip install -ve . + + #in another shell, setup the typescript watcher + conda activate buckaroo-dev + yarn build && yarn watch + #this will build the jupyter lab extension, and recompile on any code changes + + #start your jupyter lab server in another shell + conda activate buckaroo-dev + jupyter lab + + #work on your jupyter notebook from that lab server + +.. note:: + Getting typescript updates from the widget into a jupyter lab notebook is a little tricky. The following steps ensure that typescript code changes are picked up. + + + +Loading typescript changes +========================== + +I make my changes, confirm that ``yarn watch`` has successfully compiled them. **then** I follow these steps to ensure the new code is loaded + +#. Go to the jupyter lab notebook in a browser +#. Click the Kernel Menu > Restart Kernel and Clear all outputs +#. Save the notebook +#. Reload the web browser +#. Execute the relevant cells + +It is sometimes helpful to put a console.log in ``js/plugin.ts`` and check that the updated log statement shows up in the browser to make sure you are executing the code you think you are. + + diff --git a/docs/source/feature_reference.rst b/docs/source/feature_reference.rst new file mode 100644 index 000000000..b3181f3af --- /dev/null +++ b/docs/source/feature_reference.rst @@ -0,0 +1,67 @@ +.. _Feature_reference: + +================= +Feature Reference +================= + +Full App Diagram +================ +.. image:: _static/Buckaroo-labled.png + :width: 281 + :alt: Full widget + + +Status Bar Features +=================== +The status bar is displayed above every table, it allows quick toggling of different UI modes + +.. image:: _static/Statusbar.png + :alt: Status Bar + + +Σ Summary Statistics +-------------------- + +To View Summary Statistics click on the ``Σ`` cell . When the value below is ``1``, the summary stats view will be show in the table. + +λ Command Editting Mode +----------------------- + +To turn on Command Editting mode, click on the ``λ`` cell. This will bring up the command UI and the transformed dataframe view + +Ξ Sampled Data Mode +------------------- + +When a dataframe has more than 10k rows, Bucakroo inteligently downsamples the dataframe to only 10k rows + extents for each column. Sometimes you want to see the entire dataframe, toggling the ``Ξ`` cell enables this. Turning off sampling for large datasets can cause the table to take a long time to render, so use with caution. + +? Help +------ + +Click the ``?`` cell to display this document. + + +Other Features +============== + + +Sort by a column +---------------- + +To sort the dataframe by any column, click on the header for that column, sorting will cycle through ``ascending``, ``descending`` and ``off`` + +Operations UI +------------- + +The operations UI allows quick manipulation of dataframes. Commands operate on columns. First click on the column you want to operate on, then click on the command. This command will be added to the "operations" list. Some commands take extra arguments (fillna, groupby) and these must be provided via the UI. The transformed dataframe is instantly updated below. Further you can click the ``python`` tab to see generated python code that will perform the same transform. + +Disabling Dataframe Autodisplay +------------------------------- + +When you run ``import buckaroo`` the Buckaroo widget is automatically registered with the jupyter notebook as the default display mechanism for objects of type ``pd.DataFrame``. Occasionally you will run into bugs with Buckaroo, that prevent the table from working. Please file a bug at `Buckaroo issues `_ . You can restore the default pandas behavior with + +.. code-block:: python + + import buckaroo + buckaroo.disable() + + diff --git a/docs/source/index.rst b/docs/source/index.rst index d3403cab4..e85d446d6 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,32 +1,36 @@ -.. DCEF documentation master file, created by +.. Buckaroo documentation master file, created by sphinx-quickstart on Wed Apr 19 14:07:15 2023. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -DCEF - Data Cleaning Exploration Framework -========================================== -DCEF is a tool to quickly clean and explore DataFrames with a visual UI for common cleaning operations AND emitting python code that performs the transformation. +Buckaroo - The Data Cleaning assistant for pandas +================================================= +Buckaroo is a tool to quickly clean and explore DataFrames with a visual UI for common cleaning operations AND emitting python code that performs the transformation. -We all know how awkward it is to clean data in jupyter notebooks. Multiple cells of exploratory work, trying different transforms, looking up different transforms, adhoc functions that work in one notebook and have to be either copied/pasta-ed to the next notebook, or rewritten from scratch. DCEF aims to massively speed up that process. +We all know how awkward it is to clean data in jupyter notebooks. Multiple cells of exploratory work, trying different transforms, looking up different transforms, adhoc functions that work in one notebook and have to be either copied/pasta-ed to the next notebook, or rewritten from scratch. Buckaroo aims to massively speed up that process. -.. raw:: html +**Install Buckaroo**:: + + pip install buckaroo - +.. raw:: html + -.. note:: - This project is under active development. .. toctree:: :maxdepth: 2 - :caption: Contents: + :caption: Sitemap: using + feature_reference install + contributing FAQ + articles/index Indices and tables ================== @@ -34,4 +38,5 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` -* `DCEF on github `_ + +* `Buckaroo on github `_ diff --git a/docs/source/install.rst b/docs/source/install.rst index d7e3c3894..b850cbae0 100755 --- a/docs/source/install.rst +++ b/docs/source/install.rst @@ -1,13 +1,13 @@ .. _install: -================ -Installing DCEF -================ +=================== +Installing Buckaroo +=================== -DCEF can be installed from ``PyPI``: +Buckaroo can be installed from ``PyPI``: .. code-block:: bash - pip install dcef + pip install buckaroo -Once dcef is installed, it can be used as a a Jupyter Lab extension. See :ref:`using` for information on how to use dcef +Once Buckaroo is installed, it can be used as a a Jupyter Lab extension. See :ref:`using` for information on how to use Buckaroo. diff --git a/docs/source/using.rst b/docs/source/using.rst index c77674c3f..66d5de5bf 100644 --- a/docs/source/using.rst +++ b/docs/source/using.rst @@ -1,14 +1,14 @@ .. _using: -=========== -Using DCEF -=========== +============== +Using Buckaroo +============== -DCEF is meant to be used in a jupyterlab notebook to clean and explore pandas dataframes. +Buckaroo is meant to be used in a jupyterlab notebook to clean and explore pandas dataframes. Before you begin, make sure that you follow the steps in :ref:`install`. -The following sections cover how to use DCEF. +The following sections cover how to use Buckaroo. In a Jupyter Lab notebook cell @@ -16,16 +16,16 @@ In a Jupyter Lab notebook cell .. code-block:: python - from dcef.dcef_widget import DCEFWidget - DCEFWidget(df=df) #df being the dataframe you want to explore + from buckaroo.buckaroo_widget import BuckarooWidget + BuckarooWidget(df=df) #df being the dataframe you want to explore -And you will see the UI for DCEF. +And you will see the UI for Buckaroo. Using Commands ============== -At the core DCEF commands operate on columns. You must first click on a cell (not a header) in the top pane to select a column. +At the core Buckaroo commands operate on columns. You must first click on a cell (not a header) in the top pane to select a column. Next you must click on a command like ``dropcol``, ``fillna``, or ``groupby`` to create a new command @@ -37,7 +37,7 @@ Writing your own commands ========================= -Builtin commands are found in `all_transforms.py `_ +Builtin commands are found in `all_transforms.py `_ .. code-block:: python @@ -59,3 +59,39 @@ Builtin commands are found in `all_transforms.py { + + const conf: Configuration = { + entry: './docs/examples/index-react18.tsx', + //...(env.production || !env.development ? {} : {devtool: 'eval-source-map'}), + devtool: 'eval-source-map', + resolve: { + alias: { + 'buckaroo': path.resolve(__dirname, '../js') + }, + extensions: ['.ts', '.tsx', '.js'], + //TODO waiting on https://github.com/dividab/tsconfig-paths-webpack-plugin/issues/61 + //@ts-ignore + plugins: [new TsconfigPathsPlugin()] + }, + output: { + path: path.join(__dirname, '/build/html/examples'), + filename: 'bundle.js' + }, + // https://github.com/TypeStrong/ts-loader/issues/751 + ignoreWarnings: [{message: /export .* was not found in/}], + module: { + rules: [ + { + test: /\.tsx?$/, + loader: 'ts-loader', + options: { + transpileOnly: true, + configFile: 'docs/examples_tsconfig.json' + } + }, + { + test: /\.css$/, + use: [ + //isDev ? 'style-loader' : MiniCssExtractPlugin.loader, + 'style-loader', + 'css-loader', + { + loader: 'postcss-loader', + options: { + postcssOptions: { + plugins: ['postcss-nested'] + } + } + } + ] + }, + { + test: /\.scss$/, + use: [ + // We're in dev and want HMR, SCSS is handled in JS + // In production, we want our css as files + "style-loader", + "css-loader", + { + loader: "postcss-loader", + options: { + postcssOptions: { + plugins: [ + ["postcss-preset-env"], + ], + }, + }, + }, + "sass-loader" + ], + }, + { + test: /\.svg$/, + loader: 'svg-url-loader' + }, + { + test: /\.md$/, + use: ['html-loader', 'markdown-loader'] + } + ] + }, + plugins: [ + new HtmlWebpackPlugin({ + template: './docs/examples/index.html' + }), + new webpack.DefinePlugin({ + process: { + env: { + DEBUG: !env.production || env.development + } + }, + VERSION: JSON.stringify(require('../package.json').version), + MAPBOX_TOKEN: JSON.stringify(process.env.MAPBOX_TOKEN) + }) + ], + devServer: { + port: 8030 + } + }; + + + // if (!env.development) { + // conf.plugins.push( + // new ForkTsCheckerWebpackPlugin({ + // eslint: { + // files: './{js,docs/examples}/**/*.{ts,tsx,js}' + // } + // }) + // ); + // } + + + return conf; +}; + +export default webpackConfig; diff --git a/example-notebooks/DFViewer.ipynb b/example-notebooks/DFViewer.ipynb new file mode 100644 index 000000000..ab0578eb9 --- /dev/null +++ b/example-notebooks/DFViewer.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e95ac3e5-4532-4aad-9ad1-4096d0e2d631", + "metadata": {}, + "source": [ + "# DFViewer\n", + "\n", + "The DFViewerWidget allows you to display a dataframe like the the full BuckarooWidget, without any extra UI options.\n", + "\n", + "This works particularly well for embedding Buckaroo into widget or dashboarding frameworks like Solara" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c0150f9f-0fb0-487f-88ad-9c495c406e59", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "from buckaroo import DFViewer" + ] + }, + { + "cell_type": "markdown", + "id": "acea57ee-06b6-4244-b6d4-fa14a8747e94", + "metadata": {}, + "source": [ + "# Using the default DFViewer is straightforward" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "db41edd1-0569-4cb4-b95a-aaf82e854903", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "df = pd.DataFrame({'a':[10, 20, 339, 887], 'b': ['foo', 'bar', None, 'baz']})\n", + "DFViewer(df)" + ] + }, + { + "cell_type": "markdown", + "id": "fabc0d41-9343-463e-b2f5-b43671a1d7e2", + "metadata": {}, + "source": [ + "## Removing pinned_rows" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4887466f-afaa-4adc-809a-bb4bdf064d17", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "DFViewer(df, pinned_rows=[])" + ] + }, + { + "cell_type": "markdown", + "id": "fa8be87e-3b64-44e4-acda-76bba7566990", + "metadata": {}, + "source": [ + "## It works with polars too" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "566d9cc1-c1bb-431b-bbab-776e029adebc", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import polars as pl\n", + "from buckaroo.polars_buckaroo import PolarsDFViewer\n", + "pl_df = pl.DataFrame({'a':[10, 20, 339, 887], 'b': ['foo', 'bar', None, 'baz']})\n", + "PolarsDFViewer(pl_df)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/example-notebooks/Exception-Traits-demo.ipynb b/example-notebooks/Exception-Traits-demo.ipynb new file mode 100644 index 000000000..d8d621c1d --- /dev/null +++ b/example-notebooks/Exception-Traits-demo.ipynb @@ -0,0 +1,216 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "54685928-3f8c-430e-b270-09e51949997f", + "metadata": {}, + "source": [ + "# Demo of the trait exception rewriting\n", + "\n", + "Traitlets results in very long stacktraces. Look at the difference between these two stack traces.\n", + "\n", + "Watch this space, These stacktraces still aren't great, but they are much better" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "3ba20b97-144d-459a-8217-f9e1793acbc7", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import sys\n", + "from traitlets import Unicode, Any, observe, HasTraits, Dict\n", + "import six" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "091125db-b117-4b92-b1d4-231c54a8b1ea", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "ename": "ZeroDivisionError", + "evalue": "division by zero", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[2], line 28\u001b[0m\n\u001b[1;32m 25\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcompute_second\u001b[39m(\u001b[38;5;28mself\u001b[39m, val):\n\u001b[1;32m 26\u001b[0m \u001b[38;5;241m1\u001b[39m\u001b[38;5;241m/\u001b[39m\u001b[38;5;241m0\u001b[39m\n\u001b[0;32m---> 28\u001b[0m ErrorSecond(\u001b[38;5;241m5\u001b[39m)\n", + "Cell \u001b[0;32mIn[2], line 8\u001b[0m, in \u001b[0;36mDumbBase.__init__\u001b[0;34m(self, val)\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__init__\u001b[39m(\u001b[38;5;28mself\u001b[39m, val):\n\u001b[1;32m 7\u001b[0m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39m\u001b[38;5;21m__init__\u001b[39m()\n\u001b[0;32m----> 8\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfirst_trait \u001b[38;5;241m=\u001b[39m val\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/traitlets/traitlets.py:729\u001b[0m, in \u001b[0;36mTraitType.__set__\u001b[0;34m(self, obj, value)\u001b[0m\n\u001b[1;32m 727\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m TraitError(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mThe \u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m trait is read-only.\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;241m%\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mname)\n\u001b[1;32m 728\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 729\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mset(obj, value)\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/traitlets/traitlets.py:718\u001b[0m, in \u001b[0;36mTraitType.set\u001b[0;34m(self, obj, value)\u001b[0m\n\u001b[1;32m 714\u001b[0m silent \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 715\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m silent \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m 716\u001b[0m \u001b[38;5;66;03m# we explicitly compare silent to True just in case the equality\u001b[39;00m\n\u001b[1;32m 717\u001b[0m \u001b[38;5;66;03m# comparison above returns something other than True/False\u001b[39;00m\n\u001b[0;32m--> 718\u001b[0m obj\u001b[38;5;241m.\u001b[39m_notify_trait(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mname, old_value, new_value)\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/traitlets/traitlets.py:1503\u001b[0m, in \u001b[0;36mHasTraits._notify_trait\u001b[0;34m(self, name, old_value, new_value)\u001b[0m\n\u001b[1;32m 1500\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_notify_trait\u001b[39m(\u001b[38;5;28mself\u001b[39m, name, old_value, new_value):\n\u001b[1;32m 1501\u001b[0m \u001b[38;5;66;03m# print(\"name\", name, \"old_value\", old_value)\u001b[39;00m\n\u001b[1;32m 1502\u001b[0m \u001b[38;5;66;03m# try:\u001b[39;00m\n\u001b[0;32m-> 1503\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnotify_change(\n\u001b[1;32m 1504\u001b[0m Bunch(\n\u001b[1;32m 1505\u001b[0m name\u001b[38;5;241m=\u001b[39mname,\n\u001b[1;32m 1506\u001b[0m old\u001b[38;5;241m=\u001b[39mold_value,\n\u001b[1;32m 1507\u001b[0m new\u001b[38;5;241m=\u001b[39mnew_value,\n\u001b[1;32m 1508\u001b[0m owner\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 1509\u001b[0m \u001b[38;5;28mtype\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mchange\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 1510\u001b[0m )\n\u001b[1;32m 1511\u001b[0m )\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/traitlets/traitlets.py:1519\u001b[0m, in \u001b[0;36mHasTraits.notify_change\u001b[0;34m(self, change)\u001b[0m\n\u001b[1;32m 1517\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mnotify_change\u001b[39m(\u001b[38;5;28mself\u001b[39m, change):\n\u001b[1;32m 1518\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Notify observers of a change event\"\"\"\u001b[39;00m\n\u001b[0;32m-> 1519\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_notify_observers(change)\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/traitlets/traitlets.py:1566\u001b[0m, in \u001b[0;36mHasTraits._notify_observers\u001b[0;34m(self, event)\u001b[0m\n\u001b[1;32m 1563\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(c, EventHandler) \u001b[38;5;129;01mand\u001b[39;00m c\u001b[38;5;241m.\u001b[39mname \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 1564\u001b[0m c \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mgetattr\u001b[39m(\u001b[38;5;28mself\u001b[39m, c\u001b[38;5;241m.\u001b[39mname)\n\u001b[0;32m-> 1566\u001b[0m c(event)\n", + "Cell \u001b[0;32mIn[2], line 15\u001b[0m, in \u001b[0;36mDumbBase.handle_first\u001b[0;34m(self, change)\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[38;5;129m@observe\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mfirst_trait\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 14\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mhandle_first\u001b[39m(\u001b[38;5;28mself\u001b[39m, change):\n\u001b[0;32m---> 15\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msecond_trait \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcompute_first(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfirst_trait)\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/traitlets/traitlets.py:729\u001b[0m, in \u001b[0;36mTraitType.__set__\u001b[0;34m(self, obj, value)\u001b[0m\n\u001b[1;32m 727\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m TraitError(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mThe \u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m trait is read-only.\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;241m%\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mname)\n\u001b[1;32m 728\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 729\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mset(obj, value)\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/traitlets/traitlets.py:718\u001b[0m, in \u001b[0;36mTraitType.set\u001b[0;34m(self, obj, value)\u001b[0m\n\u001b[1;32m 714\u001b[0m silent \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 715\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m silent \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m 716\u001b[0m \u001b[38;5;66;03m# we explicitly compare silent to True just in case the equality\u001b[39;00m\n\u001b[1;32m 717\u001b[0m \u001b[38;5;66;03m# comparison above returns something other than True/False\u001b[39;00m\n\u001b[0;32m--> 718\u001b[0m obj\u001b[38;5;241m.\u001b[39m_notify_trait(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mname, old_value, new_value)\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/traitlets/traitlets.py:1503\u001b[0m, in \u001b[0;36mHasTraits._notify_trait\u001b[0;34m(self, name, old_value, new_value)\u001b[0m\n\u001b[1;32m 1500\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_notify_trait\u001b[39m(\u001b[38;5;28mself\u001b[39m, name, old_value, new_value):\n\u001b[1;32m 1501\u001b[0m \u001b[38;5;66;03m# print(\"name\", name, \"old_value\", old_value)\u001b[39;00m\n\u001b[1;32m 1502\u001b[0m \u001b[38;5;66;03m# try:\u001b[39;00m\n\u001b[0;32m-> 1503\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnotify_change(\n\u001b[1;32m 1504\u001b[0m Bunch(\n\u001b[1;32m 1505\u001b[0m name\u001b[38;5;241m=\u001b[39mname,\n\u001b[1;32m 1506\u001b[0m old\u001b[38;5;241m=\u001b[39mold_value,\n\u001b[1;32m 1507\u001b[0m new\u001b[38;5;241m=\u001b[39mnew_value,\n\u001b[1;32m 1508\u001b[0m owner\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 1509\u001b[0m \u001b[38;5;28mtype\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mchange\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 1510\u001b[0m )\n\u001b[1;32m 1511\u001b[0m )\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/traitlets/traitlets.py:1519\u001b[0m, in \u001b[0;36mHasTraits.notify_change\u001b[0;34m(self, change)\u001b[0m\n\u001b[1;32m 1517\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mnotify_change\u001b[39m(\u001b[38;5;28mself\u001b[39m, change):\n\u001b[1;32m 1518\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Notify observers of a change event\"\"\"\u001b[39;00m\n\u001b[0;32m-> 1519\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_notify_observers(change)\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/traitlets/traitlets.py:1566\u001b[0m, in \u001b[0;36mHasTraits._notify_observers\u001b[0;34m(self, event)\u001b[0m\n\u001b[1;32m 1563\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(c, EventHandler) \u001b[38;5;129;01mand\u001b[39;00m c\u001b[38;5;241m.\u001b[39mname \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 1564\u001b[0m c \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mgetattr\u001b[39m(\u001b[38;5;28mself\u001b[39m, c\u001b[38;5;241m.\u001b[39mname)\n\u001b[0;32m-> 1566\u001b[0m c(event)\n", + "Cell \u001b[0;32mIn[2], line 22\u001b[0m, in \u001b[0;36mDumbBase.handle_second\u001b[0;34m(self, change)\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[38;5;129m@observe\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124msecond_trait\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 21\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mhandle_second\u001b[39m(\u001b[38;5;28mself\u001b[39m, change):\n\u001b[0;32m---> 22\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mthird_trait \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcompute_second(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msecond_trait)\n", + "Cell \u001b[0;32mIn[2], line 26\u001b[0m, in \u001b[0;36mErrorSecond.compute_second\u001b[0;34m(self, val)\u001b[0m\n\u001b[1;32m 25\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcompute_second\u001b[39m(\u001b[38;5;28mself\u001b[39m, val):\n\u001b[0;32m---> 26\u001b[0m \u001b[38;5;241m1\u001b[39m\u001b[38;5;241m/\u001b[39m\u001b[38;5;241m0\u001b[39m\n", + "\u001b[0;31mZeroDivisionError\u001b[0m: division by zero" + ] + } + ], + "source": [ + "class DumbBase(HasTraits):\n", + " first_trait = Any()\n", + " second_trait = Any()\n", + " third_trait = Any()\n", + "\n", + " def __init__(self, val):\n", + " super().__init__()\n", + " self.first_trait = val\n", + " \n", + " def compute_first(self, val):\n", + " return val\n", + " \n", + " @observe('first_trait')\n", + " def handle_first(self, change):\n", + " self.second_trait = self.compute_first(self.first_trait)\n", + "\n", + " def compute_second(self, val):\n", + " return val\n", + " \n", + " @observe('second_trait')\n", + " def handle_second(self, change):\n", + " self.third_trait = self.compute_second(self.second_trait)\n", + "\n", + "class ErrorSecond(DumbBase):\n", + " def compute_second(self, val):\n", + " 1/0\n", + " \n", + "ErrorSecond(5)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "1876620c-eb2c-4bdc-8a90-761c51a9a77b", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "self.exception (, ZeroDivisionError('division by zero'), )\n" + ] + }, + { + "ename": "ZeroDivisionError", + "evalue": "division by zero", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[4], line 50\u001b[0m\n\u001b[1;32m 48\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcompute_second\u001b[39m(\u001b[38;5;28mself\u001b[39m, val):\n\u001b[1;32m 49\u001b[0m \u001b[38;5;241m1\u001b[39m\u001b[38;5;241m/\u001b[39m\u001b[38;5;241m0\u001b[39m\n\u001b[0;32m---> 50\u001b[0m ab \u001b[38;5;241m=\u001b[39m ErrorSecondSmart(\u001b[38;5;241m5\u001b[39m)\n\u001b[1;32m 51\u001b[0m ab\n", + "Cell \u001b[0;32mIn[4], line 25\u001b[0m, in \u001b[0;36mSmartBase.__init__\u001b[0;34m(self, val)\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mself.exception\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexception)\n\u001b[1;32m 24\u001b[0m exc, exc1, tb \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexception\n\u001b[0;32m---> 25\u001b[0m six\u001b[38;5;241m.\u001b[39mreraise(exc, exc1, tb)\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/six.py:718\u001b[0m, in \u001b[0;36mreraise\u001b[0;34m(tp, value, tb)\u001b[0m\n\u001b[1;32m 716\u001b[0m value \u001b[38;5;241m=\u001b[39m tp()\n\u001b[1;32m 717\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m value\u001b[38;5;241m.\u001b[39m__traceback__ \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m tb:\n\u001b[0;32m--> 718\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m value\u001b[38;5;241m.\u001b[39mwith_traceback(tb)\n\u001b[1;32m 719\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m value\n\u001b[1;32m 720\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n", + "Cell \u001b[0;32mIn[4], line 42\u001b[0m, in \u001b[0;36mSmartBase.handle_second\u001b[0;34m(self, change)\u001b[0m\n\u001b[1;32m 38\u001b[0m \u001b[38;5;129m@observe\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124msecond_trait\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 39\u001b[0m \u001b[38;5;129m@exception_protect\u001b[39m\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mhandle_second\u001b[39m(\u001b[38;5;28mself\u001b[39m, change):\n\u001b[1;32m 41\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m---> 42\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mthird_trait \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcompute_second(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msecond_trait)\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 44\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexception \u001b[38;5;241m=\u001b[39m sys\u001b[38;5;241m.\u001b[39mexc_info()\n", + "Cell \u001b[0;32mIn[4], line 49\u001b[0m, in \u001b[0;36mErrorSecondSmart.compute_second\u001b[0;34m(self, val)\u001b[0m\n\u001b[1;32m 48\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcompute_second\u001b[39m(\u001b[38;5;28mself\u001b[39m, val):\n\u001b[0;32m---> 49\u001b[0m \u001b[38;5;241m1\u001b[39m\u001b[38;5;241m/\u001b[39m\u001b[38;5;241m0\u001b[39m\n", + "\u001b[0;31mZeroDivisionError\u001b[0m: division by zero" + ] + } + ], + "source": [ + "def exception_protect(func):\n", + " def wrapped(self, *args, **kwargs):\n", + " try:\n", + " func(self, *args, **kwargs)\n", + " except Exception as e:\n", + " if self.exception is None:\n", + " self.exception = sys.exc_info()\n", + " raise\n", + " return wrapped\n", + "\n", + "class SmartBase(HasTraits):\n", + " first_trait = Any()\n", + " second_trait = Any()\n", + " third_trait = Any()\n", + "\n", + " def __init__(self, val):\n", + " super().__init__()\n", + " self.exception = None\n", + " try:\n", + " self.first_trait = val\n", + " except Exception as e:\n", + " # print(\"e\", sys.exc_info())\n", + " print(\"self.exception\", self.exception)\n", + " exc, exc1, tb = self.exception\n", + " six.reraise(exc, exc1, tb)\n", + " \n", + " def compute_first(self, val):\n", + " return val\n", + " \n", + " @observe('first_trait')\n", + " @exception_protect\n", + " def handle_first(self, change):\n", + " self.second_trait = self.compute_first(self.first_trait)\n", + "\n", + " def compute_second(self, val):\n", + " return val\n", + " \n", + " @observe('second_trait')\n", + " @exception_protect\n", + " def handle_second(self, change):\n", + " try:\n", + " self.third_trait = self.compute_second(self.second_trait)\n", + " except Exception as e:\n", + " self.exception = sys.exc_info()\n", + " raise\n", + "\n", + "class ErrorSecondSmart(SmartBase):\n", + " def compute_second(self, val):\n", + " 1/0\n", + "ab = ErrorSecondSmart(5)\n", + "ab" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "48b4e65c-8ac9-487b-9e9e-7cb5e9dd4fb1", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/example-notebooks/Extending-pandas.ipynb b/example-notebooks/Extending-pandas.ipynb new file mode 100644 index 000000000..c54fddd00 --- /dev/null +++ b/example-notebooks/Extending-pandas.ipynb @@ -0,0 +1,422 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4d39f5cc-7791-4e90-8108-60752647487c", + "metadata": {}, + "source": [ + "# Extending Buckaroo for pandas\n", + "Buckaroo is built for exploratory data analysis on unknown data. Data in the wild is incredibly varied and so are the ways of visualizing it. Most table tools are built around allowing a single bespoke customization, with middle of the road defaults. Buckaroo takes a different approach. Buckaroo lets you build many highly specific configurations and then toggle between them quickly. This makes it easier to build each configuration because you don't have to solve for every possibility.\n", + "\n", + "This document walks you through how to add your own analysis to Buckaroo and allow users to toggle it\n", + "\n", + "The extension points are\n", + "* [PluggableAnalysisFramework](https://buckaroo-data.readthedocs.io/en/latest/articles/pluggable.html) Used to add summary stats and column metadata for use by other steps\n", + "* [Styling](./styling-howto.ipynb) control the visual display of the table\n", + "* PostProcessing used to transform an entire dataframe\n", + "* AutoCleaning Automate transformations for dropping nulls, removing outliers and other pre-processing steps, cleans the dataframe and generates python code. Not yet supported in 0.6\n", + "\n", + "Each extension point is composable, and can be interactively mixed and matched" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73f3516e-2273-495a-b3b9-f68593b0018b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from buckaroo.dataflow.dataflow_extras import StylingAnalysis\n", + "from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import ColAnalysis\n", + "from buckaroo import BuckarooWidget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45a03efb-ec32-4cda-b443-99425e80a458", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ROWS = 200\n", + "typed_df = pd.DataFrame({'int_col':np.random.randint(1,50, ROWS), 'float_col': np.random.randint(1,30, ROWS)/.7,\n", + " 'timestamp':[\"2020-01-01 01:00Z\", \"2020-01-01 02:00Z\", \"2020-02-28 02:00Z\", \"2020-03-15 02:00Z\", None] * 40,\n", + " \"str_col\": [\"foobar\", \"Realllllly long string\", \"\", None, \"normal\"]* 40})\n", + "typed_df['timestamp'] = pd.to_datetime(typed_df['timestamp'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8086b3b9-f97e-4b4c-9c0a-85566be060a3", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "bw = BuckarooWidget(typed_df)\n", + "bw" + ] + }, + { + "cell_type": "markdown", + "id": "85054e95-edc2-4842-994d-3f6131660a8e", + "metadata": {}, + "source": [ + "# Using the Pluggable Analysis Framework\n", + "\n", + "The PAF allows users to add summary analysis that runs for every dataframe, and exposes created measures to subsequent steps.\n", + "There are implementations for pandas and polars. Individual analysis classes cna depend on other calsess that provide measures, the framwork ensures that they are excecuted in the correct order.\n", + "\n", + "These measures form the column metadata used by styling, and the summary information used for pinned rows.\n", + "\n", + "You can read more here\n", + "\n", + "* https://github.com/paddymul/buckaroo/blob/main/tests/unit/analysis_management_test.py\n", + "* https://github.com/paddymul/buckaroo/blob/main/buckaroo/customizations/analysis.py\n", + "\n", + "The following cell adds a 99th quintile measure and displays it." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "912b478d-bd67-4bb8-a31d-a5f8e95f8f40", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class Quin99Analysis(StylingAnalysis):\n", + " provides_defaults = {'quin99': None}\n", + "\n", + " @staticmethod\n", + " def series_summary(sampled_ser, ser):\n", + " if pd.api.types.is_numeric_dtype(ser) and not pd.api.types.is_bool_dtype(ser):\n", + " return dict(\n", + " quin99=ser.quantile(.99))\n", + " return {}\n", + " \n", + " pinned_rows = [{'primary_key_val': 'quin99', 'displayer_args': {'displayer': 'obj' }}]\n", + " df_display_name = 'quin99'\n", + " data_key = \"empty\" # the non pinned rows will pull from the empty dataframe\n", + "\n", + "pbw = BuckarooWidget(typed_df)\n", + "pbw.add_analysis(Quin99Analysis)\n", + "pbw" + ] + }, + { + "cell_type": "markdown", + "id": "05ecd1e4-1bde-48ce-ac51-bf53f7bb91c4", + "metadata": {}, + "source": [ + "# Adding a styling analysis\n", + "The `StylingAnalysis` class is used to control the display of a column based on the column metadata. \n", + "\n", + "\n", + "Overriding the `config_from_column_metadata(col:str, sd:SingleColumnMetadata) -> ColumnConfig` computes the config for a single column given that column's metadata.\n", + "\n", + "This lets you customize based on metadata collected about a column. This works with the [PluggableAnalysisFramework](https://buckaroo-data.readthedocs.io/en/latest/articles/pluggable.html), you can specify required fields that are necessary. Adding requirements like this guarantees that errors are spotted early.\n", + "\n", + "The same StylingAnalysis class can generally work for both Polars and Pandas because it only receives a dictionary with simple python values.\n", + "\n", + "The following cell defines two StylingAnalysis, one that shows great detail `everything` the other shows shortened versions `Abrev`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c03b5bc4-0025-4b55-9e7c-cc1a69508688", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class EverythingStyling(StylingAnalysis):\n", + " \"\"\"\n", + " This styling shows as much detail as possible\n", + " \"\"\"\n", + " df_display_name = \"Everything\"\n", + " requires_summary = [\"histogram\", \"is_numeric\", \"dtype\", \"_type\"]\n", + " pinned_rows = [{'primary_key_val': 'dtype', 'displayer_args': {'displayer': 'obj' }}]\n", + "\n", + " #Styling analysis handles column iteration for us.\n", + " @classmethod\n", + " def style_column(kls, col:str, column_metadata):\n", + " digits = 10\n", + " t = column_metadata['_type']\n", + " if column_metadata['is_integer']:\n", + " disp = {'displayer': 'float', 'min_fraction_digits':0, 'max_fraction_digits':0}\n", + " elif column_metadata['is_numeric']:\n", + " disp = {'displayer': 'float', 'min_fraction_digits':digits, 'max_fraction_digits':digits} \n", + " elif t == 'temporal':\n", + " disp = {'displayer': 'datetimeLocaleString','locale': 'en-US', 'args': {}}\n", + " elif t == 'string':\n", + " disp = {'displayer': 'string', 'max_length': 100}\n", + " else:\n", + " disp = {'displayer': 'obj'}\n", + " return {'col_name':col, 'displayer_args': disp }\n", + "\n", + "class AbrevStyling(StylingAnalysis):\n", + " \"\"\"This styling shows shortened versions of columns \"\"\"\n", + " requires_summary = [\"histogram\", \"is_numeric\", \"dtype\", \"_type\"]\n", + " df_display_name = \"Abrev\"\n", + " pinned_rows = []\n", + "\n", + " @classmethod\n", + " def style_column(kls, col:str, column_metadata):\n", + " digits = 3\n", + " t = column_metadata['_type']\n", + " if column_metadata['is_integer']:\n", + " disp = {'displayer': 'float', 'min_fraction_digits':0, 'max_fraction_digits':0}\n", + " elif column_metadata['is_numeric']:\n", + " disp = {'displayer': 'float', 'min_fraction_digits':digits, 'max_fraction_digits':digits}\n", + " elif t == 'temporal':\n", + " disp = {'displayer': 'datetimeLocaleString','locale': 'en-US', 'args': {}}\n", + " elif t == 'string':\n", + " disp = {'displayer': 'string', 'max_length':10}\n", + " else:\n", + " disp = {'displayer': 'obj'}\n", + " return {'col_name':col, 'displayer_args': disp }\n", + "\n", + "sbw = BuckarooWidget(typed_df)\n", + "sbw.add_analysis(EverythingStyling)\n", + "sbw.add_analysis(AbrevStyling)\n", + "sbw" + ] + }, + { + "cell_type": "markdown", + "id": "a3116fa5-174e-4c67-98d7-dd33dc9b2275", + "metadata": {}, + "source": [ + "Let's look at pinned_rows, they can be modified by setting `pinned_rows` on Buckaroo Instaniation" + ] + }, + { + "cell_type": "markdown", + "id": "be8c2eb7-a791-46f8-b3b4-62f596799b21", + "metadata": {}, + "source": [ + "# lets add a post processing method" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c2088225-051e-4cd7-b353-03df60124cc2", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "bw = BuckarooWidget(typed_df[:5]) #this throws a bunch of warnings\n", + "@bw.add_processing\n", + "def transpose(df):\n", + " return df.transpose()\n", + "bw" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "708da9e2-6311-4755-a3af-38afcaa49a3d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class ValueCountPostProcessing(ColAnalysis):\n", + " @classmethod\n", + " def post_process_df(kls, df):\n", + " dfs = []\n", + " for c in df.columns:\n", + " vc = df[c].value_counts()\n", + " if len(vc) > 10:\n", + " vc = vc.iloc[:10]\n", + " tdf = pd.DataFrame({'%s_vals' %c:vc.index.values, '%s_counts'% c:vc.values})\n", + " tdf.reindex(pd.RangeIndex(10))\n", + " dfs.append(tdf)\n", + " return [pd.concat(dfs, axis=1), {}]\n", + " post_processing_method = \"value_counts\"\n", + "\n", + "class ShowErrorsPostProcessing(ColAnalysis):\n", + " @classmethod\n", + " def post_process_df(kls, df):\n", + " tdf = df.copy()\n", + " tdf['errored_float'] = \"some error\"\n", + " tdf.loc[typed_df['float_col'].lt(20) == False, 'errored_float'] = None\n", + " extra_column_config = {\n", + " 'float_col': {'column_config_override': {\n", + " 'color_map_config': {\n", + " 'color_rule': 'color_not_null',\n", + " 'conditional_color': 'red',\n", + " 'exist_column': 'errored_float'},\n", + " 'tooltip_config': { 'tooltip_type':'simple', 'val_column': 'errored_float'}}},\n", + " 'errored_float': {'column_config_override': {'merge_rule': 'hidden'}}}\n", + " return (tdf, extra_column_config)\n", + " post_processing_method = \"show_errors\"\n", + "\n", + "# In this case we are going to extend BuckarooWidget so we can take this combination with us\n", + "base_a_klasses = BuckarooWidget.analysis_klasses.copy()\n", + "base_a_klasses.extend([ValueCountPostProcessing, \n", + " ShowErrorsPostProcessing])\n", + "class VCBuckarooWidget(BuckarooWidget):\n", + " analysis_klasses = base_a_klasses\n", + "vcb = VCBuckarooWidget(typed_df, debug=False)\n", + "vcb" + ] + }, + { + "cell_type": "markdown", + "id": "8f2a47ec-0067-4e10-ac6d-d45c46ed6171", + "metadata": {}, + "source": [ + "## Where to use PostProcessing\n", + "Post processing functions are no argument transformations. I can't think of a lot of generic whole dataframe operations.\n", + "\n", + "`ValueCount` and `Transpose` are generic. `ShowErrors` depends on two specific columns.\n", + "\n", + "I expect Post processing to be very useful for small custom apps built on top of Buckaroo. When you know the columns and you want a strict set of transforms, PostProcessing is a great fit.\n", + "\n", + "\n", + "\n", + "Post processing is also useful when combined with a preprocessing function to compare DataFrames\n", + "\n", + "Here is some pseudo code\n", + "```python\n", + "class ComparePost(ColAnalysis):\n", + "\n", + " @classmethod\n", + " def post_process_df(kls, df):\n", + " df1,df2 = split_columns(\"|\")\n", + " compare_df = run_compare(df1, df2)\n", + " return [compare_df, {}]\n", + " post_processing_method = 'compare'\n", + " \n", + "class CompareWidget(BuckarooWidget):\n", + " analysis_klasses = [ComparePost]\n", + " \n", + "def compare(df1, df2):\n", + " joined = pd.concat([prefix_columns(df1, 'df1|'), prefix_columns(df2, 'df21|')])\n", + " return CompareWidget(joined)\n", + "\n", + "#run this by the following command\n", + "compare(sales_march_2022_df, sales_march_2023_df)\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "1a9e4db3-82ca-4478-ab87-0e29cccdf108", + "metadata": {}, + "source": [ + "# Putting it all together\n", + "\n", + "You can compose (combine) the PluggableAnalysisFramework, PostProcessing and Styling into a single widget. And you can manipulate PostProcessing separately from Styling." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d8ccbb77-5cc1-4501-bb84-45480d1213ad", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from buckaroo.customizations.analysis import (TypingStats, ComputedDefaultSummaryStats, DefaultSummaryStats)\n", + "from buckaroo.customizations.histogram import (Histogram)\n", + "from buckaroo.customizations.styling import DefaultSummaryStatsStyling, DefaultMainStyling\n", + "\n", + "class KitchenSinkWidget(BuckarooWidget):\n", + " #let's be explicit here and show all of the built in analysis klasses\n", + " analysis_klasses = [\n", + " TypingStats, DefaultSummaryStats,\n", + " Histogram, ComputedDefaultSummaryStats,\n", + " # default buckaroo styling\n", + " DefaultSummaryStatsStyling, DefaultMainStyling,\n", + " # our Quin99 analysis\n", + " Quin99Analysis, # adds a styling method\n", + " #our PostProcessing classes\n", + " ValueCountPostProcessing, ShowErrorsPostProcessing,\n", + " #our styling methods\n", + " EverythingStyling, AbrevStyling]\n", + "ksw = KitchenSinkWidget(typed_df)\n", + "ksw" + ] + }, + { + "cell_type": "markdown", + "id": "c83014fe-7a61-415d-862d-b7b055b2835e", + "metadata": {}, + "source": [ + "# Why aren't there click handlers?\n", + "\n", + "Buckaroo doesn't allow arbitrary click handlers and this is by design. When you allow arbitrary click handlers, you then have to manage state. If you have noticed, every method of extending buckaroo is a pure function. Managing application state is difficult and the primary source of errors when building GUIs.\n", + "\n", + "Buckaroo is designed purely around displaying DataFrames along with the most common operations that are performed on DataFrames. If you want more traditional app experiences, right now you can use IPYWidgets and integrate buckaroo into it. Soon I will be releasing the DFViewer (core component that shows the table) for Streamlit and Solara." + ] + }, + { + "cell_type": "markdown", + "id": "e19b6de0-5684-4f0e-b821-dd3ba1198e72", + "metadata": {}, + "source": [ + "# What about autocleaning and the low code UI\n", + "\n", + "Auto cleaning and the low code UI work together for more fine grained editting of data. The low code UI presents a gui that works on columns and allows functions with arguments. \n", + "\n", + "Auto cleaning works to suggest operations that are then loaded into the low code ui. Then these operations can be editted or removed.\n", + "Auto cleaning options can be cycled through to generate different cleanings.\n", + "\n", + "## Why did this release remove auto cleaning and the low code UI?\n", + "\n", + "Although auto cleaning and the low code UI is my favorite feature of Buckaroo, and the first part I built, it hasn't seemed to have gained traction with users. Buckaroo for that matter hasn't gained a lot of traction. For the time being I have decided to put more effort into refining and promoting the parts of Buckaroo that people do understand. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "db2eb990-b6b0-47aa-b7ca-2fe40b9dcebe", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/example-notebooks/Extending.ipynb b/example-notebooks/Extending.ipynb new file mode 100644 index 000000000..e2b0662d3 --- /dev/null +++ b/example-notebooks/Extending.ipynb @@ -0,0 +1,441 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4d39f5cc-7791-4e90-8108-60752647487c", + "metadata": {}, + "source": [ + "# Extending Buckaroo\n", + "Buckaroo is built for exploratory data analysis on unknown data. Data in the wild is incredibly varied and so are the ways of visualizing it. Most table tools are built around allowing a single bespoke customization, with middle of the road defaults. Buckaroo takes a different approach. Buckaroo lets you build many highly specific configurations and then toggle between them quickly. This makes it easier to build each configuration because you don't have to solve for every possibility.\n", + "\n", + "This document walks you through how to add your own analysis to Buckaroo and allow users to toggle it\n", + "\n", + "The extension points are\n", + "* [PluggableAnalysisFramework](https://buckaroo-data.readthedocs.io/en/latest/articles/pluggable.html) Used to add summary stats and column metadata for use by other steps\n", + "* [Styling](./styling-howto.ipynb) control the visual display of the table\n", + "* PostProcessing used to transform an entire dataframe\n", + "* AutoCleaning Automate transformations for dropping nulls, removing outliers and other pre-processing steps, cleans the dataframe and generates python code. Not yet supported in 0.6\n", + "\n", + "Each extension point is composable, and can be interactively mixed and matched" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73f3516e-2273-495a-b3b9-f68593b0018b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from buckaroo.dataflow.dataflow_extras import StylingAnalysis\n", + "from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import ColAnalysis\n", + "import polars as pl\n", + "from polars import functions as F\n", + "from buckaroo.polars_buckaroo import PolarsBuckarooWidget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45a03efb-ec32-4cda-b443-99425e80a458", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ROWS = 200\n", + "typed_df = pl.DataFrame({'int_col':np.random.randint(1,50, ROWS), 'float_col': np.random.randint(1,30, ROWS)/.7,\n", + " 'timestamp':[\"2020-01-01 01:00Z\", \"2020-01-01 02:00Z\", \"2020-02-28 02:00Z\", \"2020-03-15 02:00Z\", None] * 40,\n", + " \"str_col\": [\"foobar\", \"Realllllly long string\", \"\", None, \"normal\"]* 40})\n", + "typed_df = typed_df.with_columns(timestamp=pl.col('timestamp').str.to_datetime() )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8086b3b9-f97e-4b4c-9c0a-85566be060a3", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pbw = PolarsBuckarooWidget(typed_df)\n", + "pbw" + ] + }, + { + "cell_type": "markdown", + "id": "85054e95-edc2-4842-994d-3f6131660a8e", + "metadata": {}, + "source": [ + "# Using the Pluggable Analysis Framework\n", + "\n", + "The PAF allows users to add summary analysis that runs for every dataframe, and exposes created measures to subsequent steps.\n", + "There are implementations for pandas and polars. Individual analysis classes cna depend on other calsess that provide measures, the framwork ensures that they are excecuted in the correct order.\n", + "\n", + "These measures form the column metadata used by styling, and the summary information used for pinned rows.\n", + "\n", + "You can read more here\n", + "\n", + "* https://github.com/paddymul/buckaroo/blob/main/tests/unit/polars_analysis_management_test.py\n", + "* https://github.com/paddymul/buckaroo/blob/main/buckaroo/customizations/polars_analysis.py\n", + "\n", + "The following cell adds a 99th quintile measure and displays it." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "37f0be6a-e94d-4650-b11d-cf3418ff0944", + "metadata": {}, + "outputs": [], + "source": [ + "from buckaroo.pluggable_analysis_framework.utils import (json_postfix)\n", + "import polars.selectors as cs\n", + "class Quin99Analysis(StylingAnalysis):\n", + " select_clauses = [\n", + " cs.numeric().quantile(.99).name.map(json_postfix('quin99'))]\n", + " \n", + " pinned_rows = [{'primary_key_val': 'quin99', 'displayer_args': {'displayer': 'obj' }}]\n", + " df_display_name = 'quin99'\n", + " data_key = \"empty\" # the non pinned rows will pull from the empty dataframe\n", + "\n", + "sbw = PolarsBuckarooWidget(typed_df)\n", + "sbw.add_analysis(Quin99Analysis)\n", + "sbw" + ] + }, + { + "cell_type": "markdown", + "id": "05ecd1e4-1bde-48ce-ac51-bf53f7bb91c4", + "metadata": {}, + "source": [ + "# Adding a styling analysis\n", + "The `StylingAnalysis` class is used to control the display of a column based on the column metadata. \n", + "\n", + "\n", + "Overriding the `config_from_column_metadata(col:str, sd:SingleColumnMetadata) -> ColumnConfig` computes the config for a single column given that column's metadata.\n", + "\n", + "This lets you customize based on metadata collected about a column. This works with the [PluggableAnalysisFramework](https://buckaroo-data.readthedocs.io/en/latest/articles/pluggable.html), you can specify required fields that are necessary. Adding requirements like this guarantees that errors are spotted early.\n", + "\n", + "The same StylingAnalysis class can generally work for both Polars and Pandas because it only receives a dictionary with simple python values.\n", + "\n", + "The following cell defines two StylingAnalysis, one that shows great detail `everything` the other shows shortened versions `Abrev`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c03b5bc4-0025-4b55-9e7c-cc1a69508688", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class EverythingStyling(StylingAnalysis):\n", + " \"\"\"\n", + " This styling shows as much detail as possible\n", + " \"\"\"\n", + " df_display_name = \"Everything\"\n", + " requires_summary = [\"histogram\", \"is_numeric\", \"dtype\", \"_type\"]\n", + " pinned_rows = [{'primary_key_val': 'dtype', 'displayer_args': {'displayer': 'obj' }}]\n", + "\n", + " #Styling analysis handles column iteration for us.\n", + " @classmethod\n", + " def style_column(kls, col:str, column_metadata):\n", + " digits = 10\n", + " t = column_metadata['_type']\n", + " if column_metadata['is_integer']:\n", + " disp = {'displayer': 'float', 'min_fraction_digits':0, 'max_fraction_digits':0}\n", + " elif column_metadata['is_numeric']:\n", + " disp = {'displayer': 'float', 'min_fraction_digits':digits, 'max_fraction_digits':digits} \n", + " elif t == 'temporal':\n", + " disp = {'displayer': 'datetimeLocaleString','locale': 'en-US', 'args': {}}\n", + " elif t == 'string':\n", + " disp = {'displayer': 'string', 'max_length': 100}\n", + " else:\n", + " disp = {'displayer': 'obj'}\n", + " return {'col_name':col, 'displayer_args': disp }\n", + "\n", + "class AbrevStyling(StylingAnalysis):\n", + " \"\"\"This styling shows shortened versions of columns \"\"\"\n", + " requires_summary = [\"histogram\", \"is_numeric\", \"dtype\", \"_type\"]\n", + " df_display_name = \"Abrev\"\n", + " pinned_rows = []\n", + "\n", + " @classmethod\n", + " def style_column(kls, col:str, column_metadata):\n", + " digits = 3\n", + " t = column_metadata['_type']\n", + " if column_metadata['is_integer']:\n", + " disp = {'displayer': 'float', 'min_fraction_digits':0, 'max_fraction_digits':0}\n", + " elif column_metadata['is_numeric']:\n", + " disp = {'displayer': 'float', 'min_fraction_digits':digits, 'max_fraction_digits':digits}\n", + " elif column_metadata['dtype'] == pl.Datetime:\n", + " disp = {'displayer': 'datetimeLocaleString','locale': 'en-US', 'args': {}}\n", + " elif column_metadata['dtype'] == pl.String:\n", + " disp = {'displayer': 'string', 'max_length':10}\n", + " else:\n", + " disp = {'displayer': 'obj'}\n", + " return {'col_name':col, 'displayer_args': disp }\n", + "\n", + "sbw = PolarsBuckarooWidget(typed_df)\n", + "sbw.add_analysis(EverythingStyling)\n", + "sbw.add_analysis(AbrevStyling)\n", + "sbw" + ] + }, + { + "cell_type": "markdown", + "id": "a3116fa5-174e-4c67-98d7-dd33dc9b2275", + "metadata": {}, + "source": [ + "Let's look at pinned_rows, they can be modified by setting `pinned_rows` on Buckaroo Instaniation" + ] + }, + { + "cell_type": "markdown", + "id": "be8c2eb7-a791-46f8-b3b4-62f596799b21", + "metadata": {}, + "source": [ + "# lets add a post processing method" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3ca85511-9a03-4477-aaf3-586947d8db02", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from polars import functions as F\n", + "from buckaroo.pluggable_analysis_framework.polars_analysis_management import PolarsAnalysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "49243e53-e52c-45d8-bcd7-ca98d05ced5a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#typed_df.select(F.all(), pl.col('float_col').lt(5).replace(True, \"foo\").replace(False, None).alias('errored_float'))[:3]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c2088225-051e-4cd7-b353-03df60124cc2", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "bw = PolarsBuckarooWidget(typed_df)\n", + "@bw.add_processing\n", + "def transpose(df):\n", + " return df.transpose()\n", + "bw" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0bdd2826-1716-4b88-b54d-74241f42549d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class ValueCountPostProcessing(PolarsAnalysis):\n", + " @classmethod\n", + " def post_process_df(kls, df):\n", + " result_df = df.select(\n", + " F.all().value_counts().implode().list.gather(pl.arange(0, 10), null_on_oob=True).explode().struct.rename_fields(['val', 'unused_count']).struct.field('val').prefix('val_'),\n", + " F.all().value_counts().implode().list.gather(pl.arange(0, 10), null_on_oob=True).explode().struct.field('count').prefix('count_'))\n", + " return [result_df, {}]\n", + " post_processing_method = \"value_counts\"\n", + "\n", + "class ShowErrorsPostProcessing(PolarsAnalysis):\n", + " @classmethod\n", + " def post_process_df(kls, df):\n", + " result_df = df.select(\n", + " F.all(),\n", + " pl.col('float_col').lt(20).replace(True, \"some error\").replace(False, None).alias('errored_float'))\n", + " extra_column_config = {\n", + " 'float_col': {'column_config_override': {\n", + " 'color_map_config': {\n", + " 'color_rule': 'color_not_null',\n", + " 'conditional_color': 'red',\n", + " 'exist_column': 'errored_float'},\n", + " 'tooltip_config': { 'tooltip_type':'simple', 'val_column': 'errored_float'}}},\n", + " 'errored_float': {'column_config_override': {'merge_rule': 'hidden'}}}\n", + " return (result_df, extra_column_config)\n", + " post_processing_method = \"show_errors\"\n", + "\n", + "# In this case we are going to extend PolarsBuckarooWidget so we can take this combination with us\n", + "base_a_klasses = PolarsBuckarooWidget.analysis_klasses.copy()\n", + "base_a_klasses.extend([ValueCountPostProcessing, \n", + " ShowErrorsPostProcessing])\n", + "class VCBuckarooWidget(PolarsBuckarooWidget):\n", + " analysis_klasses = base_a_klasses\n", + "vcb = VCBuckarooWidget(typed_df, debug=False)\n", + "vcb" + ] + }, + { + "cell_type": "markdown", + "id": "8f2a47ec-0067-4e10-ac6d-d45c46ed6171", + "metadata": {}, + "source": [ + "## Where to use PostProcessing\n", + "Post processing functions are no argument transformations. I can't think of a lot of generic whole dataframe operations.\n", + "\n", + "`ValueCount` and `Transpose` are generic. `ShowErrors` depends on two specific columns.\n", + "\n", + "I expect Post processing to be very useful for small custom apps built on top of Buckaroo. When you know the columns and you want a strict set of transforms, PostProcessing is a great fit.\n", + "\n", + "\n", + "\n", + "Post processing is also useful when combined with a preprocessing function to compare DataFrames\n", + "\n", + "Here is some pseudo code\n", + "```python\n", + "class ComparePost(ColAnalysis):\n", + "\n", + " @classmethod\n", + " def post_process_df(kls, df):\n", + " df1,df2 = split_columns(\"|\")\n", + " compare_df = run_compare(df1, df2)\n", + " return [compare_df, {}]\n", + " post_processing_method = 'compare'\n", + " \n", + "class CompareWidget(BuckarooWidget):\n", + " analysis_klasses = [ComparePost]\n", + " \n", + "def compare(df1, df2):\n", + " joined = pd.concat([prefix_columns(df1, 'df1|'), prefix_columns(df2, 'df21|')])\n", + " return CompareWidget(joined)\n", + "\n", + "#run this by the following command\n", + "compare(sales_march_2022_df, sales_march_2023_df)\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "1a9e4db3-82ca-4478-ab87-0e29cccdf108", + "metadata": {}, + "source": [ + "# Putting it all together\n", + "\n", + "You can compose (combine) the PluggableAnalysisFramework, PostProcessing and Styling into a single widget. And you can manipulate PostProcessing separately from Styling." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d8ccbb77-5cc1-4501-bb84-45480d1213ad", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from buckaroo.customizations.polars_analysis import (\n", + " VCAnalysis, BasicAnalysis, PlTyping,\n", + " HistogramAnalysis, ComputedDefaultSummaryStats)\n", + "from buckaroo.customizations.styling import DefaultSummaryStatsStyling, DefaultMainStyling\n", + "\n", + "class KitchenSinkWidget(PolarsBuckarooWidget):\n", + " #let's be explicit here and show all of the built in analysis klasses\n", + " analysis_klasses = [\n", + " # The default analysis methods for Polars\n", + " VCAnalysis, BasicAnalysis, PlTyping,\n", + " HistogramAnalysis, ComputedDefaultSummaryStats,\n", + " # default buckaroo styling\n", + " DefaultSummaryStatsStyling, DefaultMainStyling,\n", + " \n", + " # our Quin99 analysis\n", + " Quin99Analysis, # adds a styling method\n", + " #our PostProcessing classes\n", + " ValueCountPostProcessing, ShowErrorsPostProcessing,\n", + " #our styling methods\n", + " EverythingStyling, AbrevStyling]\n", + "ksw = KitchenSinkWidget(typed_df)\n", + "ksw" + ] + }, + { + "cell_type": "markdown", + "id": "c83014fe-7a61-415d-862d-b7b055b2835e", + "metadata": {}, + "source": [ + "# Why aren't there click handlers?\n", + "\n", + "Buckaroo doesn't allow arbitrary click handlers and this is by design. When you allow arbitrary click handlers, you then have to manage state. If you have noticed, every method of extending buckaroo is a pure function. Managing application state is difficult and the primary source of errors when building GUIs.\n", + "\n", + "Buckaroo is designed purely around displaying DataFrames along with the most common operations that are performed on DataFrames. If you want more traditional app experiences, right now you can use IPYWidgets and integrate buckaroo into it. Soon I will be releasing the DFViewer (core component that shows the table) for Streamlit and Solara." + ] + }, + { + "cell_type": "markdown", + "id": "e19b6de0-5684-4f0e-b821-dd3ba1198e72", + "metadata": {}, + "source": [ + "# What about autocleaning and the low code UI\n", + "\n", + "Auto cleaning and the low code UI work together for more fine grained editting of data. The low code UI presents a gui that works on columns and allows functions with arguments. \n", + "\n", + "Auto cleaning works to suggest operations that are then loaded into the low code ui. Then these operations can be editted or removed.\n", + "Auto cleaning options can be cycled through to generate different cleanings.\n", + "\n", + "## Why did this release remove auto cleaning and the low code UI?\n", + "\n", + "Although auto cleaning and the low code UI is my favorite feature of Buckaroo, and the first part I built, it hasn't seemed to have gained traction with users. Buckaroo for that matter hasn't gained a lot of traction. For the time being I have decided to put more effort into refining and promoting the parts of Buckaroo that people do understand. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "db2eb990-b6b0-47aa-b7ca-2fe40b9dcebe", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/example-notebooks/Full-tour.ipynb b/example-notebooks/Full-tour.ipynb new file mode 100644 index 000000000..6741809d9 --- /dev/null +++ b/example-notebooks/Full-tour.ipynb @@ -0,0 +1,283 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%pip install buckaroo[polars]\n", + "try:\n", + " from google.colab import output\n", + " output.enable_custom_widget_manager()\n", + "except Exception as e:\n", + " print(e)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## A simple DataFrame in Pandas" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "num_df = pd.DataFrame(\n", + " {'a':[111_111, 77_777, 777_777, 1_000_000, 2_111_111, 1_235_999],\n", + " 'b':[111_111, 555_555, 0, 28_123, 482_388, 5_666]})\n", + "num_df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import buckaroo\n", + "num_df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Demonstrating Buckaroo on Citibike data.\n", + "This might take a little time to download\n", + "\n", + "*once the view loads click 0's and 1's on the top left to toggle different parts of the UI*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "df = pd.read_csv(\"https://github.com/paddymul/buckaroo-data/raw/main/cb_data/2016-04.csv\")\n", + "#df = pd.read_parquet(\"https://github.com/paddymul/buckaroo-data/raw/main/cb_data/2016-04.parq\")\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Histograms\n", + "\n", + "Histograms are built into Buckaroo. They enable users to quickly identify distributions of data in columns" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#these are some utility functions for generating random distributions\n", + "#execute and ignore this cell\n", + "import numpy as np \n", + "def bimodal(mean_1, mean_2, N, sigma=5):\n", + " X1 = np.random.normal(mean_1, sigma, int(N/2))\n", + " X2 = np.random.normal(mean_2, sigma, int(N/2))\n", + " X = np.concatenate([X1, X2])\n", + " return X\n", + "\n", + "def rand_cat(named_p, na_per, N):\n", + " choices, p = [], []\n", + " named_total_per = sum(named_p.values()) + na_per\n", + " total_len = int(np.floor(named_total_per * N))\n", + " if named_total_per > 0:\n", + " for k, v in named_p.items():\n", + " choices.append(k)\n", + " p.append(v/named_total_per)\n", + " choices.append(pd.NA)\n", + " p.append(na_per/named_total_per) \n", + " return [np.random.choice(choices, p=p) for k in range(total_len)]\n", + " return []\n", + "\n", + "def random_categorical(named_p, unique_per, na_per, longtail_per, N):\n", + " choice_arr = rand_cat(named_p, na_per, N)\n", + " discrete_choice_len = len(choice_arr)\n", + "\n", + " longtail_count = int(np.floor(longtail_per * N))//2\n", + " extra_arr = []\n", + " for i in range(longtail_count):\n", + " extra_arr.append(\"long_%d\" % i)\n", + " extra_arr.append(\"long_%d\" % i)\n", + "\n", + " unique_len = N - (len(extra_arr) + discrete_choice_len)\n", + " for i in range(unique_len):\n", + " extra_arr.append(\"unique_%d\" % i)\n", + " all_arr = np.concatenate([choice_arr, extra_arr])\n", + " np.random.shuffle(all_arr)\n", + " try:\n", + " return pd.Series(all_arr, dtype='UInt64')\n", + " except:\n", + " return pd.Series(all_arr, dtype=pd.StringDtype()) \n", + "N = 4000" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Common histogram shapes\n", + "The following shows the most common shapes you will see in histograms, allowing you to quickly identify patterns\n", + "\n", + "Notice the three columns on the right. Those are categorical histograms as opposed to numerical histograms" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import buckaroo\n", + "pd.DataFrame({\n", + " 'normal': np.random.normal(25, .3, N),\n", + " 'exponential' : np.random.exponential(1.0, N) * 10 ,\n", + " 'increasing':[i for i in range(N)],\n", + " 'one': [1]*N,\n", + " 'dominant_categories': random_categorical({'foo': .6, 'bar': .25, 'baz':.15}, unique_per=0, na_per=0, longtail_per=0, N=N),\n", + " 'all_unique_cat': random_categorical({}, unique_per=1, na_per=0, longtail_per=0, N=N)})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Categorical histograms\n", + "Categorical histograms have special colors and patterns for `NA`/`NaN`, `longtail` (values that occur at least twice) and `unique`\n", + "Categorical histograms are always arranged from most frequent on the left to least frequent on the right.\n", + "\n", + "When a column is numerical, but has less than 5 distinct values it is displayed with a categorical histogram, because the numbers were probably flags" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pd.DataFrame({\n", + " 'all_NA' : pd.Series([pd.NA] * N, dtype='UInt8'),\n", + " 'half_NA' : random_categorical({1: .55}, unique_per=0, na_per=.45, longtail_per=.0, N=N),\n", + " 'dominant_categories': random_categorical({'foo': .45, 'bar': .2, 'baz':.15}, unique_per=.2, na_per=0, longtail_per=0, N=N),\n", + " 'longtail' : random_categorical({}, unique_per=0, na_per=.2, longtail_per=.8, N=N),\n", + " 'longtail_unique' : random_categorical({}, unique_per=0.5, na_per=.0, longtail_per=.5, N=N)})" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## Notice the different distributions of the numeric histograms" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pd.DataFrame({\n", + " 'bimodal' : bimodal(20,40, N),\n", + " 'exponential' : np.random.exponential(1.0, N) * 10 ,\n", + " 'geometric': np.random.geometric(.2, N) * 10,\n", + " 'log_normal': np.random.lognormal(25, .3, N),\n", + " 'normal': np.random.normal(25, .3, N),})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Buckaroo also works on polars" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import polars as pl\n", + "df = pl.read_parquet(\"https://github.com/paddymul/buckaroo-data/raw/main/cb_data/2016-04.parq\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "buckaroo.debug_packages()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/example-notebooks/GeoPandas.ipynb b/example-notebooks/GeoPandas.ipynb new file mode 100644 index 000000000..442e1357d --- /dev/null +++ b/example-notebooks/GeoPandas.ipynb @@ -0,0 +1,217 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "5b17aae3-6857-4eda-b8e0-a5b824edbbf4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import buckaroo\n", + "import geopandas\n", + "from buckaroo.geopandas_buckaroo import GeopandasBuckarooWidget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8c2d060d-7430-4d54-855d-44cd9376cdab", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "world_df = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "147ecebd-952c-4fe0-832d-8b93421e69a1", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "world_df" + ] + }, + { + "cell_type": "markdown", + "id": "f6622889-e4a7-4835-90f4-639492052eb5", + "metadata": {}, + "source": [ + "# Use GeopandasSVGBuckarooWidget to see renderings of geometry" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6cc1aaea-6add-4b1b-901e-9abacb0425a4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from buckaroo.geopandas_buckaroo import GeopandasSVGBuckarooWidget\n", + "GeopandasSVGBuckarooWidget(world_df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dea5fb3e-1e0c-41c0-bbe4-3f4564681665", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "abbrev_geo_obj = {\n", + " \"type\": \"FeatureCollection\",\n", + " \"features\": [\n", + " { \"id\": \"0\",\n", + " \"type\": \"Feature\",\n", + " \"properties\": { \"sovereignt\": \"Ethiopia\"},\n", + " \"geometry\": {\n", + " \"type\": \"Polygon\",\n", + " \"coordinates\": [[[ 47.78, 8.00],\n", + " [ 44.96, 5.00],\n", + " [ 43.66, 4.95],\n", + " [ 46.94, 7.99],\n", + " [ 47.78, 8.00]]]}},\n", + " { \"id\": \"1\",\n", + " \"type\": \"Feature\",\n", + " \"properties\": { \"sovereignt\": \"South Sudan\"},\n", + " \"geometry\": {\n", + " \"type\": \"Polygon\",\n", + " \"coordinates\": [[[ 30.83, 3.50],\n", + " [ 29.95, 4.17],\n", + " [ 29.71, 4.60],\n", + " [ 29.15, 4.38],\n", + " [ 30.83, 3.50]]]}},\n", + " { \"id\": \"2\",\n", + " \"type\": \"Feature\",\n", + " \"properties\": { \"sovereignt\": \"Somalia\"},\n", + " \"geometry\": {\n", + " \"type\": \"Polygon\",\n", + " \"coordinates\": [[[ 41.58, -1.68],\n", + " [ 40.93, -0.85],\n", + " [ 40.95, 2.78],\n", + " [ 41.85, 3.91],\n", + " [ 42.13, 4.23],\n", + " [ 41.58, -1.68]]]}}]}\n", + "abbrev_df = geopandas.GeoDataFrame.from_features(abbrev_geo_obj)\n", + "abbrev_df" + ] + }, + { + "cell_type": "markdown", + "id": "04381d81-91d2-48ed-a10a-436a6bce568d", + "metadata": {}, + "source": [ + "## Tweaking row height\n", + "Shapely emits SVG graphics, they seem to vary in height, Buckaroo needs a global rowHeight, here is how to set it\n", + "We also made buckaroo larger" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a69c95d7-d66d-4ca5-b11e-5b00c4b7e500", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "nybb_df = geopandas.read_file(geopandas.datasets.get_path('nybb'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "432e571c-e7dc-46b3-9707-f301033fee8a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "GeopandasBuckarooWidget(nybb_df, component_config={'height_fraction':1.2},\n", + " extra_grid_config={'rowHeight':305})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b309bab6-01f7-4a21-a895-b4075d4c757d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import requests\n", + "geojson = requests.get('https://gist.githubusercontent.com/chbrandt/bb64d9a6fc00a89d7410e6db8d126dfe/raw/8bc7a45c57e1c701618c940525d83bee80fd6b90/africa.geojson')\n", + "assert 200 <= geojson.status_code < 400\n", + "gdf = geopandas.GeoDataFrame.from_features(geojson.json())\n", + "gdf" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd9b37da-b9a8-4a22-a20d-81edde8060f8", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "cities = geopandas.read_file(geopandas.datasets.get_path('naturalearth_cities'))\n", + "cities" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aae6abe4-227e-481a-9af7-daf9c25b0df1", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "bigdf = pd.concat([world_df] *100)\n", + "bigdf['newindex'] = np.arange(17700)\n", + "bigdf.set_index('newindex')\n", + "print(len(bigdf))\n", + "%timeit GeopandasBuckarooWidget(bigdf[:1500])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/example-notebooks/Histograms-demo.ipynb b/example-notebooks/Histograms-demo.ipynb new file mode 100644 index 000000000..6f47a24f2 --- /dev/null +++ b/example-notebooks/Histograms-demo.ipynb @@ -0,0 +1,216 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "d99a7ecf-6cce-4b9a-b8be-8b0d1c206b67", + "metadata": {}, + "outputs": [], + "source": [ + "%pip install buckaroo\n", + "try:\n", + " from google.colab import output\n", + " output.enable_custom_widget_manager()\n", + "except Exception as e:\n", + " print(e)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "75a6af82-5029-4d16-abf1-f0aeb0489957", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "import itertools\n", + "import pandas as pd\n", + "import buckaroo" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aa9097b0-1c99-46b1-b966-06a9e47e57d6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def bimodal(mean_1, mean_2, N, sigma=5, sigma2=5):\n", + " X1 = np.random.normal(mean_1, sigma, int(N/2))\n", + " X2 = np.random.normal(mean_2, sigma2, int(N/2))\n", + " X = np.concatenate([X1, X2])\n", + " return X\n", + "#ab = plt.hist(bimodal(20,40, 400),bins=10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "91c4cf93-4a15-48ba-a1e9-a46683fcfccf", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def rand_cat(named_p, na_per, N):\n", + " choices, p = [], []\n", + " named_total_per = sum(named_p.values()) + na_per\n", + " total_len = int(np.floor(named_total_per * N))\n", + " if named_total_per > 0:\n", + " for k, v in named_p.items():\n", + " choices.append(k)\n", + " p.append(v/named_total_per)\n", + "\n", + " choices.append(pd.NA)\n", + " p.append(na_per/named_total_per) \n", + " return [np.random.choice(choices, p=p) for k in range(total_len)]\n", + " else:\n", + " return []\n", + "\n", + "def random_categorical(named_p, unique_per, na_per, longtail_per, N):\n", + " choice_arr = rand_cat(named_p, na_per, N)\n", + " discrete_choice_len = len(choice_arr)\n", + "\n", + " longtail_count = int(np.floor(longtail_per * N))//2\n", + " extra_arr = []\n", + " for i in range(longtail_count):\n", + " extra_arr.append(\"long_%d\" % i)\n", + " extra_arr.append(\"long_%d\" % i)\n", + "\n", + " unique_len = N - (len(extra_arr) + discrete_choice_len)\n", + " #print(\"discrete_choice_len\", discrete_choice_len, \"longtail_count\", longtail_count, \"unique_len\", unique_len)\n", + " for i in range(unique_len):\n", + " extra_arr.append(\"unique_%d\" % i)\n", + " all_arr = np.concatenate([choice_arr, extra_arr])\n", + " np.random.shuffle(all_arr)\n", + " return all_arr " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9cfe316a-077c-4347-8b5e-c6048c16b5ca", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "N = 4000\n", + "pd.DataFrame({\n", + " 'all_NA' : [pd.NA] * N,\n", + " 'half_NA' : random_categorical({1: .5}, unique_per=0, na_per=.5, longtail_per=.0, N=N),\n", + " 'longtail' : random_categorical({}, unique_per=0, na_per=.2, longtail_per=.8, N=N),\n", + " 'longtail_unique' : random_categorical({}, unique_per=0.5, na_per=.0, longtail_per=.5, N=N),\n", + "})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36089fd7-cb7d-43d8-8e91-dbdf30f6a032", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#kitchen sink\n", + "pd.DataFrame({\n", + " 'one': [1]*N, \n", + " 'log_normal': np.random.lognormal(25, .3, N),\n", + " 'bimodal': bimodal(20,40, N),\n", + " 'cat_1':random_categorical({'foo': .35, 'bar': .2}, unique_per=.25, na_per=.2, longtail_per=0, N=N),\n", + " 'all_unique_cat':[str(i)+ \"_a\" for i in range(N)],\n", + " 'all_unique_N':[i for i in range(N)],\n", + " 'cat_long_tail': random_categorical({}, unique_per=0, na_per=.2, longtail_per=.8, N=N),\n", + " 'all_NA': [pd.NA] * N,\n", + "\n", + " 'cat_3':random_categorical({'foo': .3, 'bar': .05, 'baz':.1}, unique_per=.3, na_per=.25, longtail_per=0, N=N),\n", + " 'cat_4':random_categorical({'foo': .3, 'bar': .05, 'baz':.1}, unique_per=.3, na_per=.25, longtail_per=0, N=N)\n", + "})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "02d70ce5-4dc6-42ea-853e-b5d5e99d684f", + "metadata": {}, + "outputs": [], + "source": [ + "pd.DataFrame({\n", + " 'normal': np.random.normal(25, .3, N),\n", + " 'exponential' : np.random.exponential(1.0, N) * 10 ,\n", + " 'increasing':[i for i in range(N)],\n", + " 'one': [1]*N, \n", + " 'all_unique_cat': random_categorical({}, unique_per=1, na_per=0, longtail_per=0, N=N)\n", + "})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0bb02641-0653-4ee7-86c5-7b058abaeb79", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pd.DataFrame({\n", + " 'bimodal' : bimodal(20,40, N),\n", + " 'exponential' : np.random.exponential(1.0, N) * 10 ,\n", + " 'geometric': np.random.geometric(.2, N) * 10,\n", + " 'log_normal': np.random.lognormal(25, .3, N),\n", + " 'normal': np.random.normal(25, .3, N),\n", + "})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "425e2df3-54cd-4127-bac7-549fe2c15520", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#categoricals\n", + "pd.DataFrame({\n", + " 'two_vals': random_categorical({1: .75, 2: .25}, unique_per=0, na_per=0, longtail_per=0, N=N),\n", + " 'dominant_categories': random_categorical({'foo': .6, 'bar': .25, 'baz':.15}, unique_per=0, na_per=0, longtail_per=0, N=N),\n", + " 'dispersed_categories': random_categorical({'foo': .3, 'bar': .05, 'baz':.1}, unique_per=.3, na_per=.25, longtail_per=0, N=N),\n", + "})" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/example-notebooks/Itables-testcases.ipynb b/example-notebooks/Itables-testcases.ipynb new file mode 100644 index 000000000..8e4b01884 --- /dev/null +++ b/example-notebooks/Itables-testcases.ipynb @@ -0,0 +1,347 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "b45fa7dc-e098-40ee-adf4-c3a4c6a5545c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import buckaroo\n", + "from itables.sample_dfs import get_dict_of_test_dfs\n", + "dict_of_test_dfs = get_dict_of_test_dfs()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8ddb9152-702f-4bcb-86c6-0de2a138bb89", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"empty\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "053d0453-5615-4f7b-a519-bb67912b28da", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"no_rows\"] # results in ColDisplayHints Error" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7969cc05-1ebe-4b72-beb5-7ea35174bfaa", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"no_rows_one_column\"] # results in ColDisplayHints Error" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9b6cae85-33b9-425b-af7d-299c448a6ea1", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"no_columns\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d777553-3aeb-4467-99ef-b1a96cbaee8d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"no_columns_one_row\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9e9f4664-9139-4fbd-974d-f16efe53b608", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"bool\"] #Col Display hints error" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1ac46685-7288-467b-afad-a4d7699a998a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"nullable_boolean\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0748b5cf-1166-4208-94e6-b64b7859e356", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"int\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a4fafb72-1011-4048-a4b4-4c16b7924e02", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"nullable_int\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f8b40fbd-1b9a-4c3f-8d72-3fc0b7855dc6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"float\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cdaa4682-e2d6-4d89-9b46-eb7313855903", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"str\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cdc821e1-e3f9-4846-ad06-74a887a6ee84", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"time\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f4bf7e0f-3c80-4fbe-b59f-aa49febc3a38", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"object\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "857e6532-c352-49f1-a2f2-fd0125144207", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"ordered_categories\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d5479ba8-9f55-48e6-9a6c-fe9ee246c91a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"ordered_categories_in_multiindex\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "23be7ceb-de1a-44e8-91e0-2cc894399854", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"multiindex\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92856cdc-a024-4232-b849-15bab83c16e1", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"countries\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8d7d9912-2a13-4153-af4c-1239a929bc7e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"capital\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "70329ae8-99a5-4b9c-9128-9c3fc2b6362b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"complex_index\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "998748f6-a664-4cf6-9388-ab9ab742e069", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"int_float_str\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "622a3fc5-ca35-4c5c-b48f-b2749ecaac87", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"wide\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "929ab710-d645-4376-99ac-dfcc43a247c6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"long_column_names\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "204d1b91-b58b-45d8-8b73-ff212b962abb", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"duplicated_columns\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a5b35a2b-34c4-455c-9653-eb10b0249344", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"named_column_index\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "37b655c1-4937-4ba1-898f-3e225d71a178", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dict_of_test_dfs[\"big_integers\"]" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.5" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/example-notebooks/Pluggable-Analysis-Framework.ipynb b/example-notebooks/Pluggable-Analysis-Framework.ipynb new file mode 100644 index 000000000..5e0fb1dd3 --- /dev/null +++ b/example-notebooks/Pluggable-Analysis-Framework.ipynb @@ -0,0 +1,320 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "375845a4-837a-4a32-a84a-ddb0d546878b", + "metadata": { + "tags": [] + }, + "source": [ + "# Customizing Buckaroo\n", + "Buckaroo consists of\n", + "* The BuckarooWidget which coordinates updates to the frontend, management of analysis, the lowcode UI, and auto_cleaning functionality.\n", + "* The frontend JS Table - handles display of dataframes, configured through interfaces.\n", + "* The pluggable analysis framework which orders execution of customized analysis objects, and handles catching errors along with error reporting.\n", + "* User supplied analyis objects, these operate on the dataframes to build the summary stats table, and configure the frontend display\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9b04f052-6973-4d29-b637-1d350d86798f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "from buckaroo.buckaroo_widget import BuckarooWidget\n", + "\n", + "#df = pd.read_csv(\"https://s3.amazonaws.com/tripdata/201401-citibike-tripdata.zip\")\n", + "df = pd.read_csv(\"/Users/paddy/code/example-notebooks/citibike-trips.csv\") #for airplane work\n", + "#df[:500]" + ] + }, + { + "cell_type": "markdown", + "id": "441e9e82-34ec-4359-9000-dff97f537e12", + "metadata": {}, + "source": [ + "**These docs need updating for 0.5** Take a look at the [customizations](https://github.com/paddymul/buckaroo/tree/main/buckaroo/customizations) directory in the codebase and file some bugs asking for your suggested improvement. I expect to add a lot more xamples around the 0.6 series" + ] + }, + { + "cell_type": "markdown", + "id": "a1ec3e18-1649-49d2-8e3b-8e93236d93e1", + "metadata": {}, + "source": [ + "# Adding a summary stat\n", + "Buckaroo is completely customizeable. In the next cells we will add `Variance` to an instance of the BuckarooWidget with the `Pluggable Analysis Framework`.\n", + "\n", + "## Why was the Pluggable Analysis Framework built?\n", + "The `Pluggable Analysis Framework` is engineered to allow summary_stats to be built up piecemeal and incrementally. Traditionally when writing bits of analysis code, the tendency is to have large brittle functions that do a lot at once. Adding extra stats either requires copying and pasting the existing function with one small addition, writing each stat independently and possibly recomputing existing stats, having a strictly ordered set of analysis functions, or some complex adhoc argument passing scheme. I have written adhoc versions in each of these patterns. Problems are manifest and the aparatus rarely survives even copy-pasting to the next notebook.\n", + "\n", + "## How does the Pluggable Analysis Framework work?\n", + "The `Pluggable Analysis Framework` is built around a [DAG](https://en.wikipedia.org/wiki/Directed_acyclic_graph) of `ColAnalysis` nodes that can depend (`requires_summary`) on other summary stats which `provides_summary` the right values, and provide one or more summary stats. Nodes cand be added to the dag with `add_analysis`. If a class with the same name is inserted into the DAG, the newly inserted node replaces the previous instantiation. This all facilitates interactive development of analysis functions. During execution errors are caught and execution proceeds. This is important because breaking the default dataframe mechanism is a show stopping problem for users" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "63fab4e4-5dbb-4b34-ae7c-b4b065d0ed26", + "metadata": {}, + "outputs": [], + "source": [ + "w = BuckarooWidget(df[:500])\n", + "w" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "67d6d3da-cc93-4566-b542-74c8cd5758b9", + "metadata": {}, + "outputs": [], + "source": [ + "from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import (ColAnalysis)\n", + "from buckaroo.dataflow import StylingAnalysis\n", + "\n", + "class Variance(StylingAnalysis):\n", + " #note we also override pinned rows so you can see this new stat, this is mainly used for development. \n", + " # Normally you would want to extend \"ColAnalysis\" to just provide the stat\n", + " pinned_rows = [\n", + " {'primary_key_val': 'variance', 'displayer_args': {'displayer': 'obj' }}]\n", + "\n", + " provides_summary = [\"variance\"]\n", + " #a bit hacky, the newly added analyis needs to be the last in the dependency chain\n", + " requires_summary = [\"histogram\"]\n", + "\n", + " @staticmethod\n", + " def series_summary(sampled_ser, ser):\n", + " if pd.api.types.is_numeric_dtype(ser):\n", + " return dict(variance=ser.var())\n", + " return dict(variance=\"NA\")\n", + "\n", + "w.add_analysis(Variance)" + ] + }, + { + "cell_type": "markdown", + "id": "ffdd52ed-443c-4ec3-9063-b067e779cbc4", + "metadata": {}, + "source": [ + "## Basic Unit testing is built in\n", + "\n", + "Because there are so many corner cases with numerical code, every time a new summary stat is added, a variety of simple tests are run against it. This lets you discover bugs earlier." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f3c58fc-b742-4251-9778-e1a33bf4f500", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#broken as 0f 0.6\n", + "\n", + "small_df = df[:500][df.columns[:4]]\n", + "# we are going to create, but not display a BuckarooWidget here, we are looking at the error behavior\n", + "w = BuckarooWidget(small_df, debug=True)\n", + "\n", + "class Variance(ColAnalysis):\n", + " provides_summary = [\"variance\"]\n", + " requires_summary = [\"mean\"]\n", + " \n", + " @staticmethod\n", + " def summary(sampled_ser, summary_ser, ser):\n", + " mean = summary_ser.get('mean', False)\n", + " arr = ser.to_numpy()\n", + " #toggle SIMULATED_BUG to easily see behavior with and without a bug\n", + " SIMULATED_BUG = False\n", + " if SIMULATED_BUG:\n", + " if mean in [pd.NA, np.nan, False]:\n", + " return dict(variance=\"NA\")\n", + " else:\n", + " if mean is pd.NA or mean is np.nan or mean is False:\n", + " return dict(variance=\"NA\")\n", + " if mean and pd.api.types.is_integer_dtype(ser):\n", + " return dict(variance=np.mean((arr - mean)**2))\n", + " elif mean and pd.api.types.is_float_dtype(ser):\n", + " return dict(variance=np.mean((arr - mean)**2))\n", + " return dict(variance=\"NA\")\n", + "\n", + "w.add_analysis(Variance)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c8faf375-9aa5-4904-a228-08592cb8ad66", + "metadata": {}, + "outputs": [], + "source": [ + "from buckaroo.pluggable_analysis_framework.analysis_management import PERVERSE_DF\n", + "Variance.summary(PERVERSE_DF['all_nan'], pd.Series({'mean': np.nan, }), PERVERSE_DF['all_nan']) # boolean value of NA is ambiguous" + ] + }, + { + "cell_type": "markdown", + "id": "d28c3fb7-62bf-48db-ae68-f32a01116628", + "metadata": {}, + "source": [ + "## Reproducing errors in the notebook\n", + "Buckaroo printed reproduction instructions like\n", + "```\n", + "from buckaroo.pluggable_analysis_framework.analysis_management import PERVERSE_DF\n", + "Variance.summary(PERVERSE_DF['all_nan'], pd.Series({'mean': np.nan, }), PERVERSE_DF['all_nan']) # boolean value of NA is ambiguous\n", + "\n", + "```\n", + "\n", + "`PERVERSE_DF` is a DataFame with all kinds of edgecases that normally trip up numerical code. You can run the above two lines, and quickly start iterating on your `ColAnalysis` class to fix the error. Normally adhoc analysis code that iterates over a list of functions blows up in a stack trace referencing an anonymous function in the middle of a for loop called with opaque variables. Bucakroo gives you a single line that can reproduce the error, with easily inspectable variables" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d41b448c-6533-4a1e-a216-cb18da7e20ca", + "metadata": {}, + "outputs": [], + "source": [ + "from buckaroo.pluggable_analysis_framework.analysis_management import PERVERSE_DF\n", + "Variance.summary(PERVERSE_DF['all_nan'], pd.Series({'mean': np.nan, }), PERVERSE_DF['all_nan']) # boolean value of NA is ambiguous" + ] + }, + { + "cell_type": "markdown", + "id": "e2e8eb43-79ed-4652-90d0-32f5dd4cb74e", + "metadata": {}, + "source": [ + "## Quiet mode\n", + "Sometimes you just want to get on with it. Buckaroo has a setting for that too, set `quiet=True` and unit test errors, and regular processing errors will be silenced. Not recommended, but if I didn't add it, users would write their own adhoc version." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6163569-9fd7-4692-9f95-e9fadb6615c1", + "metadata": {}, + "outputs": [], + "source": [ + "w = buckaroo.BuckarooWidget(small_df, showCommands=False)\n", + "#There are errors in the following functions, quiet = True will ignore them\n", + "\n", + "def int_digits(n):\n", + " if np.isnan(n):\n", + " return 1\n", + " if n == 0:\n", + " return 1\n", + " if np.sign(n) == -1:\n", + " return int(np.floor(np.log10(np.abs(n)))) + 2\n", + " return int(np.floor(np.log10(n)+1))\n", + "class MinDigits(ColAnalysis):\n", + " \n", + " requires_summary = [\"min\"]\n", + " provides_summary = [\"min_digits\"]\n", + " quiet = True\n", + " \n", + " @staticmethod\n", + " def summary(sampled_ser, summary_ser, ser):\n", + " is_numeric = pd.api.types.is_numeric_dtype(sampled_ser.dtype)\n", + " if is_numeric:\n", + " return {\n", + " 'min_digits':int_digits(summary_ser.loc['min'])}\n", + " else:\n", + " return {\n", + " 'min_digits':0}\n", + "w.add_analysis(MinDigits)\n", + "w" + ] + }, + { + "cell_type": "markdown", + "id": "cf664880-3a8e-451d-8ff1-fb657de0a76a", + "metadata": { + "tags": [] + }, + "source": [ + "# Making a new default dataframe display function" + ] + }, + { + "cell_type": "markdown", + "id": "5f184bb2-3a1e-4a74-9c5b-388742ac6b67", + "metadata": { + "tags": [] + }, + "source": [ + "## Adding a Command to the Low Code UI\n", + "Previous versions of Buckaroo included a customizable low code UI. This is temporarily deprecated as of 0.6\n", + "Look at https://github.com/paddymul/buckaroo/blob/86df365278ac6933f7266c0b055a2ff90b072e9a/example-notebooks/Customizing-Buckaroo.ipynb for more info and install buckaroo at 0.4.6 or 0.5.1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "44f4d9da-5b06-4d6f-b319-e435e3d62944", + "metadata": {}, + "outputs": [], + "source": [ + "from buckaroo.widget_utils import disable\n", + "from IPython.core.getipython import get_ipython\n", + "from IPython.display import display\n", + "import warnings\n", + "\n", + "disable()\n", + "def my_display_as_buckaroo(df):\n", + " w = BuckarooWidget(df, showCommands=False)\n", + " #the analysis we added throws warnings, let's muffle that when used as the default display\n", + " warnings.filterwarnings('ignore')\n", + " w.add_analysis(Skew)\n", + " warnings.filterwarnings('default')\n", + " return display(w)\n", + "\n", + "def my_enable():\n", + " \"\"\"\n", + " Automatically use buckaroo to display all DataFrames\n", + " instances in the notebook.\n", + "\n", + " \"\"\"\n", + " ip = get_ipython()\n", + " if ip is None:\n", + " print(\"must be running inside ipython to enable default display via enable()\")\n", + " return\n", + " ip_formatter = ip.display_formatter.ipython_display_formatter\n", + " ip_formatter.for_type(pd.DataFrame, my_display_as_buckaroo)\n", + "my_enable()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/example-notebooks/Solara-Buckaroo.ipynb b/example-notebooks/Solara-Buckaroo.ipynb new file mode 100644 index 000000000..f88628441 --- /dev/null +++ b/example-notebooks/Solara-Buckaroo.ipynb @@ -0,0 +1,229 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "d69037a0-5b72-469c-8de7-d48a2788bede", + "metadata": {}, + "source": [ + "# Buckaroo works in Solara too" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79fc4322-12b9-42bb-8bc6-2139e1a7d1f8", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import solara\n", + "from buckaroo.solara_buckaroo import SolaraDFViewer, SolaraBuckarooWidget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd085457-3ecf-438d-bf03-be1c2f0fa8ef", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "df = pd.DataFrame({'a':[10,20]})\n", + "@solara.component\n", + "def Page():\n", + " bw = SolaraDFViewer(df=df)\n", + "display(Page())" + ] + }, + { + "cell_type": "markdown", + "id": "ce7aec8e-412a-46a4-af4e-7a026fd33fa1", + "metadata": {}, + "source": [ + "## You can turn off pinned_rows too" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b3558422-55f4-4f88-b85d-71e910d10bd5", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "df = pd.DataFrame({'a':[10,20]})\n", + "@solara.component\n", + "def Page():\n", + " bw = SolaraDFViewer(df=df, pinned_rows=[])\n", + "display(Page())" + ] + }, + { + "cell_type": "markdown", + "id": "1551cd59-2e52-4fd0-9d93-f136eed71e2d", + "metadata": {}, + "source": [ + "# And it works with Polars" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7e2556c-b768-408b-8aa2-bb81bd91ee9c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import polars as pl\n", + "from buckaroo.solara_buckaroo import SolaraPolarsDFViewer, SolaraPolarsBuckarooWidget\n", + "pldf = pl.DataFrame({'a':[10,20]})\n", + "@solara.component\n", + "def Page():\n", + " bw = SolaraPolarsDFViewer(df=pldf, pinned_rows=[])\n", + "display(Page())" + ] + }, + { + "cell_type": "markdown", + "id": "02db2eb2-0b6a-40c4-bcc8-b310a1d6e405", + "metadata": {}, + "source": [ + "# Let's look at more data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3f74b8fb-7ba3-4c33-ad2e-e17baad839bc", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "cb_trips_df = pd.read_csv(\"https://github.com/paddymul/buckaroo-data/raw/main/cb_data/2016-04.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22d571e5-6bf2-4a5f-8bfe-2c69d679f8f8", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "@solara.component\n", + "def Page():\n", + " bw = SolaraDFViewer(df=cb_trips_df, pinned_rows=[])\n", + "display(Page())" + ] + }, + { + "cell_type": "markdown", + "id": "5e4c06cc-7e9c-4d77-afec-7c9e78d8ca3b", + "metadata": {}, + "source": [ + "# Building an app around SolaraDFViewer\n", + "The following app hardcodes two dataframes and lets you select between them" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4d1256ef-edf5-494a-8a2c-a5c1a6a38b29", + "metadata": {}, + "outputs": [], + "source": [ + "dataframe_names = [\"foo\", \"bar\"]\n", + "df_name = solara.reactive(\"foo\")\n", + "\n", + "dataframes = dict(foo=df,\n", + " bar=pd.DataFrame({'c':[20,50,90], 'd':[False, True, True]}))\n", + "\n", + "@solara.component\n", + "def Page():\n", + " solara.Select(label=\"df_name\", value=df_name, values=dataframe_names)\n", + " active_df = dataframes[df_name.value]\n", + " bw = SolaraDFViewer(active_df)\n", + "\n", + " solara.Markdown(f\"**Selected**: {df_name.value}\")\n", + "display(Page())" + ] + }, + { + "cell_type": "markdown", + "id": "9ca33684-b15f-48f9-a19d-f3a5221343ba", + "metadata": {}, + "source": [ + "# Reading large dataframes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "48f11839-2fe0-454b-b616-d82d5fcabf38", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "url_base = \"https://github.com/paddymul/buckaroo-data/raw/main/cb_data/\"\n", + "\n", + "dataframe_names = [\n", + " \"2016-01.parq\", \"2016-02.parq\",\n", + " \"2016-03.parq\", \"2016-04.parq\"]\n", + "\n", + "df_name = solara.reactive(\"2016-01.parq\")\n", + "\n", + "@solara.component\n", + "def Page():\n", + " solara.Select(label=\"df_name\", value=df_name, values=dataframe_names)\n", + "\n", + " @solara.lab.use_task(dependencies=[df_name.value])\n", + " def read_df():\n", + " return pl.read_parquet(url_base+df_name.value)\n", + "\n", + " solara.ProgressLinear(read_df.pending)\n", + " if read_df.latest is not None:\n", + " with solara.Div(style={\"opacity\": 0.3 if read_df.pending else 1.0}):\n", + " SolaraPolarsDFViewer(read_df.latest)\n", + "\n", + " solara.Markdown(f\"**Selected**: {df_name.value}\")\n", + "display(Page())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/example-notebooks/styling-gallery.ipynb b/example-notebooks/styling-gallery.ipynb new file mode 100644 index 000000000..65ddadaf6 --- /dev/null +++ b/example-notebooks/styling-gallery.ipynb @@ -0,0 +1,1388 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "99218d54-79db-4c3c-8ca5-373e3c1ed677", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from buckaroo.dataflow.dataflow import StylingAnalysis\n", + "from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import ColAnalysis\n", + "import polars as pl\n", + "from buckaroo.polars_buckaroo import PolarsBuckarooWidget\n", + "from buckaroo.customizations.polars_analysis import PlTyping\n", + "N=500" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "840e09f3-8153-4800-a383-636556af4f32", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# This works with polars or pandas, these variables let us quickly swap between the two\n", + "DataFrame = pl.DataFrame\n", + "BUCKAROOWidget = PolarsBuckarooWidget\n", + "NA = pl.Null" + ] + }, + { + "cell_type": "markdown", + "id": "cf49c5fd-b617-4495-b018-1fadbc90cb4c", + "metadata": {}, + "source": [ + "This notebook generally follows the order of [DFWhole.ts](https://github.com/paddymul/buckaroo/blob/feat/dfviewer-config/js/components/DFViewerParts/DFWhole.ts)\n", + "\n", + "Starting with the simple Displayers\n", + "```js\n", + "export interface ObjDisplayerA {\n", + " displayer: 'obj';}\n", + "\n", + "export interface BooleanDisplayerA {\n", + " displayer: 'boolean';}\n", + "\n", + "export interface StringDisplayerA {\n", + " displayer: 'string';\n", + " max_length?: number;} \n", + " \n", + "export interface FloatDisplayerA {\n", + " displayer: 'float';\n", + " min_fraction_digits: number;\n", + " max_fraction_digits: number;}\n", + "\n", + "export interface DatetimeDefaultDisplayerA {\n", + " displayer: 'datetimeDefault';}\n", + "export interface IntegerDisplayerA {\n", + " displayer: 'integer';\n", + " min_digits: number;\n", + " max_digits: number;}\n", + "\n", + "export interface DatetimeLocaleDisplayerA {\n", + " displayer: 'datetimeLocaleString';\n", + " locale: 'en-US' | 'en-GB' | 'en-CA' | 'fr-FR' | 'es-ES' | 'de-DE' | 'ja-JP';\n", + " // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat\n", + " args: Intl.DateTimeFormatOptions;}\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4697fa58-9609-412f-b2d0-48a63fed0c99", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#simpler Buckaroo that really shows the styling\n", + "def obj_(pkey):\n", + " return {'primary_key_val': pkey, 'displayer_args': { 'displayer': 'obj' } }\n", + "\n", + "class GalleryStyling(StylingAnalysis):\n", + " requires_summary = ['dtype']\n", + " pinned_rows = [obj_('dtype')]\n", + "class GalleryBuckaroo(PolarsBuckarooWidget):\n", + " analysis_klasses = [GalleryStyling, PlTyping]\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "6e84d497-539f-4c62-810f-1cef72f417d2", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f1de7ec8051b4cdfa908edb2b3f69291", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "GalleryBuckaroo(buckaroo_options={'sampled': ['random'], 'auto_clean': ['aggressive', 'conservative'], 'post_p…" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "obj_df = pl.DataFrame({\n", + " 'bools':[True, True, False, False, True, None],\n", + " 'ints': [ 5, 20, 30, -10, 7772, None],\n", + " 'timestamp':[\"2020-01-01 01:00Z\", \"2020-01-01 02:00Z\", \"2020-02-28 02:00Z\", \"2020-03-15 02:00Z\", None, None],\n", + " 'dicts': [ {'a':10, 'b':20, 'c':'some string'}, None, None, None, None, None], #polars\n", + " 'nested_dicts': [{'level_1': {'a':10, 'b':20, 'c':'some string'}}, None, None, None, None, None],\n", + " 'lists': [['a','b'], [1,2], None, None, None, None],\n", + " 'lists-string': [['a','b'], ['foo', 'bar'], None, None, None, None],\n", + " 'lists-int': [[10, 20], [100, 500], [8], None, None, None]}\n", + ")\n", + "GalleryBuckaroo(obj_df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "540dcd65-248d-43a3-b8c3-2db3159d3f8d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "obj_df = pl.DataFrame({\n", + " 'bools':[True, True, False, False, True, None],\n", + " 'ints': [ 5, 20, 30, -10, 7772, None],\n", + " 'dicts': [ {'a':10, 'b':20, 'c':'some string'}, None, None, None, None, None], #polars\n", + " 'nested_dicts': [{'level_1': {'a':10, 'b':20, 'c':'some string'}}, None, None, None, None, None],\n", + " #'nested_dicts2': pl.Series([{'level_1': {'a':10, 'b':20, 'c':'some string'}}, None, None, None, None, None], dtype=pl.Object)}\n", + " }\n", + ")\n", + "GalleryBuckaroo(obj_df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c49dd11-9727-4ac1-829c-bed1a155629b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "bool_df = pl.DataFrame({'bools':[True, True, False, False, True, None]})\n", + "bool_df = bool_df.select(\n", + " pl.col('bools').alias('bools_obj_displayer'), \n", + " pl.col('bools').alias('bools_boolean_displayer'))\n", + "#fix #'bools_bool_checkbox_displayer': {'displayer_args': {'displayer': 'boolean_checkbox'}\n", + "PolarsBuckarooWidget(\n", + " bool_df, \n", + "# column_config_overrides={\n", + "# 'bools_obj_displayer': {'displayer_args': {'displayer': 'obj'}}, \n", + "# 'bools_boolean_displayer': {'displayer_args': {'displayer': 'boolean'}}}\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "18e5adba-49b8-453a-86f7-ce438c61113a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "string_df = pl.DataFrame({'strings':[\"asdf\", \"qwerty\", \"really long string, much much longer\", None, \"A\"]})\n", + "string_df = string_df.select(\n", + " pl.col('strings').alias('strings_obj_displayer'), \n", + " pl.col('strings').alias('strings_string_displayer'),\n", + " pl.col('strings').alias('strings_string_displayer_max_len'))\n", + "PolarsBuckarooWidget(\n", + " string_df, \n", + " column_config_overrides={\n", + " 'strings_obj_displayer': {'displayer_args': {'displayer': 'obj'}}, \n", + " 'strings_string_displayer': {'displayer_args': {'displayer': 'string'}},\n", + " 'strings_string_displayer_max_len': {'displayer_args': {'displayer': 'string', 'max_length':15}}\n", + " })" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e8cefca2-6db8-4599-b46a-40e7cc45caef", + "metadata": {}, + "outputs": [], + "source": [ + "float_df = pl.DataFrame({\n", + " 'float': [5, -8, 13.23, -8.01, -999.345245234, None]})\n", + "\n", + "def float_(min_digits, max_digits):\n", + " return {'displayer_args': { 'displayer': 'float', 'min_fraction_digits':min_digits, 'max_fraction_digits': max_digits}}\n", + "float_df = float_df.select(\n", + " pl.col('float').alias('float_obj_displayer'), \n", + " pl.col('float').alias('float_float_displayer_1__3'),\n", + " pl.col('float').alias('float_float_displayer_0__3'),\n", + " pl.col('float').alias('float_float_displayer_3__3'),\n", + " pl.col('float').alias('float_float_displayer_3_13'))\n", + "PolarsBuckarooWidget(\n", + " float_df,\n", + " column_config_overrides={\n", + " 'float_obj_displayer': {'displayer_args': {'displayer': 'obj'}}, \n", + " 'float_float_displayer_1__3' : float_(1,3),\n", + " 'float_float_displayer_0__3' : float_(0,3),\n", + " 'float_float_displayer_3__3' : float_(3,3),\n", + " 'float_float_displayer_3_13' : float_(3,13)})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa1410bf-8540-4daf-8080-ae7d52e70546", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from polars import functions as F\n", + "\n", + "datetime_df = pl.DataFrame({'timestamp':[\"2020-01-01 01:00Z\", \"2020-01-01 02:00Z\", \"2020-02-28 02:00Z\", \"2020-03-15 02:00Z\", None]})\n", + "datetime_df = datetime_df.select(\n", + " pl.col('timestamp').alias('timestamp_obj_displayer'),\n", + " pl.col('timestamp').alias('timestamp_datetime_default_displayer'),\n", + " pl.col('timestamp').alias('timestamp_datetime_locale_en-US'),\n", + " pl.col('timestamp').alias('timestamp_datetime_locale_en-US-Long'),\n", + " pl.col('timestamp').alias('timestamp_datetime_locale_en-GB'))\n", + "datetime_df = datetime_df.select(F.all().str.to_datetime())\n", + "def locale(locale, args={}):\n", + " return {'displayer_args': {'displayer': 'datetimeLocaleString',\n", + " 'locale':locale,\n", + " 'args':args}}\n", + "PolarsBuckarooWidget(datetime_df,\n", + " column_config_overrides={\n", + " 'timestamp_obj_displayer': {'displayer_args': {'displayer': 'obj'}}, \n", + " 'timestamp_datetime_default_displayer' : {'displayer_args': { 'displayer': 'datetimeDefault'}},\n", + " 'timestamp_datetime_locale_en-US' :locale('en-US'),\n", + " 'timestamp_datetime_locale_en-US-Long': locale('en-US', { 'weekday': 'long'}),\n", + " 'timestamp_datetime_locale_en-GB' : locale('en-GB')})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c943c155-1266-45b3-a790-c98a89e75cf8", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "link_df = DataFrame({'raw': ['https://github.com/paddymul/buckaroo', 'https://github.com/pola-rs/polars'],\n", + " 'linkify' : ['https://github.com/paddymul/buckaroo', 'https://github.com/pola-rs/polars']})\n", + "BUCKAROOWidget(link_df,\n", + " column_config_overrides={'linkify': {'displayer_args': { 'displayer': 'linkify'}}})\n", + "#fixme no underline or blue highlighting of links... but they are links" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06a67f09-191a-40d1-8cf3-2ef240290516", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "histo_df = pd.DataFrame({\n", + " 'names': ['index', 'all_NA', 'half_NA', 'longtail', 'longtail_unique'],\n", + " 'histogram_props': ['histogram',\n", + " [{'name': 'NA', 'NA': 100.0}],\n", + " [{'name': 1, 'cat_pop': 44.0}, {'name': 'NA', 'NA': 56.0}],\n", + " [{'name': 'long_97', 'cat_pop': 0.0},\n", + " {'name': 'long_139', 'cat_pop': 0.0},\n", + " {'name': 'long_12', 'cat_pop': 0.0},\n", + " {'name': 'long_134', 'cat_pop': 0.0},\n", + " {'name': 'long_21', 'cat_pop': 0.0},\n", + " {'name': 'long_44', 'cat_pop': 0.0},\n", + " {'name': 'long_58', 'cat_pop': 0.0},\n", + " {'name': 'longtail', 'longtail': 77.0},\n", + " {'name': 'NA', 'NA': 20.0}],\n", + " [{'name': 'long_113', 'cat_pop': 0.0},\n", + " {'name': 'long_116', 'cat_pop': 0.0},\n", + " {'name': 'long_33', 'cat_pop': 0.0},\n", + " {'name': 'long_72', 'cat_pop': 0.0},\n", + " {'name': 'long_122', 'cat_pop': 0.0},\n", + " {'name': 'long_6', 'cat_pop': 0.0},\n", + " {'name': 'long_83', 'cat_pop': 0.0},\n", + " {'name': 'longtail', 'unique': 50.0, 'longtail': 47.0}]]})\n", + "from buckaroo.customizations.analysis import TypingStats\n", + "from buckaroo.buckaroo_widget import BuckarooWidget\n", + "class PdGalleryBuckaroo(BuckarooWidget):\n", + " analysis_klasses = [GalleryStyling, TypingStats]\n", + "PdGalleryBuckaroo(histo_df,\n", + " column_config_overrides={\n", + " 'histogram_props': {'displayer_args': {'displayer': 'histogram'}}})\n", + "#Fixme, this doesn't work with polars right now, probably related to the object dtype problem" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "fd4dd7b5-ed26-42b6-aa20-f9d7211b7e95", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "png_smiley = 'iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=';" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "0f6231ea-a570-40d7-ab9d-86e8ce08c5a9", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "65cbba804f404b3fa5ed81c9e3bc877d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "PolarsBuckarooWidget(buckaroo_options={'sampled': ['random'], 'auto_clean': ['aggressive', 'conservative'], 'p…" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "img_df = DataFrame({'raw': [png_smiley, None],\n", + " 'img_displayer' : [png_smiley, None]})\n", + "BUCKAROOWidget(img_df,\n", + " column_config_overrides={\n", + " 'raw': {'displayer_args': {'displayer': 'string', 'max_length':40}},\n", + " 'img_displayer': {'displayer_args': {'displayer': 'Base64PNGImageDisplayer'}, 'ag_grid_specs' : {'width':150}}})" + ] + }, + { + "cell_type": "markdown", + "id": "c8d2accd-4732-43ff-b92a-d827b330b538", + "metadata": {}, + "source": [ + "# Tooltips" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "344ce005-1c0d-4ee6-8ef3-95c2cde977ac", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ROWS = 200\n", + "typed_df = pl.DataFrame({'int_col':np.random.randint(1,50, ROWS), 'float_col': np.random.randint(1,30, ROWS)/.7,\n", + " \"str_col\": [\"foobar\"]* ROWS})\n", + "PolarsBuckarooWidget(\n", + " typed_df, \n", + " column_config_overrides={\n", + " 'str_col':\n", + " {'tooltip_config': { 'tooltip_type':'simple', 'val_column': 'int_col'}}})" + ] + }, + { + "cell_type": "markdown", + "id": "f7a91713-b95d-4546-a5ad-0be964f4b2df", + "metadata": {}, + "source": [ + "# Color_map_config\n", + "```ts\n", + "//ColorMapRules\n", + "export interface ColorMapRules {\n", + " color_rule: 'color_map';\n", + " map_name: 'BLUE_TO_YELLOW' | 'DIVERGING_RED_WHITE_BLUE';\n", + " //optional, the column to base the ranges on. the proper histogram_bins must still be sent in for that column\n", + " val_column?: string;\n", + "}\n", + "\n", + "//if exist_column is not null, set cell style to condtional_color... used for highlighting changed values or errored_rows\n", + "export interface ColorWhenNotNullRules {\n", + " color_rule: 'color_not_null';\n", + " conditional_color: string | 'red';\n", + " exist_column: string;\n", + "}\n", + "\n", + "export interface ColorFromColumn {\n", + " color_rule: 'color_from_column';\n", + " col_name: string;\n", + "}\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3dbf1c45-7725-4cd7-8008-da3085f55667", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "PolarsBuckarooWidget(\n", + " typed_df, \n", + " column_config_overrides={\n", + " 'float_col': {'color_map_config': {\n", + " 'color_rule': 'color_map',\n", + " 'map_name': 'BLUE_TO_YELLOW',\n", + " }}})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a43ecbfb-ae8d-428f-9cb5-29eb53afa076", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "error_df = pl.DataFrame({\n", + " 'a': [10, 20, 30],\n", + " 'err_messages': [None, \"a must be less than 19, it is 20\", \"a must be less than 19, it is 30\"]})\n", + "\n", + "PolarsBuckarooWidget(\n", + " error_df, \n", + " column_config_overrides={\n", + " 'a': {'color_map_config': {\n", + " 'color_rule': 'color_not_null',\n", + " 'conditional_color': 'red',\n", + " 'exist_column': 'err_messages'}}})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0bc7cef8-1f93-4415-a420-c9aa44fd583e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "color_df = pl.DataFrame({\n", + " 'a': [10, 20, 30],\n", + " 'a_colors': ['red', '#d3a', 'green']})\n", + "\n", + "PolarsBuckarooWidget(\n", + " color_df, \n", + " column_config_overrides={\n", + " 'a': { 'color_map_config': {\n", + " 'color_rule': 'color_from_column',\n", + " 'col_name': 'a_colors'}}})" + ] + }, + { + "cell_type": "markdown", + "id": "1768186c-14fc-49fa-8e03-e8f454411d5b", + "metadata": {}, + "source": [ + "Extra col def type\n", + "\n", + "`ag_grid_specs`\n", + "only to be used for very specific hacking. You can set any primitive property, but can't set function props\n", + "https://github.com/ag-grid/ag-grid/blob/3cce76f1f2fd7142126f659fdc1dc3f0b7bc6191/grid-community-modules/core/src/ts/entities/colDef.ts#L4\n", + "\n", + "latest\n", + "https://github.com/ag-grid/ag-grid/blob/latest/grid-community-modules/core/src/ts/entities/colDef.ts" + ] + }, + { + "cell_type": "markdown", + "id": "2ebaa204-9a32-47d0-9d87-14d9755a738b", + "metadata": {}, + "source": [ + "# Utility Code" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3fd31184-6197-4d13-a319-aaefee224745", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#utility code for generating histogram data structures\n", + "from buckaroo.buckaroo_widget import BuckarooWidget\n", + "\n", + "NA = pd.NA\n", + "def rand_cat(named_p, na_per, N):\n", + " choices, p = [], []\n", + " named_total_per = sum(named_p.values()) + na_per\n", + " total_len = int(np.floor(named_total_per * N))\n", + " if named_total_per > 0:\n", + " for k, v in named_p.items():\n", + " choices.append(k)\n", + " p.append(v/named_total_per)\n", + "\n", + " choices.append(NA)\n", + " p.append(na_per/named_total_per) \n", + " return [np.random.choice(choices, p=p) for k in range(total_len)]\n", + " else:\n", + " return []\n", + "\n", + "def random_categorical(named_p, unique_per, na_per, longtail_per, N):\n", + " choice_arr = rand_cat(named_p, na_per, N)\n", + " discrete_choice_len = len(choice_arr)\n", + "\n", + " longtail_count = int(np.floor(longtail_per * N))//2\n", + " extra_arr = []\n", + " for i in range(longtail_count):\n", + " extra_arr.append(\"long_%d\" % i)\n", + " extra_arr.append(\"long_%d\" % i)\n", + "\n", + " unique_len = N - (len(extra_arr) + discrete_choice_len)\n", + " #print(\"discrete_choice_len\", discrete_choice_len, \"longtail_count\", longtail_count, \"unique_len\", unique_len)\n", + " for i in range(unique_len):\n", + " extra_arr.append(\"unique_%d\" % i)\n", + " all_arr = np.concatenate([choice_arr, extra_arr])\n", + " np.random.shuffle(all_arr)\n", + " return all_arr \n", + "cat_histo_df = pd.DataFrame({\n", + " 'all_NA' : [NA] * N,\n", + " 'half_NA' : random_categorical({1: .5}, unique_per=0, na_per=.5, longtail_per=.0, N=N),\n", + " 'longtail' : random_categorical({}, unique_per=0, na_per=.2, longtail_per=.8, N=N),\n", + " 'longtail_unique' : random_categorical({}, unique_per=0.5, na_per=.0, longtail_per=.5, N=N),\n", + "})\n", + "bw = BuckarooWidget(\n", + " cat_histo_df, \n", + " pinned_rows=[\n", + " { 'primary_key_val': 'dtype', 'displayer_args': { 'displayer': 'obj' } },\n", + " { 'primary_key_val': 'histogram', 'displayer_args': { 'displayer': 'histogram' }}, \n", + " ])\n", + "histogram_vals = [x for x in bw.df_data_dict['all_stats'] if x['index'] == 'histogram'][0]\n", + "def format_histo(bw):\n", + " histogram_vals = [x for x in bw.df_data_dict['all_stats'] if x['index'] == 'histogram'][0]\n", + " return dict(\n", + " names = list(histogram_vals.keys()),\n", + " histogram_props = list(histogram_vals.values()))\n", + "format_histo(bw)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9eee93ff-49c2-41ca-b402-5378afa04ab8", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from buckaroo.customizations.analysis import TypingStats\n", + "from buckaroo.buckaroo_widget import BuckarooWidget\n", + "class PdGalleryBuckaroo(BuckarooWidget):\n", + " analysis_klasses = [GalleryStyling, TypingStats]\n", + "\n", + "class PdGalleryBuckaroo(BuckarooWidget):\n", + " analysis_klasses = [GalleryStyling, TypingStats]\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df395ef4-2f33-49d5-a380-6cead5926566", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pd_histo = pd.DataFrame(format_histo(bw))\n", + "col_dict = dict(pd_histo.to_numpy().tolist()[1:])\n", + "pl_histo = pl.DataFrame(dict([(k, [v]) for k,v in col_dict.items()]))\n", + "PolarsBuckarooWidget(pl_histo)\n", + "GalleryBuckaroo(pl_histo,\n", + " column_config_overrides={\n", + " 'histogram_props': {'displayer_args': {'displayer': 'histogram'}}})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8a8b8b12-d094-4dcc-9152-1b00e77fb182", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pl_gb = GalleryBuckaroo(pl.DataFrame(format_histo(bw)))\n", + "pd_gb = PdGalleryBuckaroo(pd.DataFrame(format_histo(bw)))\n", + "pd_gb.df_data_dict['main']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "440fb9fe-96b5-49c2-a341-41583b8fc0c6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pl_gb.df_data_dict['main']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a10fe4bf-4522-41b5-b634-736cf5280cf5", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from buckaroo.customizations.analysis import TypingStats\n", + "from buckaroo.buckaroo_widget import BuckarooWidget\n", + "class PdGalleryBuckaroo(BuckarooWidget):\n", + " analysis_klasses = [GalleryStyling, TypingStats]\n", + "PdGalleryBuckaroo(pd.DataFrame(format_histo(bw)),\n", + " column_config_overrides={\n", + " 'histogram_props': {'displayer_args': {'displayer': 'histogram'}}})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57adf339-87aa-4e34-a2ab-ad02846a871c", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8e80393b-fa65-4c1b-89df-7345c4206b60", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": { + "65cbba804f404b3fa5ed81c9e3bc877d": { + "model_module": "buckaroo", + "model_module_version": "^0.6.2", + "model_name": "DCEFWidgetModel", + "state": { + "_model_module_version": "^0.6.2", + "_view_module_version": "^0.6.2", + "_view_name": "DCEFWidgetView", + "buckaroo_options": { + "auto_clean": [ + "aggressive", + "conservative" + ], + "df_display": [ + "summary", + "main" + ], + "post_processing": [ + "" + ], + "sampled": [ + "random" + ], + "show_commands": [ + "on" + ], + "summary_stats": [ + "all" + ] + }, + "buckaroo_state": { + "auto_clean": "conservative", + "df_display": "main", + "post_processing": "", + "sampled": false, + "search_string": "", + "show_commands": false + }, + "commandConfig": {}, + "df_data_dict": { + "all_stats": [ + { + "img_displayer": "shape: (2,)\nSeries: '' [struct[2]]\n[\n\t{\"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=\",1}\n\t{null,1}\n]", + "index": "value_counts", + "raw": "shape: (2,)\nSeries: '' [struct[2]]\n[\n\t{\"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=\",1}\n\t{null,1}\n]" + }, + { + "img_displayer": "String", + "index": "dtype", + "raw": "String" + }, + { + "img_displayer": "string", + "index": "_type", + "raw": "string" + }, + { + "img_displayer": false, + "index": "is_numeric", + "raw": false + }, + { + "img_displayer": false, + "index": "is_integer", + "raw": false + }, + { + "img_displayer": 2, + "index": "length", + "raw": 2 + }, + { + "img_displayer": 1, + "index": "nan_count", + "raw": 1 + }, + { + "img_displayer": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=", + "index": "min", + "raw": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=" + }, + { + "img_displayer": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=", + "index": "max", + "raw": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=" + }, + { + "img_displayer": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=", + "index": "mode", + "raw": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=" + }, + { + "img_displayer": null, + "index": "mean", + "raw": null + }, + { + "img_displayer": 2, + "index": "unique_count", + "raw": 2 + }, + { + "img_displayer": 0, + "index": "empty_count", + "raw": 0 + }, + { + "img_displayer": 2, + "index": "distinct_count", + "raw": 2 + }, + { + "img_displayer": 1, + "index": "distinct_per", + "raw": 1 + }, + { + "img_displayer": 0, + "index": "empty_per", + "raw": 0 + }, + { + "img_displayer": 1, + "index": "unique_per", + "raw": 1 + }, + { + "img_displayer": 0.5, + "index": "nan_per", + "raw": 0.5 + }, + { + "img_displayer": { + "None": 0.5, + "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=": 0.5, + "longtail": -1, + "unique": 1 + }, + "index": "categorical_histogram", + "raw": { + "None": 0.5, + "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=": 0.5, + "longtail": -1, + "unique": 1 + } + }, + { + "img_displayer": [ + { + "cat_pop": 50, + "name": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=" + }, + { + "cat_pop": 50, + "name": null + }, + { + "name": "unique", + "unique": 100 + }, + { + "NA": 50, + "name": "NA" + } + ], + "index": "histogram", + "raw": [ + { + "cat_pop": 50, + "name": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=" + }, + { + "cat_pop": 50, + "name": null + }, + { + "name": "unique", + "unique": 100 + }, + { + "NA": 50, + "name": "NA" + } + ] + }, + { + "img_displayer": [ + "faked" + ], + "index": "histogram_bins", + "raw": [ + "faked" + ] + } + ], + "empty": [], + "main": [ + { + "img_displayer": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=", + "index": 0, + "raw": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=" + }, + { + "img_displayer": null, + "index": 1, + "raw": null + } + ] + }, + "df_display_args": { + "main": { + "data_key": "main", + "df_viewer_config": { + "column_config": [ + { + "col_name": "index", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "raw", + "displayer_args": { + "displayer": "string", + "max_length": 40 + } + }, + { + "ag_grid_specs": { + "width": 150 + }, + "col_name": "img_displayer", + "displayer_args": { + "displayer": "Base64PNGImageDisplayer" + } + } + ], + "pinned_rows": [ + { + "displayer_args": { + "displayer": "obj" + }, + "primary_key_val": "dtype" + }, + { + "displayer_args": { + "displayer": "histogram" + }, + "primary_key_val": "histogram" + } + ] + }, + "summary_stats_key": "all_stats" + }, + "summary": { + "data_key": "empty", + "df_viewer_config": { + "column_config": [ + { + "col_name": "index", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "raw", + "displayer_args": { + "displayer": "string", + "max_length": 40 + } + }, + { + "ag_grid_specs": { + "width": 150 + }, + "col_name": "img_displayer", + "displayer_args": { + "displayer": "Base64PNGImageDisplayer" + } + } + ], + "pinned_rows": [ + { + "displayer_args": { + "displayer": "obj" + }, + "primary_key_val": "dtype" + }, + { + "displayer_args": { + "displayer": "float", + "max_fraction_digits": 3, + "min_fraction_digits": 3 + }, + "primary_key_val": "min" + }, + { + "displayer_args": { + "displayer": "float", + "max_fraction_digits": 3, + "min_fraction_digits": 3 + }, + "primary_key_val": "mean" + }, + { + "displayer_args": { + "displayer": "float", + "max_fraction_digits": 3, + "min_fraction_digits": 3 + }, + "primary_key_val": "max" + }, + { + "displayer_args": { + "displayer": "float", + "max_fraction_digits": 0, + "min_fraction_digits": 0 + }, + "primary_key_val": "unique_count" + }, + { + "displayer_args": { + "displayer": "float", + "max_fraction_digits": 0, + "min_fraction_digits": 0 + }, + "primary_key_val": "distinct_count" + }, + { + "displayer_args": { + "displayer": "float", + "max_fraction_digits": 0, + "min_fraction_digits": 0 + }, + "primary_key_val": "empty_count" + } + ] + }, + "summary_stats_key": "all_stats" + } + }, + "df_meta": { + "columns": 2, + "rows_shown": 2, + "total_rows": 2 + }, + "layout": "IPY_MODEL_c5d9e4c6ea08435daa316270b5977d54", + "operation_results": { + "generated_py_code": "# instantiation, unused", + "transformed_df": { + "column_config": [], + "data": [], + "pinned_rows": [] + } + }, + "operations": [] + } + }, + "c5d9e4c6ea08435daa316270b5977d54": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "2.0.0", + "model_name": "LayoutModel", + "state": {} + }, + "dee2e1643b05493fa3422d21b0f0817d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "2.0.0", + "model_name": "LayoutModel", + "state": {} + }, + "f1de7ec8051b4cdfa908edb2b3f69291": { + "model_module": "buckaroo", + "model_module_version": "^0.6.2", + "model_name": "DCEFWidgetModel", + "state": { + "_model_module_version": "^0.6.2", + "_view_module_version": "^0.6.2", + "_view_name": "DCEFWidgetView", + "buckaroo_options": { + "auto_clean": [ + "aggressive", + "conservative" + ], + "df_display": [ + "main" + ], + "post_processing": [ + "" + ], + "sampled": [ + "random" + ], + "show_commands": [ + "on" + ], + "summary_stats": [ + "all" + ] + }, + "buckaroo_state": { + "auto_clean": "conservative", + "df_display": "main", + "post_processing": "", + "sampled": false, + "search_string": "", + "show_commands": false + }, + "commandConfig": {}, + "df_data_dict": { + "all_stats": [ + { + "bools": "Boolean", + "dicts": "Struct({'a': Int64, 'b': Int64, 'c': String})", + "index": "dtype", + "ints": "Int64", + "lists": "List(String)", + "lists-int": "List(Int64)", + "lists-string": "List(String)", + "nested_dicts": "Struct({'level_1': Struct({'a': Int64, 'b': Int64, 'c': String})})", + "timestamp": "String" + }, + { + "bools": "boolean", + "dicts": "unknown", + "index": "_type", + "ints": "integer", + "lists": "unknown", + "lists-int": "unknown", + "lists-string": "unknown", + "nested_dicts": "unknown", + "timestamp": "string" + }, + { + "bools": false, + "dicts": false, + "index": "is_numeric", + "ints": true, + "lists": false, + "lists-int": false, + "lists-string": false, + "nested_dicts": false, + "timestamp": false + }, + { + "bools": false, + "dicts": false, + "index": "is_integer", + "ints": true, + "lists": false, + "lists-int": false, + "lists-string": false, + "nested_dicts": false, + "timestamp": false + } + ], + "empty": [], + "main": [ + { + "bools": true, + "dicts": { + "a": 10, + "b": 20, + "c": "some string" + }, + "index": 0, + "ints": 5, + "lists": [ + "a", + "b" + ], + "lists-int": [ + 10, + 20 + ], + "lists-string": [ + "a", + "b" + ], + "nested_dicts": { + "level_1": { + "a": 10, + "b": 20, + "c": "some string" + } + }, + "timestamp": "2020-01-01 01:00Z" + }, + { + "bools": true, + "dicts": { + "a": null, + "b": null, + "c": null + }, + "index": 1, + "ints": 20, + "lists": [ + "1", + "2" + ], + "lists-int": [ + 100, + 500 + ], + "lists-string": [ + "foo", + "bar" + ], + "nested_dicts": { + "level_1": { + "a": null, + "b": null, + "c": null + } + }, + "timestamp": "2020-01-01 02:00Z" + }, + { + "bools": false, + "dicts": { + "a": null, + "b": null, + "c": null + }, + "index": 2, + "ints": 30, + "lists": null, + "lists-int": [ + 8 + ], + "lists-string": null, + "nested_dicts": { + "level_1": { + "a": null, + "b": null, + "c": null + } + }, + "timestamp": "2020-02-28 02:00Z" + }, + { + "bools": false, + "dicts": { + "a": null, + "b": null, + "c": null + }, + "index": 3, + "ints": -10, + "lists": null, + "lists-int": null, + "lists-string": null, + "nested_dicts": { + "level_1": { + "a": null, + "b": null, + "c": null + } + }, + "timestamp": "2020-03-15 02:00Z" + }, + { + "bools": true, + "dicts": { + "a": null, + "b": null, + "c": null + }, + "index": 4, + "ints": 7772, + "lists": null, + "lists-int": null, + "lists-string": null, + "nested_dicts": { + "level_1": { + "a": null, + "b": null, + "c": null + } + }, + "timestamp": null + }, + { + "bools": null, + "dicts": { + "a": null, + "b": null, + "c": null + }, + "index": 5, + "ints": null, + "lists": null, + "lists-int": null, + "lists-string": null, + "nested_dicts": { + "level_1": { + "a": null, + "b": null, + "c": null + } + }, + "timestamp": null + } + ] + }, + "df_display_args": { + "main": { + "data_key": "main", + "df_viewer_config": { + "column_config": [ + { + "col_name": "index", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "bools", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "ints", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "timestamp", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "dicts", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "nested_dicts", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "lists", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "lists-string", + "displayer_args": { + "displayer": "obj" + } + }, + { + "col_name": "lists-int", + "displayer_args": { + "displayer": "obj" + } + } + ], + "pinned_rows": [ + { + "displayer_args": { + "displayer": "obj" + }, + "primary_key_val": "dtype" + } + ] + }, + "summary_stats_key": "all_stats" + } + }, + "df_meta": { + "columns": 8, + "rows_shown": 6, + "total_rows": 6 + }, + "layout": "IPY_MODEL_dee2e1643b05493fa3422d21b0f0817d", + "operation_results": { + "generated_py_code": "# instantiation, unused", + "transformed_df": { + "column_config": [], + "data": [], + "pinned_rows": [] + } + }, + "operations": [] + } + } + }, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/example-notebooks/styling-howto.ipynb b/example-notebooks/styling-howto.ipynb new file mode 100644 index 000000000..7d0171ed5 --- /dev/null +++ b/example-notebooks/styling-howto.ipynb @@ -0,0 +1,545 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f7fd6f90-3a45-4090-a0aa-bf0e03aab56b", + "metadata": { + "tags": [] + }, + "source": [ + "# How to style Buckaroo tables\n", + "Buckaroo had a major refactoring of the styling system and callbacks with the 0.6 release.\n", + "\n", + "This notebook walks through\n", + "* Styling columns via the `displayer`\n", + "* How to override columns\n", + "* Tooltips\n", + "* Cell Coloring\n", + "* Column hiding\n", + "* pinned_rows\n", + "* How to add automatic styling methods that are available via the UI to cycle through" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73f3516e-2273-495a-b3b9-f68593b0018b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from buckaroo.dataflow import StylingAnalysis\n", + "from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import ColAnalysis\n", + "import polars as pl\n", + "from buckaroo.polars_buckaroo import PolarsBuckarooWidget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45a03efb-ec32-4cda-b443-99425e80a458", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ROWS = 200\n", + "typed_df = pl.DataFrame({'int_col':np.random.randint(1,50, ROWS), 'float_col': np.random.randint(1,30, ROWS)/.7,\n", + " \"str_col\": [\"foobar\"]* ROWS})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8086b3b9-f97e-4b4c-9c0a-85566be060a3", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "PolarsBuckarooWidget(typed_df)" + ] + }, + { + "cell_type": "markdown", + "id": "04bae28c-68e4-43d1-b323-1ac503efa18a", + "metadata": {}, + "source": [ + "## `displayer`\n", + "Changing the `displayer` is the most common way to customize the styling of a column, in the next example, we override the column_config for `float_col`\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3c6d50c3-004b-4850-8404-bef00a990e55", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "bw2 = PolarsBuckarooWidget(\n", + " typed_df, \n", + " debug=False,\n", + " column_config_overrides={\n", + " 'float_col':\n", + " {'displayer_args': { 'displayer': 'float', 'min_fraction_digits':0, 'max_fraction_digits':3}}})\n", + "bw2" + ] + }, + { + "cell_type": "markdown", + "id": "de8b7829-c898-4fec-93b0-09c3f7552146", + "metadata": {}, + "source": [ + "Now we are going to force `float_col` to be displayed with a 'float' displayer\n", + "notice how the decimal point aligns as opposed to above where 10 is floored without a decimal portion\n", + "\n", + "Currently the types are best viewed in their typescript definition [DFWhole.ts](https://github.com/paddymul/buckaroo/blob/feat/dfviewer-config/js/components/DFViewerParts/DFWhole.ts)\n", + "\n", + "There are Displayers of\n", + "\n", + "`ObjDisplayer`, `BooleanDisplayer`, `StringDisplayer`, `FloatDisplayer`, \n", + "`DatetimeDefaultDisplayer`, `DatetimeLocaleDisplayer`, `IntegerDisplayer`,\n", + "\n", + "`HistogramDisplayer`, and `LinkifyDisplayer`,\n", + "\n", + "There are planned displayers of [HumanAbbreviationDisplayer](https://github.com/paddymul/buckaroo/issues/83), [LineChartDisplayer](https://github.com/paddymul/buckaroo/issues/210), [GoogleMapsLinkDisplayer](https://github.com/paddymul/buckaroo/issues/211) , [InlineMapDisplayer](https://github.com/paddymul/buckaroo/issues/212)\n", + "\n", + "\n", + "There is experimental work building mirrored PyDantic types, and work to integrate this typechecking into Buckaroo. There are also plans for a gallery of examples of the different options." + ] + }, + { + "cell_type": "markdown", + "id": "8999d568-ddbe-40c8-a7cb-fa7fe0c47c9c", + "metadata": {}, + "source": [ + "# `tooltip_config`\n", + "\n", + "There are tooltip_configs of simple summary_series available\n", + "\n", + "Tooltips are helpful for adding extra context to cells. Particularly for noting errors or values changed via auto-cleaning\n", + "\n", + "Notice that `column_config_overrides` is merged with the existing column config from Buckaroo, every column still has a displayer" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "abc0e795-4ab9-4a5d-b09d-3b926e82afee", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "bw3 = PolarsBuckarooWidget(\n", + " typed_df, \n", + " column_config_overrides={\n", + " 'str_col':\n", + " {'tooltip_config': { 'tooltip_type':'simple', 'val_column': 'int_col'}}})\n", + "bw3" + ] + }, + { + "cell_type": "markdown", + "id": "c5e17dd6-f658-48d1-b40c-a4ac354ea5d5", + "metadata": {}, + "source": [ + "# color_map_config\n", + "\n", + "Color_map_config controls coloring of columns. \n", + "* `color_map` uses the bins from histogram to show a values place in the distribution. wit the `val_column` parameter, you can color one column based on another.\n", + "* `color_when_not_null` hilights a cell when another row is not null. This is meant for error highlighting, the other column can be hidden\n", + "* `color_from_column` bases the color of a cell based on the RGB value written to another column. It is the most generic coloring option" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a75b18b-c61d-45d7-b0e1-295ad869a17c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "bw3 = PolarsBuckarooWidget(\n", + " typed_df, \n", + " column_config_overrides={\n", + " 'float_col': {'color_map_config': {\n", + " 'color_rule': 'color_map',\n", + " 'map_name': 'BLUE_TO_YELLOW',\n", + " }}})\n", + "bw3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3a2a125c-75c7-42ae-a87f-6a47bd41068c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "bw3 = PolarsBuckarooWidget(\n", + " typed_df, \n", + " column_config_overrides={\n", + " 'int_col': {'color_map_config': {\n", + " 'color_rule': 'color_map',\n", + " 'map_name': 'DIVERGING_RED_WHITE_BLUE',\n", + " 'val_column': 'float_col'\n", + " }}})\n", + "bw3" + ] + }, + { + "cell_type": "markdown", + "id": "0ca07426-086c-4041-bf08-07c7447c8eb5", + "metadata": {}, + "source": [ + "# Hiding a column\n", + "\n", + "You can hide a column with `merge_rule:'hidden'`. This removes that column from the column_config array.\n", + "\n", + "Column hiding can be used to keep data in a dataframe (sent to the table widget) for use as a tooltip, or color, but preventing display which would distract the user\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "924c506c-123c-43ed-80f8-e239014f7e75", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "bw_ = PolarsBuckarooWidget(\n", + " typed_df, \n", + " column_config_overrides={\n", + " 'int_col': {'merge_rule': 'hidden'}})\n", + "bw_" + ] + }, + { + "cell_type": "markdown", + "id": "621d5306-ba11-487b-bb5b-3841c412bf3a", + "metadata": {}, + "source": [ + "# Pinned rows\n", + "Pinned rows are visible in each view. They read data from the summary data that is assembled from the [PluggableAnalysisFramework](https://buckaroo-data.readthedocs.io/en/latest/articles/pluggable.html).\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "42da3b2a-a3bf-4c89-be15-0227fc9b916a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "bw = PolarsBuckarooWidget(\n", + " typed_df, \n", + " pinned_rows=[\n", + " {'primary_key_val': 'dtype', 'displayer_args': {'displayer': 'obj' } },\n", + " {'primary_key_val': 'histogram', 'displayer_args': {'displayer': 'histogram' }}, \n", + " ])\n", + "bw" + ] + }, + { + "cell_type": "markdown", + "id": "05ecd1e4-1bde-48ce-ac51-bf53f7bb91c4", + "metadata": {}, + "source": [ + "# Packaging and reusing styling configurations with the `StylingAnalysis` class\n", + "Up to this point we have been hardcoding config overrides. You can package sets of styling configuration with the `StylingAnalysis` class. These configs can then be toggled in the UI.\n", + "\n", + "If you just want to return a fixed `DFViewerConfig` override the `style_columns` method. Most likely though, you will want to overide the singular `style_column` method that gets `SingleColumnMetadata` and returns a `ColumnConfig`. \n", + "The `StylingAnalysis` class is used to control the display of a column based on the column metadata. \n", + "\n", + "return {'col_name':str(col), 'displayer_args': {'displayer': 'obj'}}\n", + "\n", + "\n", + "This lets you customize based on metadata collected about a column. This works with the [PluggableAnalysisFramework](https://buckaroo-data.readthedocs.io/en/latest/articles/pluggable.html), you can specify required fields that are necessary. Adding requirements like this garuntees that errors are spotted early.\n", + "\n", + "StylingAnalysis works for both Polars and Pandas because it only receives a dictionary with simple python values" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c03b5bc4-0025-4b55-9e7c-cc1a69508688", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class SimpleStylingAnalysis(StylingAnalysis):\n", + " pinned_rows = [{'primary_key_val': 'dtype', 'displayer_args': {'displayer': 'obj'}}]\n", + "\n", + " #typing is still be worked out\n", + " #def style_column(col:str, column_metadata: SingleColumnMetadata) -> ColumnConfig:\n", + " @classmethod\n", + " def style_column(kls, col, column_metadata):\n", + " return {'col_name':str(col), 'displayer_args': {'displayer': 'obj'}}\n", + "\n", + " \n", + " #what is the key for this in the df_display_args_dictionary\n", + " df_display_name = \"MyStyles\"\n", + "def obj_(pkey):\n", + " return {'primary_key_val': pkey, 'displayer_args': { 'displayer': 'obj' } }\n", + "def float_(pkey, digits=3):\n", + " return {'primary_key_val': pkey, \n", + " 'displayer_args': { 'displayer': 'float', 'min_fraction_digits':digits, 'max_fraction_digits':digits}}" + ] + }, + { + "cell_type": "markdown", + "id": "a60bf7a8-4d5d-4089-8157-dafbd5a689ef", + "metadata": {}, + "source": [ + "## Toggling between styles\n", + "In the following example, you can cycle between the two configs by clicking on \"main\". Eventually I will add a Select (dropdown) box for this. I personally prefer click to cycle" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e8b25177-de65-4f5f-838f-152e1b621f5c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#The following analysis only\n", + "class SummaryStatsAnalysis(StylingAnalysis):\n", + " requires_summary = ['dtype', 'min', 'mode', 'mean', 'max', 'unique_count', 'distinct_count', 'empty_count']\n", + " pinned_rows = [obj_('dtype'), float_('min'), \n", + " #float_('mode'), float_('mean'), \n", + " float_('max'), float_('unique_count', 0),\n", + " float_('distinct_count', 0), float_('empty_count', 0)]\n", + " df_display_name = \"summary\"\n", + " data_key = \"empty\"\n", + " summary_stats_key= 'all_stats'\n", + "\n", + "sbw = PolarsBuckarooWidget(typed_df, debug=True)\n", + "sbw.add_analysis(SummaryStatsAnalysis)\n", + "\n", + "sbw" + ] + }, + { + "cell_type": "markdown", + "id": "1b0b5aa9-e820-49bd-a242-d8cf68441191", + "metadata": {}, + "source": [ + "## overriding styling from post_processing\n", + "\n", + "`PostProcessing` returns a tuple of Dataframe, extra column metadata.\n", + "\n", + "The default base styling class which all examples here extend, handles the key of `column_config_override` speically.\n", + "\n", + "This lets you build a specialized dataframe along with specific styling rules. Auto_cleaning and regular polars/pandas analysis can use the same facility. It is not recommended for regular analysis.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df64d5b2-e408-48ff-978f-8790c46dff21", + "metadata": {}, + "outputs": [], + "source": [ + "class ColumnConfigOverride(ColAnalysis):\n", + " @classmethod\n", + " def post_process_df(kls, df):\n", + " return [df, {\n", + " 'int_col':{\n", + " 'column_config_override': {'color_map_config': {\n", + " 'color_rule': 'color_map',\n", + " 'map_name': 'BLUE_TO_YELLOW',\n", + " }}}}]\n", + " post_processing_method = \"override\"\n", + "bw = PolarsBuckarooWidget(typed_df)\n", + "bw.add_analysis(ColumnConfigOverride)\n", + "bw " + ] + }, + { + "cell_type": "markdown", + "id": "a2618a7e-b8d9-44ca-b598-07428e654668", + "metadata": {}, + "source": [ + "# Buckaroo internals related to styling\n", + "this can help debug what is going on with styling" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "323a5a9d-933b-4bad-856d-17162a22913a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#you can view the main display_args with the following statement, this lets you check what is actually being sent to the frontend\n", + "sbw.df_display_args['main']['df_viewer_config']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d8ee357c-ba69-49b1-a8a9-bc31cb8cde47", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# it's annoying to type out all of those pinned rows, lets make some convienence functions\n", + "def obj_(pkey):\n", + " return {'primary_key_val': pkey, 'displayer_args': { 'displayer': 'obj' } }\n", + "\n", + "def float_(pkey, digits=3):\n", + " return {'primary_key_val': pkey, \n", + " 'displayer_args': { 'displayer': 'float', 'min_fraction_digits':digits, 'max_fraction_digits':digits}}\n", + "\n", + "class SummaryStatsAnalysis1(SimpleStylingAnalysis):\n", + " pinned_rows = [\n", + " { 'primary_key_val': 'dtype', 'displayer_args': { 'displayer': 'obj' } },\n", + " { 'primary_key_val': 'histogram', 'displayer_args': { 'displayer': 'histogram' }}, \n", + " ]\n", + " df_display_name = \"summary1\"\n", + " data_key = \"empty\"\n", + " summary_stats_key= 'all_stats'\n", + "class SummaryStatsAnalysis(SimpleStylingAnalysis):\n", + " pinned_rows = [\n", + " obj_('dtype'),\n", + " float_('min'),\n", + " float_('mean'),\n", + " float_('max'),\n", + " ]\n", + " df_display_name = \"summary\"\n", + " data_key = \"empty\"\n", + " summary_stats_key= 'all_stats'\n", + "base_a_klasses = PolarsBuckarooWidget.analysis_klasses.copy()\n", + "base_a_klasses.extend([SummaryStatsAnalysis1, SummaryStatsAnalysis])\n", + "class SummaryBuckarooWidget(PolarsBuckarooWidget):\n", + " analysis_klasses = base_a_klasses\n", + "sbw = SummaryBuckarooWidget(typed_df)\n", + "#also lets do some hacking so that we start with the summary stats view\n", + "bstate = sbw.buckaroo_state.copy()\n", + "bstate['df_display'] = 'summary1'\n", + "sbw.buckaroo_state= bstate\n", + "sbw" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29aa8f47-7cd9-43c5-99e5-84ffeb39e188", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class SummaryStatsAnalysis(SimpleStylingAnalysis):\n", + " pinned_rows = [\n", + " obj_('dtype'),\n", + " float_('min'),\n", + " #float_('median'),\n", + " float_('mean'),\n", + " float_('max'),\n", + " float_('unique_count', 0),\n", + " float_('distinct_count', 0),\n", + " float_('empty_count', 0)\n", + " ]\n", + " df_display_name = \"summary\"\n", + " data_key = \"empty\"\n", + " summary_stats_key= 'all_stats'\n", + "base_a_klasses = PolarsBuckarooWidget.analysis_klasses.copy()\n", + "base_a_klasses.append(SummaryStatsAnalysis)\n", + "class SummaryBuckarooWidget(PolarsBuckarooWidget):\n", + " analysis_klasses = base_a_klasses\n", + "sbw = SummaryBuckarooWidget(typed_df)\n", + "#also lets do some hacking so that we start with the summary stats view\n", + "bstate = sbw.buckaroo_state.copy()\n", + "bstate['df_display'] = 'summary'\n", + "sbw.buckaroo_state= bstate\n", + "sbw" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "216936c9-8863-47af-bbcd-68eab766e91d", + "metadata": {}, + "outputs": [], + "source": [ + "class AdaptiveStyling(StylingAnalysis):\n", + " requires_summary = [\"histogram\", \"is_numeric\", \"dtype\", \"is_integer\"]\n", + " pinned_rows = [\n", + " obj_('dtype'),\n", + " {'primary_key_val': 'histogram', 'displayer_args': { 'displayer': 'histogram' }}]\n", + "\n", + " @classmethod\n", + " def style_columns(kls, col, sd):\n", + " digits = 3\n", + " if sd['is_integer']:\n", + " disp = {'displayer': 'float', 'min_fraction_digits':0, 'max_fraction_digits':0}\n", + " elif sd['is_numeric']:\n", + " disp = {'displayer': 'float', 'min_fraction_digits':digits, 'max_fraction_digits':digits}\n", + " else:\n", + " disp = {'displayer': 'obj'}\n", + " return {'col_name':col, 'displayer_args': disp }\n", + "base_a_klasses = PolarsBuckarooWidget.analysis_klasses.copy()\n", + "base_a_klasses.extend([AdaptiveStyling, ValueCountPostProcessing])\n", + "class ABuckarooWidget(PolarsBuckarooWidget):\n", + " analysis_klasses = base_a_klasses\n", + "acb = ABuckarooWidget(typed_df)\n", + "acb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "91a3d9a8-cbed-496e-95d1-39068bc1c99d", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/example-notebooks/testcases-fast.ipynb b/example-notebooks/testcases-fast.ipynb new file mode 100644 index 000000000..6af16ec89 --- /dev/null +++ b/example-notebooks/testcases-fast.ipynb @@ -0,0 +1,256 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "51091834-6d31-4e0e-b13c-a7be0a02ddb4", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import polars as pl\n", + "import numpy as np\n", + "import json\n", + "from buckaroo.buckaroo_widget import BuckarooWidget as PandasBuckarooWidget\n", + "from buckaroo.polars_buckaroo import PolarsBuckarooWidget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "040f826c-8bfe-4c03-bd8b-c65986d2ac2f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "df = pd.read_csv(\"/Users/paddy/code/example-notebooks/citibike-trips.csv\") #for airplane work\n", + "pl_df = pl.read_csv(\"/Users/paddy/code/example-notebooks/citibike-trips.csv\") #for" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "54790361-302e-4266-bc5e-47273997b8d2", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%timeit PandasBuckarooWidget(df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1da53d4a-1fc8-4705-acb5-d2b38d505c03", + "metadata": {}, + "outputs": [], + "source": [ + "%timeit PolarsBuckarooWidget(pl_df)" + ] + }, + { + "cell_type": "markdown", + "id": "4bc0a224-fcf7-4835-8efa-1714ef9f08b4", + "metadata": {}, + "source": [ + "# At first glance the performance is close\n", + "that looks like the performance is fairly close between polars and pandas\n", + "\n", + "I think I'm missing something" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "91062062-940e-4448-8c71-46f060b9dac3", + "metadata": {}, + "outputs": [], + "source": [ + "from buckaroo.dataflow import Sampling\n", + "class FullSampling(Sampling):\n", + " pre_limit = False\n", + "class FullPandasBuckarooWidget(PandasBuckarooWidget):\n", + " sampling_klass=FullSampling\n", + "%timeit FullPandasBuckarooWidget(df)\n", + "bw = FullPandasBuckarooWidget(df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bb36ce16-9f52-4bf3-a119-e1c490c3622f", + "metadata": {}, + "outputs": [], + "source": [ + "bw = FullPandasBuckarooWidget(df)\n", + "len(bw.processed_df)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad7249a2-6960-4505-9ae5-b0173f251463", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30063897-1b67-4507-a3b8-0d98ab0f4b9f", + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_parquet('banklist.parquet')\n", + "print(len(df) * len(df.columns), len(df), len(df.columns))\n", + "%timeit bw = BuckarooWidget(df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd8b3a75-a615-402d-9c6c-fc57c2759fe4", + "metadata": {}, + "outputs": [], + "source": [ + "df2 = pd.read_csv('death-by-suicide-hispanic.csv')\n", + "print(len(df2) * len(df2.columns), len(df2), len(df2.columns))\n", + "%timeit bw = BuckarooWidget(df2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5e338ccf-5a61-457d-addd-bdfd8510aa86", + "metadata": {}, + "outputs": [], + "source": [ + "df10 = pd.read_csv('Machine_readable_file_bd_employ.csv')\n", + "print(len(df10) * len(df10.columns), len(df10), len(df10.columns))\n", + "%timeit bw = BuckarooWidget(df10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd5b1809-5d8d-4c26-b263-165592918b2a", + "metadata": {}, + "outputs": [], + "source": [ + "df9 = pd.read_csv('scorecard.csv')\n", + "print(len(df9) * len(df9.columns), len(df9), len(df9.columns))\n", + "%timeit bw = BuckarooWidget(df9)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5159536e-bad0-46cd-ba99-77c17f42dacd", + "metadata": {}, + "outputs": [], + "source": [ + "df6 = pd.read_parquet('1993-flights.gzip.parquet')\n", + "print(len(df6) * len(df6.columns), len(df6), len(df6.columns))\n", + "%timeit bw = BuckarooWidget(df6[:10_000])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c223dcb4-a354-4f3a-b492-e6ae33c99188", + "metadata": {}, + "outputs": [], + "source": [ + "df8 = pd.read_csv('train_extended.csv')\n", + "print(len(df8) * len(df8.columns), len(df8), len(df8.columns))\n", + "%timeit bw = BuckarooWidget(df8)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c1c73c91-0343-417a-a45f-ef5f8c39e884", + "metadata": {}, + "outputs": [], + "source": [ + "df4 = pd.read_csv('WPP2022_Demographic_Indicators_Medium.csv')\n", + "print(len(df4) * len(df4.columns), len(df4), len(df4.columns))\n", + "%timeit bw = BuckarooWidget(df4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "97851149-49b4-41e2-a14f-ee9fbfcf7848", + "metadata": {}, + "outputs": [], + "source": [ + "df5 = pd.read_parquet('2014-01-citibike-trip-data.parquet')\n", + "print(len(df5) * len(df5.columns), len(df5), len(df5.columns))\n", + "%timeit bw = BuckarooWidget(df5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1bb274bb-27b0-4bb4-b296-7c246ced9ce5", + "metadata": {}, + "outputs": [], + "source": [ + "df3 = pd.read_parquet('Covid-data.gzip.parquet')\n", + "print(len(df3) * len(df3.columns), len(df3), len(df3.columns))\n", + "%timeit bw = BuckarooWidget(df3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12553bd6-be53-4001-be9a-dfc939981d38", + "metadata": {}, + "outputs": [], + "source": [ + "%timeit bw = BuckarooWidget(df6)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "257f2303-2b64-447b-8523-f8defac60cd9", + "metadata": {}, + "outputs": [], + "source": [ + "%prun -s cumtime " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/full_build.sh b/full_build.sh index 7aac4e27b..3f666b7c0 100755 --- a/full_build.sh +++ b/full_build.sh @@ -1,9 +1,10 @@ #!/bin/bash set -e -rm -rf node_modules +#rm -rf node_modules rm -rf dist python -m build . -rm dist/index.js dist/index.js.LICENSE.txt +rm -f dist/index.js dist/index.js.LICENSE.txt twine check dist/* -python -m twine upload --repository testpypi dist/* -python -m twine upload --repository pypi dist/* +#python -m twine upload --repository testpypi dist/* +#python -m twine upload --repository pypi dist/* +#npm publish diff --git a/introduction.ipynb b/introduction.ipynb index 2124de69c..97706d67f 100644 --- a/introduction.ipynb +++ b/introduction.ipynb @@ -7,7 +7,8 @@ "outputs": [], "source": [ "import pandas as pd\n", - "from dcef.dcef_widget import DCEFWidget" + "import numpy as np\n", + "from buckaroo.buckaroo_widget import BuckarooWidget" ] }, { @@ -16,22 +17,230 @@ "metadata": {}, "outputs": [], "source": [ - "df = pd.read_csv('./examples/data/2014-01-citibike-tripdata.csv')\n", - "w = DCEFWidget(df)\n", + "df = pd.read_csv('./examples/data/yellow_tripdata_2021-02.csv')\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "w = BuckarooWidget(df, showCommands=False)\n", "w" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Adding a summary stat" + ] + }, { "cell_type": "code", "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from buckaroo.pluggable_analysis_framework import (ColAnalysis)\n", + "from scipy.stats import skew\n", + "class Skew(ColAnalysis):\n", + " provides_summary = [\"skew\"]\n", + " requires_summary = []\n", + " \n", + " @staticmethod\n", + " def summary(sampled_ser, summary_ser, ser):\n", + " if pd.api.types.is_integer_dtype(sampled_ser):\n", + " return dict(skew=skew(sampled_ser.dropna().astype('int64')))\n", + " elif pd.api.types.is_float_dtype(sampled_ser):\n", + " return dict(skew=skew(sampled_ser.astype('float64')))\n", + " else:\n", + " return dict(skew=\"NA\")\n", + " summary_stats_display = [\n", + " 'dtype',\n", + " 'length',\n", + " 'nan_count',\n", + " 'distinct_count',\n", + " 'empty_count',\n", + " 'empty_per',\n", + " 'unique_per',\n", + " 'nan_per',\n", + " 'is_numeric',\n", + " 'is_integer',\n", + " 'is_datetime',\n", + " 'mode',\n", + " 'min',\n", + " 'max',\n", + " 'mean',\n", + " # we must add skew to the list of summary_stats_display, otherwise our new stat won't be displayed\n", + " 'skew']\n", + "w.add_analysis(Skew)" + ] + }, + { + "cell_type": "markdown", "metadata": {}, + "source": [ + "## Basic Unit testing is built in\n", + "\n", + "Because there are so many corner cases with numerical code, every time a new summary stat is added, a variety of simple tests are run against it. This lets you discover bugs earlier." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "w = BuckarooWidget(df[:500], showCommands=False)\n", + "# Here we try to replace min_digits with a version that throws errors on bools.\n", + "# Small error, but representantive of the types of erros that we see in the wild.\n", + "def int_digits(n):\n", + " if np.isnan(n):\n", + " return 1\n", + " if n == 0:\n", + " return 1\n", + " if np.sign(n) == -1:\n", + " return int(np.floor(np.log10(np.abs(n)))) + 2\n", + " return int(np.floor(np.log10(n)+1))\n", + "\n", + "class MinDigits(ColAnalysis):\n", + " requires_summary = [\"min\"]\n", + " provides_summary = [\"min_digits\"]\n", + " \n", + " @staticmethod\n", + " def summary(sampled_ser, summary_ser, ser):\n", + " is_numeric = pd.api.types.is_numeric_dtype(sampled_ser.dtype)\n", + " if is_numeric:\n", + " return {\n", + " 'min_digits':int_digits(summary_ser.loc['min'])}\n", + " else:\n", + " return {\n", + " 'min_digits':0}\n", + "w.add_analysis(MinDigits)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ - "from dcef.all_transforms import Transform\n", - "from dcef.lispy import s\n", - "#Here we start adding commands to the DCF Widget. Every call to add_command replaces a command with the same name\n", + "#now we can use the reproduce line to quickly try this and iterate until we get to a solution\n", + "from buckaroo.analysis_management import PERVERSE_DF\n", + "MinDigits.summary(PERVERSE_DF['UInt8None'], pd.Series({'min': pd.NA, }), PERVERSE_DF['UInt8None'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# use quiet = True if you just want the analysis to shutup and work for the most part.\n", + "# not generally recommended, but expedient. If this wasn't built in, users would write\n", + "# this functionality again over and over, poorly\n", + "\n", + "class MinDigits(ColAnalysis):\n", + " requires_summary = [\"min\"]\n", + " provides_summary = [\"min_digits\"]\n", + " quiet = True\n", + " \n", + " @staticmethod\n", + " def summary(sampled_ser, summary_ser, ser):\n", + " is_numeric = pd.api.types.is_numeric_dtype(sampled_ser.dtype)\n", + " if is_numeric:\n", + " return {\n", + " 'min_digits':int_digits(summary_ser.loc['min'])}\n", + " else:\n", + " return {\n", + " 'min_digits':0}\n", + "w.add_analysis(MinDigits)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Making a new default dataframe display function" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from buckaroo.widget_utils import disable\n", + "from IPython.core.getipython import get_ipython\n", + "from IPython.display import display\n", + "import warnings\n", + "\n", + "disable()\n", + "def my_display_as_buckaroo(df):\n", + " w = BuckarooWidget(df, showCommands=False)\n", + " #the analysis we added throws warnings, let's muffle that when used as the default display\n", + " warnings.filterwarnings('ignore')\n", + " w.add_analysis(Skew)\n", + " warnings.filterwarnings('default')\n", + " return display(w)\n", + "\n", + "def my_enable():\n", + " \"\"\"\n", + " Automatically use buckaroo to display all DataFrames\n", + " instances in the notebook.\n", + "\n", + " \"\"\"\n", + " ip = get_ipython()\n", + " if ip is None:\n", + " print(\"must be running inside ipython to enable default display via enable()\")\n", + " return\n", + " ip_formatter = ip.display_formatter.ipython_display_formatter\n", + " ip_formatter.for_type(pd.DataFrame, my_display_as_buckaroo)\n", + "my_enable()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Adding a Command to the Low Code UI" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from buckaroo.all_transforms import Command\n", + "from buckaroo.lispy import s\n", + "#Here we start adding commands to the Buckaroo Widget. Every call to add_command replaces a command with the same name\n", "@w.add_command\n", - "class GroupBy2(Transform):\n", + "class GroupBy2(Command):\n", " command_default = [s(\"groupby2\"), s('df'), 'col', {}]\n", " command_pattern = [[3, 'colMap', 'colEnum', ['null', 'sum', 'mean', 'median', 'count']]]\n", " @staticmethod \n", @@ -68,14 +277,31 @@ " return \"\\n\".join(commands)\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that `groupby2` has been added to the commands" + ] + }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ - "# notice that there is now a Groupby2 Command in the widget" + "import polars as pl\n", + "pl.read_csv('./examples/data/yellow_tripdata_2021-02.csv')" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -94,7 +320,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.3" + "version": "3.11.5" } }, "nbformat": 4, diff --git a/ipydatagrid.json b/ipydatagrid.json deleted file mode 100644 index 1e3d24062..000000000 --- a/ipydatagrid.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "load_extensions": { - "ipydatagrid/extension": true - } -} diff --git a/ipydatagrid/__init__.py b/ipydatagrid/__init__.py deleted file mode 100644 index 3d25dbab5..000000000 --- a/ipydatagrid/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Bloomberg. -# Distributed under the terms of the Modified BSD License. - -from ._version import __version__ -from .paddy_widget import PaddyWidget - -def _jupyter_nbextension_paths(): - return [ - { - "section": "notebook", - "src": "nbextension", - "dest": "ipydatagrid", - "require": "ipydatagrid/extension", - } - ] - - -def _jupyter_labextension_paths(): - return [{"src": "labextension", "dest": "ipydatagrid"}] - - -__all__ = [ - "__version__", - "PaddyWidget" -] diff --git a/ipydatagrid/_version.py b/ipydatagrid/_version.py deleted file mode 100644 index e7eef18bc..000000000 --- a/ipydatagrid/_version.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) Bloomberg. -# Distributed under the terms of the Modified BSD License. - -__version__ = "1.1.15" diff --git a/ipydatagrid/labextension/static/style.js b/ipydatagrid/labextension/static/style.js deleted file mode 100644 index cdf3d73b8..000000000 --- a/ipydatagrid/labextension/static/style.js +++ /dev/null @@ -1,4 +0,0 @@ -/* This is a generated file of CSS imports */ -/* It was generated by @jupyterlab/builder in Build.ensureAssets() */ - - diff --git a/ipydatagrid/nbextension/extension.js b/ipydatagrid/nbextension/extension.js deleted file mode 100644 index 72030ccaa..000000000 --- a/ipydatagrid/nbextension/extension.js +++ /dev/null @@ -1,18 +0,0 @@ -// Entry point for the notebook bundle containing custom model definitions. -// -define(function () { - 'use strict'; - - window['requirejs'].config({ - map: { - '*': { - ipydatagrid: 'nbextensions/ipydatagrid/index', - }, - }, - }); - // Export the required load_ipython_extension function - return { - // eslint-disable-next-line @typescript-eslint/no-empty-function - load_ipython_extension: function () {}, - }; -}); diff --git a/ipydatagrid/nbextension/index.js.LICENSE.txt b/ipydatagrid/nbextension/index.js.LICENSE.txt deleted file mode 100644 index 73838b328..000000000 --- a/ipydatagrid/nbextension/index.js.LICENSE.txt +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @ag-grid-community/all-modules - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue * @version v29.2.0 - * @link https://www.ag-grid.com/ - * @license MIT - */ - -/** - * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue - * @version v29.2.0 - * @link https://www.ag-grid.com/ - * @license MIT - */ - -/** - * @license - * Lodash - * Copyright OpenJS Foundation and other contributors - * Released under MIT license - * Based on Underscore.js 1.8.3 - * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - */ - -/** - * @license React - * react-dom-server-legacy.browser.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** - * @license React - * react-dom-server.browser.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** - * @license React - * react-dom.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** - * @license React - * react.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** - * @license React - * scheduler.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ diff --git a/ipydatagrid/paddy_widget.py b/ipydatagrid/paddy_widget.py deleted file mode 100644 index 35f4afa3a..000000000 --- a/ipydatagrid/paddy_widget.py +++ /dev/null @@ -1,15 +0,0 @@ -from ipywidgets import DOMWidget -from traitlets import Unicode -from ._frontend import module_name, module_version - -class PaddyWidget(DOMWidget): - """TODO: Add docstring here - """ - _model_name = Unicode('PaddyModel').tag(sync=True) - _model_module = Unicode(module_name).tag(sync=True) - _model_module_version = Unicode(module_version).tag(sync=True) - _view_name = Unicode('PaddyView').tag(sync=True) - _view_module = Unicode(module_name).tag(sync=True) - _view_module_version = Unicode(module_version).tag(sync=True) - - value = Unicode('Paddy Widget from python').tag(sync=True) diff --git a/jest.config.js b/jest.config.js index ca602dcda..8f7ba325f 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,8 +5,6 @@ module.exports = { }, transformIgnorePatterns: ['node_modules/?!(@jupyter-widgets)'], testPathIgnorePatterns: ['ui-tests-ipw7/', 'ui-tests-ipw8/'], - setupFiles: ['./tests/js/setupFile.js'], - testEnvironment: 'jsdom', moduleNameMapper: { '\\.(css|less)$': '/__mocks__/styleMock.js', }, diff --git a/js/baked_data/colorMap.ts b/js/baked_data/colorMap.ts new file mode 100644 index 000000000..42ec1fd49 --- /dev/null +++ b/js/baked_data/colorMap.ts @@ -0,0 +1,83 @@ +//diverging +// +// Reversed from the colorcet default because that had Blue to the left +// colorcet.CET_D9[::-1] + +export const DIVERGING_RED_WHITE_BLUE = [ + '#e65036', '#e65138', '#e75339', '#e7553a', '#e8563c', '#e8583d', '#e9593f', + '#e95b40', '#e95c41', '#ea5e43', '#ea5f44', '#eb6046', '#eb6247', '#ec6349', + '#ec654a', '#ec664b', '#ed684d', '#ed694e', '#ee6a50', '#ee6c51', '#ee6d52', + '#ef6f54', '#ef7055', '#ef7157', '#f07358', '#f0745a', '#f1765b', '#f1775d', + '#f1785e', '#f27a5f', '#f27b61', '#f27c62', '#f37e64', '#f37f65', '#f38067', + '#f48268', '#f4836a', '#f4846b', '#f5866c', '#f5876e', '#f5886f', '#f58a71', + '#f68b72', '#f68c74', '#f68d75', '#f78f77', '#f79078', '#f7917a', '#f7937b', + '#f8947d', '#f8957e', '#f89780', '#f89881', '#f99983', '#f99a84', '#f99c86', + '#f99d87', '#f99e89', '#faa08a', '#faa18c', '#faa28d', '#faa38f', '#faa590', + '#fba692', '#fba793', '#fba995', '#fbaa96', '#fbab98', '#fbac99', '#fcae9b', + '#fcaf9c', '#fcb09e', '#fcb19f', '#fcb3a1', '#fcb4a2', '#fcb5a4', '#fcb7a5', + '#fdb8a7', '#fdb9a8', '#fdbaaa', '#fdbcac', '#fdbdad', '#fdbeaf', '#fdbfb0', + '#fdc1b2', '#fdc2b3', '#fdc3b5', '#fdc4b6', '#fdc6b8', '#fdc7ba', '#fdc8bb', + '#fdcabd', '#fdcbbe', '#fdccc0', '#fdcdc1', '#fdcfc3', '#fdd0c5', '#fdd1c6', + '#fdd2c8', '#fdd4c9', '#fdd5cb', '#fdd6cc', '#fdd7ce', '#fdd9d0', '#fddad1', + '#fddbd3', '#fddcd4', '#fdded6', '#fcdfd8', '#fce0d9', '#fce1db', '#fce3dc', + '#fce4de', '#fce5e0', '#fce7e1', '#fce8e3', '#fbe9e5', '#fbeae6', '#fbece8', + '#fbede9', '#fbeeeb', '#faefed', '#faf1ee', '#faf2f0', '#faf3f2', '#f9f4f3', + '#f9f5f5', '#f8f6f6', '#f7f6f7', '#f6f6f8', '#f5f5f9', '#f4f4f9', '#f3f3f9', + '#f1f2f9', '#f0f1f9', '#eff0f9', '#eeeffa', '#edeefa', '#ecedfa', '#eaecfa', + '#e9ebfa', '#e8eafa', '#e7e9fa', '#e6e8fa', '#e5e7fa', '#e3e6fa', '#e2e5fa', + '#e1e4fa', '#e0e3fa', '#dfe2fb', '#dde1fb', '#dce0fb', '#dbdffb', '#dadefb', + '#d9ddfb', '#d7dcfb', '#d6dbfb', '#d5dafb', '#d4d9fb', '#d3d8fb', '#d1d7fb', + '#d0d6fb', '#cfd5fb', '#ced4fb', '#cdd3fc', '#cbd2fc', '#cad1fc', '#c9d0fc', + '#c8cffc', '#c6cefc', '#c5cdfc', '#c4ccfc', '#c3cbfc', '#c1cafc', '#c0c9fc', + '#bfc8fc', '#bdc7fc', '#bcc7fc', '#bbc6fc', '#bac5fc', '#b8c4fc', '#b7c3fc', + '#b6c2fc', '#b4c1fd', '#b3c0fd', '#b2bffd', '#b0befd', '#afbdfd', '#aebcfd', + '#acbbfd', '#abbafd', '#aab9fd', '#a8b8fd', '#a7b7fd', '#a5b6fd', '#a4b5fd', + '#a3b4fd', '#a1b3fd', '#a0b2fd', '#9eb2fd', '#9db1fd', '#9bb0fd', '#9aaffd', + '#99aefd', '#97adfd', '#96acfd', '#94abfd', '#93aafd', '#91a9fd', '#90a8fd', + '#8ea7fd', '#8ca6fd', '#8ba5fe', '#89a4fe', '#88a4fe', '#86a3fe', '#84a2fe', + '#83a1fe', '#81a0fe', '#809ffe', '#7e9efe', '#7c9dfe', '#7a9cfe', '#799bfe', + '#779afe', '#759afe', '#7399fe', '#7198fe', '#7097fe', '#6e96fe', '#6c95fe', + '#6a94fe', '#6893fe', '#6692fe', '#6491fe', '#6291fe', '#5f90fe', '#5d8ffe', + '#5b8efe', '#598dfe', '#568cfe', '#548bfe', '#518afe', '#4f8afe', '#4c89fe', + '#4988fe', '#4787fe', '#4486fe', '#4085fe', '#3d84fe', '#3a83fe', '#3683fe', + '#3282fe', '#2e81fe', '#2980fe', '#247ffe',]; + +//colorcet.CET_CBD2 +export const BLUE_TO_YELLOW = [ + '#0488fc', '#1089fb', '#1789fb', '#1d89fa', '#228afa', '#268af9', '#2a8af9', + '#2e8af8', '#318bf7', '#348bf7', '#378bf6', '#3a8cf6', '#3c8cf5', '#3f8cf5', + '#418df4', '#438df4', '#458df3', '#488df2', '#4a8ef2', '#4c8ef1', '#4d8ef1', + '#4f8ff0', '#518ff0', '#538fef', '#5490ee', '#5690ee', '#5890ed', '#5991ed', + '#5b91ec', '#5c91ec', '#5e92eb', '#5f92ea', '#6192ea', '#6292e9', '#6393e9', + '#6593e8', '#6693e8', '#6794e7', '#6994e6', '#6a94e6', '#6b95e5', '#6c95e5', + '#6e95e4', '#6f96e4', '#7096e3', '#7196e3', '#7297e2', '#7397e1', '#7497e1', + '#7698e0', '#7798e0', '#7898df', '#7999df', '#7a99de', '#7b99dd', '#7c9add', + '#7d9adc', '#7e9adc', '#7f9bdb', '#809bdb', '#819bda', '#829cd9', '#839cd9', + '#849cd8', '#849dd8', '#859dd7', '#869dd7', '#879ed6', '#889ed5', '#899ed5', + '#8a9fd4', '#8b9fd4', '#8c9fd3', '#8ca0d3', '#8da0d2', '#8ea0d1', '#8fa1d1', + '#90a1d0', '#91a1d0', '#91a2cf', '#92a2ce', '#93a2ce', '#94a3cd', '#95a3cd', + '#95a3cc', '#96a4cc', '#97a4cb', '#98a4ca', '#98a5ca', '#99a5c9', '#9aa5c9', + '#9ba6c8', '#9ba6c8', '#9ca6c7', '#9da7c6', '#9ea7c6', '#9ea7c5', '#9fa8c5', + '#a0a8c4', '#a0a9c3', '#a1a9c3', '#a2a9c2', '#a2aac2', '#a3aac1', '#a4aac1', + '#a4abc0', '#a5abbf', '#a6abbf', '#a6acbe', '#a7acbe', '#a8acbd', '#a8adbc', + '#a9adbc', '#aaadbb', '#aaaebb', '#abaeba', '#acafb9', '#acafb9', '#adafb8', + '#adb0b8', '#aeb0b7', '#afb0b7', '#afb1b6', '#b0b1b5', '#b1b1b5', '#b1b2b4', + '#b2b2b4', '#b2b2b3', '#b3b3b2', '#b4b3b2', '#b4b3b1', '#b5b4b1', '#b6b4b0', + '#b7b4af', '#b7b5af', '#b8b5ae', '#b9b5ad', '#bab6ad', '#bab6ac', '#bbb6ac', + '#bcb7ab', '#bcb7aa', '#bdb7aa', '#beb8a9', '#beb8a8', '#bfb8a8', '#c0b9a7', + '#c0b9a7', '#c1b9a6', '#c2baa5', '#c2baa5', '#c3baa4', '#c4bba3', '#c4bba3', + '#c5bba2', '#c6bca2', '#c6bca1', '#c7bca0', '#c8bca0', '#c8bd9f', '#c9bd9e', + '#cabd9e', '#cabe9d', '#cbbe9c', '#ccbe9c', '#ccbf9b', '#cdbf9b', '#cdbf9a', + '#cec099', '#cfc099', '#cfc098', '#d0c197', '#d1c197', '#d1c196', '#d2c295', + '#d2c295', '#d3c294', '#d4c393', '#d4c393', '#d5c392', '#d5c491', '#d6c491', + '#d7c490', '#d7c58f', '#d8c58f', '#d8c58e', '#d9c68d', '#dac68d', '#dac68c', + '#dbc78b', '#dbc78b', '#dcc78a', '#dcc889', '#ddc889', '#dec888', '#dec987', + '#dfc987', '#dfc986', '#e0ca85', '#e0ca85', '#e1ca84', '#e2cb83', '#e2cb83', + '#e3cc82', '#e3cc81', '#e4cc80', '#e4cd80', '#e5cd7f', '#e6cd7e', '#e6ce7e', + '#e7ce7d', '#e7ce7c', '#e8cf7b', '#e8cf7b', '#e9cf7a', '#e9d079', '#ead078', + '#ead078', '#ebd177', '#ecd176', '#ecd176', '#edd275', '#edd274', '#eed273', + '#eed373', '#efd372', '#efd371', '#f0d470', '#f0d46f', '#f1d46f', '#f1d56e', + '#f2d56d', '#f2d56c', '#f3d66c', '#f3d66b', '#f4d66a', '#f5d769', '#f5d768', + '#f6d868', '#f6d867', '#f7d866', '#f7d965', '#f8d964', '#f8d963', '#f9da63', + '#f9da62', '#fada61', '#fadb60', '#fbdb5f', '#fbdb5e', '#fcdc5d', '#fcdc5d', + '#fddc5c', '#fddd5b', '#fedd5a', '#fedd59',]; diff --git a/js/baked_data/staticData.ts b/js/baked_data/staticData.ts new file mode 100644 index 000000000..205b2391a --- /dev/null +++ b/js/baked_data/staticData.ts @@ -0,0 +1,509 @@ +import { OperationDefaultArgs, Operation } from '../components/OperationUtils'; +import { sym } from '../components/utils'; +import { + symDf, + CommandConfigT, + bakedArgSpecs, +} from '../components/CommandUtils'; +import { + DFData, + DFViewerConfig, + DFWhole, +} from '../components/DFViewerParts/DFWhole'; + +export const bakedOperationDefaults: OperationDefaultArgs = { + dropcol: [sym('dropcol'), symDf, 'col'], + fillna: [sym('fillna'), symDf, 'col', 8], + resample: [sym('resample'), symDf, 'col', 'monthly', {}], +}; + +export const bakedCommandConfig: CommandConfigT = { + argspecs: bakedArgSpecs, + defaultArgs: bakedOperationDefaults, +}; + +export const bakedOperations: Operation[] = [ + [sym('dropcol'), symDf, 'col1'], + [sym('fillna'), symDf, 'col2', 5], + [sym('resample'), symDf, 'month', 'monthly', {}], +]; + +export const histograms = { + num_histo: [ + { name: '-406 - -332', population: 1 }, + { name: '-332 - -258', population: 0 }, + { name: '-258 - -184', population: 2 }, + { name: '-184 - -111', population: 10 }, + { name: '-111 - -37', population: 22 }, + { name: '-37 - 36', population: 30 }, + { name: '36 - 109', population: 22 }, + { name: '109 - 183', population: 10 }, + { name: '183 - 257', population: 3 }, + { name: '257 - 331', population: 0 }, + ], + + bool_histo: [ + { name: 'False', false: 50 }, + { name: 'True', true: 30 }, + { name: 'NA', NA: 20 }, + ], + + NA_Only: [{ name: 'NA', NA: 100 }], + + simple_catgeorical: [ + { name: 2, cat_pop: 87.0 }, + { name: 1, cat_pop: 13.0 }, + ], + + categorical_histo: [ + { name: 'KTM', cat_pop: 30 }, + { name: 'Gas Gas', cat_pop: 15 }, + { name: 'Yamaha', cat_pop: 10 }, + { name: 'unique', unique: 25 }, + { name: 'NA', NA: 20 }, + ], + + categorical_histo_lt: [ + { name: 'KTM', cat_pop: 25 }, + { name: 'Gas Gas', cat_pop: 12 }, + { name: 'Yamaha', cat_pop: 8 }, + { name: 'NA', NA: 20 }, + { name: 'longtail', unique: 15, longtail: 20 }, + ], + + all_unique: [{ name: 'unique', unique: 100 }], + + unique_na: [ + { name: 'unique', unique: 80 }, + { name: 'NA', NA: 20 }, + ], + + unique_continuous: [ + { name: '-406 -332', population: 1 }, + { name: '-332 -258', population: 0 }, + { name: '-258 -184', population: 0 }, + { name: '-184 -111', population: 10 }, + { name: '-111 -37', population: 21 }, + { name: '-37 36', population: 29 }, + { name: '36 109', population: 22 }, + { name: '109 183', population: 9 }, + { name: '183 257', population: 3 }, + { name: '257 331', population: 0 }, + { name: 'unique', unique: 100 }, + ], + + unique_continuous_scaled: [ + { name: '-406 -332', population: 0 }, + { name: '-332 -258', population: 0 }, + { name: '-258 -184', population: 0 }, + { name: '-184 -111', population: 10 }, + { name: '-111 -37', population: 21 }, + { name: '-37 36', population: 29 }, + { name: '36 109', population: 22 }, + { name: '109 183', population: 9 }, + { name: '183 257', population: 3 }, + { name: '257 331', population: 0 }, + { name: 'unique', unique: 29 }, + ], + + unique_continuous_scaled_50: [ + { name: '-406 -332', population: 0 }, + { name: '-332 -258', population: 0 }, + { name: '-258 -184', population: 0 }, + { name: '-184 -111', population: 10 }, + { name: '-111 -37', population: 21 }, + { name: '-37 36', population: 29 }, + { name: '36 109', population: 22 }, + { name: '109 183', population: 9 }, + { name: '183 257', population: 3 }, + { name: '257 331', population: 0 }, + { name: 'longtail', unique: 15 }, + ], + start_station_categorical: [ + { name: 'Pershing Square N', cat_pop: 1 }, + { name: '8 Ave & W 31 St', cat_pop: 1 }, + { name: 'Lafayette St & E 8 St', cat_pop: 1 }, + { name: 'W 21 St & 6 Ave', cat_pop: 1 }, + { name: 'E 17 St & Broadway', cat_pop: 1 }, + { name: '8 Ave & W 33 St', cat_pop: 1 }, + { name: 'E 43 St & Vanderbilt Ave', cat_pop: 1 }, + { name: 'unique', cat_pop: 0 }, + { name: 'long_tail', cat_pop: 92 }, + { name: 'NA', cat_pop: 0 }, + ], +}; + +export const smileyPNGString = + 'iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII='; + +//export const tableDf2:DFWhole = { +export const foo: DFWhole = { + dfviewer_config: { + column_config: [ + { col_name: 'index', displayer_args: { displayer: 'obj' } }, + + { col_name: 'tripduration', displayer_args: { displayer: 'obj' } }, + { col_name: 'starttime', displayer_args: { displayer: 'obj' } }, + { col_name: 'stoptime', displayer_args: { displayer: 'obj' } }, + { col_name: 'start station id', displayer_args: { displayer: 'obj' } }, + { col_name: 'start station name', displayer_args: { displayer: 'obj' } }, + { + col_name: 'start station lattitude', + displayer_args: { displayer: 'obj' }, + }, + { col_name: 'bikeid', displayer_args: { displayer: 'obj' } }, + { col_name: 'birth year', displayer_args: { displayer: 'obj' } }, + { col_name: 'gender', displayer_args: { displayer: 'obj' } }, + ], + pinned_rows: [], + }, + + // index: { type: 'obj' }, + // tripduration: { histogram: histograms.num_histo, type: 'obj' }, + /* + starttime: { type: 'obj' }, + stoptime: { type: 'obj' }, + 'start station id': { type: 'obj' }, + 'start station name': { type: 'obj' }, + 'start station latitude': { type: 'obj' }, + bikeid: { type: 'obj' }, + 'birth year': { type: 'obj' }, + gender: { type: 'obj' }, + */ + data: [ + { + index: 0, + tripduration: 404, + starttime: '2014-07-01 00:00:04', + stoptime: '2014-07-01 00:06:48', + 'start station id': 545, + 'start station name': 'E 23 St & 1 Ave', + 'start station latitude': 40.736502, + bikeid: 19578, + 'birth year': '1987', + gender: 2, + img_: smileyPNGString, + }, + { + index: 1, + tripduration: 850, + starttime: '2014-07-01 00:00:06', + stoptime: '2014-07-01 00:14:16', + 'start station id': 238, + 'start station name': 'Bank St & Washington St', + 'start station latitude': 40.7361967, + bikeid: 19224, + 'birth year': '1987', + gender: 1, + }, + { + index: 2, + tripduration: 1550, + starttime: '2014-07-01 00:00:21', + stoptime: '2014-07-01 00:26:11', + 'start station id': 223, + 'start station name': 'W 13 St & 7 Ave', + 'start station latitude': 40.73781509, + bikeid: 17627, + 'birth year': '1973', + gender: 2, + }, + { + index: 3, + tripduration: 397, + starttime: '2014-07-01 00:00:29', + stoptime: '2014-07-01 00:07:06', + 'start station id': 224, + 'start station name': 'Spruce St & Nassau St', + 'start station latitude': 40.71146364, + bikeid: 15304, + 'birth year': '1982', + gender: 1, + }, + { + index: 4, + tripduration: 609, + starttime: '2014-07-01 00:00:37', + stoptime: '2014-07-01 00:10:46', + 'start station id': 346, + 'start station name': 'Bank St & Hudson St', + 'start station latitude': 40.73652889, + bikeid: 20062, + 'birth year': '1972', + gender: 2, + }, + ], +}; +export const stringIndexDf = foo; + +export const tableDf: DFWhole = { + dfviewer_config: { + column_config: [ + { + col_name: 'index', + displayer_args: { displayer: 'integer', min_digits: 3, max_digits: 5 }, + }, + { + col_name: 'svg_column', + displayer_args: { displayer: 'SVGDisplayer' }, + }, + { + col_name: 'link_column', + displayer_args: { displayer: 'linkify' }, + }, + { + col_name: 'nanObject', + displayer_args: { displayer: 'integer', min_digits: 3, max_digits: 5 }, + color_map_config: { + color_rule: 'color_map', + //map_name: 'DIVERGING_RED_WHITE_BLUE', + map_name: 'BLUE_TO_YELLOW', + val_column: 'tripduration', + }, + }, + { + col_name: 'nanFloat', + displayer_args: { + displayer: 'float', + min_fraction_digits: 2, + max_fraction_digits: 8, + }, + tooltip_config: { tooltip_type: 'summary_series' }, + }, + { col_name: 'end station name', displayer_args: { displayer: 'obj' } }, + { + col_name: 'tripduration', + displayer_args: { displayer: 'integer', min_digits: 1, max_digits: 5 }, + color_map_config: { + color_rule: 'color_map', + map_name: 'BLUE_TO_YELLOW', + }, + }, + { + col_name: 'start station name', + displayer_args: { displayer: 'obj' }, + color_map_config: { + color_rule: 'color_not_null', + conditional_color: 'red', + exist_column: 'nanFloat', + }, + }, + { + col_name: 'floatCol', + displayer_args: { + displayer: 'float', + min_fraction_digits: 1, + max_fraction_digits: 3, + }, + }, + { + col_name: 'nanNumeric', + displayer_args: { displayer: 'integer', min_digits: 3, max_digits: 5 }, + tooltip_config: { + tooltip_type: 'simple', + val_column: 'start station name', + }, + }, + { + col_name: 'img_', + displayer_args: { displayer: 'Base64PNGImageDisplayer' }, + ag_grid_specs: { width: 150 }, + }, + ], + extra_grid_config: { rowHeight: 105 }, + component_config: { height_fraction: 1 }, + pinned_rows: [ + // { primary_key_val: 'dtype', displayer_args: { displayer: 'obj' } }, + // { primary_key_val: 'histogram', displayer_args: { displayer: 'histogram' }, }, + ], + }, + data: [ + { + index: 0, + 'end station name': 'Elizabeth St & Hester St', + tripduration: 471, + 'start station name': 'Catherine St & Monroe St', + floatCol: '1.111', + nanNumeric: null, + nanObject: null, + nanFloat: null, + //svg_column: '

paddy

', + link_column: 'https://buckaroo.dev', + img_: smileyPNGString, + }, + { + index: 1, + 'end station name': 'South St & Whitehall St', + tripduration: 1494, + 'start station name': '1 Ave & E 30 St', + floatCol: '8.888', + nanNumeric: null, + nanObject: null, + nanFloat: null, + svg_column: + '', + link_column: 'https://pola.rs/', + }, + { + index: 2, + 'end station name': 'E 59 St & Sutton Pl', + tripduration: 464, + 'start station name': 'E 48 St & 3 Ave', + floatCol: '9.999', + nanNumeric: null, + nanObject: null, + svg_column: + '', + nanFloat: 10, + }, + { + index: 3, + 'end station name': 'E 33 St & 5 Ave', + tripduration: 373, + 'start station name': 'Pershing Square N', + floatCol: '-10.1', + nanCol: null, + nanNumeric: null, + nanObject: null, + svg_column: + '', + nanFloat: null, + }, + { + index: 4, + 'end station name': 'Hancock St & Bedford Ave', + tripduration: 660, + 'start station name': 'Atlantic Ave & Fort Greene Pl', + floatCol: '10.99', + nanNumeric: null, + nanObject: null, + nanFloat: 3, + }, + ], +}; + +export const dfviewer_config_no_pinned: DFViewerConfig = { + column_config: tableDf.dfviewer_config.column_config, + pinned_rows: [ + { primary_key_val: 'dtype', displayer_args: { displayer: 'obj' } }, + { + primary_key_val: 'histogram', + displayer_args: { displayer: 'histogram' }, + }, + ], +}; +const tripDurationBins = [0, 300, 500, 1000, 1500]; + +export const summaryDfForTableDf: DFData = [ + { + index: 'histogram', + 'end station name': histograms.categorical_histo_lt, + tripduration: histograms.num_histo, + 'start station name': histograms.bool_histo, + nanNumeric: histograms.num_histo, + nanFloat: histograms.num_histo, + nanObject: histograms.num_histo, + floatCol: [ + { name: 521, cat_pop: 0.0103 }, + { name: 358, cat_pop: 0.0096 }, + { name: 519, cat_pop: 0.009 }, + { name: 497, cat_pop: 0.0087 }, + { name: 293, cat_pop: 0.0082 }, + { name: 285, cat_pop: 0.0081 }, + { name: 435, cat_pop: 0.008 }, + { name: 'unique', cat_pop: 0.0001 }, + { name: 'long_tail', cat_pop: 0.938 }, + { name: 'NA', cat_pop: 0.0 }, + ], + }, + { + index: 'histogram_bins', + tripduration: tripDurationBins, + nanObject: tripDurationBins, + }, + { + index: 'dtype', + 'end station name': 'String6666', + tripduration: 'object', + 'start station name': 'object', + nanNumeric: 'float64', + nanFloat: 'flot64', + nanObject: 'object', + floatCol: 'float', + }, +]; + +export const realSummaryTableData: DFData = [ + { index: 'dtype', int_col: 'int64', float_col: 'float64', str_col: 'object' }, + { index: 'min', int_col: 1, float_col: 1.4285714286 }, + { index: 'max', int_col: 49, float_col: 41.4285714286, str_col: null }, + { index: 'mean', int_col: 24.75, float_col: 22.4714285714 }, + { index: 'unique_count', int_col: 4, float_col: 0, str_col: 0 }, + { index: 'empty_count', int_col: 0, float_col: 0, str_col: 0 }, + { index: 'distinct_count', int_col: 49, float_col: 29, str_col: 1 }, +]; + +export const realSummaryConfig: DFViewerConfig = { + pinned_rows: [ + { primary_key_val: 'dtype', displayer_args: { displayer: 'obj' } }, + { + primary_key_val: 'min', + displayer_args: { + displayer: 'float', + min_fraction_digits: 3, + max_fraction_digits: 3, + }, + }, + { + primary_key_val: 'mean', + displayer_args: { + displayer: 'float', + min_fraction_digits: 3, + max_fraction_digits: 3, + }, + }, + { + primary_key_val: 'max', + displayer_args: { + displayer: 'float', + min_fraction_digits: 3, + max_fraction_digits: 3, + }, + }, + { + primary_key_val: 'unique_count', + displayer_args: { + displayer: 'float', + min_fraction_digits: 0, + max_fraction_digits: 0, + }, + }, + { + primary_key_val: 'distinct_count', + displayer_args: { + displayer: 'float', + min_fraction_digits: 0, + max_fraction_digits: 0, + }, + }, + { + primary_key_val: 'empty_count', + displayer_args: { + displayer: 'float', + min_fraction_digits: 0, + max_fraction_digits: 0, + }, + }, + ], + column_config: [ + // {'col_name': 'index', 'displayer_args': {'displayer': 'string'}}, + { + col_name: 'index', + displayer_args: { displayer: 'string' }, + ag_grid_specs: { minWidth: 150, pinned: 'left' }, + }, + { col_name: 'int_col', displayer_args: { displayer: 'obj' } }, + { col_name: 'float_col', displayer_args: { displayer: 'obj' } }, + { col_name: 'str_col', displayer_args: { displayer: 'obj' } }, + ], +}; diff --git a/js/components/ColumnsEditor.tsx b/js/components/ColumnsEditor.tsx new file mode 100644 index 000000000..412242054 --- /dev/null +++ b/js/components/ColumnsEditor.tsx @@ -0,0 +1,71 @@ +import React, { useState } from 'react'; +import { bakedOperations } from '../baked_data/staticData'; +import { DFViewerConfig, EmptyDf } from './DFViewerParts/DFWhole'; +import { OperationViewer } from './Operations'; +import { Operation } from './OperationUtils'; +import { CommandConfigT } from './CommandUtils'; +//import {bakedCommandConfig} from './bakedOperationDefaults'; +import { DependentTabs, OperationResult } from './DependentTabs'; +import { tableDf, bakedCommandConfig } from '../baked_data/staticData'; + +export type OperationSetter = (ops: Operation[]) => void; +export interface WidgetConfig { + showCommands: boolean; +} + +export function ColumnsEditor({ + df_viewer_config, + activeColumn, + operations, + setOperations, + operationResult, + commandConfig, +}: { + df_viewer_config: DFViewerConfig; + activeColumn: string; + operations: Operation[]; + setOperations: OperationSetter; + operationResult: OperationResult; + commandConfig: CommandConfigT; +}) { + const allColumns = df_viewer_config.column_config.map( + (field) => field.col_name + ); + return ( +
+
+ + +
+
+ ); +} + +export function ColumnsEditorEx() { + const [operations, setOperations] = useState(bakedOperations); + + const baseOperationResults: OperationResult = { + transformed_df: EmptyDf, + generated_py_code: 'default py code', + transform_error: undefined, + }; + return ( + + ); +} diff --git a/js/components/CommandUtils.ts b/js/components/CommandUtils.ts new file mode 100644 index 000000000..eb5085c6e --- /dev/null +++ b/js/components/CommandUtils.ts @@ -0,0 +1,38 @@ +import { OperationDefaultArgs } from './OperationUtils'; + +export type TypeSpec = [number, string, 'type', 'integer' | 'float' | 'string']; +export type EnumSpec = [number, string, 'enum', string[]]; +export type ColEnumSpec = [number, string, 'colEnum', string[]]; + +export type NoArgs = null; +export type ActualArg = TypeSpec | EnumSpec | ColEnumSpec; +export type ArgSpec = TypeSpec | EnumSpec | ColEnumSpec | NoArgs; + +export interface SymbolT { + symbol: string; +} + +export interface SymbolDf { + symbol: 'df'; +} + +export const symDf: SymbolDf = { + symbol: 'df', +}; + +export type ColEnumArgs = Record; + +export type CommandArgSpec = Record; +export const bakedArgSpecs: CommandArgSpec = { + dropcol: [null], + fillna: [[3, 'fillVal', 'type', 'integer']], + resample: [ + [3, 'frequency', 'enum', ['daily', 'weekly', 'monthly']], + [4, 'colMap', 'colEnum', ['null', 'sum', 'mean', 'count']], + ], +}; + +export type CommandConfigT = { + argspecs: CommandArgSpec; + defaultArgs: OperationDefaultArgs; +}; diff --git a/js/components/DCFCell.tsx b/js/components/DCFCell.tsx new file mode 100644 index 000000000..6042dcabb --- /dev/null +++ b/js/components/DCFCell.tsx @@ -0,0 +1,183 @@ +import React, { useState, Dispatch, SetStateAction } from 'react'; +import _ from 'lodash'; +import { OperationResult, baseOperationResults } from './DependentTabs'; +import { ColumnsEditor } from './ColumnsEditor'; +import { + dfviewer_config_no_pinned, + realSummaryConfig, + realSummaryTableData, + summaryDfForTableDf, + tableDf, +} from '../baked_data/staticData'; +import { DFData, DFViewerConfig } from './DFViewerParts/DFWhole'; +import { DFViewer } from './DFViewerParts/DFViewer'; +import { StatusBar } from './StatusBar'; +import { BuckarooState } from './WidgetTypes'; +import { BuckarooOptions } from './WidgetTypes'; +import { DFMeta } from './WidgetTypes'; +import { CommandConfigT } from './CommandUtils'; +import { bakedCommandConfig } from './bakedOperationDefaults'; +import { Operation, bakedOperations } from './OperationUtils'; + +export type CommandConfigSetterT = ( + setter: Dispatch> +) => void; + +/* + Widget DCFCell is meant to be used with callback functions and passed values, not explicit http calls + + TODO:add height settings to dfConfig rather than hardcoded. + */ +export interface IDisplayArgs { + data_key: string; + df_viewer_config: DFViewerConfig; + summary_stats_key: string; +} +export function WidgetDCFCell({ + df_data_dict, + df_display_args, + df_meta, + operations, + on_operations, + operation_results, + commandConfig, + buckaroo_state, + on_buckaroo_state, + buckaroo_options, +}: { + df_meta: DFMeta; + df_data_dict: Record; + df_display_args: Record; + operations: Operation[]; + on_operations: (ops: Operation[]) => void; + operation_results: OperationResult; + commandConfig: CommandConfigT; + buckaroo_state: BuckarooState; + on_buckaroo_state: React.Dispatch>; + buckaroo_options: BuckarooOptions; +}) { + const [activeCol, setActiveCol] = useState('stoptime'); + + const cDisp = df_display_args[buckaroo_state.df_display]; + if (cDisp === undefined) { + console.log( + 'cDisp undefined', + buckaroo_state.df_display, + buckaroo_options.df_display + ); + } else { + // console.log("cDisp", cDisp); + } + const dfData = df_data_dict[cDisp.data_key]; + //console.log("dfData", dfData); + const summaryStatsData = df_data_dict[cDisp.summary_stats_key]; + + return ( +
+
+ + +
+ {buckaroo_state.show_commands ? ( + + ) : ( + + )} +
+ ); +} + +export function WidgetDCFCellExample() { + const dfm: DFMeta = { + columns: 5, + rows_shown: 20, + total_rows: 877, + }; + + const [bState, setBState] = useState({ + auto_clean: '', + sampled: false, + show_commands: false, + df_display: 'main', + post_processing: '', + search_string: '', + }); + + const bOptions: BuckarooOptions = { + auto_clean: ['', 'aggressive', 'conservative'], + df_display: ['main', 'realSummary', 'no_pinned'], + sampled: ['random'], + post_processing: ['', 'foo', 'bar'], + show_commands: ['on'], + // 'summary_stats' : ['full', 'all', 'typing_stats'] + }; + + const [operations, setOperations] = useState(bakedOperations); + + const bakedDfDisplay: Record = { + main: { + data_key: 'main', + df_viewer_config: tableDf.dfviewer_config, + summary_stats_key: 'all', + }, + realSummary: { + data_key: 'empty', + df_viewer_config: realSummaryConfig, + summary_stats_key: 'real_summary', + }, + + no_pinned: { + data_key: 'main', + df_viewer_config: dfviewer_config_no_pinned, + summary_stats_key: 'all', + }, + }; + + const df_data_dict = { + main: tableDf.data, + all: summaryDfForTableDf, + real_summary: realSummaryTableData, + empty: [{ index: 'distinct_count' }], + }; + return ( + + ); +} diff --git a/js/components/DFViewerParts/DFViewer.tsx b/js/components/DFViewerParts/DFViewer.tsx new file mode 100644 index 000000000..35ca415ef --- /dev/null +++ b/js/components/DFViewerParts/DFViewer.tsx @@ -0,0 +1,212 @@ +import React, { useRef, CSSProperties, useState } from 'react'; +import _ from 'lodash'; +import { ComponentConfig, DFData, DFViewerConfig } from './DFWhole'; + +import { dfToAgrid, extractPinnedRows } from './gridUtils'; +import { replaceAtMatch } from '../utils'; +import { AgGridReact } from 'ag-grid-react'; // the AG Grid React Component +import { + DomLayoutType, + GridOptions, + SizeColumnsToContentStrategy, + SizeColumnsToFitProvidedWidthStrategy, +} from 'ag-grid-community'; +import { summaryDfForTableDf, tableDf } from '../../baked_data/staticData'; + +import { getCellRendererSelector } from './gridUtils'; + +export type setColumFunc = (newCol: string) => void; + +export function DFViewer({ + df_data: df, + df_viewer_config, + summary_stats_data, + style, + activeCol, + setActiveCol, +}: { + df_data: DFData; + df_viewer_config: DFViewerConfig; + summary_stats_data?: DFData; + style?: CSSProperties; + activeCol?: string; + setActiveCol?: setColumFunc; +}) { + /* = { + df: EmptyDf.data, + df_viewer_config: EmptyDf.dfviewer_config, + summary_stats_data: [], + style: { height: '300px' }, + setActiveCol: () => null, + }*/ + //console.log("dfviewer df_viewer_config", df_viewer_config); + // console.log("summary_stats_data", summary_stats_data); + // console.log("full_object", {'df':df, 'df_viewer_config':df_viewer_config, 'summary_stats_data': summary_stats_data}) + const [agColsPure, agData] = dfToAgrid( + df, + df_viewer_config, + summary_stats_data || [] + ); + + const styledColumns = replaceAtMatch( + _.clone(agColsPure), + activeCol || '___never', + { + cellStyle: { background: 'var(--ag-range-selection-background-color-3)' }, + } + ); + + const defaultColDef = { + sortable: true, + type: 'rightAligned', + cellRendererSelector: getCellRendererSelector(df_viewer_config.pinned_rows), + }; + + const gridOptions: GridOptions = { + rowSelection: 'single', + onRowClicked: (event) => console.log('A row was clicked'), + tooltipShowDelay: 0, + + // defaultColDef needs to be specifically passed in as a prop to the component, not defined here, + // otherwise updates aren't reactive + + onCellClicked: (event) => { + const colName = event.column.getColId(); + if (setActiveCol === undefined || colName === undefined) { + return; + } else { + setActiveCol(colName); + } + }, + ...(df_viewer_config.extra_grid_config + ? df_viewer_config.extra_grid_config + : {}), + }; + const gridRef = useRef>(null); + const pinned_rows = df_viewer_config.pinned_rows; + const topRowData = summary_stats_data + ? extractPinnedRows(summary_stats_data, pinned_rows ? pinned_rows : []) + : []; + + const getAutoSize = (): + | SizeColumnsToFitProvidedWidthStrategy + | SizeColumnsToContentStrategy => { + if (styledColumns.length < 1) { + return { + type: 'fitProvidedWidth', + width: window.innerWidth - 100, + }; + } + return { + type: 'fitCellContents', + }; + }; + + const hs = heightStyle({ + numRows: agData.length, + pinnedRowLen: df_viewer_config.pinned_rows.length, + location: window.location, + compC: df_viewer_config?.component_config, + rowHeight: df_viewer_config?.extra_grid_config?.rowHeight, + }); + + return ( +
+
+ +
+
+ ); +} + +interface HeightStyleArgs { + numRows: number; + pinnedRowLen: number; + readonly location: Location; + rowHeight?: number; + compC?: ComponentConfig; +} +interface HeightStyleI { + domLayout: DomLayoutType; + inIframe: string; + classMode: 'short-mode' | 'regular-mode'; + applicableStyle: CSSProperties; +} + +export const heightStyle = (hArgs: HeightStyleArgs): HeightStyleI => { + const { numRows, pinnedRowLen, location, rowHeight, compC } = hArgs; + const isGoogleColab = + location.host.indexOf('colab.googleusercontent.com') !== -1; + + const inIframe = window.parent !== window; + const regularCompHeight = window.innerHeight / (compC?.height_fraction || 2); + const dfvHeight = compC?.dfvHeight || regularCompHeight; + const regularDivStyle = { height: dfvHeight }; + const shortDivStyle = { minHeight: 50, maxHeight: dfvHeight }; + + const belowMinRows = numRows + pinnedRowLen < 10; + + const shortMode = + compC?.shortMode || (belowMinRows && rowHeight === undefined); + console.log( + 'shortMode', + shortMode, + 'dfvHeight', + dfvHeight, + 'isGoogleColab', + isGoogleColab, + 'inIframe', + inIframe + ); + const inIframeClass = inIframe ? 'inIframe' : ''; + if (isGoogleColab || inIframe) { + return { + classMode: 'regular-mode', + domLayout: 'normal', + applicableStyle: { height: 500 }, + inIframe: inIframeClass, + }; + } + const domLayout: DomLayoutType = + compC?.layoutType || (shortMode ? 'autoHeight' : 'normal'); + const applicableStyle = shortMode ? shortDivStyle : regularDivStyle; + const classMode = shortMode ? 'short-mode' : 'regular-mode'; + return { + classMode, + domLayout, + applicableStyle, + inIframe: inIframeClass, + }; + + /* + ab = window.location.host; + "cskfus796ts-496ff2e9c6d22116-0-colab.googleusercontent.com" + bc = window.location.pathname + "/outputframe.html" +*/ +}; + +export function DFViewerEx() { + const [activeCol, setActiveCol] = useState('tripduration'); + return ( + + ); +} diff --git a/js/components/DFViewerParts/DFWhole.ts b/js/components/DFViewerParts/DFWhole.ts new file mode 100644 index 000000000..561d728fd --- /dev/null +++ b/js/components/DFViewerParts/DFWhole.ts @@ -0,0 +1,193 @@ +// I'm not sure about adding underlying types too + +import { ColDef, GridOptions } from 'ag-grid-community'; +import _ from 'lodash'; + +type AGGrid_ColDef = ColDef; + +export interface ObjDisplayerA { + displayer: 'obj'; + max_length?: number; +} +export interface BooleanDisplayerA { + displayer: 'boolean'; +} +export interface StringDisplayerA { + displayer: 'string'; + max_length?: number; +} +export interface FloatDisplayerA { + displayer: 'float'; + min_fraction_digits: number; + max_fraction_digits: number; +} + +export interface DatetimeDefaultDisplayerA { + displayer: 'datetimeDefault'; +} +export interface IntegerDisplayerA { + displayer: 'integer'; + min_digits: number; + max_digits: number; +} + +export interface DatetimeLocaleDisplayerA { + displayer: 'datetimeLocaleString'; + locale: 'en-US' | 'en-GB' | 'en-CA' | 'fr-FR' | 'es-ES' | 'de-DE' | 'ja-JP'; + args: Intl.DateTimeFormatOptions; +} + +// Used DisplayerA instead of FormatterArgs, Displayer makes sense from the python side +// python doesn't care that histogram requires a cellRenderer and Integer only changes the formatter +export type FormatterArgs = + | ObjDisplayerA + | BooleanDisplayerA + | StringDisplayerA + | FloatDisplayerA + | DatetimeDefaultDisplayerA + | DatetimeLocaleDisplayerA + | IntegerDisplayerA; + +export interface HistogramDisplayerA { + displayer: 'histogram'; +} + +export interface LinkifyDisplayerA { + displayer: 'linkify'; +} +export interface BooleanCheckboxDisplayerA { + displayer: 'boolean_checkbox'; +} + +export interface Base64PNGImageDisplayerA { + displayer: 'Base64PNGImageDisplayer'; +} + +export interface SVGDisplayerA { + displayer: 'SVGDisplayer'; +} + +export type CellRendererArgs = + | HistogramDisplayerA + | LinkifyDisplayerA + | BooleanCheckboxDisplayerA + | Base64PNGImageDisplayerA + | SVGDisplayerA; + +export type DisplayerArgs = FormatterArgs | CellRendererArgs; + +export const cellRendererDisplayers = [ + 'histogram', + 'linkify', + 'Base64PNGImageDisplayer', + 'SVGDisplayer', +]; + +//ColorMapRules +export interface ColorMapRules { + color_rule: 'color_map'; + map_name: 'BLUE_TO_YELLOW' | 'DIVERGING_RED_WHITE_BLUE'; + //optional, the column to base the ranges on. the proper histogram_bins must still be sent in for that column + val_column?: string; +} + +//if exist_column is not null, set cell style to condtional_color... used for highlighting changed values or errored_rows +export interface ColorWhenNotNullRules { + color_rule: 'color_not_null'; + conditional_color: string | 'red'; + exist_column: string; +} + +export interface ColorFromColumn { + color_rule: 'color_from_column'; + col_name: string; +} + +export type ColorMappingConfig = + | ColorMapRules + | ColorWhenNotNullRules + | ColorFromColumn; + +//TooltipRules +export interface SimpleTooltip { + tooltip_type: 'simple'; + val_column: string; +} + +export interface SummarySeriesTooltip { + tooltip_type: 'summary_series'; +} + +export type TooltipConfig = SimpleTooltip | SummarySeriesTooltip; //more to be added + +export type ColumnConfig = { + col_name: string; + displayer_args: DisplayerArgs; + color_map_config?: ColorMappingConfig; + tooltip_config?: TooltipConfig; + ag_grid_specs?: AGGrid_ColDef; +}; + +export type PinnedRowConfig = { + primary_key_val: string; + displayer_args: DisplayerArgs; + //used to render index column values with string not the specified displayer, otherwise the column will be listed as NaN or blank + //by default the "index" column is always rendered with "obj" + default_renderer_columns?: string[]; +}; + +export type ComponentConfig = { + height_fraction?: number; + // temporary debugging props + dfvHeight?: number; + layoutType?: 'autoHeight' | 'normal'; + shortMode?: boolean; +}; + +export interface DFViewerConfig { + pinned_rows: PinnedRowConfig[]; + column_config: ColumnConfig[]; + extra_grid_config?: GridOptions; + component_config?: ComponentConfig; +} + +export type DFDataRow = Record< + string, + string | number | boolean | any[] | Record | null +>; + +export type DFData = DFDataRow[]; + +/* +When I want to start tagging metadata onto DFData +export interface DFData { + rows: DFDataRow[]; + //data_meta expansion point for typing info about the data as needed by non-display stuff + // typing, sorting, null handling I'm not sure about it +}; +*/ + +export interface DFWhole { + dfviewer_config: DFViewerConfig; + data: DFData; +} + +export const EmptyDf: DFWhole = { + dfviewer_config: { + pinned_rows: [], + column_config: [], + }, + data: [], +}; + +//actually SDFT is summary stats transposed to be useful +// SDFT[col][stat_name] +// SDFT really only needs histogramBins and histogramLogBins and...? at this point +//type SDFT = any; + +export interface SDFMeasure { + histogram_bins: number[]; + histogram_log_bins: number[]; +} + +export type SDFT = Record; diff --git a/js/components/DFViewerParts/Displayer.ts b/js/components/DFViewerParts/Displayer.ts new file mode 100644 index 000000000..46f33e80d --- /dev/null +++ b/js/components/DFViewerParts/Displayer.ts @@ -0,0 +1,227 @@ +import { ValueFormatterFunc, ValueFormatterParams } from 'ag-grid-community'; +import { + DisplayerArgs, + cellRendererDisplayers, + FloatDisplayerA, + IntegerDisplayerA, + DatetimeLocaleDisplayerA, + StringDisplayerA, + ObjDisplayerA, +} from './DFWhole'; +import _ from 'lodash'; +import { + Base64PNGDisplayer, + HistogramCell, + LinkCellRenderer, + SVGDisplayer, +} from './HistogramCell'; +import { CellRendererArgs, FormatterArgs } from './DFWhole'; + +/* + this code should all be unit tested and in examples. Examples will + show potential developers how this behaves. Examples should be made + inside of AG-Grid, and independently. + */ + +export const basicIntFormatter = new Intl.NumberFormat('en-US', { + minimumFractionDigits: 0, + maximumFractionDigits: 3, +}); + +export const getStringFormatter = (args: StringDisplayerA) => { + const stringFormatter = (params: ValueFormatterParams): string => { + const val = params.value; + if (val && args.max_length) { + return val.slice(0, args.max_length); + } + return val; + }; + return stringFormatter; +}; + +const dictDisplayer = (val: Record): string => { + const objBody = _.map( + val, + (value, key) => `'${key}': ${objDisplayer(value)}` + ).join(','); + return `{ ${objBody} }`; +}; + +export const isValidDate = (possibleDate: any): boolean => { + if (_.isDate(possibleDate) && isFinite(possibleDate.getTime())) { + return true; + } + return false; +}; +const DEFAULT_DATE_FORMAT: Intl.DateTimeFormatOptions = { + year: 'numeric', + month: 'numeric', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + hour12: false, +}; + +export const dateDisplayerDefault = (d: Date): string => { + const fullStr = d.toLocaleDateString('en-CA', DEFAULT_DATE_FORMAT); + const [dateStr, timeStr] = fullStr.split(','); + const retVal = `${dateStr} ${timeStr}`; + return retVal; +}; +const objDisplayer = (val: any | any[]): string => { + if (val === undefined || val === null) { + return 'None'; + } else if (_.isArray(val)) { + return `[ ${val.map(objDisplayer).join(', ')}]`; + } else if (_.isBoolean(val)) { + return boolDisplayer(val); + } else if (_.isObject(val)) { + return dictDisplayer(val); + } else { + return val.toString(); + } + return val; +}; + +export const getObjectFormatter = (fArgs: ObjDisplayerA) => { + const objFormatter = (params: ValueFormatterParams): string => { + const val = params.value; + const fullString = objDisplayer(val); + if (fArgs.max_length) { + return fullString.slice(0, fArgs.max_length); + } else { + return fullString; + } + }; + return objFormatter; +}; +export const objFormatter = getObjectFormatter({ displayer: 'obj' }); + +export const boolDisplayer = (val: boolean) => { + if (val === true) { + return 'True'; + } else if (val === false) { + return 'False'; + } + return ''; +}; + +export const booleanFormatter = (params: ValueFormatterParams): string => { + const val = params.value; + return boolDisplayer(val); +}; +const getIntegerFormatter = (hint: IntegerDisplayerA) => { + const commas = Math.floor(hint.max_digits / 3); + const totalWidth = commas + hint.max_digits; + + const formatter = new Intl.NumberFormat('en-US'); + const numericFormatter = (params: ValueFormatterParams): string => { + const val = params.value; + if (val === null) { + return ''; + } + return formatter.format(params.value).padStart(totalWidth, ' '); + }; + return numericFormatter; +}; +export const getFloatFormatter = (hint: FloatDisplayerA) => { + const floatFormatter = new Intl.NumberFormat('en-US', { + minimumFractionDigits: hint.min_fraction_digits, + maximumFractionDigits: hint.max_fraction_digits, + }); + return (params: ValueFormatterParams): string => { + if (params.value === null) { + return ''; + } + const res: string = floatFormatter.format(params.value); + if (!_.includes(res, '.')) { + const padLength = res.length + hint.max_fraction_digits + 1; + return res.padEnd(padLength); + } else { + const fracPart = res.split('.')[1]; + const padLength = hint.max_fraction_digits - fracPart.length + res.length; + return res.padEnd(padLength); + } + }; +}; + +export const getDatetimeFormatter = (colHint: DatetimeLocaleDisplayerA) => { + return (params: ValueFormatterParams): string => { + const val = params.value; + if (val === null || val === undefined) { + return ''; + } + const d = new Date(val); + if (!isValidDate(d)) { + return ''; + } + return d.toLocaleDateString(colHint.locale, colHint.args); + }; +}; + +export const defaultDatetimeFormatter = ( + params: ValueFormatterParams +): string => { + const val = params.value; + if (val === null || val === undefined) { + return ''; + } + const d = new Date(val); + if (!isValidDate(d)) { + return ''; + } + return dateDisplayerDefault(d); +}; + +export function getFormatter( + fArgs: FormatterArgs +): ValueFormatterFunc { + switch (fArgs.displayer) { + case 'integer': + return getIntegerFormatter(fArgs); + case 'string': + return getStringFormatter(fArgs); + case 'datetimeDefault': + return defaultDatetimeFormatter; + case 'datetimeLocaleString': + return getDatetimeFormatter(fArgs); + case 'float': + return getFloatFormatter(fArgs); + case 'boolean': + return booleanFormatter; + case 'obj': + return getObjectFormatter(fArgs); + default: + return getStringFormatter({ displayer: 'string' }); + } +} + +/* +{ + cellRenderer: 'agCheckboxCellRenderer', + cellRendererParams: { disabled: true} + } + */ +export function getCellRenderer(crArgs: CellRendererArgs) { + switch (crArgs.displayer) { + case 'histogram': + return HistogramCell; + case 'linkify': + return LinkCellRenderer; + case 'Base64PNGImageDisplayer': + return Base64PNGDisplayer; + case 'boolean_checkbox': + return 'agCheckboxCellRenderer'; + case 'SVGDisplayer': + return SVGDisplayer; + } +} + +export function getFormatterFromArgs(dispArgs: DisplayerArgs) { + if (_.includes(cellRendererDisplayers, dispArgs.displayer)) { + return undefined; + } + const fArgs = dispArgs as FormatterArgs; + return getFormatter(fArgs); +} diff --git a/js/components/DFViewerParts/HistogramCell.tsx b/js/components/DFViewerParts/HistogramCell.tsx new file mode 100644 index 000000000..79d838fa1 --- /dev/null +++ b/js/components/DFViewerParts/HistogramCell.tsx @@ -0,0 +1,286 @@ +import _ from 'lodash'; +import React from 'react'; +import { createPortal } from 'react-dom'; + +import { + BarChart, + Bar, + //Tooltip, + //Legend, + //Cell, XAxis, YAxis, CartesianGrid, , ResponsiveContainer, +} from 'recharts'; +import { Tooltip } from '../../vendor/RechartTooltip'; + +import { isNumOrStr, ValueType } from '../../vendor/RechartExtra'; +import { ValueFormatterFunc } from 'ag-grid-community'; + +function defaultFormatter(value: TValue) { + return _.isArray(value) && isNumOrStr(value[0]) && isNumOrStr(value[1]) + ? (value.join(' ~ ') as TValue) + : value; +} + +export const bakedData = [ + { + name: 'Page A', + population: 4000, + }, + { + name: 'Page B', + population: 3000, + }, + { + name: 'Page C', + population: 2000, + }, + { + name: 'Page D', + population: 2780, + }, + { + name: 'Page E', + population: 1890, + }, +]; + +export const makeData = (histogram: number[]) => { + const accum = []; + for (let i = 0; i < histogram.length; i++) { + accum.push({ + name: `${i + 1}/${histogram.length}`, + population: histogram[i], + }); + } + //console.log('accum', accum) + return accum; +}; + +export const formatter = (value: any, name: any, props: any) => { + if (props.payload.name === 'longtail') { + return [value, name]; + } else { + return [value, props.payload.name]; + } +}; + +export function FloatingTooltip({ items, x, y }: any) { + const offset = 30; + const renderedItems = items.map( + (name: [string, number], value: number | string) => { + const [realName, realValue] = name; + const formattedVal = realValue === 0 ? '<1' : realValue; + return ( + +
{realName}
+
{formattedVal}%
+
+ ); + } + ); + return createPortal( +
+
{renderedItems}
+
, + document.body + ); +} + +export const ToolTipAdapter = (args: any) => { + const { active, formatter, payload } = args; + if (active && payload && payload.length) { + const renderContent2 = () => { + //const items = (itemSorter ? _.sortBy(payload, itemSorter) : payload).map((entry, i) => { + const items = payload.map((entry: any, i: number) => { + if (entry.type === 'none') { + return null; + } + + const finalFormatter = entry.formatter || formatter || defaultFormatter; + const { value, name } = entry; + let finalValue: React.ReactNode = value; + let finalName: React.ReactNode = name; + if (finalFormatter && finalValue !== null && finalName !== null) { + const formatted = finalFormatter(value, name, entry, i, payload); + if (Array.isArray(formatted)) { + [finalValue, finalName] = formatted; + } else { + finalValue = formatted; + } + } + + return [finalName, finalValue]; + }); + return items; + }; + return ( +
+ +
+ ); + } + + return null; +}; + +export const getTextCellRenderer = (formatter: ValueFormatterFunc) => { + const TextCellRenderer = (props: any) => { + return {formatter(props)}; + }; + return TextCellRenderer; +}; + +export const LinkCellRenderer = (props: any) => { + return {props.value}; +}; + +export const Base64PNGDisplayer = (props: any) => { + const imgString = 'data:image/png;base64,' + props.value; + return ; +}; + +export const SVGDisplayer = (props: any) => { + const markup = { __html: props.value }; + + return ( +
+ ); +}; + +export const HistogramCell = (props: any) => { + //debugger; + if (props === undefined || props.value === undefined) { + return ; + } + const histogram = props.value; + //for key "index", the value is "histogram" + // this causes ReChart to blow up, so we check to see if it's an array + if (histogram === undefined || !_.isArray(histogram)) { + return ; + } + const dumbClickHandler = (rechartsArgs: any, _unused_react: any) => { + // I can't find the type for rechartsArgs + // these are probably the keys we care about + // activeTooltipIndex + // activeLabel + console.log('dumbClickHandler', rechartsArgs); + }; + + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } + offset={20} + allowEscapeViewBox={{ x: true }} + /> + +
+ ); +}; diff --git a/js/components/DFViewerParts/SeriesSummaryTooltip.tsx b/js/components/DFViewerParts/SeriesSummaryTooltip.tsx new file mode 100644 index 000000000..789ae8056 --- /dev/null +++ b/js/components/DFViewerParts/SeriesSummaryTooltip.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { DFViewer } from './DFViewer'; +import { DFWhole } from './DFWhole'; +import { ITooltipParams } from 'ag-grid-community'; + +export function getBakedDFViewer(seriesDf: DFWhole) { + const retFunc = (props: ITooltipParams) => { + return ( +
+

series_summary

+ +
+ ); + }; + return retFunc; +} diff --git a/js/components/DFViewerParts/gridUtils.ts b/js/components/DFViewerParts/gridUtils.ts new file mode 100644 index 000000000..6fb2083da --- /dev/null +++ b/js/components/DFViewerParts/gridUtils.ts @@ -0,0 +1,322 @@ +import { + CellClassParams, + CellRendererSelectorResult, + ColDef, + ICellRendererParams, +} from 'ag-grid-community'; +import { + BLUE_TO_YELLOW, + DIVERGING_RED_WHITE_BLUE, +} from '../../baked_data/colorMap'; + +import { + DFWhole, + DisplayerArgs, + cellRendererDisplayers, + ColumnConfig, + ColorMappingConfig, + ColorMapRules, + TooltipConfig, + ColorWhenNotNullRules, + DFViewerConfig, +} from './DFWhole'; +import _, { zipObject } from 'lodash'; +import { getTextCellRenderer } from './HistogramCell'; + +import { DFData, SDFMeasure, SDFT } from './DFWhole'; + +import { CellRendererArgs, FormatterArgs, PinnedRowConfig } from './DFWhole'; +import { getBakedDFViewer } from './SeriesSummaryTooltip'; +import { + getFormatterFromArgs, + getCellRenderer, + objFormatter, + getFormatter, +} from './Displayer'; + +// for now colDef stuff with less than 3 implementantions should stay in this file +// as implementations grow large or with many implmentations, they should move to separate files +// like displayer + +export function addToColDef( + dispArgs: DisplayerArgs, + summary_stats_column: SDFMeasure +) { + const formatter = getFormatterFromArgs(dispArgs); + if (formatter !== undefined) { + const colDefExtras: ColDef = { valueFormatter: formatter }; + return colDefExtras; + } + + if (_.includes(cellRendererDisplayers, dispArgs.displayer)) { + const crArgs: CellRendererArgs = dispArgs as CellRendererArgs; + return { + cellRenderer: getCellRenderer(crArgs), + }; + } + return undefined; +} + +export function getHistoIndex(val: number, histogram_edges: number[]): number { + /* +np.histogram([1, 2, 3, 4, 10, 20, 30, 40, 300, 300, 400, 500], bins=5) +( [ 8, 0, 2, 1, 1], +[ 1. , 100.8, 200.6, 300.4, 400.2, 500. ]) +The bottom matters for us, those are the endge + +this means that 8 values are between 1 and 100.8 and 2 values are between 200.6 and 300.4 + */ + if (histogram_edges.length === 0) { + return 0; + } + for (let i = 0; i < histogram_edges.length; i++) { + if (val <= histogram_edges[i]) { + return i; + } + } + return histogram_edges.length; +} + +export function colorMap(cmr: ColorMapRules, histogram_edges: number[]) { + // https://colorcet.com/gallery.html#isoluminant + // https://github.com/holoviz/colorcet/tree/main/assets/CET + // https://github.com/bokeh/bokeh/blob/ed285b11ab196e72336b47bf12f44e1bef5abed3/src/bokeh/models/mappers.py#L304 + const maps: Record = { + BLUE_TO_YELLOW: BLUE_TO_YELLOW, + DIVERGING_RED_WHITE_BLUE: DIVERGING_RED_WHITE_BLUE, + }; + const cmap = maps[cmr.map_name]; + + function numberToColor(val: number) { + const histoIndex = getHistoIndex(val, histogram_edges); + const scaledIndex = Math.round( + (histoIndex / histogram_edges.length) * cmap.length + ); + return cmap[scaledIndex]; + } + + function cellStyle(params: CellClassParams) { + const val = cmr.val_column ? params.data[cmr.val_column] : params.value; + const color = numberToColor(val); + return { + backgroundColor: color, + }; + } + + const retProps = { + cellStyle: cellStyle, + }; + return retProps; +} + +export function colorNotNull(cmr: ColorWhenNotNullRules) { + function cellStyle(params: CellClassParams) { + if (params.data === undefined) { + return { backgroundColor: 'inherit' }; + } + const val = params.data[cmr.exist_column]; + const valPresent = val && val !== null; + const isPinned = params.node.rowPinned; + const color = valPresent && !isPinned ? cmr.conditional_color : 'inherit'; + return { + backgroundColor: color, + }; + } + + const retProps = { + cellStyle: cellStyle, + }; + return retProps; +} + +export function getStyler( + cmr: ColorMappingConfig, + col_name: string, + histogram_stats: SDFT +) { + switch (cmr.color_rule) { + case 'color_map': { + //block necessary because you cant define varaibles in case blocks + const statsCol = cmr.val_column || col_name; + const summary_stats_cell = histogram_stats[statsCol]; + + if ( + summary_stats_cell && + summary_stats_cell.histogram_bins !== undefined + ) { + return colorMap(cmr, summary_stats_cell.histogram_bins); + } else { + console.log('histogram bins not found for color_map'); + return {}; + } + } + case 'color_not_null': + return colorNotNull(cmr); + } +} + +export function extractPinnedRows(sdf: DFData, prc: PinnedRowConfig[]) { + return _.map(_.map(prc, 'primary_key_val'), (x) => _.find(sdf, { index: x })); +} + +export function getTooltip( + ttc: TooltipConfig, + single_series_summary_df: DFWhole +): Partial { + switch (ttc.tooltip_type) { + case 'simple': + return { tooltipField: ttc.val_column }; + + case 'summary_series': + return { + tooltipComponent: getBakedDFViewer(single_series_summary_df), + tooltipField: 'index', + tooltipComponentParams: {}, + }; + } +} + +export function extractSingleSeriesSummary( + full_summary_stats_df: DFData, + col_name: string +): DFWhole { + return { + dfviewer_config: { + column_config: [ + { col_name: 'index', displayer_args: { displayer: 'obj' } }, + { col_name: col_name, displayer_args: { displayer: 'obj' } }, + ], + pinned_rows: [], + }, + data: _.filter( + _.map(full_summary_stats_df, (row) => _.pick(row, ['index', col_name])), + { index: 'dtype' } + ), + }; +} + +export function dfToAgrid( + tdf: DFData, + dfviewer_config: DFViewerConfig, + full_summary_stats_df: DFData +): [ColDef[], unknown[]] { + //more convienient df format for some formatters + const hdf = extractSDFT(full_summary_stats_df || []); + + const retColumns: ColDef[] = dfviewer_config.column_config.map( + (f: ColumnConfig) => { + const single_series_summary_df = extractSingleSeriesSummary( + full_summary_stats_df, + f.col_name + ); + + const color_map_config = f.color_map_config + ? getStyler(f.color_map_config, f.col_name, hdf) + : {}; + + const tooltip_config = f.tooltip_config + ? getTooltip(f.tooltip_config, single_series_summary_df) + : {}; + const colDef: ColDef = { + field: f.col_name, + headerName: f.col_name, + cellDataType: false, + cellStyle: {}, // necessary for colormapped columns to have a default + ...addToColDef(f.displayer_args, hdf[f.col_name]), + ...color_map_config, + ...tooltip_config, + ...f.ag_grid_specs, + }; + return colDef; + } + ); + return [retColumns, tdf]; +} + +// this is very similar to the colDef parts of dfToAgrid +export function getCellRendererSelector(pinned_rows: PinnedRowConfig[]) { + const anyRenderer: CellRendererSelectorResult = { + component: getTextCellRenderer(objFormatter), + }; + return ( + params: ICellRendererParams + ): CellRendererSelectorResult | undefined => { + if (params.node.rowPinned) { + const pk = _.get(params.node.data, 'index'); + if (pk === undefined) { + return anyRenderer; // default renderer + } + const maybePrc: PinnedRowConfig | undefined = _.find(pinned_rows, { + primary_key_val: pk, + }); + if (maybePrc === undefined) { + return anyRenderer; + } + const prc: PinnedRowConfig = maybePrc; + console.log('params', params); + const currentCol = params.column?.getColId(); + if ( + (prc.default_renderer_columns === undefined && + currentCol === 'index') || + _.includes(prc.default_renderer_columns, currentCol) + ) { + return anyRenderer; + } + const possibCellRenderer = getCellRenderer( + prc.displayer_args as CellRendererArgs + ); + + if (possibCellRenderer === undefined) { + const formattedRenderer: CellRendererSelectorResult = { + component: getTextCellRenderer( + getFormatter(prc.displayer_args as FormatterArgs) + ), + }; + return formattedRenderer; + } + return { component: possibCellRenderer }; + } else { + return undefined; // rows that are not pinned don't use a row level cell renderer + } + }; +} + +export function extractSDFT(summaryStatsDf: DFData): SDFT { + const maybeHistogramBins = + _.find(summaryStatsDf, { index: 'histogram_bins' }) || {}; + const maybeHistogramLogBins = + _.find(summaryStatsDf, { index: 'histogram_log_bins' }) || {}; + const allColumns: string[] = _.without( + _.union(_.keys(maybeHistogramBins), _.keys(maybeHistogramLogBins)), + 'index' + ); + const vals: SDFMeasure[] = _.map(allColumns, (colName) => { + return { + histogram_bins: _.get(maybeHistogramBins, colName, []) as number[], + histogram_log_bins: _.get(maybeHistogramLogBins, colName, []) as number[], + }; + }); + return zipObject(allColumns, vals) as SDFT; +} + +/* +I would love for extractSDF to be more elegant like the following function. I just can't quite get it to work +time to move on + +export function extractSDFT2(summaryStatsDf:DFData) : SDFT { + const rows = ['histogram_bins', 'histogram_log_bins'] + + const extracted = _.map(rows, (pk) => { + return _.find(summaryStatsDf, {'index': pk}) || {} + }) + const dupKeys: string[][] = _.map(extracted, _.keys); + const allColumns: string[] = _.without(_.union(...dupKeys), 'index'); + const vals:SDFMeasure[] = _.map(allColumns, (colName) => { + const pairs = _.map(_.zip(rows, extracted), (rname, row) => { + return [rname, (_.get(row, colName, []) as number[])]; + }) + return _.fromPairs(pairs) as SDFMeasure; + }); + return zipObject(allColumns, vals) as SDFT; +} +*/ diff --git a/js/components/DependentTabs.tsx b/js/components/DependentTabs.tsx new file mode 100644 index 000000000..865342b57 --- /dev/null +++ b/js/components/DependentTabs.tsx @@ -0,0 +1,150 @@ +import React, { + useState, + CSSProperties, + Dispatch, + SetStateAction, +} from 'react'; +import { DFWhole, EmptyDf } from './DFViewerParts/DFWhole'; +import _ from 'lodash'; +import { Operation } from './OperationUtils'; + +export function OperationDisplayer({ + filledOperations, + style, +}: { + filledOperations: Operation[]; + style: CSSProperties; +}): React.JSX.Element { + const baseStyle: CSSProperties = { margin: '0', textAlign: 'left' }; + const localStyle: CSSProperties = { ...baseStyle, ...style }; + return ( +
+
{JSON.stringify(filledOperations)}
+
+ ); +} + +export function PythonDisplayer({ + style, + generatedPyCode, +}: { + style: CSSProperties; + generatedPyCode: string; +}) { + const baseStyle: CSSProperties = { margin: '0', textAlign: 'left' }; + const localStyle: CSSProperties = { ...baseStyle, ...style }; + return ( +
+
{generatedPyCode}
+
+ ); +} + +export function TransformViewer({ + style, + transformedDf, +}: { + style: CSSProperties; + transformedDf: DFWhole; +}) { + return
"transformed view"
; +} +export type OperationResult = { + transformed_df: DFWhole; + generated_py_code: string; + transform_error?: string; +}; + +export type OrRequesterT = (ops: Operation[]) => void; +export type getOperationResultSetterT = ( + setter: Dispatch> +) => OrRequesterT; + +export const baseOperationResults: OperationResult = { + transformed_df: EmptyDf, + generated_py_code: 'default py code', +}; + +export function TabComponent({ + currentTab, + _setTab, + tabName, +}: { + currentTab: any; + _setTab: any; + tabName: any; +}): JSX.Element { + return ( +
  • { + _setTab(tabName); + }} + className={currentTab === tabName ? 'active' : ''} + > + {tabName} +
  • + ); +} + +export function DependentTabs({ + filledOperations, + operationResult, +}: { + filledOperations: Operation[]; + operationResult: OperationResult; +}) { + const [tab, _setTab] = useState('DataFrame'); + const style: CSSProperties = { height: '45vh' }; + return ( +
    +
      + + + +
    +
    + {operationResult.transform_error ? ( +
    +

    error

    + +
    + ) : ( + + )} + { + { + Operations: ( + + ), + Python: ( + + ), + DataFrame: ( + + ), + }[tab] + } +
    +
    + ); +} diff --git a/js/components/OperationDetail.tsx b/js/components/OperationDetail.tsx new file mode 100644 index 000000000..ee0e5cf9c --- /dev/null +++ b/js/components/OperationDetail.tsx @@ -0,0 +1,197 @@ +import _ from 'lodash'; +import { + Operation, + SettableArg, + OperationEventFunc, + NoArgEventFunc, +} from './OperationUtils'; +import { ActualArg, CommandArgSpec } from './CommandUtils'; +import { objWithoutNull, replaceAtIdx, replaceAtKey } from './utils'; +import React from 'react'; + +export const OperationDetail = ({ + command, + setCommand, + deleteCB, + columns, + commandPatterns, +}: { + command: Operation; + setCommand: OperationEventFunc; + deleteCB: NoArgEventFunc; + columns: string[]; + commandPatterns: CommandArgSpec; +}) => { + if (command === undefined) { + return

    error undefined command

    ; + } + const commandName = command[0]['symbol']; + const pattern = commandPatterns[commandName]; + + if (!_.isArray(pattern)) { + //we shouldn't get here + return

    unknown command {commandName}

    ; + } else if (_.isEqual(pattern, [null])) { + return ( +
    + +
    + ); + } else { + const fullPattern = pattern as ActualArg[]; + return ( +
    + +
    + ); + } + return

    ; +}; + +export const ArgGetters = ({ + command, + fullPattern, + setCommand, + columns, + deleteCB, +}: { + command: Operation; + fullPattern: ActualArg[]; + setCommand: OperationEventFunc; + columns: string[]; + deleteCB: () => void; +}) => { + const makeArgGetter = (pattern: ActualArg) => { + const idx = pattern[0]; + const val = command[idx] as SettableArg; + const valSetter = (newVal: unknown) => { + const newCommand = replaceAtIdx(command, idx, newVal); + //console.log('newCommand', newCommand); + setCommand(newCommand as Operation); + }; + return ( +
    + +
    + ); + }; + return ( +
    + + {fullPattern.map(makeArgGetter)} +
    + ); +}; + +const ArgGetter = ({ + argProps, + val, + setter, + columns, +}: { + argProps: ActualArg; + val: SettableArg; + setter: (arg: SettableArg) => void; + columns: string[]; +}) => { + const [_argPos, label, argType, lastArg] = argProps; + + const defaultShim = (event: { target: { value: SettableArg } }) => + setter(event.target.value); + if (argType === 'enum' && _.isArray(lastArg)) { + return ( +
    + + +
    + ); + } else if (argType === 'type') { + if (lastArg === 'integer') { + const valSetterShim = (event: { target: { value: string } }) => + setter(parseInt(event.target.value)); + return ( +
    + + +
    + ); + } else { + return ( +
    + + +
    + ); + } + } else if (argType === 'colEnum') { + const widgetRow = columns.map((colName: string) => { + const colSetter = (event: { target: { value: any } }) => { + const newColVal = event.target.value; + if (_.isString(newColVal)) { + const updatedColDict = replaceAtKey( + val as Record, + colName, + newColVal as string + ); // as Record + setter(objWithoutNull(updatedColDict, ['null'])); + } + }; + const colVal = _.get(val, colName, 'null'); + if (!_.isArray(lastArg)) { + return

    arg error

    ; + } + return ( + + + + ); + }); + + return ( +
    + + + + {columns.map((colName) => ( + + ))} + + + + {widgetRow} + +
    {colName}
    +
    + ); + } else { + return

    unknown argtype

    ; + } +}; diff --git a/js/components/OperationUtils.ts b/js/components/OperationUtils.ts new file mode 100644 index 000000000..57b503a6b --- /dev/null +++ b/js/components/OperationUtils.ts @@ -0,0 +1,36 @@ +/* + used for manipulating the JSON Flavored lisp of operations and commands + */ +import _ from 'lodash'; +import { SymbolT, ColEnumArgs, SymbolDf, symDf } from './CommandUtils'; + +export const sym = (symbolName: string) => { + return { symbol: symbolName }; +}; + +export type Atom = number | string | SymbolT | ColEnumArgs; +export type SettableArg = number | string | ColEnumArgs; + +export type OperationSingleColumn = [SymbolT, SymbolDf, string]; +export type OperationSingleArg = [SymbolT, SymbolDf, string, Atom]; +export type OperationTwoArg = [SymbolT, SymbolDf, string, Atom, Atom]; +export type Operation = + | OperationSingleColumn + | OperationSingleArg + | OperationTwoArg; + +export type SetOperationFunc = (newCommand: Operation) => void; +export type SetOperationsFunc = (newCommands: Operation[]) => void; + +export type OperationDefaultArgs = Record; + +//const ArgNames = ['Idx', 'label', 'specName', 'extraSpecArgs']; +export const bakedOperations: Operation[] = [ + [sym('dropcol'), symDf, 'col1'], + [sym('fillna'), symDf, 'col2', 5], + [sym('resample'), symDf, 'month', 'monthly', {}], +]; + +//this will become OperationEventFunc +export type OperationEventFunc = (newCommand: Operation) => void; +export type NoArgEventFunc = () => void; diff --git a/js/components/Operations.tsx b/js/components/Operations.tsx new file mode 100644 index 000000000..a64dfb22e --- /dev/null +++ b/js/components/Operations.tsx @@ -0,0 +1,243 @@ +import React, { useState, useEffect } from 'react'; +import _ from 'lodash'; +import { + Operation, + SetOperationsFunc, + OperationEventFunc, + NoArgEventFunc, +} from './OperationUtils'; +import { CommandConfigT } from './CommandUtils'; +import { replaceInArr } from './utils'; +import { bakedCommandConfig } from './bakedOperationDefaults'; +import { OperationDetail } from './OperationDetail'; +import { AgGridReact } from 'ag-grid-react'; // the AG Grid React Component +import { ColDef, GridOptions } from 'ag-grid-community'; +import { updateAtMatch } from './utils'; +import 'ag-grid-community/styles/ag-grid.css'; +import 'ag-grid-community/styles/ag-theme-alpine.css'; +import { bakedOperations } from '../baked_data/staticData'; + +const getColumns = (passedOperations: Operation[]): ColDef[] => + _.map(Array.from(passedOperations.entries()), ([index, element]) => { + const name = element[0]['symbol']; + const key = name + index.toString(); + const column = { field: key, headerName: name }; // width: 20, maxWidth: 60}; + return column; + }); + +export const OperationsList = ({ + operations, + activeKey, + setActiveKey, +}: { + operations: Operation[]; + activeKey?: string; + setActiveKey: React.Dispatch>; +}) => { + const rowElements = _.map( + Array.from(operations.entries()), + ([index, element]) => { + const name = element[0]['symbol']; + const key = name + index.toString(); + const rowEl: Record = {}; + rowEl[key] = element[2]; + return rowEl; + } + ); + const rows = [_.merge({}, ...rowElements)]; + const columns = getColumns(operations); + + const styledColumns = updateAtMatch( + _.clone(columns), + activeKey || '___never', + { + cellStyle: { background: 'var(--ag-range-selection-background-color-3)' }, + }, + { cellStyle: {} } + ); + + const gridOptions: GridOptions = { + rowSelection: 'single', + headerHeight: 30, + onCellClicked: (event) => { + const colName = event.column.getColId(); + setActiveKey(colName); + }, + }; + return ( +
    + +
    + ); +}; + +export const OperationAdder = ({ + column, + addOperationCb, + defaultArgs, +}: { + column: string; + addOperationCb: any; + defaultArgs: any; +}): JSX.Element => { + const addOperationByName = (localOperationName: string) => { + return () => { + const defaultOperation = defaultArgs[localOperationName]; + addOperationCb(replaceInArr(defaultOperation, 'col', column)); + }; + }; + + return ( +
    + Column: {column} +
    + {_.keys(defaultArgs).map((optionVal) => ( + + ))} +
    +
    + ); +}; + +export const OperationViewer = ({ + operations, + setOperations, + activeColumn, + allColumns, + commandConfig, +}: { + operations: Operation[]; + setOperations: SetOperationsFunc; + activeColumn: string; + allColumns: string[]; + commandConfig: CommandConfigT; +}) => { + const operationObjs = _.map( + Array.from(operations.entries()), + ([index, element]) => { + const name = element[0]['symbol']; + const key = name + index.toString(); + const rowEl: Record = {}; + rowEl[key] = element; + return rowEl; + } + ); + //why am I doing this? probably something so I gauruntee a clean dict + + const operationDict = _.merge({}, ...operationObjs); + + const idxObjs = _.map( + Array.from(operations.entries()), + ([index, element]) => { + const name = element[0]['symbol']; + const key = name + index.toString(); + const rowEl: Record = {}; + rowEl[key] = index; + return rowEl; + } + ); + const keyToIdx = _.merge({}, ...idxObjs); + + // previously was null + const [activeKey, setActiveKey] = useState(''); + + function getSetOperation(key: string): OperationEventFunc { + return (newOperation: Operation) => { + const index = keyToIdx[key]; + const nextOperations = operations.map((c, i) => { + if (i === index) { + return newOperation; + } else { + return c; + } + }); + setOperations(nextOperations); + }; + } + + function getDeleteOperation(key: string): NoArgEventFunc { + return (): void => { + const index = keyToIdx[key]; + const nextOperations = operations.map((c, i) => { + if (i === index) { + return undefined; + } else { + return c; + } + }); + setActiveKey(''); + setOperations(_.filter(nextOperations) as Operation[]); + }; + } + + const addOperation: OperationEventFunc = (newOperation: Operation) => { + const newOperationArr = [...operations, newOperation]; + setOperations(newOperationArr); + const newOperationKey = + getColumns(newOperationArr)[newOperationArr.length - 1].field; + if (newOperationKey !== undefined) { + setActiveKey(newOperationKey); + } + }; + const { argspecs, defaultArgs } = commandConfig; + return ( +
    + +
    +

    Operations

    + +
    + {activeKey && ( + + )} +
    + ); +}; + +export const Commands = () => { + const [c, setC] = useState(bakedOperations); + const [commandConfig, setCommandConfig] = useState(bakedCommandConfig); + + useEffect(() => { + fetch('http://localhost:5000/dcf/command-config').then(async (response) => { + setCommandConfig(await response.json()); + }); + }, []); + + return ( +
    + + + {' '} + {JSON.stringify(c, null, '\t\n\r')}{' '} + +
    + ); +}; diff --git a/js/components/StatusBar.tsx b/js/components/StatusBar.tsx new file mode 100644 index 000000000..1ce68f86c --- /dev/null +++ b/js/components/StatusBar.tsx @@ -0,0 +1,229 @@ +// https://plnkr.co/edit/QTNwBb2VEn81lf4t?open=index.tsx +import React, { useState, useRef } from 'react'; +import _ from 'lodash'; +import { AgGridReact } from 'ag-grid-react'; // the AG Grid React Component +import { ColDef, GridOptions } from 'ag-grid-community'; +import { basicIntFormatter } from './DFViewerParts/Displayer'; +import { DFMeta } from './WidgetTypes'; +import { BuckarooOptions } from './WidgetTypes'; +import { BuckarooState, BKeys } from './WidgetTypes'; +export type setColumFunc = (newCol: string) => void; + +const getSearchForm = (initialVal: string, setSearchVal: any) => { + return function MyForm() { + function handleSubmit(e: any) { + // Prevent the browser from reloading the page + e.preventDefault(); + // Read the form data + const form = e.target; + const formData = new FormData(form); + + const entries = Array.from(formData.entries()); + + const formDict = _.fromPairs(entries) as Record; + + console.log('formDict', formDict); + setSearchVal(formDict['search']); + } + + return ( +
    + +
    + ); + }; +}; + +const helpCell = function (params: any) { + return ( + + ? + + ); +}; + +export function StatusBar({ + dfMeta, + buckarooState, + setBuckarooState, + buckarooOptions, +}: { + dfMeta: DFMeta; + buckarooState: BuckarooState; + setBuckarooState: React.Dispatch>; + buckarooOptions: BuckarooOptions; +}) { + console.log('initial buckarooState', buckarooState); + // const optionCycles = _.fromPairs( + // // _.map(buckarooOptions, (v: any, k) => [k, ( k==='df_display' ? v : _.concat([false], v) ) ]) + // _.map(buckarooOptions, (v: any, k) => [k, ( k==='post_processing' ? v : _.concat([false], v) ) ]) + + // ) as Record; + const optionCycles = buckarooOptions; + const idxs = _.fromPairs( + _.map(_.keys(optionCycles), (k) => [ + k, + _.indexOf(optionCycles[k as BKeys], buckarooState[k as BKeys]), + ]) + ); + + const nextIndex = (curIdx: number, arr: any[]) => { + if (curIdx === arr.length - 1) { + return 0; + } + return curIdx + 1; + }; + + const newBuckarooState = (k: BKeys) => { + const arr = optionCycles[k]; + const curIdx = idxs[k]; + const nextIdx = nextIndex(curIdx, arr); + const newVal = arr[nextIdx]; + const newState = _.clone(buckarooState); + newState[k] = newVal; + return newState; + }; + const updateDict = (event: any) => { + const colName = event.column.getColId(); + if (colName === 'search') { + return; + } + if (_.includes(_.keys(buckarooState), colName)) { + const nbstate = newBuckarooState(colName as BKeys); + setBuckarooState(nbstate); + } + }; + const showSearch = false; + const localSetSearchString = (search_query: string) => { + setBuckarooState({ ...buckarooState, search_string: search_query }); + }; + + const columnDefs: ColDef[] = [ + { + field: 'search', + width: 200, + cellRenderer: getSearchForm( + buckarooState.search_string, + localSetSearchString + ), + hide: !showSearch, + }, + + { + field: 'df_display', + headerName: 'Σ', //note the greek symbols instead of icons which require buildchain work + headerTooltip: 'Summary Stats', + width: 120, + }, + /* + { + field: 'auto_clean', + //headerName: 'Σ', //note the greek symbols instead of icons which require buildchain work + headerName: 'auto cleaning', + headerTooltip: 'Auto Cleaning config', + width: 120, + }, + */ + { + field: 'post_processing', + // headerName: "Θ", + headerName: 'post processing', + headerTooltip: 'post process method', + width: 100, + }, + { + field: 'show_commands', + headerName: 'λ', + headerTooltip: 'Show Commands', + width: 30, + }, + + { field: 'sampled', headerName: 'Ξ', headerTooltip: 'Sampled', width: 30 }, + { + field: 'help', + headerName: '?', + headerTooltip: 'Help', + width: 30, + cellRenderer: helpCell, + }, + { field: 'total_rows', width: 100 }, + { field: 'rows_shown', headerName: 'displayed', width: 85 }, + { field: 'columns', width: 75 }, + ]; + + const rowData = [ + { + total_rows: basicIntFormatter.format(dfMeta.total_rows), + columns: dfMeta.columns, + rows_shown: basicIntFormatter.format(dfMeta.rows_shown), + sampled: buckarooState.sampled || '0', + auto_clean: buckarooState.auto_clean || '0', + df_display: buckarooState.df_display, + post_processing: buckarooState.post_processing, + show_commands: buckarooState.show_commands || '0', + }, + ]; + + const gridOptions: GridOptions = { + suppressRowClickSelection: true, + }; + + const gridRef = useRef>(null); + const defaultColDef = { + // type: 'left-aligned', + cellStyle: { textAlign: 'left' }, + }; + return ( +
    +
    + +
    +
    + ); +} +export function StatusBarEx() { + const dfm: DFMeta = { + columns: 5, + rows_shown: 20, + total_rows: 8_777_444, + }; + + const [bState, setBState] = useState({ + auto_clean: 'conservative', + sampled: false, + df_display: 'main', + post_processing: 'asdf', + show_commands: false, + search_string: '', + }); + + const bOptions: BuckarooOptions = { + auto_clean: ['aggressive', 'conservative'], + post_processing: ['', 'asdf'], + sampled: ['random'], + show_commands: ['on'], + df_display: ['main'], + }; + + return ( + + ); +} diff --git a/js/components/WidgetTypes.tsx b/js/components/WidgetTypes.tsx new file mode 100644 index 000000000..0de348093 --- /dev/null +++ b/js/components/WidgetTypes.tsx @@ -0,0 +1,38 @@ +export interface DFMeta { + // static, + total_rows: number; + columns: number; + rows_shown: number; +} +export interface BuckarooOptions { + sampled: string[]; + auto_clean: string[]; + post_processing: string[]; + df_display: string[]; // keys into Into df_display_args + show_commands: string[]; +} +export interface BuckarooState { + sampled: string | false; + auto_clean: string | false; + search_string: string; + post_processing: string | false; + df_display: string; //at least one dataframe must always be displayed + show_commands: string | false; +} + +export type BKeys = keyof BuckarooOptions; + +// df_dict: Record; +// df_meta: DFMeta; +/* + + df_dict: Record; + df_meta: DFMeta; + operations: Operation[]; + on_operations: (ops: Operation[]) => void; + operation_results: OperationResult; + commandConfig: CommandConfigT; + buckaroo_state: BuckarooState; + on_buckaroo_state: React.Dispatch>; + buckaroo_options: BuckarooOptions; +*/ diff --git a/js/components/bakedOperationDefaults.ts b/js/components/bakedOperationDefaults.ts new file mode 100644 index 000000000..5b922344e --- /dev/null +++ b/js/components/bakedOperationDefaults.ts @@ -0,0 +1,14 @@ +import { OperationDefaultArgs } from './OperationUtils'; +import { sym } from './utils'; +import { symDf, CommandConfigT, bakedArgSpecs } from './CommandUtils'; + +export const bakedOperationDefaults: OperationDefaultArgs = { + dropcol: [sym('dropcol'), symDf, 'col'], + fillna: [sym('fillna'), symDf, 'col', 8], + resample: [sym('resample'), symDf, 'col', 'monthly', {}], +}; + +export const bakedCommandConfig: CommandConfigT = { + argspecs: bakedArgSpecs, + defaultArgs: bakedOperationDefaults, +}; diff --git a/js/components/utils.ts b/js/components/utils.ts new file mode 100644 index 000000000..3e59f37c6 --- /dev/null +++ b/js/components/utils.ts @@ -0,0 +1,72 @@ +import _ from 'lodash'; +import { DFWhole } from './DFViewerParts/DFWhole'; +import { ColDef } from 'ag-grid-community'; + +export type setDFFunc = (newDf: DFWhole) => void; + +export const requestDf = (url: string, setCallBack: setDFFunc) => { + const retPromise = fetch(url).then(async (response) => { + const tableDf = await response.json(); + setCallBack(tableDf); + }); + return retPromise; +}; + +export const sym = (symbolName: string) => { + return { symbol: symbolName }; +}; + +export function replaceInArr(arr: T[], old: T, subst: T): T[] { + return arr.map((item: T) => (item === old ? subst : item)); +} + +export function replaceAtIdx(arr: T[], idx: number, subst: T): T[] { + return arr.map((item: T, innerIdx: number) => + innerIdx === idx ? subst : item + ); +} + +export function replaceAtKey( + obj: Record, + key: string, + subst: T +): Record { + const objCopy = _.clone(obj); + objCopy[key] = subst; + return objCopy; +} + +export const objWithoutNull = ( + obj: Record, + extraStrips: string[] = [] +) => _.pickBy(obj, (x) => ![null, undefined, ...extraStrips].includes(x)); +export const updateAtMatch = ( + cols: ColDef[], + key: string, + subst: Partial, + negative: Partial +) => { + const retColumns = cols.map((x) => { + if (x.field === key) { + return { ...x, ...subst }; + } else { + return { ...x, ...negative }; + } + }); + return retColumns; +}; + +export const replaceAtMatch = ( + cols: ColDef[], + key: string, + subst: Partial +) => { + const retColumns = cols.map((x) => { + if (x.field === key) { + return { ...x, ...subst }; + } else { + return { ...x }; + } + }); + return retColumns; +}; diff --git a/js/dcefwidget.ts b/js/dcefwidget.ts new file mode 100644 index 000000000..b995149bb --- /dev/null +++ b/js/dcefwidget.ts @@ -0,0 +1,133 @@ +// Copyright (c) Paddy Mullen +// Distributed under the terms of the Modified BSD License. +import _ from 'lodash'; +import { + DOMWidgetModel, + DOMWidgetView, + ISerializers, +} from '@jupyter-widgets/base'; + +import { WidgetDCFCell } from './components/DCFCell'; + +import * as Backbone from 'backbone'; + +import React, { useEffect, useState } from 'react'; +import * as ReactDOMClient from 'react-dom/client'; +import { MODULE_NAME, MODULE_VERSION } from './version'; + +// Import the CSS + +import 'ag-grid-community/styles/ag-grid.css'; +import 'ag-grid-community/styles/ag-theme-alpine.css'; +import '../js/style/dcf-npm.css'; +import { DFViewer } from './components/DFViewerParts/DFViewer'; + +export class DCEFWidgetModel extends DOMWidgetModel { + defaults(): Backbone.ObjectHash { + return { + ...super.defaults(), + _model_name: DCEFWidgetModel.model_name, + _model_module: DCEFWidgetModel.model_module, + _model_module_version: DCEFWidgetModel.model_module_version, + _view_name: DCEFWidgetModel.view_name, + _view_module: DCEFWidgetModel.view_module, + _view_module_version: DCEFWidgetModel.view_module_version, + }; + } + + static serializers: ISerializers = { + ...DOMWidgetModel.serializers, + // Add any extra serializers here + }; + + static model_name = 'DCEFWidgetModel'; + static model_module = MODULE_NAME; + static model_module_version = MODULE_VERSION; + static view_name = 'ExampleView'; // Set to null if no view + static view_module = MODULE_NAME; // Set to null if no view + static view_module_version = MODULE_VERSION; +} +export class DCEFWidgetView extends DOMWidgetView { + render(): void { + this.el.classList.add('custom-widget'); + + const Component = () => { + const [_, setCounter] = useState(0); + const forceRerender = () => { + setCounter((x: number) => x + 1); + }; + useEffect(() => { + this.listenTo(this.model, 'change', forceRerender); + }, []); + + const props: any = {}; + for (const key of Object.keys(this.model.attributes)) { + props[key] = this.model.get(key); + props['on_' + key] = (value: any) => { + this.model.set(key, value); + this.touch(); + }; + } + return React.createElement(WidgetDCFCell, props); + }; + + const root = ReactDOMClient.createRoot(this.el); + const componentEl = React.createElement(Component, {}); + root.render(componentEl); + } +} +export class DFViewerModel extends DOMWidgetModel { + defaults(): Backbone.ObjectHash { + return { + ...super.defaults(), + _model_name: DFViewerModel.model_name, + _model_module: DFViewerModel.model_module, + _model_module_version: DFViewerModel.model_module_version, + _view_name: DFViewerModel.view_name, + _view_module: DFViewerModel.view_module, + _view_module_version: DFViewerModel.view_module_version, + }; + } + + static serializers: ISerializers = { + ...DOMWidgetModel.serializers, + // Add any extra serializers here + }; + + static model_name = 'DFViewerModel'; + static model_module = MODULE_NAME; + static model_module_version = MODULE_VERSION; + static view_name = 'DFViewerView'; // Set to null if no view + static view_module = MODULE_NAME; // Set to null if no view + static view_module_version = MODULE_VERSION; +} +export class DFViewerView extends DOMWidgetView { + render(): void { + this.el.classList.add('dfviewer-widget'); + + const Component = () => { + const [_, setCounter] = useState(0); + const forceRerender = () => { + setCounter((x: number) => x + 1); + }; + useEffect(() => { + this.listenTo(this.model, 'change', forceRerender); + }, []); + + const props: any = {}; + for (const key of Object.keys(this.model.attributes)) { + props[key] = this.model.get(key); + props['on_' + key] = (value: any) => { + this.model.set(key, value); + this.touch(); + }; + } + return React.createElement(DFViewer, props); + //return React.createElement(WidgetDCFCell, props); + }; + + const root = ReactDOMClient.createRoot(this.el); + const componentEl = React.createElement(Component, {}); + root.render(componentEl); + } +} diff --git a/js/dcfwidget.ts b/js/dcfwidget.ts deleted file mode 100644 index eb8238ce6..000000000 --- a/js/dcfwidget.ts +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) Paddy Mullen -// Distributed under the terms of the Modified BSD License. - -import { - DOMWidgetModel, - DOMWidgetView, - ISerializers, -} from '@jupyter-widgets/base'; - - -import _ from 'lodash'; - -import {WidgetDCFCell, CommandConfigT, DFWhole, CommandConfigSetterT, Operation, DependentTabs } from 'paddy-react-edit-list'; - -import { createRoot } from "react-dom/client"; -import React from "react"; - -import { MODULE_NAME, MODULE_VERSION } from './version'; - -// Import the CSS - -import 'ag-grid-community/styles/ag-grid.css'; -import 'ag-grid-community/styles/ag-theme-alpine.css'; -import 'paddy-react-edit-list/css/dcf-npm.css'; -import '../style/widget.css'; - - -export class DCFWidgetModel extends DOMWidgetModel { - defaults() { - return { - ...super.defaults(), - _model_name: DCFWidgetModel.model_name, - _model_module: DCFWidgetModel.model_module, - _model_module_version: DCFWidgetModel.model_module_version, - _view_name: DCFWidgetModel.view_name, - _view_module: DCFWidgetModel.view_module, - _view_module_version: DCFWidgetModel.view_module_version, - //add typing from OperationUtils - command_config: {} as CommandConfigT, - commands: [] as Operation[], - operation_results: {} // {transformed_df:DFWhole, generated_py_code:string} - }; - } - - - static serializers: ISerializers = { - ...DOMWidgetModel.serializers, - // Add any extra serializers here - }; - - static model_name = 'DCFWidgetModel'; - static model_module = MODULE_NAME; - static model_module_version = MODULE_VERSION; - static view_name = 'ExampleView'; // Set to null if no view - static view_module = MODULE_NAME; // Set to null if no view - static view_module_version = MODULE_VERSION; -} - - -export class DCFWidgetView extends DOMWidgetView { - render() { - console.log('DCFWidget View... renamed ') - this.el.classList.add('custom-widget'); - //this.value_changed(); - const root = createRoot(this.el as HTMLElement) - - const widgetModel = this.model - const widget = this - widgetModel.on( - 'change:command_config', - () => { - widget.setCommandConfig(widgetModel.get('command_config'))}, - this) - - const widgetGetOrRequester:DependentTabs.getOperationResultSetterT = (setOpResult) => { - widgetModel.on('change:operation_results', () => { - const opResults:DependentTabs.OperationResult = widgetModel.get('operation_results') - console.log("about to call setOpResult with", opResults) - setOpResult(opResults) - }, this) - - const retFunc = (passedOperations:Operation[]) => { - console.log("orRequester passed operations", passedOperations) - widgetModel.set('commands', passedOperations) - widgetModel.save_changes() - - } - return retFunc - }; - - const commandConfig = widgetModel.get('command_config') - console.log("widget, commandConfig", commandConfig, widgetModel) - const plumbCommandConfig:CommandConfigSetterT = (setter) => { - widget.setCommandConfig = setter - } - - const reactEl = React.createElement(WidgetDCFCell, { - origDf:widgetModel.get('js_df'), - getOrRequester:widgetGetOrRequester, - commandConfig, - exposeCommandConfigSetter:plumbCommandConfig, - }, null) - - root.render(reactEl); - } - - setCommandConfig = (conf:CommandConfigT) => { - console.log("default setCommandConfig") - } - setPyCode = (newPyCode:string) => { - console.log("default setPyCode") - } - setTransformedDf = (newDf:DFWhole) => { - console.log("default setTransformedDf") - } -} - -/* -console.log("144") - - const widgetGetTransformRequester = (setDf:any) => { - widget.setTransformedDf = (inputDf:DFWhole) => { - const opResults = widgetModel.get('operation_results') - const generated_py_code = opResults.generated_py_code - console.log("setDf Wrapper being called - generated_py_code", generated_py_code) - setDf(inputDf) - }; - // widgetModel.on('change:transformed_df', () => { - // setDf(widgetModel.get('transformed_df') as DFWhole) - // }, this) - - const baseRequestTransform = (passedInstructions:any) => { - console.log("transform passedInstructions", passedInstructions) - widgetModel.set('commands', passedInstructions) - widgetModel.save_changes() - }; - return baseRequestTransform; - }; - //_.delay(() => {widget.setPyCode("widget level getPyRequester")}, 500) - //this onChange gets called, the one inside of widgetGetPyRequester doesn't get called - - widgetModel.on('change:operation_results', () => { - const opResults = widgetModel.get('operation_results') - console.log("operation_results", opResults) - widget.setPyCode(opResults.generated_py_code) - widget.setTransformedDf(opResults.transformed_df) - //widget.setPyCode("padddy") - //widgetModel.save_changes() - }, this) -*/ diff --git a/js/extension.ts b/js/extension.ts index 81a30da77..86f007172 100644 --- a/js/extension.ts +++ b/js/extension.ts @@ -12,6 +12,6 @@ (window as any).__webpack_public_path__ = // eslint-disable-next-line @typescript-eslint/no-non-null-assertion document.querySelector('body')!.getAttribute('data-base-url') + - 'nbextensions/ipydatagrid'; + 'nbextensions/buckaroo'; export * from './index'; diff --git a/js/index.ts b/js/index.ts index 658c30cb4..83419ef06 100644 --- a/js/index.ts +++ b/js/index.ts @@ -1,8 +1,36 @@ // Copyright (c) Bloomberg // Distributed under the terms of the Modified BSD License. +import { ColumnsEditor, ColumnsEditorEx } from './components/ColumnsEditor'; +import { WidgetDCFCellExample } from './components/DCFCell'; +import { DFViewer, DFViewerEx } from './components/DFViewerParts/DFViewer'; +import { HistogramCell } from './components/DFViewerParts/HistogramCell'; +import { DependentTabs } from './components/DependentTabs'; +import { OperationViewer } from './components/Operations'; +//import { DFData, DFViewerConfig } from './components/DFViewerParts/DFWhole'; +import { StatusBarEx } from './components/StatusBar'; + // In case of classic Jupyter Notebook and embed, we provide the PhosphorJS CSS export * from './version'; -export * from './paddywidget'; -export * from './dcfwidget'; +export * from './dcefwidget'; +export * as bakedData from './baked_data/staticData'; + +export const extraComponents = { + ColumnsEditor, + DependentTabs, + OperationViewer, + WidgetDCFCellExample, + ColumnsEditorEx, + DFViewer, + DFViewerEx, + StatusBarEx, + HistogramCell, +}; + +/* +export const typing = { + DFData, + DFViewerConfig + }; +*/ diff --git a/js/paddywidget.ts b/js/paddywidget.ts deleted file mode 100644 index d59379166..000000000 --- a/js/paddywidget.ts +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) Paddy Mullen -// Distributed under the terms of the Modified BSD License. - -import { - DOMWidgetModel, - DOMWidgetView, - ISerializers, -} from '@jupyter-widgets/base'; - -import { MODULE_NAME, MODULE_VERSION } from './version'; - - -import { createRoot } from "react-dom/client"; -import React from "react"; - -function ExampleComponent(props:any) { - return React.createElement('h1', null, `Hello ${props.name}`); -} - - -console.log("paddy model module level"); - -//export const localModuleName = "PaddyModule" -export class PaddyModel extends DOMWidgetModel { - defaults() { - return { - ...super.defaults(), - _model_name: PaddyModel.model_name, - _model_module: PaddyModel.model_module, - _model_module_version: PaddyModel.model_module_version, - _view_name: PaddyModel.view_name, - _view_module: PaddyModel.view_module, - _view_module_version: PaddyModel.view_module_version, - value: 'Paddy Model', - }; - } - - static serializers: ISerializers = { - ...DOMWidgetModel.serializers, - // Add any extra serializers here - }; - - static model_name = 'PaddyModel'; - static model_module = MODULE_NAME; //localModuleName - static model_module_version = MODULE_VERSION; - static view_name = 'PaddyView'; // Set to null if no view - static view_module = MODULE_NAME; // Set to null if no view - static view_module_version = MODULE_VERSION; -} - -export class PaddyView extends DOMWidgetView { - render() { - console.log("paddy 5555735") - this.el.classList.add('custom-widget'); - this.value_changed(); - try { - const root = createRoot(this.el as HTMLElement) - root.render(React.createElement(ExampleComponent, { name: "Paddy" }, null)); - console.log("react calls worked fine") - } catch (e) { - console.log("error instatiating React components", e) - } - this.model.on('change:value', this.value_changed, this); - } - - value_changed() { - //this.el.textContent = this.model.get('value') + "from_Paddy view render"; - } -} diff --git a/js/plugin.ts b/js/plugin.ts index 5751f1428..f95e79c51 100644 --- a/js/plugin.ts +++ b/js/plugin.ts @@ -9,12 +9,10 @@ import { IJupyterWidgetRegistry } from '@jupyter-widgets/base'; import { IThemeManager } from '@jupyterlab/apputils'; - import { MODULE_NAME, MODULE_VERSION } from './version'; -import * as paddywidget from './paddywidget'; -import * as dcfwidget from './dcfwidget'; +import * as dcefwidget from './dcefwidget'; -const EXTENSION_ID = 'ipydatagrid:plugin'; +const EXTENSION_ID = 'buckaroo:plugin'; /** * The datagrid plugin. @@ -36,16 +34,15 @@ export default datagridPlugin; function activateWidgetExtension( app: Application, registry: IJupyterWidgetRegistry, - themeManager: IThemeManager | null, + themeManager: IThemeManager | null ): void { + console.log('buckaroo_widget plugin.ts after change EXTENSION_ID'); // Exporting a patched DataGridView widget which handles dynamic theme changes - console.log("ipydatagrid dcfwidget", dcfwidget) registry.registerWidget({ name: MODULE_NAME, version: MODULE_VERSION, exports: { - ...paddywidget, - ...dcfwidget + ...dcefwidget, }, }); } diff --git a/js/style/dcf-npm.css b/js/style/dcf-npm.css new file mode 100644 index 000000000..c22ccf3f0 --- /dev/null +++ b/js/style/dcf-npm.css @@ -0,0 +1,237 @@ +.column-list { + width: 100%; + font-size: 1rem; +} +.column-list dl { + display: flex; + margin: 0; + padding: 0; +} +.column-list dl div.list-item { + padding: 3px; +} +.column-list dl div.list-item dt { + float: left; + max-width: 90px; + overflow: hidden; + max-height: 1rem; +} +.column-list dl div.list-item dd { + float: right; +} +.column-list dl div.list-item .column-editor { + width: 100%; + clear: both; + height: 30px; +} +.column-list dl div.list-item .column-editor label span { + float: left; +} +.column-list dl div.list-item .column-editor label input[type=checkbox] { + float: left; +} +.dependent-tabs { + font-size: 1rem; +} +.dependent-tabs ul.tabs li { + float: left; + background: var(--ag-background-color); + color: var(--ag-foreground-color); + border: 1px solid purple; + border-bottom: none; + list-style: none; + margin-right: 5px; + padding: 2px; +} +.dependent-tabs ul.tabs li.active { + background: var(--ag-range-selection-background-color-3); + color: var(--ag-alpine-active-color); +} +.dependent-tabs .output-area { + clear: both; + float: none; +} + +.python-displayer, .command-displayer { + width: 100%; + height: 100%; + background: hsl(0, 0%, 13%); + overflow: hidden; + padding: 16px; + /*border:1px solid red; */ +} +.python-displayer pre, .command-displayer pre { + color: #41FF00; +} + +.command-displayer pre { + overflow: hidden; +} + +.features { + font-size: 1.7rem; +} +.features div { + padding: 0.5rem; +} + +.modal { + position: absolute; + background-color: #ffffff; + border: 1px solid black; + padding: 16px; + list-style: none; +} +.modal > li { + padding: 8px; +} + +.command-viewer { + border: 1px solid; + color: black; + font-size: 1rem; +} +.command-viewer .operation-adder { + clear: both; +} +.command-viewer .operation-adder span.column-name { + float: left; + display: block; + color: black; +} +.command-viewer .operation-adder fieldset { + float: left; +} +.command-viewer .operations-box { + clear: left; + display: flex; + overflow: auto; +} +.command-viewer .operations-box h4 { + font-size: 1em; + border: 1px orange; + color: black; +} +.command-viewer .operations-box div { + overflow-x: scroll; +} + +.operation-detail { + overflow: auto; +} +.operation-detail button { + float: left; +} +.operation-detail .arg-getters button { + float: left; +} +.operation-detail .arg-getters fieldset { + float: left; +} +.operation-detail .arg-getters div.col-enum { + float: left; + width: 800px; + overflow-x: scroll; +} +.operation-detail .arg-getters div.col-enum table td, .operation-detail .arg-getters div.col-enum table th { + border: 1px solid black; +} + +.col-enum table { + margin-bottom:9px; +} + +.ag-theme-alpine-dark { + --ag-grid-size:3px; + --ag-list-item-height: 20px; + } + +div.dependent-tabs ul.tabs li.active { + background:rgba(33, 150, 243, 0.49); +/* border:1px solid red; */ +} + +.ag-row .ag-cell { + font-family: monospace; + white-space: pre; +} +.left-menu { + color:black; +} + +.dev-examples .statusBar { + width:800px; border:3px dashed purple; + + + + + +} + +.custom-tooltip { + color:black; + background:green; +} + + +.histogram-component { + margin:0; + border-left:1px solid #68686e; + border-right:1px solid #68686e; + + +} + +.floating-tooltip { + color:black;; + background:white; +} + + +.floating-tooltip dl { + border:1px solid black; + padding:1px 4px; + margin:0; + display:flow-root; +} +.floating-tooltip dl dt { + font-weight:bold; + float:left; + margin:0; + padding:0; + +} +.floating-tooltip dl dd { + + float:left; + margin:0 0 0 10px; + clear:right; +} + +.df-viewer.short-mode .ag-center-cols-viewport { +/* min-height: unset !important; */ + min-height: 50px; +} + +.df-viewer.in-iframe.short-mode { + .ag-center-cols-viewport { + min-height:450px; + } +} +.df-viewer.in-iframe { + .ag-center-cols-viewport { + min-height:450px; + } + } + + +/* +.df-viewer.short-mode > div { + + min-height: 100; + max-height: 800 +} +*/ +/*# sourceMappingURL=dcf-npm.css.map */ + + diff --git a/style/icons/arrow-down-short-dark.svg b/js/style/icons/arrow-down-short-dark.svg similarity index 100% rename from style/icons/arrow-down-short-dark.svg rename to js/style/icons/arrow-down-short-dark.svg diff --git a/style/icons/arrow-down-short.svg b/js/style/icons/arrow-down-short.svg similarity index 100% rename from style/icons/arrow-down-short.svg rename to js/style/icons/arrow-down-short.svg diff --git a/style/icons/arrow-up-short-dark.svg b/js/style/icons/arrow-up-short-dark.svg similarity index 100% rename from style/icons/arrow-up-short-dark.svg rename to js/style/icons/arrow-up-short-dark.svg diff --git a/style/icons/arrow-up-short.svg b/js/style/icons/arrow-up-short.svg similarity index 100% rename from style/icons/arrow-up-short.svg rename to js/style/icons/arrow-up-short.svg diff --git a/style/icons/filter-dark.svg b/js/style/icons/filter-dark.svg similarity index 100% rename from style/icons/filter-dark.svg rename to js/style/icons/filter-dark.svg diff --git a/style/icons/filter.svg b/js/style/icons/filter.svg similarity index 100% rename from style/icons/filter.svg rename to js/style/icons/filter.svg diff --git a/js/vendor/RechartExtra.ts b/js/vendor/RechartExtra.ts new file mode 100644 index 000000000..df8d351a8 --- /dev/null +++ b/js/vendor/RechartExtra.ts @@ -0,0 +1,72 @@ +/** + * This module contains the standard library from rechart so that base rechart code cna be imported with the minimum amount of rewriting + */ + +import _ from 'lodash'; +import { CSSProperties, ReactNode } from 'react'; +export { Global, DefaultTooltipContent } from 'recharts'; + +//export Global; + +//import { AnimationDuration, AnimationTiming } from '../util/types'; +/** The type of easing function to use for animations */ +export type AnimationTiming = + | 'ease' + | 'ease-in' + | 'ease-out' + | 'ease-in-out' + | 'linear'; +/** Specifies the duration of animation, the unit of this option is ms. */ +export type AnimationDuration = number; + +export type TooltipType = 'none'; +export type ValueType = number | string | Array; +export type NameType = number | string; + +export type Formatter = ( + value: TValue, + name: TName, + item: Payload, + index: number, + payload: Array> +) => [React.ReactNode, TName] | React.ReactNode; + +export interface Payload { + type?: TooltipType; + color?: string; + formatter?: Formatter; + name?: TName; + value?: TValue; + unit?: ReactNode; + dataKey?: string | number; + payload?: any; + chartType?: string; + stroke?: string; + strokeDasharray?: string | number; + strokeWidth?: number | string; +} + +export interface DefaultProps< + TValue extends ValueType, + TName extends NameType +> { + separator?: string; + wrapperClassName?: string; + labelClassName?: string; + formatter?: Formatter; + contentStyle?: CSSProperties; + itemStyle?: CSSProperties; + labelStyle?: CSSProperties; + labelFormatter?: ( + label: any, + payload: Array> + ) => ReactNode; + label?: any; + payload?: Array>; + itemSorter?: (item: Payload) => number | string; +} + +export const isNumber = (value: unknown): value is number => + _.isNumber(value) && !_.isNaN(value); +export const isNumOrStr = (value: unknown): value is number | string => + isNumber(value as number) || _.isString(value); diff --git a/js/vendor/RechartTooltip.tsx b/js/vendor/RechartTooltip.tsx new file mode 100644 index 000000000..270087154 --- /dev/null +++ b/js/vendor/RechartTooltip.tsx @@ -0,0 +1,375 @@ +//@ts-nocheck +/** + * Reimplementation of rechart tooltips. most of this is copied from ??? in the recharts source tree because the parts we are editting are deeply embedded into functions. + + Most of the point of this is to get tooltips to be absolutely positioned off of document.body, not the nearest parent element. AG-Grid hides those tooltips otherwise. + */ +import React, { + CSSProperties, + ReactNode, + ReactElement, + SVGProps, + useEffect, + useState, + useRef, + useCallback, +} from 'react'; +import { translateStyle } from 'react-smooth'; +import _ from 'lodash'; +//import classNames from 'classnames'; + +//import { DefaultTooltipContent, ValueType, NameType, Payload, Props as DefaultProps } from './DefaultTooltipContent'; + +import type { + ValueType, + NameType, + Payload, + DefaultProps, +} from './RechartExtra'; +//import { Global } from '../util/Global'; +//import { isNumber } from '../util/DataUtils'; +import { Global, isNumber } from './RechartExtra'; + +//import { AnimationDuration, AnimationTiming } from '../util/types'; +import { AnimationDuration, AnimationTiming } from './RechartExtra'; + +import { DefaultTooltipContent } from 'recharts'; + +const CLS_PREFIX = 'recharts-tooltip-wrapper'; + +const EPS = 1; + +export type ContentType = + | ReactElement + | ((props: TooltipProps) => ReactNode); + +type UniqueFunc = ( + entry: Payload +) => unknown; +type UniqueOption = + | boolean + | UniqueFunc; +function defaultUniqBy( + entry: Payload +) { + return entry.dataKey; +} +function getUniqPayload( + option: UniqueOption, + payload: Array> +) { + if (option === true) { + //@ts-ignore + return _.uniqBy(payload, defaultUniqBy); + } + + if (_.isFunction(option)) { + return _.uniqBy(payload, option); + } + + return payload; +} + +function renderContent( + content: ContentType, + props: TooltipProps +) { + if (React.isValidElement(content)) { + return React.cloneElement(content, props); + } + if (_.isFunction(content)) { + return React.createElement(content as any, props); + } + + return ; +} + +export type OptionalCoords = { + x?: number; + y?: number; +}; + +export type TooltipProps< + TValue extends ValueType, + TName extends NameType +> = DefaultProps & { + allowEscapeViewBox?: { + x?: boolean; + y?: boolean; + }; + reverseDirection?: { + x?: boolean; + y?: boolean; + }; + content?: ContentType; + viewBox?: { + x?: number; + y?: number; + width?: number; + height?: number; + }; + active?: boolean; + offset?: number; + wrapperStyle?: CSSProperties; + cursor?: boolean | ReactElement | SVGProps; + coordinate?: OptionalCoords; + position?: OptionalCoords; + trigger?: 'hover' | 'click'; + shared?: boolean; + payloadUniqBy?: UniqueOption; + isAnimationActive?: boolean; + animationDuration?: AnimationDuration; + animationEasing?: AnimationTiming; + filterNull?: boolean; + useTranslate3d?: boolean; + box?: OptionalCoords; +}; + +const tooltipDefaultProps: TooltipProps = { + active: false, + allowEscapeViewBox: { x: false, y: false }, + reverseDirection: { x: false, y: false }, + offset: 10, + viewBox: { x: 0, y: 0, height: 0, width: 0 }, + coordinate: { x: 0, y: 0 }, + // this doesn't exist on TooltipProps + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + cursorStyle: {}, + separator: ' : ', + wrapperStyle: {}, + contentStyle: {}, + itemStyle: {}, + labelStyle: {}, + cursor: true, + trigger: 'hover', + isAnimationActive: !Global.isSsr, + animationEasing: 'ease', + animationDuration: 400, + filterNull: true, + useTranslate3d: false, + box: { x: 0, y: 0 }, +}; + +export const Tooltip = ( + props: TooltipProps & { children?: React.ReactNode } +) => { + const [boxWidth, setBoxWidth] = useState(-1); + const [boxHeight, setBoxHeight] = useState(-1); + const [dismissed, setDismissed] = useState(false); + const [dismissedAtCoordinate, setDismissedAtCoordinate] = useState({ + x: 0, + y: 0, + }); + const [boxCoords, setBoxCoords] = useState({ x: 0, y: 0 }); + + const wrapperNode = useRef(); + const { + allowEscapeViewBox, + reverseDirection, + coordinate, + offset, + position, + viewBox, + } = props; + + const handleKeyDown = useCallback( + (event: KeyboardEvent) => { + if (event.key === 'Escape') { + setDismissed(true); + setDismissedAtCoordinate((prev) => ({ + ...prev, + x: coordinate?.x, + y: coordinate?.y, + })); + } + }, + [coordinate?.x, coordinate?.y] + ); + + useEffect(() => { + const updateBBox = () => { + if (dismissed) { + document.removeEventListener('keydown', handleKeyDown); + if ( + coordinate?.x !== dismissedAtCoordinate.x || + coordinate?.y !== dismissedAtCoordinate.y + ) { + setDismissed(false); + } + } else { + document.addEventListener('keydown', handleKeyDown); + } + + if (wrapperNode.current && wrapperNode.current.getBoundingClientRect) { + const box = wrapperNode.current.getBoundingClientRect(); + setBoxCoords({ x: box.x, y: box.y }); + if ( + Math.abs(box.width - boxWidth) > EPS || + Math.abs(box.height - boxHeight) > EPS + ) { + setBoxWidth(box.width); + setBoxHeight(box.height); + } + } else if (boxWidth !== -1 || boxHeight !== -1) { + setBoxWidth(-1); + setBoxHeight(-1); + } + }; + + updateBBox(); + + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [ + boxHeight, + boxWidth, + coordinate, + dismissed, + dismissedAtCoordinate.x, + dismissedAtCoordinate.y, + handleKeyDown, + ]); + + const getTranslate = ({ + key, + tooltipDimension, + viewBoxDimension, + }: { + key: 'x' | 'y'; + tooltipDimension: number; + viewBoxDimension: number; + }) => { + if (position && isNumber(position[key])) { + return position[key]; + } + + const pCoordinate = coordinate || { x: 0, y: 0 }; + const negative = (pCoordinate[key] || 0) - tooltipDimension - (offset || 0); + const positive = (pCoordinate[key] || 0) + offset; + if (allowEscapeViewBox?.[key]) { + return reverseDirection[key] ? negative : positive; + } + + if (reverseDirection?.[key]) { + const tooltipBoundary = negative; + const viewBoxBoundary = viewBox[key]; + if (tooltipBoundary < viewBoxBoundary) { + return Math.max(positive, viewBox[key]); + } + return Math.max(negative, viewBox[key]); + } + const tooltipBoundary = positive + tooltipDimension; + const viewBoxBoundary = viewBox[key] + viewBoxDimension; + if (tooltipBoundary > viewBoxBoundary) { + return Math.max(negative, viewBox[key]); + } + return Math.max(positive, viewBox[key]); + }; + + const { + payload, + payloadUniqBy, + filterNull, + active, + wrapperStyle, + useTranslate3d, + isAnimationActive, + animationDuration, + animationEasing, + } = props; + const finalPayload = getUniqPayload( + payloadUniqBy, + filterNull && payload && payload.length + ? payload.filter((entry) => !_.isNil(entry.value)) + : payload + ); + const hasPayload = finalPayload && finalPayload.length; + const { content } = props; + let outerStyle: CSSProperties = { + pointerEvents: 'none', + visibility: !dismissed && active && hasPayload ? 'visible' : 'hidden', + position: 'absolute', + top: 0, + left: 0, + ...wrapperStyle, + }; + let translateX, translateY; + + if (position && isNumber(position.x) && isNumber(position.y)) { + translateX = position.x; + translateY = position.y; + } else if (boxWidth > 0 && boxHeight > 0 && coordinate) { + translateX = getTranslate({ + key: 'x', + tooltipDimension: boxWidth, + viewBoxDimension: viewBox.width, + }); + + translateY = getTranslate({ + key: 'y', + tooltipDimension: boxHeight, + viewBoxDimension: viewBox.height, + }); + } else { + outerStyle.visibility = 'hidden'; + } + + outerStyle = { + ...translateStyle({ + transform: useTranslate3d + ? `translate3d(${translateX}px, ${translateY}px, 0)` + : `translate(${translateX}px, ${translateY}px)`, + }), + ...outerStyle, + }; + + if (isAnimationActive && active) { + outerStyle = { + ...translateStyle({ + transition: `transform ${animationDuration}ms ${animationEasing}`, + }), + ...outerStyle, + }; + } + + // eslint-disable-next-line + // const cls = classNames(CLS_PREFIX, { + // [`${CLS_PREFIX}-right`]: isNumber(translateX) && coordinate && isNumber(coordinate.x) && translateX >= coordinate.x, + // [`${CLS_PREFIX}-left`]: isNumber(translateX) && coordinate && isNumber(coordinate.x) && translateX < coordinate.x, + // [`${CLS_PREFIX}-bottom`]: + // isNumber(translateY) && coordinate && isNumber(coordinate.y) && translateY >= coordinate.y, + // [`${CLS_PREFIX}-top`]: isNumber(translateY) && coordinate && isNumber(coordinate.y) && translateY < coordinate.y, + // }); + + const cls = `${CLS_PREFIX}-top`; + return ( + // ESLint is disabled to allow listening to the `Escape` key. Refer to + // https://github.com/recharts/recharts/pull/2925 + // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions +
    + {renderContent(content, { + ...props, + box: boxCoords, + payload: finalPayload, + })} +
    + ); +}; + +// needs to be set so that renderByOrder can find the correct handler function +Tooltip.displayName = 'Tooltip'; + +/** + * needs to be set so that renderByOrder can access an have default values for + * children.props when there are no props set by the consumer + * doesn't work if using default parameters + */ +Tooltip.defaultProps = tooltipDefaultProps; diff --git a/js/version.ts b/js/version.ts index fb199c96d..05377383b 100644 --- a/js/version.ts +++ b/js/version.ts @@ -1,8 +1,8 @@ // Copyright (c) Bloomberg // Distributed under the terms of the Modified BSD License. +//import * as data from '../package.json'; const data = require('../package.json'); - /** * The _model_module_version/_view_module_version this package implements. * diff --git a/package.json b/package.json index 7dabe76f1..d7db10989 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "ipydatagrid", - "version": "1.1.15", + "name": "buckaroo", + "version": "0.6.12", "description": "Fast Datagrid widget for the Jupyter Notebook and JupyterLab", "keywords": [ "jupyter", @@ -17,91 +17,128 @@ "dist/*.png", "style/**/*.*" ], - "homepage": "https://github.com/Bloomberg/ipydatagrid", + "homepage": "https://github.com/paddymul/buckaroo", "bugs": { - "url": "https://github.com/Bloomberg/ipydatagrid/issues" + "url": "https://github.com/paddymul/buckaroo/issues" }, "license": "BSD-3-Clause", "author": { - "name": "Bloomberg", + "name": "Paddy Mullen", "email": "" }, "main": "lib/index.js", "types": "./lib/index.d.ts", "repository": { "type": "git", - "url": "https://github.com/Bloomberg/ipydatagrid" + "url": "https://github.com/paddymul/buckaroo" }, "scripts": { "build": "yarn run build:lib && yarn run build:nbextension && yarn run build:labextension", + "build-full": "yarn run build:lib && run build:nbextension && yarn run build:labextension", "build:dev": "yarn run build:lib && yarn run build:nbextension && yarn run build:labextension:dev", "build:labextension": "jupyter labextension build .", - "build:labextension:dev": "jupyter labextension build --development True .", + "build:labextension:dev": "which jupyter && jupyter labextension build --development True .", "build:lib": "tsc", "build:nbextension": "webpack --mode=production --no-devtool", "build:widget-examples": "cd widget-examples/basic && webpack --mode=production", + "build:examples": "webpack --mode=production --config docs/webpack.typescript.localdev.ts --env production", "build:all": "yarn run build:labextension && yarn run build:nbextension && yarn run build:widget-examples", "clean": "rimraf dist && yarn run clean:lib && yarn run clean:labextension && yarn run clean:nbextension", "clean:lib": "rimraf lib", - "clean:labextension": "rimraf ipydatagrid/labextension", - "clean:nbextension": "rimraf ipydatagrid/nbextension/index.*", - "lint": "eslint 'js/**/*.{js,ts}' --quiet --fix", + "clean:labextension": "rimraf buckaroo/labextension", + "clean:nbextension": "rimraf buckaroo/nbextension/index.*", + "lint": "eslint 'js/**/*.{ts,tsx}'", + "lint:check": "eslint 'js/**/*.{ts,tsx}'", + "lint:fix": "eslint 'js/**/*.{ts,tsx}' --fix", "prepack": "yarn run build:labextension && yarn run build:nbextension", - "test": "jest --verbose", + "test": "jest --verbose --passWithNoTests", "watch": "npm-run-all -p watch:*", "watch:lib": "tsc -w", "watch:nbextension": "webpack --watch", - "watch:labextension": "jupyter labextension watch ." + "watch:labextension": "jupyter labextension watch .", + "dev": "webpack-cli serve --config docs/webpack.typescript.localdev.ts --mode=development --env development --open" }, "dependencies": { - "@jupyter-widgets/base": "^2 || ^3 || ^4 || ^6.0.0", - "@jupyterlab/apputils": "^3.0.2", - "paddy-react-edit-list": ">=1.1.25", + "@jupyter-widgets/base": "6.0.6", + "@jupyterlab/apputils": "^3 || ^4", + "@lumino/application": "^1 || ^2", + "@lumino/coreutils": "2.1.2", + "@lumino/widgets": "2.3.2", + "@types/backbone": "^1.4.19", + "@types/lodash": "^4.17.0", + "ag-grid-community": "^31.0.3", + "ag-grid-react": "^31.0.3", "lodash": "^4.17.21", + "react": "^18.0.0", "react-dom": "^18.0.0", - "react": "^18.0.0" + "react-smooth": "^2.0.3", + "recharts": "^2.7.3" }, "devDependencies": { "@babel/cli": "^7.6.3", "@babel/core": "^7.6.3", - "@babel/preset-env": "^7.6.3", - "@babel/preset-typescript": "^7.6.0", - "@jupyterlab/builder": "^3.0.1", - "@types/jest": "^27.4.1", + "@babel/preset-env": "^7.6.11", + "@babel/preset-typescript": "7.16.7", + "@jupyterlab/builder": "^4.0.5", + "@types/jest": "^28", + "@types/node": "^10.11.6", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", - "@types/node": "^10.11.6", + "@types/webpack-dev-server": "^3.11.1", "@types/webpack-env": "^1.13.6", - "@typescript-eslint/eslint-plugin": "^3.5.0", - "@typescript-eslint/parser": "^3.5.0", + "@typescript-eslint/eslint-plugin": "^5.9.1", + "@typescript-eslint/parser": "^5.9.1", "acorn": "^6.2.0", - "babel-jest": "^28.1.3", + "babel-jest": "^28", "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", - "css-loader": "^3.0.0", - "eslint": "^7.3.1", - "eslint-config-prettier": "^6.11.0", - "eslint-plugin-prettier": "^3.1.4", + "bootstrap": "^5.1.3", + "css-loader": "^5.0.0", + "eslint": "^8.6.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-react": "^7.28.0", + "eslint-plugin-react-hooks": "^4.3.0", + "fork-ts-checker-webpack-plugin": "^6.1.0", "fs-extra": "^7.0.0", - "jest": "^28.1.3", + "html-loader": "^2.1.2", + "html-webpack-plugin": "^5.0.0", + "jest": "^28", "lint-staged": "^10.2.11", + "markdown-loader": "^7.0.0", "mkdirp": "^0.5.1", "npm-run-all": "^4.1.3", - "prettier": "^2.0.5", - "rimraf": "^2.6.2", + "postcss": "^8.4.14", + "postcss-loader": "^7.0.1", + "postcss-nested": "^6.0.0", + "postcss-preset-env": "^7.7.2", + "prettier": "^2.6.2", + "prettier-standalone": "^1.3.1-0", + "prism-themes": "^1.6.0", + "prismjs": "^1.28.0", + "raw-loader": "^4.0.2", + "react-bootstrap": "^2.0.0", + "react-router": "^6.3.0", + "react-router-dom": "^5.2.0", + "rimraf": "^3.0.2", + "sass": "^1.53.0", + "sass-loader": "^13.0.2", "source-map-loader": "^0.2.4", - "style-loader": "^0.23.1", - "svg-url-loader": "~3.0.3", + "style-loader": "^2.0.0", + "svg-url-loader": "^7.1.1", "ts-jest": "^28.0.8", - "ts-loader": "^6.0.4", - "typescript": "~4.2.4", + "ts-loader": "^8.0.14", + "ts-node": "^9.1.1", + "tsconfig-paths-webpack-plugin": "^3.3.0", + "typescript": "^4.4.3", "url-loader": "^4.1.0", "webpack": "^5", - "webpack-cli": "^4.4.0" + "webpack-cli": "^4.5.0", + "webpack-dev-server": "^4.0.0" }, "jupyterlab": { "extension": "lib/plugin", "webpackConfig": "webpack.lab.config.js", - "outputDir": "./ipydatagrid/labextension", + "outputDir": "./buckaroo/labextension", "sharedPackages": { "@jupyter-widgets/base": { "bundled": false, @@ -143,8 +180,8 @@ "bundled": false, "singleton": true }, - "react":false, - "react-dom":false + "react": false, + "react-dom": false } } } diff --git a/pyproject.toml b/pyproject.toml index c1009c74f..b9657753a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,15 +1,15 @@ [build-system] requires = [ "hatchling", - "jupyterlab~=3.0", + "jupyterlab~=4.0", ] build-backend = "hatchling.build" [project] -name = "dcef" -description = "Data Cleaning Framework - UI for quickly cleaning pandas dataframes " +name = "buckaroo" +description = "Buckaroo - GUI Data wrangling for pandas" readme = "README.md" -requires-python = ">=3.7" +requires-python = ">=3.9" authors = [ { name = "Paddy Mullen" }, ] @@ -17,6 +17,7 @@ keywords = [ "IPython", "Jupyter", "Widgets", + "pandas", ] classifiers = [ "Framework :: Jupyter", @@ -26,40 +27,62 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", ] dependencies = [ - "ipywidgets>=7.6.0,<9" + "ipywidgets>=7.6.0,<9", ] -version = "0.2.1" + +version = "0.6.12" [project.license] file = "LICENSE.txt" [project.optional-dependencies] + test = [ "nbval>=0.9", - "pandas<=1.3.5", + "pandas>=1.3.5", "pytest-cov>=3", "pytest>=6", + "hypothesis>=6.88.1", + "polars>=0.20.7", + "polars[timezone]", + "pydantic>=2.5.2", + "pyarrow", + "geopandas" +] +polars = ["polars>=0.20.7", + "polars[timezone]" ] +jupyterlab = ["jupyterlab>=3.6.0"] +notebook = ["notebook>=7.0.0"] + +docs = [ + "sphinx>=1.5", + "graphviz>=0.20.1" +] + +build = [ +"twine", +"build", +] + [project.urls] -Homepage = "https://github.com/bloomberg/ipydatagrid" +Homepage = "https://github.com/paddymul/buckaroo" [tool.hatch.build] artifacts = [ - "ipydatagrid/nbextension/index.*", - "ipydatagrid/labextension", + "buckaroo/nbextension/index.*", + "buckaroo/labextension", ] [tool.hatch.build.targets.wheel.shared-data] -"ipydatagrid/nbextension" = "share/jupyter/nbextensions/ipydatagrid" -"ipydatagrid/labextension" = "share/jupyter/labextensions/ipydatagrid" -"ipydatagrid.json" = "etc/jupyter/nbconfig/notebook.d/ipydatagrid.json" +"buckaroo/nbextension" = "share/jupyter/nbextensions/buckaroo" +"buckaroo/labextension" = "share/jupyter/labextensions/buckaroo" +"buckaroo.json" = "etc/jupyter/nbconfig/notebook.d/buckaroo.json" [tool.hatch.build.targets.sdist] exclude = [ @@ -80,13 +103,14 @@ exclude = [ ] [tool.hatch.build.hooks.jupyter-builder] + ensured-targets = [ - "ipydatagrid/nbextension/index.js", - "ipydatagrid/labextension/package.json", -] -dependencies = [ - "hatch-jupyter-builder>=0.8.1", + "buckaroo/nbextension/index.js", + "buckaroo/labextension/package.json", ] +dependencies = ["hatch-jupyter-builder>=0.8.1"] +#dependencies = ["hatch-jupyter-builder@file:///Users/paddy/code/hatch-jupyter-builder"] + build-function = "hatch_jupyter_builder.npm_builder" [tool.hatch.build.hooks.jupyter-builder.build-kwargs] @@ -99,42 +123,97 @@ npm = [ [tool.isort] profile = "black" known_first_party = [ - "ipydatagrid", + "buckaroo", "tests", ] line_length = 80 -[tool.pylint.messages_control] -disable = "C0330, C0326" - -[tool.pylint.format] -max-line-length = "80" -[tool.black] -line-length = 80 -exclude = "/(\n \\.eggs\n | \\.git\n | \\.hg\n | \\.mypy_cache\n | \\.tox\n | \\.venv\n | _build\n | buck-out\n | build\n | dist\n)/\n" +[tool.ruff] +# Exclude a variety of commonly ignored directories. +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".mypy_cache", + ".nox", + ".pants.d", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "venv", +] -[tool.tbump] -field = [ - { name = "channel", default = "" }, - { name = "release", default = "" }, +# Same as Black. +line-length = 88 +indent-width = 4 + +# Assume Python 3.8 +target-version = "py38" + +[tool.ruff.lint] +# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. +# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or +# McCabe complexity (`C901`) by default. +select = ["E4", "E7", "E9", "F"] +ignore = [] + +# Allow fix for all enabled rules (when `--fix`) is provided. +fixable = ["F401"] +unfixable = [] + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +[tool.ruff.per-file-ignores] +# lispy.py is a vendored and slightly modified bit of code from Peter Norvig +# Anyone trying to understand it is recommended to read Peter Norvig's writings +# don't want to add extaneous diffs +"buckaroo/jlisp/lispy.py" = [ + "E401", "F601", + "E701", "E702", "E703", "E712"] + +#__init__.py and widget utils does some bare excepts because it absolutely cannot error +#and give a non displayable dataframe +"buckaroo/__init__.py" = ["E722", + "F401", #it's an __init__.py, it needs to import unused imports ] -[tool.tbump.version] -current = "1.1.15" -regex = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)((?Pa|b|rc|.dev)(?P\\d+))?" +"buckaroo/widget_utils.py" = ["E722"] +"buckaroo/customizations/order_columns.py" = ["ALL"] + +#used for safe_int +"buckaroo/customizations/all_transforms.py" = ["E722"] #bare except + +"buckaroo/customizations/analysis.py" = [ + "E741", #ambiguous variable name + "E722"] #bare except + +#bare except used in a convience method for developer ergonomics +"tests/unit/commands/command_tests.py" = ["E722"] #bare except +"tests/unit/commands/polars_command_tests.py" = ["E722"] #bare except + -[tool.tbump.git] -message_template = "Bump to {new_version}" -tag_template = "v{new_version}" +[tool.ruff.format] +# Like Black, use double quotes for strings. +quote-style = "double" -[[tool.tbump.file]] -src = "pyproject.toml" -version_template = "version = \"{major}.{minor}.{patch}{channel}{release}\"" +# Like Black, indent with spaces, rather than tabs. +indent-style = "space" -[[tool.tbump.file]] -src = "ipydatagrid/_version.py" +# Like Black, respect magic trailing commas. +skip-magic-trailing-comma = false -[[tool.tbump.file]] -src = "package.json" -version_template = "\"version\": \"{major}.{minor}.{patch}{channel}{release}\"" +# Like Black, automatically detect the appropriate line ending. +line-ending = "auto" \ No newline at end of file diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..1b6aa55d4 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +testpaths=tests diff --git a/regular-summary-stats.ipynb b/regular-summary-stats.ipynb new file mode 100644 index 000000000..00c49832c --- /dev/null +++ b/regular-summary-stats.ipynb @@ -0,0 +1,3039 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "f43d2958-7872-4d38-ad01-a6b75cac29eb", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "2cc2ce06-572f-4962-aee9-345d4db6d0a2", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    tripdurationstarttimestoptimestart station idstart station namestart station latitudestart station longitudeend station idend station nameend station latitudeend station longitudebikeidusertypebirth yeargender
    04712014-01-01 00:00:062014-01-01 00:07:572009Catherine St & Monroe St40.711174-73.996826263Elizabeth St & Hester St40.717290-73.99637516379Subscriber19861
    114942014-01-01 00:00:382014-01-01 00:25:325361 Ave & E 30 St40.741444-73.975361259South St & Whitehall St40.701221-74.01234215611Subscriber19631
    24642014-01-01 00:03:592014-01-01 00:11:43228E 48 St & 3 Ave40.754601-73.9718792022E 59 St & Sutton Pl40.758491-73.95920616613Subscriber19911
    33732014-01-01 00:05:152014-01-01 00:11:28519Pershing Square N40.751884-73.977702526E 33 St & 5 Ave40.747659-73.98490715938Subscriber19891
    46602014-01-01 00:05:182014-01-01 00:16:1883Atlantic Ave & Fort Greene Pl40.683826-73.976323436Hancock St & Bedford Ave40.682166-73.95399019830Subscriber19901
    ................................................
    3003957802014-01-31 23:57:342014-02-01 00:10:34308St James Pl & Oliver St40.713079-73.998512312Allen St & E Houston St40.722055-73.98911117299Subscriber19881
    30039610742014-01-31 23:57:452014-02-01 00:15:39482W 15 St & 7 Ave40.739355-73.999318488W 39 St & 9 Ave40.756458-73.99372219886Subscriber19821
    3003971912014-01-31 23:58:162014-02-01 00:01:27247Perry St & Bleecker St40.735354-74.004831368Carmine St & 6 Ave40.730386-74.00215020249Subscriber19692
    30039810522014-01-31 23:58:342014-02-01 00:16:06482W 15 St & 7 Ave40.739355-73.999318488W 39 St & 9 Ave40.756458-73.99372219922Subscriber19812
    30039911332014-01-31 23:58:432014-02-01 00:17:36450W 49 St & 8 Ave40.762272-73.987882294Washington Square E40.730494-73.99572118944Subscriber19691
    \n", + "

    300400 rows × 15 columns

    \n", + "
    " + ], + "text/plain": [ + " tripduration starttime stoptime \\\n", + "0 471 2014-01-01 00:00:06 2014-01-01 00:07:57 \n", + "1 1494 2014-01-01 00:00:38 2014-01-01 00:25:32 \n", + "2 464 2014-01-01 00:03:59 2014-01-01 00:11:43 \n", + "3 373 2014-01-01 00:05:15 2014-01-01 00:11:28 \n", + "4 660 2014-01-01 00:05:18 2014-01-01 00:16:18 \n", + "... ... ... ... \n", + "300395 780 2014-01-31 23:57:34 2014-02-01 00:10:34 \n", + "300396 1074 2014-01-31 23:57:45 2014-02-01 00:15:39 \n", + "300397 191 2014-01-31 23:58:16 2014-02-01 00:01:27 \n", + "300398 1052 2014-01-31 23:58:34 2014-02-01 00:16:06 \n", + "300399 1133 2014-01-31 23:58:43 2014-02-01 00:17:36 \n", + "\n", + " start station id start station name \\\n", + "0 2009 Catherine St & Monroe St \n", + "1 536 1 Ave & E 30 St \n", + "2 228 E 48 St & 3 Ave \n", + "3 519 Pershing Square N \n", + "4 83 Atlantic Ave & Fort Greene Pl \n", + "... ... ... \n", + "300395 308 St James Pl & Oliver St \n", + "300396 482 W 15 St & 7 Ave \n", + "300397 247 Perry St & Bleecker St \n", + "300398 482 W 15 St & 7 Ave \n", + "300399 450 W 49 St & 8 Ave \n", + "\n", + " start station latitude start station longitude end station id \\\n", + "0 40.711174 -73.996826 263 \n", + "1 40.741444 -73.975361 259 \n", + "2 40.754601 -73.971879 2022 \n", + "3 40.751884 -73.977702 526 \n", + "4 40.683826 -73.976323 436 \n", + "... ... ... ... \n", + "300395 40.713079 -73.998512 312 \n", + "300396 40.739355 -73.999318 488 \n", + "300397 40.735354 -74.004831 368 \n", + "300398 40.739355 -73.999318 488 \n", + "300399 40.762272 -73.987882 294 \n", + "\n", + " end station name end station latitude end station longitude \\\n", + "0 Elizabeth St & Hester St 40.717290 -73.996375 \n", + "1 South St & Whitehall St 40.701221 -74.012342 \n", + "2 E 59 St & Sutton Pl 40.758491 -73.959206 \n", + "3 E 33 St & 5 Ave 40.747659 -73.984907 \n", + "4 Hancock St & Bedford Ave 40.682166 -73.953990 \n", + "... ... ... ... \n", + "300395 Allen St & E Houston St 40.722055 -73.989111 \n", + "300396 W 39 St & 9 Ave 40.756458 -73.993722 \n", + "300397 Carmine St & 6 Ave 40.730386 -74.002150 \n", + "300398 W 39 St & 9 Ave 40.756458 -73.993722 \n", + "300399 Washington Square E 40.730494 -73.995721 \n", + "\n", + " bikeid usertype birth year gender \n", + "0 16379 Subscriber 1986 1 \n", + "1 15611 Subscriber 1963 1 \n", + "2 16613 Subscriber 1991 1 \n", + "3 15938 Subscriber 1989 1 \n", + "4 19830 Subscriber 1990 1 \n", + "... ... ... ... ... \n", + "300395 17299 Subscriber 1988 1 \n", + "300396 19886 Subscriber 1982 1 \n", + "300397 20249 Subscriber 1969 2 \n", + "300398 19922 Subscriber 1981 2 \n", + "300399 18944 Subscriber 1969 1 \n", + "\n", + "[300400 rows x 15 columns]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv('/Users/paddy/code/citibike-play/2014-01 - Citi Bike trip data.csv')\n", + "df" + ] + }, + { + "cell_type": "markdown", + "id": "183717a8-d476-4dd1-a024-8e33ff8cbcf1", + "metadata": {}, + "source": [ + "# Basic Dataframe exploration" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "d5e43b62-a8ea-4d98-a9f2-f2cf97edcd83", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    tripdurationstarttimestoptimestart station idstart station namestart station latitudestart station longitudeend station idend station nameend station latitudeend station longitudebikeidusertypebirth yeargender
    04712014-01-01 00:00:062014-01-01 00:07:572009Catherine St & Monroe St40.711174-73.996826263Elizabeth St & Hester St40.717290-73.99637516379Subscriber19861
    114942014-01-01 00:00:382014-01-01 00:25:325361 Ave & E 30 St40.741444-73.975361259South St & Whitehall St40.701221-74.01234215611Subscriber19631
    24642014-01-01 00:03:592014-01-01 00:11:43228E 48 St & 3 Ave40.754601-73.9718792022E 59 St & Sutton Pl40.758491-73.95920616613Subscriber19911
    33732014-01-01 00:05:152014-01-01 00:11:28519Pershing Square N40.751884-73.977702526E 33 St & 5 Ave40.747659-73.98490715938Subscriber19891
    46602014-01-01 00:05:182014-01-01 00:16:1883Atlantic Ave & Fort Greene Pl40.683826-73.976323436Hancock St & Bedford Ave40.682166-73.95399019830Subscriber19901
    53302014-01-01 00:05:552014-01-01 00:11:25422W 59 St & 10 Ave40.770513-73.988038526E 33 St & 5 Ave40.747659-73.98490717343Subscriber19871
    62612014-01-01 00:06:042014-01-01 00:10:25516E 47 St & 1 Ave40.752069-73.967844167E 39 St & 3 Ave40.748901-73.97604917880Subscriber19831
    73372014-01-01 00:06:412014-01-01 00:12:18380W 4 St & 7 Ave S40.734011-74.002939435W 21 St & 6 Ave40.741740-73.99415616275Subscriber19631
    84292014-01-01 00:07:332014-01-01 00:14:42296Division St & Bowery40.714131-73.997047306Cliff St & Fulton St40.708235-74.00530117318Subscriber19722
    910252014-01-01 00:08:272014-01-01 00:25:32540Lexington Ave & E 26 St40.741473-73.9832094478 Ave & W 52 St40.763707-73.98516215525Subscriber19811
    107182014-01-01 00:09:322014-01-01 00:21:30263Elizabeth St & Hester St40.717290-73.996375251Mott St & Prince St40.723180-73.99480015693Customer\\N0
    117862014-01-01 00:10:592014-01-01 00:24:05153E 40 St & 5 Ave40.752062-73.9816322902 Ave & E 58 St40.760203-73.96478515281Subscriber19681
    122672014-01-01 00:11:172014-01-01 00:15:44151Cleveland Pl & Spring St40.721816-73.997203410Suffolk St & Stanton St40.720664-73.98518015159Subscriber19831
    137442014-01-01 00:12:232014-01-01 00:24:47450W 49 St & 8 Ave40.762272-73.9878825056 Ave & W 33 St40.749013-73.98848415157Subscriber19761
    147042014-01-01 00:12:252014-01-01 00:24:09331Pike St & Monroe St40.711731-73.991930195Liberty St & Broadway40.709056-74.01043417080Subscriber19802
    1513672014-01-01 00:12:472014-01-01 00:35:34519Pershing Square N40.751884-73.977702386Centre St & Worth St40.714948-74.00234520731Customer\\N0
    163272014-01-01 00:13:112014-01-01 00:18:38502Henry St & Grand St40.714215-73.981346411E 6 St & Avenue D40.722281-73.97668715655Subscriber19732
    172232014-01-01 00:15:302014-01-01 00:19:135282 Ave & E 31 St40.742909-73.977061518E 39 St & 2 Ave40.747804-73.97344215737Subscriber19821
    185772014-01-01 00:16:042014-01-01 00:25:41467Dean St & 4 Ave40.683125-73.978951270Adelphi St & Myrtle Ave40.693083-73.97178916115Subscriber19831
    195662014-01-01 00:16:132014-01-01 00:25:39467Dean St & 4 Ave40.683125-73.978951270Adelphi St & Myrtle Ave40.693083-73.97178915753Subscriber19832
    206372014-01-01 00:16:322014-01-01 00:27:09285Broadway & E 14 St40.734546-73.9907415056 Ave & W 33 St40.749013-73.98848415440Subscriber19811
    215132014-01-01 00:16:382014-01-01 00:25:11382University Pl & E 14 St40.734927-73.992005401Allen St & Rivington St40.720196-73.98997814650Subscriber19901
    224302014-01-01 00:18:472014-01-01 00:25:57285Broadway & E 14 St40.734546-73.990741380W 4 St & 7 Ave S40.734011-74.00293919415Subscriber19712
    238372014-01-01 00:18:542014-01-01 00:32:51488W 39 St & 9 Ave40.756458-73.993722380W 4 St & 7 Ave S40.734011-74.00293916827Subscriber19631
    248342014-01-01 00:19:032014-01-01 00:32:57488W 39 St & 9 Ave40.756458-73.993722380W 4 St & 7 Ave S40.734011-74.00293920280Subscriber19631
    \n", + "
    " + ], + "text/plain": [ + " tripduration starttime stoptime start station id \\\n", + "0 471 2014-01-01 00:00:06 2014-01-01 00:07:57 2009 \n", + "1 1494 2014-01-01 00:00:38 2014-01-01 00:25:32 536 \n", + "2 464 2014-01-01 00:03:59 2014-01-01 00:11:43 228 \n", + "3 373 2014-01-01 00:05:15 2014-01-01 00:11:28 519 \n", + "4 660 2014-01-01 00:05:18 2014-01-01 00:16:18 83 \n", + "5 330 2014-01-01 00:05:55 2014-01-01 00:11:25 422 \n", + "6 261 2014-01-01 00:06:04 2014-01-01 00:10:25 516 \n", + "7 337 2014-01-01 00:06:41 2014-01-01 00:12:18 380 \n", + "8 429 2014-01-01 00:07:33 2014-01-01 00:14:42 296 \n", + "9 1025 2014-01-01 00:08:27 2014-01-01 00:25:32 540 \n", + "10 718 2014-01-01 00:09:32 2014-01-01 00:21:30 263 \n", + "11 786 2014-01-01 00:10:59 2014-01-01 00:24:05 153 \n", + "12 267 2014-01-01 00:11:17 2014-01-01 00:15:44 151 \n", + "13 744 2014-01-01 00:12:23 2014-01-01 00:24:47 450 \n", + "14 704 2014-01-01 00:12:25 2014-01-01 00:24:09 331 \n", + "15 1367 2014-01-01 00:12:47 2014-01-01 00:35:34 519 \n", + "16 327 2014-01-01 00:13:11 2014-01-01 00:18:38 502 \n", + "17 223 2014-01-01 00:15:30 2014-01-01 00:19:13 528 \n", + "18 577 2014-01-01 00:16:04 2014-01-01 00:25:41 467 \n", + "19 566 2014-01-01 00:16:13 2014-01-01 00:25:39 467 \n", + "20 637 2014-01-01 00:16:32 2014-01-01 00:27:09 285 \n", + "21 513 2014-01-01 00:16:38 2014-01-01 00:25:11 382 \n", + "22 430 2014-01-01 00:18:47 2014-01-01 00:25:57 285 \n", + "23 837 2014-01-01 00:18:54 2014-01-01 00:32:51 488 \n", + "24 834 2014-01-01 00:19:03 2014-01-01 00:32:57 488 \n", + "\n", + " start station name start station latitude \\\n", + "0 Catherine St & Monroe St 40.711174 \n", + "1 1 Ave & E 30 St 40.741444 \n", + "2 E 48 St & 3 Ave 40.754601 \n", + "3 Pershing Square N 40.751884 \n", + "4 Atlantic Ave & Fort Greene Pl 40.683826 \n", + "5 W 59 St & 10 Ave 40.770513 \n", + "6 E 47 St & 1 Ave 40.752069 \n", + "7 W 4 St & 7 Ave S 40.734011 \n", + "8 Division St & Bowery 40.714131 \n", + "9 Lexington Ave & E 26 St 40.741473 \n", + "10 Elizabeth St & Hester St 40.717290 \n", + "11 E 40 St & 5 Ave 40.752062 \n", + "12 Cleveland Pl & Spring St 40.721816 \n", + "13 W 49 St & 8 Ave 40.762272 \n", + "14 Pike St & Monroe St 40.711731 \n", + "15 Pershing Square N 40.751884 \n", + "16 Henry St & Grand St 40.714215 \n", + "17 2 Ave & E 31 St 40.742909 \n", + "18 Dean St & 4 Ave 40.683125 \n", + "19 Dean St & 4 Ave 40.683125 \n", + "20 Broadway & E 14 St 40.734546 \n", + "21 University Pl & E 14 St 40.734927 \n", + "22 Broadway & E 14 St 40.734546 \n", + "23 W 39 St & 9 Ave 40.756458 \n", + "24 W 39 St & 9 Ave 40.756458 \n", + "\n", + " start station longitude end station id end station name \\\n", + "0 -73.996826 263 Elizabeth St & Hester St \n", + "1 -73.975361 259 South St & Whitehall St \n", + "2 -73.971879 2022 E 59 St & Sutton Pl \n", + "3 -73.977702 526 E 33 St & 5 Ave \n", + "4 -73.976323 436 Hancock St & Bedford Ave \n", + "5 -73.988038 526 E 33 St & 5 Ave \n", + "6 -73.967844 167 E 39 St & 3 Ave \n", + "7 -74.002939 435 W 21 St & 6 Ave \n", + "8 -73.997047 306 Cliff St & Fulton St \n", + "9 -73.983209 447 8 Ave & W 52 St \n", + "10 -73.996375 251 Mott St & Prince St \n", + "11 -73.981632 290 2 Ave & E 58 St \n", + "12 -73.997203 410 Suffolk St & Stanton St \n", + "13 -73.987882 505 6 Ave & W 33 St \n", + "14 -73.991930 195 Liberty St & Broadway \n", + "15 -73.977702 386 Centre St & Worth St \n", + "16 -73.981346 411 E 6 St & Avenue D \n", + "17 -73.977061 518 E 39 St & 2 Ave \n", + "18 -73.978951 270 Adelphi St & Myrtle Ave \n", + "19 -73.978951 270 Adelphi St & Myrtle Ave \n", + "20 -73.990741 505 6 Ave & W 33 St \n", + "21 -73.992005 401 Allen St & Rivington St \n", + "22 -73.990741 380 W 4 St & 7 Ave S \n", + "23 -73.993722 380 W 4 St & 7 Ave S \n", + "24 -73.993722 380 W 4 St & 7 Ave S \n", + "\n", + " end station latitude end station longitude bikeid usertype \\\n", + "0 40.717290 -73.996375 16379 Subscriber \n", + "1 40.701221 -74.012342 15611 Subscriber \n", + "2 40.758491 -73.959206 16613 Subscriber \n", + "3 40.747659 -73.984907 15938 Subscriber \n", + "4 40.682166 -73.953990 19830 Subscriber \n", + "5 40.747659 -73.984907 17343 Subscriber \n", + "6 40.748901 -73.976049 17880 Subscriber \n", + "7 40.741740 -73.994156 16275 Subscriber \n", + "8 40.708235 -74.005301 17318 Subscriber \n", + "9 40.763707 -73.985162 15525 Subscriber \n", + "10 40.723180 -73.994800 15693 Customer \n", + "11 40.760203 -73.964785 15281 Subscriber \n", + "12 40.720664 -73.985180 15159 Subscriber \n", + "13 40.749013 -73.988484 15157 Subscriber \n", + "14 40.709056 -74.010434 17080 Subscriber \n", + "15 40.714948 -74.002345 20731 Customer \n", + "16 40.722281 -73.976687 15655 Subscriber \n", + "17 40.747804 -73.973442 15737 Subscriber \n", + "18 40.693083 -73.971789 16115 Subscriber \n", + "19 40.693083 -73.971789 15753 Subscriber \n", + "20 40.749013 -73.988484 15440 Subscriber \n", + "21 40.720196 -73.989978 14650 Subscriber \n", + "22 40.734011 -74.002939 19415 Subscriber \n", + "23 40.734011 -74.002939 16827 Subscriber \n", + "24 40.734011 -74.002939 20280 Subscriber \n", + "\n", + " birth year gender \n", + "0 1986 1 \n", + "1 1963 1 \n", + "2 1991 1 \n", + "3 1989 1 \n", + "4 1990 1 \n", + "5 1987 1 \n", + "6 1983 1 \n", + "7 1963 1 \n", + "8 1972 2 \n", + "9 1981 1 \n", + "10 \\N 0 \n", + "11 1968 1 \n", + "12 1983 1 \n", + "13 1976 1 \n", + "14 1980 2 \n", + "15 \\N 0 \n", + "16 1973 2 \n", + "17 1982 1 \n", + "18 1983 1 \n", + "19 1983 2 \n", + "20 1981 1 \n", + "21 1990 1 \n", + "22 1971 2 \n", + "23 1963 1 \n", + "24 1963 1 " + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.head(25)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "bd6ccdd6-b2e6-4d7b-b824-12d01469a6f6", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Index(['tripduration', 'starttime', 'stoptime', 'start station id',\n", + " 'start station name', 'start station latitude',\n", + " 'start station longitude', 'end station id', 'end station name',\n", + " 'end station latitude', 'end station longitude', 'bikeid', 'usertype',\n", + " 'birth year', 'gender'],\n", + " dtype='object')" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.columns" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "fa48ade1-86de-4fcd-84c0-2064a4a42b0a", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    tripdurationstart station idstart station latitudestart station longitudeend station idend station latitudeend station longitudebikeidgender
    count3.004000e+05300400.000000300400.000000300400.000000300400.000000300400.000000300400.000000300400.000000300400.000000
    mean7.339689e+02436.93659840.734996-73.990135437.74276340.734814-73.99032817992.0820441.165632
    std5.271464e+03323.8956430.0194080.011779328.9314040.0193830.0118542000.8325640.431966
    min6.000000e+0172.00000040.680342-74.01713472.00000040.680342-74.01713414529.0000000.000000
    25%3.400000e+02306.00000040.722055-73.998102306.00000040.721816-73.99852216249.0000001.000000
    50%5.130000e+02406.00000040.737050-73.990093405.00000040.736529-73.99021417971.0000001.000000
    75%7.880000e+02490.00000040.750224-73.981854489.00000040.750200-73.98185419700.0000001.000000
    max1.990440e+063002.00000040.770513-73.9500483002.00000040.770513-73.95004821536.0000002.000000
    \n", + "
    " + ], + "text/plain": [ + " tripduration start station id start station latitude \\\n", + "count 3.004000e+05 300400.000000 300400.000000 \n", + "mean 7.339689e+02 436.936598 40.734996 \n", + "std 5.271464e+03 323.895643 0.019408 \n", + "min 6.000000e+01 72.000000 40.680342 \n", + "25% 3.400000e+02 306.000000 40.722055 \n", + "50% 5.130000e+02 406.000000 40.737050 \n", + "75% 7.880000e+02 490.000000 40.750224 \n", + "max 1.990440e+06 3002.000000 40.770513 \n", + "\n", + " start station longitude end station id end station latitude \\\n", + "count 300400.000000 300400.000000 300400.000000 \n", + "mean -73.990135 437.742763 40.734814 \n", + "std 0.011779 328.931404 0.019383 \n", + "min -74.017134 72.000000 40.680342 \n", + "25% -73.998102 306.000000 40.721816 \n", + "50% -73.990093 405.000000 40.736529 \n", + "75% -73.981854 489.000000 40.750200 \n", + "max -73.950048 3002.000000 40.770513 \n", + "\n", + " end station longitude bikeid gender \n", + "count 300400.000000 300400.000000 300400.000000 \n", + "mean -73.990328 17992.082044 1.165632 \n", + "std 0.011854 2000.832564 0.431966 \n", + "min -74.017134 14529.000000 0.000000 \n", + "25% -73.998522 16249.000000 1.000000 \n", + "50% -73.990214 17971.000000 1.000000 \n", + "75% -73.981854 19700.000000 1.000000 \n", + "max -73.950048 21536.000000 2.000000 " + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.describe()\n", + "# we can't edit this function\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "aad2dd62-c406-4cbc-a197-60906b365536", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    tripdurationstarttimestoptimestart station idstart station namestart station latitudestart station longitudeend station idend station nameend station latitudeend station longitudebikeidusertypebirth yeargender
    1637795052014-01-17 08:16:122014-01-17 08:24:3772W 52 St & 11 Ave40.767272-73.993929326E 11 St & 1 Ave40.729538-73.98426719234Subscriber19862
    1559874572014-01-16 18:02:012014-01-16 18:09:3872W 52 St & 11 Ave40.767272-73.993929510W 51 St & 6 Ave40.760660-73.98042020725Subscriber19841
    950898882014-01-13 10:20:022014-01-13 10:34:5072W 52 St & 11 Ave40.767272-73.993929462W 22 St & 10 Ave40.746920-74.00451915847Subscriber19592
    555635572014-01-09 18:13:562014-01-09 18:23:1372W 52 St & 11 Ave40.767272-73.993929405Washington St & Gansevoort St40.739323-74.00811915790Subscriber19711
    2035602312014-01-20 11:40:422014-01-20 11:44:3372W 52 St & 11 Ave40.767272-73.993929449W 52 St & 9 Ave40.764618-73.98789518405Subscriber19892
    ................................................
    15799411612014-01-16 19:03:382014-01-16 19:22:593002South End Ave & Liberty St40.711512-74.015756483E 12 St & 3 Ave40.732233-73.98890021097Subscriber19881
    2656824382014-01-29 09:23:152014-01-29 09:30:333002South End Ave & Liberty St40.711512-74.015756304Broadway & Battery Pl40.704633-74.01361719839Subscriber19821
    2655905032014-01-29 09:15:592014-01-29 09:24:223002South End Ave & Liberty St40.711512-74.015756152Warren St & Church St40.714740-74.00910619624Subscriber19772
    18343213232014-01-18 10:47:592014-01-18 11:10:023002South End Ave & Liberty St40.711512-74.015756435W 21 St & 6 Ave40.741740-73.99415617215Subscriber19682
    18564810302014-01-18 14:12:012014-01-18 14:29:113002South End Ave & Liberty St40.711512-74.01575672W 52 St & 11 Ave40.767272-73.99392921108Subscriber19841
    \n", + "

    300400 rows × 15 columns

    \n", + "
    " + ], + "text/plain": [ + " tripduration starttime stoptime \\\n", + "163779 505 2014-01-17 08:16:12 2014-01-17 08:24:37 \n", + "155987 457 2014-01-16 18:02:01 2014-01-16 18:09:38 \n", + "95089 888 2014-01-13 10:20:02 2014-01-13 10:34:50 \n", + "55563 557 2014-01-09 18:13:56 2014-01-09 18:23:13 \n", + "203560 231 2014-01-20 11:40:42 2014-01-20 11:44:33 \n", + "... ... ... ... \n", + "157994 1161 2014-01-16 19:03:38 2014-01-16 19:22:59 \n", + "265682 438 2014-01-29 09:23:15 2014-01-29 09:30:33 \n", + "265590 503 2014-01-29 09:15:59 2014-01-29 09:24:22 \n", + "183432 1323 2014-01-18 10:47:59 2014-01-18 11:10:02 \n", + "185648 1030 2014-01-18 14:12:01 2014-01-18 14:29:11 \n", + "\n", + " start station id start station name start station latitude \\\n", + "163779 72 W 52 St & 11 Ave 40.767272 \n", + "155987 72 W 52 St & 11 Ave 40.767272 \n", + "95089 72 W 52 St & 11 Ave 40.767272 \n", + "55563 72 W 52 St & 11 Ave 40.767272 \n", + "203560 72 W 52 St & 11 Ave 40.767272 \n", + "... ... ... ... \n", + "157994 3002 South End Ave & Liberty St 40.711512 \n", + "265682 3002 South End Ave & Liberty St 40.711512 \n", + "265590 3002 South End Ave & Liberty St 40.711512 \n", + "183432 3002 South End Ave & Liberty St 40.711512 \n", + "185648 3002 South End Ave & Liberty St 40.711512 \n", + "\n", + " start station longitude end station id \\\n", + "163779 -73.993929 326 \n", + "155987 -73.993929 510 \n", + "95089 -73.993929 462 \n", + "55563 -73.993929 405 \n", + "203560 -73.993929 449 \n", + "... ... ... \n", + "157994 -74.015756 483 \n", + "265682 -74.015756 304 \n", + "265590 -74.015756 152 \n", + "183432 -74.015756 435 \n", + "185648 -74.015756 72 \n", + "\n", + " end station name end station latitude \\\n", + "163779 E 11 St & 1 Ave 40.729538 \n", + "155987 W 51 St & 6 Ave 40.760660 \n", + "95089 W 22 St & 10 Ave 40.746920 \n", + "55563 Washington St & Gansevoort St 40.739323 \n", + "203560 W 52 St & 9 Ave 40.764618 \n", + "... ... ... \n", + "157994 E 12 St & 3 Ave 40.732233 \n", + "265682 Broadway & Battery Pl 40.704633 \n", + "265590 Warren St & Church St 40.714740 \n", + "183432 W 21 St & 6 Ave 40.741740 \n", + "185648 W 52 St & 11 Ave 40.767272 \n", + "\n", + " end station longitude bikeid usertype birth year gender \n", + "163779 -73.984267 19234 Subscriber 1986 2 \n", + "155987 -73.980420 20725 Subscriber 1984 1 \n", + "95089 -74.004519 15847 Subscriber 1959 2 \n", + "55563 -74.008119 15790 Subscriber 1971 1 \n", + "203560 -73.987895 18405 Subscriber 1989 2 \n", + "... ... ... ... ... ... \n", + "157994 -73.988900 21097 Subscriber 1988 1 \n", + "265682 -74.013617 19839 Subscriber 1982 1 \n", + "265590 -74.009106 19624 Subscriber 1977 2 \n", + "183432 -73.994156 17215 Subscriber 1968 2 \n", + "185648 -73.993929 21108 Subscriber 1984 1 \n", + "\n", + "[300400 rows x 15 columns]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.sort_values('start station id')" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "c8ad24b4-a65c-4120-b78b-31be7991ba7f", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "tripduration int64\n", + "starttime object\n", + "stoptime object\n", + "start station id int64\n", + "start station name object\n", + "start station latitude float64\n", + "start station longitude float64\n", + "end station id int64\n", + "end station name object\n", + "end station latitude float64\n", + "end station longitude float64\n", + "bikeid int64\n", + "usertype object\n", + "birth year object\n", + "gender int64\n", + "dtype: object" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.dtypes" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "6546e639-5293-4f5c-a6ce-6b9542f8b4c6", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "tripduration 0\n", + "starttime 0\n", + "stoptime 0\n", + "start station id 0\n", + "start station name 0\n", + "start station latitude 0\n", + "start station longitude 0\n", + "end station id 0\n", + "end station name 0\n", + "end station latitude 0\n", + "end station longitude 0\n", + "bikeid 0\n", + "usertype 0\n", + "birth year 0\n", + "gender 0\n", + "dtype: int64" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.isna().sum()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "dab96c9c-b105-47e4-8781-db0148b7bbfd", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "tripduration\n", + "385 512\n", + "350 505\n", + "382 502\n", + "376 499\n", + "374 497\n", + " ... \n", + "43227 1\n", + "11723 1\n", + "32886 1\n", + "3597 1\n", + "55504 1\n", + "Name: count, Length: 4502, dtype: int64" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "trip_d_counts = df['tripduration'].value_counts()\n", + "trip_d_counts" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "dac3af6d-7b54-4ce9-b7ef-07473ed63317", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1615" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "trip_d_counts[trip_d_counts==1].sum() #durations that only happened once" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "74f69c57-d811-45fd-adc4-f30b1893cba6", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "tripduration starttime stoptime start station id start station name start station latitude start station longitude end station id end station name end station latitude end station longitude bikeid usertype birth year gender\n", + "60 2014-01-02 15:58:30 2014-01-02 15:59:30 492 W 33 St & 7 Ave 40.750200 -73.990931 492 W 33 St & 7 Ave 40.750200 -73.990931 16179 Subscriber 1986 1 1\n", + "671 2014-01-29 14:38:08 2014-01-29 14:49:19 472 E 32 St & Park Ave 40.745712 -73.981948 538 W 49 St & 5 Ave 40.757952 -73.977876 16002 Subscriber 1959 2 1\n", + " 2014-01-30 14:55:15 2014-01-30 15:06:26 367 E 53 St & Lexington Ave 40.758281 -73.970694 173 Broadway & W 49 St 40.760647 -73.984427 15672 Subscriber 1978 1 1\n", + " 2014-01-30 14:21:24 2014-01-30 14:32:35 531 Forsyth St & Broome St 40.718939 -73.992663 342 Columbia St & Rivington St 40.717400 -73.980166 16368 Subscriber 1982 2 1\n", + " 2014-01-30 14:02:25 2014-01-30 14:13:36 523 W 38 St & 8 Ave 40.754666 -73.991382 168 W 18 St & 6 Ave 40.739713 -73.994564 15657 Subscriber 1982 1 1\n", + " ..\n", + "395 2014-01-12 03:25:01 2014-01-12 03:31:36 465 Broadway & W 41 St 40.755136 -73.986580 498 Broadway & W 32 St 40.748549 -73.988084 20603 Subscriber 1989 1 1\n", + " 2014-01-11 22:36:28 2014-01-11 22:43:03 253 W 13 St & 5 Ave 40.735439 -73.994539 336 Sullivan St & Washington Sq 40.730477 -73.999061 20967 Subscriber 1983 1 1\n", + " 2014-01-11 20:26:23 2014-01-11 20:32:58 300 Shevchenko Pl & E 6 St 40.728145 -73.990214 317 E 6 St & Avenue B 40.724537 -73.981854 21050 Subscriber 1970 2 1\n", + " 2014-01-11 19:17:50 2014-01-11 19:24:25 310 State St & Smith St 40.689269 -73.989129 416 Cumberland St & Lafayette Ave 40.687534 -73.972652 16484 Subscriber 1967 1 1\n", + "1990440 2014-01-28 17:38:05 2014-02-20 18:32:08 524 W 43 St & 6 Ave 40.755273 -73.983169 152 Warren St & Church St 40.714740 -74.009106 15132 Subscriber 1980 1 1\n", + "Name: count, Length: 300400, dtype: int64" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ab = df.value_counts()\n", + "ab" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "0a45badb-8a1d-4527-b078-dae580e7b0d9", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "tripduration 4502\n", + "starttime 266586\n", + "stoptime 267463\n", + "start station id 329\n", + "start station name 329\n", + "start station latitude 329\n", + "start station longitude 329\n", + "end station id 329\n", + "end station name 329\n", + "end station latitude 329\n", + "end station longitude 329\n", + "bikeid 6354\n", + "usertype 2\n", + "birth year 79\n", + "gender 3\n", + "dtype: int64" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd.Series(dict([[col, len(df[col].value_counts())] for col in df.columns]))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "3e7589c2-bb34-477b-b1a6-e69485dbc7c4", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkIAAAGvCAYAAAC3lbrBAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA5VUlEQVR4nO3de3RU9b3+8ScJuRAk4SYJKQEiVG5y0SAx3goaMmCWSyq1YC2NCHhkJS5DTkHpQa6ehVIuYo1yWoXgqSjQFqxAQ8ZgoMoANZAjoHCU0lKLE6wIgSCTIdm/P/xlH4ZwycDExP19v9bKOs7en9nzffZOmufMJYRZlmUJAADAQOFNvQAAAICmQhECAADGoggBAABjUYQAAICxKEIAAMBYFCEAAGAsihAAADAWRQgAABirRVMvoDmrra3VkSNH1Lp1a4WFhTX1cgAAQANYlqWTJ08qKSlJ4eGXfs6HInQJR44cUXJyclMvAwAAXIF//OMf6ty58yVnKEKX0Lp1a0nfnMi4uLiQHtvv96u4uFiZmZmKjIwM6bGbC6dndHo+yfkZnZ5PIqMTOD2fFPqMlZWVSk5Otn+PXwpF6BLqXg6Li4trlCIUGxuruLg4R39jOzmj0/NJzs/o9HwSGZ3A6fmkxsvYkLe18GZpAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBYFCEAAGAsihAAADAWRQgAABgrqCL08ssvq3///va/vZWenq4//elP9v4zZ84oJydH7du31zXXXKNRo0apoqIi4BiHDx9WVlaWYmNj1bFjR02ZMkVnz54NmCktLdVNN92k6Oho9ejRQ4WFhfXWUlBQoG7duikmJkZpaWnauXNnwP6GrAUAAJgtqCLUuXNnPfvssyorK9MHH3ygu+66S/fdd5/27dsnSZo8ebLefvttrVmzRlu2bNGRI0d0//332/evqalRVlaWqqurtW3bNq1YsUKFhYWaMWOGPXPo0CFlZWVp6NChKi8vV15eniZMmKBNmzbZM6tWrVJ+fr5mzpypXbt2acCAAXK5XDp69Kg9c7m1AAAAyLpKbdu2tV555RXr+PHjVmRkpLVmzRp738cff2xJsjwej2VZlrVx40YrPDzc8nq99szLL79sxcXFWT6fz7Isy5o6darVt2/fgMcYPXq05XK57NuDBw+2cnJy7Ns1NTVWUlKSNW/ePMuyrAatpSFOnDhhSbJOnDjR4Ps0VHV1tbVu3Tqruro65MduLpye0en5LMv5GZ2ez7LI6AROz2dZoc8YzO/vFldaoGpqarRmzRpVVVUpPT1dZWVl8vv9ysjIsGd69eqlLl26yOPx6JZbbpHH41G/fv2UkJBgz7hcLk2aNEn79u3TjTfeKI/HE3CMupm8vDxJUnV1tcrKyjRt2jR7f3h4uDIyMuTxeCSpQWu5EJ/PJ5/PZ9+urKyUJPn9fvn9/is8UxdWd7zUOUXy1YaF9NiNae8sV4Nn6zKG+tw1F07PJzk/o9PzSWR0Aqfnk0KfMZjjBF2E9uzZo/T0dJ05c0bXXHON1q5dqz59+qi8vFxRUVFq06ZNwHxCQoK8Xq8kyev1BpSguv11+y41U1lZqa+//lpfffWVampqLjizf/9++xiXW8uFzJs3T7Nnz663vbi4WLGxsRe939WYO6i2UY7bWDZu3Bj0fdxudyOspPlwej7J+Rmdnk8ioxM4PZ8UuoynT59u8GzQRahnz54qLy/XiRMn9Lvf/U7Z2dnasmVLsIdplqZNm6b8/Hz7dmVlpZKTk5WZmam4uLiQPpbf75fb7dbTH4Q7+hkht9utYcOGKTIyshFX1TScnk9yfkan55PI6AROzyeFPmPdKzoNEXQRioqKUo8ePSRJqamp+stf/qIlS5Zo9OjRqq6u1vHjxwOeiamoqFBiYqIkKTExsd6nu+o+yXXuzPmf7qqoqFBcXJxatmypiIgIRUREXHDm3GNcbi0XEh0drejo6HrbIyMjG+2bz1cbJl/Nd6cIXcl5aMzz1xw4PZ/k/IxOzyeR0Qmcnk8KXcZgjnHVf0eotrZWPp9PqampioyMVElJib3vwIEDOnz4sNLT0yVJ6enp2rNnT8Cnu9xut+Li4tSnTx975txj1M3UHSMqKkqpqakBM7W1tSopKbFnGrIWAACAoJ4RmjZtmkaMGKEuXbro5MmTWrlypUpLS7Vp0ybFx8dr/Pjxys/PV7t27RQXF6fHH39c6enp9puTMzMz1adPH40dO1bz58+X1+vV9OnTlZOTYz8T89hjj+nFF1/U1KlT9cgjj2jz5s1avXq1NmzYYK8jPz9f2dnZGjRokAYPHqznn39eVVVVGjdunCQ1aC0AAABBFaGjR4/qZz/7mT7//HPFx8erf//+2rRpk4YNGyZJWrx4scLDwzVq1Cj5fD65XC699NJL9v0jIiK0fv16TZo0Senp6WrVqpWys7M1Z84ceyYlJUUbNmzQ5MmTtWTJEnXu3FmvvPKKXK7/e2/K6NGj9cUXX2jGjBnyer0aOHCgioqKAt5Afbm1AAAABFWEXn311Uvuj4mJUUFBgQoKCi4607Vr18t+8mjIkCHavXv3JWdyc3OVm5t7VWsBAABm498aAwAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBYFCEAAGAsihAAADAWRQgAABiLIgQAAIxFEQIAAMaiCAEAAGNRhAAAgLEoQgAAwFgUIQAAYCyKEAAAMBZFCAAAGIsiBAAAjEURAgAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBYFCEAAGAsihAAADAWRQgAABiLIgQAAIxFEQIAAMaiCAEAAGNRhAAAgLEoQgAAwFgUIQAAYCyKEAAAMBZFCAAAGCuoIjRv3jzdfPPNat26tTp27KiRI0fqwIEDATNDhgxRWFhYwNdjjz0WMHP48GFlZWUpNjZWHTt21JQpU3T27NmAmdLSUt10002Kjo5Wjx49VFhYWG89BQUF6tatm2JiYpSWlqadO3cG7D9z5oxycnLUvn17XXPNNRo1apQqKiqCiQwAABwsqCK0ZcsW5eTkaPv27XK73fL7/crMzFRVVVXA3MSJE/X555/bX/Pnz7f31dTUKCsrS9XV1dq2bZtWrFihwsJCzZgxw545dOiQsrKyNHToUJWXlysvL08TJkzQpk2b7JlVq1YpPz9fM2fO1K5duzRgwAC5XC4dPXrUnpk8ebLefvttrVmzRlu2bNGRI0d0//33B32SAACAM7UIZrioqCjgdmFhoTp27KiysjLdeeed9vbY2FglJiZe8BjFxcX66KOP9M477yghIUEDBw7U3Llz9eSTT2rWrFmKiorS0qVLlZKSooULF0qSevfurffee0+LFy+Wy+WSJC1atEgTJ07UuHHjJElLly7Vhg0btGzZMj311FM6ceKEXn31Va1cuVJ33XWXJGn58uXq3bu3tm/frltuuSWY6AAAwIGCKkLnO3HihCSpXbt2Adtff/11/fa3v1ViYqLuvfdePf3004qNjZUkeTwe9evXTwkJCfa8y+XSpEmTtG/fPt14443yeDzKyMgIOKbL5VJeXp4kqbq6WmVlZZo2bZq9Pzw8XBkZGfJ4PJKksrIy+f3+gOP06tVLXbp0kcfjuWAR8vl88vl89u3KykpJkt/vl9/vD/r8XErd8aLDrZAet7EFcx7qZkN97poLp+eTnJ/R6fkkMjqB0/NJoc8YzHGuuAjV1tYqLy9Pt912m2644QZ7+09+8hN17dpVSUlJ+vDDD/Xkk0/qwIED+sMf/iBJ8nq9ASVIkn3b6/VecqayslJff/21vvrqK9XU1FxwZv/+/fYxoqKi1KZNm3ozdY9zvnnz5mn27Nn1thcXF9tFLtTmDqptlOM2lo0bNwZ9H7fb3QgraT6cnk9yfkan55PI6AROzyeFLuPp06cbPHvFRSgnJ0d79+7Ve++9F7D90Ucftf+7X79+6tSpk+6++24dPHhQ3bt3v9KH+1ZMmzZN+fn59u3KykolJycrMzNTcXFxIX0sv98vt9utpz8Il682LKTHbkx7Z7kaPFuXcdiwYYqMjGzEVTUNp+eTnJ/R6fkkMjqB0/NJoc9Y94pOQ1xREcrNzdX69eu1detWde7c+ZKzaWlpkqRPP/1U3bt3V2JiYr1Pd9V9kqvufUWJiYn1Pt1VUVGhuLg4tWzZUhEREYqIiLjgzLnHqK6u1vHjxwOeFTp35nzR0dGKjo6utz0yMrLRvvl8tWHy1Xx3itCVnIfGPH/NgdPzSc7P6PR8EhmdwOn5pNBlDOYYQX1qzLIs5ebmau3atdq8ebNSUlIue5/y8nJJUqdOnSRJ6enp2rNnT8Cnu9xut+Li4tSnTx97pqSkJOA4brdb6enpkqSoqCilpqYGzNTW1qqkpMSeSU1NVWRkZMDMgQMHdPjwYXsGAACYLahnhHJycrRy5Uq99dZbat26tf1em/j4eLVs2VIHDx7UypUrdc8996h9+/b68MMPNXnyZN15553q37+/JCkzM1N9+vTR2LFjNX/+fHm9Xk2fPl05OTn2szGPPfaYXnzxRU2dOlWPPPKINm/erNWrV2vDhg32WvLz85Wdna1BgwZp8ODBev7551VVVWV/iiw+Pl7jx49Xfn6+2rVrp7i4OD3++ONKT0/nE2MAAEBSkEXo5ZdflvTNH0081/Lly/Xwww8rKipK77zzjl1KkpOTNWrUKE2fPt2ejYiI0Pr16zVp0iSlp6erVatWys7O1pw5c+yZlJQUbdiwQZMnT9aSJUvUuXNnvfLKK/ZH5yVp9OjR+uKLLzRjxgx5vV4NHDhQRUVFAW+gXrx4scLDwzVq1Cj5fD65XC699NJLQZ0gAADgXEEVIcu69Ee9k5OTtWXLlssep2vXrpf99NGQIUO0e/fuS87k5uYqNzf3ovtjYmJUUFCggoKCy64JAACYh39rDAAAGIsiBAAAjEURAgAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBYFCEAAGAsihAAADAWRQgAABiLIgQAAIxFEQIAAMaiCAEAAGNRhAAAgLEoQgAAwFgUIQAAYCyKEAAAMBZFCAAAGIsiBAAAjEURAgAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBYFCEAAGAsihAAADAWRQgAABiLIgQAAIxFEQIAAMaiCAEAAGNRhAAAgLEoQgAAwFgUIQAAYCyKEAAAMFZQRWjevHm6+eab1bp1a3Xs2FEjR47UgQMHAmbOnDmjnJwctW/fXtdcc41GjRqlioqKgJnDhw8rKytLsbGx6tixo6ZMmaKzZ88GzJSWluqmm25SdHS0evToocLCwnrrKSgoULdu3RQTE6O0tDTt3Lkz6LUAAABzBVWEtmzZopycHG3fvl1ut1t+v1+ZmZmqqqqyZyZPnqy3335ba9as0ZYtW3TkyBHdf//99v6amhplZWWpurpa27Zt04oVK1RYWKgZM2bYM4cOHVJWVpaGDh2q8vJy5eXlacKECdq0aZM9s2rVKuXn52vmzJnatWuXBgwYIJfLpaNHjzZ4LQAAwGwtghkuKioKuF1YWKiOHTuqrKxMd955p06cOKFXX31VK1eu1F133SVJWr58uXr37q3t27frlltuUXFxsT766CO98847SkhI0MCBAzV37lw9+eSTmjVrlqKiorR06VKlpKRo4cKFkqTevXvrvffe0+LFi+VyuSRJixYt0sSJEzVu3DhJ0tKlS7VhwwYtW7ZMTz31VIPWAgAAzBZUETrfiRMnJEnt2rWTJJWVlcnv9ysjI8Oe6dWrl7p06SKPx6NbbrlFHo9H/fr1U0JCgj3jcrk0adIk7du3TzfeeKM8Hk/AMepm8vLyJEnV1dUqKyvTtGnT7P3h4eHKyMiQx+Np8FrO5/P55PP57NuVlZWSJL/fL7/ff0Xn6GLqjhcdboX0uI0tmPNQNxvqc9dcOD2f5PyMTs8nkdEJnJ5PCn3GYI5zxUWotrZWeXl5uu2223TDDTdIkrxer6KiotSmTZuA2YSEBHm9Xnvm3BJUt79u36VmKisr9fXXX+urr75STU3NBWf279/f4LWcb968eZo9e3a97cXFxYqNjb3YqbgqcwfVNspxG8vGjRuDvo/b7W6ElTQfTs8nOT+j0/NJZHQCp+eTQpfx9OnTDZ694iKUk5OjvXv36r333rvSQzQ706ZNU35+vn27srJSycnJyszMVFxcXEgfy+/3y+126+kPwuWrDQvpsRvT3lmuBs/WZRw2bJgiIyMbcVVNw+n5JOdndHo+iYxO4PR8Uugz1r2i0xBXVIRyc3O1fv16bd26VZ07d7a3JyYmqrq6WsePHw94JqaiokKJiYn2zPmf7qr7JNe5M+d/uquiokJxcXFq2bKlIiIiFBERccGZc49xubWcLzo6WtHR0fW2R0ZGNto3n682TL6a704RupLz0Jjnrzlwej7J+Rmdnk8ioxM4PZ8UuozBHCOoT41ZlqXc3FytXbtWmzdvVkpKSsD+1NRURUZGqqSkxN524MABHT58WOnp6ZKk9PR07dmzJ+DTXW63W3FxcerTp489c+4x6mbqjhEVFaXU1NSAmdraWpWUlNgzDVkLAAAwW1DPCOXk5GjlypV666231Lp1a/u9NvHx8WrZsqXi4+M1fvx45efnq127doqLi9Pjjz+u9PR0+83JmZmZ6tOnj8aOHav58+fL6/Vq+vTpysnJsZ+Neeyxx/Tiiy9q6tSpeuSRR7R582atXr1aGzZssNeSn5+v7OxsDRo0SIMHD9bzzz+vqqoq+1NkDVkLAAAwW1BF6OWXX5YkDRkyJGD78uXL9fDDD0uSFi9erPDwcI0aNUo+n08ul0svvfSSPRsREaH169dr0qRJSk9PV6tWrZSdna05c+bYMykpKdqwYYMmT56sJUuWqHPnznrllVfsj85L0ujRo/XFF19oxowZ8nq9GjhwoIqKigLeQH25tQAAALMFVYQs6/If9Y6JiVFBQYEKCgouOtO1a9fLfvpoyJAh2r179yVncnNzlZube1VrAQAA5uLfGgMAAMaiCAEAAGNRhAAAgLEoQgAAwFgUIQAAYCyKEAAAMBZFCAAAGIsiBAAAjEURAgAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBYFCEAAGAsihAAADAWRQgAABiLIgQAAIxFEQIAAMaiCAEAAGNRhAAAgLEoQgAAwFgUIQAAYCyKEAAAMBZFCAAAGIsiBAAAjEURAgAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBYFCEAAGAsihAAADAWRQgAABgr6CK0detW3XvvvUpKSlJYWJjWrVsXsP/hhx9WWFhYwNfw4cMDZo4dO6aHHnpIcXFxatOmjcaPH69Tp04FzHz44Ye64447FBMTo+TkZM2fP7/eWtasWaNevXopJiZG/fr108aNGwP2W5alGTNmqFOnTmrZsqUyMjL0ySefBBsZAAA4VNBFqKqqSgMGDFBBQcFFZ4YPH67PP//c/nrjjTcC9j/00EPat2+f3G631q9fr61bt+rRRx+191dWViozM1Ndu3ZVWVmZfvnLX2rWrFn69a9/bc9s27ZNDz74oMaPH6/du3dr5MiRGjlypPbu3WvPzJ8/Xy+88IKWLl2qHTt2qFWrVnK5XDpz5kywsQEAgAO1CPYOI0aM0IgRIy45Ex0drcTExAvu+/jjj1VUVKS//OUvGjRokCTpV7/6le655x4tWLBASUlJev3111VdXa1ly5YpKipKffv2VXl5uRYtWmQXpiVLlmj48OGaMmWKJGnu3Llyu9168cUXtXTpUlmWpeeff17Tp0/XfffdJ0l67bXXlJCQoHXr1mnMmDHBRgcAAA4TdBFqiNLSUnXs2FFt27bVXXfdpWeeeUbt27eXJHk8HrVp08YuQZKUkZGh8PBw7dixQz/84Q/l8Xh05513Kioqyp5xuVx67rnn9NVXX6lt27byeDzKz88PeFyXy2W/VHfo0CF5vV5lZGTY++Pj45WWliaPx3PBIuTz+eTz+ezblZWVkiS/3y+/33/1J+YcdceLDrdCetzGFsx5qJsN9blrLpyeT3J+Rqfnk8joBE7PJ4U+YzDHCXkRGj58uO6//36lpKTo4MGD+sUvfqERI0bI4/EoIiJCXq9XHTt2DFxEixZq166dvF6vJMnr9SolJSVgJiEhwd7Xtm1beb1ee9u5M+ce49z7XWjmfPPmzdPs2bPrbS8uLlZsbGxDT0FQ5g6qbZTjNpbz34fVEG63uxFW0nw4PZ/k/IxOzyeR0Qmcnk8KXcbTp083eDbkRejcZ1r69eun/v37q3v37iotLdXdd98d6ocLqWnTpgU8y1RZWank5GRlZmYqLi4upI/l9/vldrv19Afh8tWGhfTYjWnvLFeDZ+syDhs2TJGRkY24qqbh9HyS8zM6PZ9ERidwej4p9BnrXtFpiEZ5aexc1113nTp06KBPP/1Ud999txITE3X06NGAmbNnz+rYsWP2+4oSExNVUVERMFN3+3Iz5+6v29apU6eAmYEDB15wrdHR0YqOjq63PTIystG++Xy1YfLVfHeK0JWch8Y8f82B0/NJzs/o9HwSGZ3A6fmk0GUM5hiN/neEPvvsM3355Zd2GUlPT9fx48dVVlZmz2zevFm1tbVKS0uzZ7Zu3RrwGp/b7VbPnj3Vtm1be6akpCTgsdxut9LT0yVJKSkpSkxMDJiprKzUjh077BkAAGC2oIvQqVOnVF5ervLycknfvCm5vLxchw8f1qlTpzRlyhRt375df/vb31RSUqL77rtPPXr0kMv1zUsqvXv31vDhwzVx4kTt3LlT77//vnJzczVmzBglJSVJkn7yk58oKipK48eP1759+7Rq1SotWbIk4GWrJ554QkVFRVq4cKH279+vWbNm6YMPPlBubq4kKSwsTHl5eXrmmWf0xz/+UXv27NHPfvYzJSUlaeTIkVd52gAAgBME/dLYBx98oKFDh9q368pJdna2Xn75ZX344YdasWKFjh8/rqSkJGVmZmru3LkBLzm9/vrrys3N1d13363w8HCNGjVKL7zwgr0/Pj5excXFysnJUWpqqjp06KAZM2YE/K2hW2+9VStXrtT06dP1i1/8Qt///ve1bt063XDDDfbM1KlTVVVVpUcffVTHjx/X7bffrqKiIsXExAQbGwAAOFDQRWjIkCGyrIt/5HvTpk2XPUa7du20cuXKS870799ff/7zny8588ADD+iBBx646P6wsDDNmTNHc+bMueyaAACAefi3xgAAgLEoQgAAwFgUIQAAYCyKEAAAMBZFCAAAGIsiBAAAjEURAgAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBYFCEAAGAsihAAADAWRQgAABiLIgQAAIxFEQIAAMaiCAEAAGNRhAAAgLEoQgAAwFgUIQAAYCyKEAAAMBZFCAAAGIsiBAAAjEURAgAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBYFCEAAGAsihAAADAWRQgAABiLIgQAAIxFEQIAAMaiCAEAAGMFXYS2bt2qe++9V0lJSQoLC9O6desC9luWpRkzZqhTp05q2bKlMjIy9MknnwTMHDt2TA899JDi4uLUpk0bjR8/XqdOnQqY+fDDD3XHHXcoJiZGycnJmj9/fr21rFmzRr169VJMTIz69eunjRs3Br0WAABgrqCLUFVVlQYMGKCCgoIL7p8/f75eeOEFLV26VDt27FCrVq3kcrl05swZe+ahhx7Svn375Ha7tX79em3dulWPPvqovb+yslKZmZnq2rWrysrK9Mtf/lKzZs3Sr3/9a3tm27ZtevDBBzV+/Hjt3r1bI0eO1MiRI7V3796g1gIAAMzVItg7jBgxQiNGjLjgPsuy9Pzzz2v69Om67777JEmvvfaaEhIStG7dOo0ZM0Yff/yxioqK9Je//EWDBg2SJP3qV7/SPffcowULFigpKUmvv/66qqurtWzZMkVFRalv374qLy/XokWL7MK0ZMkSDR8+XFOmTJEkzZ07V263Wy+++KKWLl3aoLUAAACzBV2ELuXQoUPyer3KyMiwt8XHxystLU0ej0djxoyRx+NRmzZt7BIkSRkZGQoPD9eOHTv0wx/+UB6PR3feeaeioqLsGZfLpeeee05fffWV2rZtK4/Ho/z8/IDHd7lc9kt1DVnL+Xw+n3w+n327srJSkuT3++X3+6/u5Jyn7njR4VZIj9vYgjkPdbOhPnfNhdPzSc7P6PR8EhmdwOn5pNBnDOY4IS1CXq9XkpSQkBCwPSEhwd7n9XrVsWPHwEW0aKF27doFzKSkpNQ7Rt2+tm3byuv1XvZxLreW882bN0+zZ8+ut724uFixsbEXSX115g6qbZTjNpbz34fVEG63uxFW0nw4PZ/k/IxOzyeR0Qmcnk8KXcbTp083eDakRei7btq0aQHPMlVWVio5OVmZmZmKi4sL6WP5/X653W49/UG4fLVhIT12Y9o7y9Xg2bqMw4YNU2RkZCOuqmk4PZ/k/IxOzyeR0Qmcnk8Kfca6V3QaIqRFKDExUZJUUVGhTp062dsrKio0cOBAe+bo0aMB9zt79qyOHTtm3z8xMVEVFRUBM3W3Lzdz7v7LreV80dHRio6Orrc9MjKy0b75fLVh8tV8d4rQlZyHxjx/zYHT80nOz+j0fBIZncDp+aTQZQzmGCH9O0IpKSlKTExUSUmJva2yslI7duxQenq6JCk9PV3Hjx9XWVmZPbN582bV1tYqLS3Nntm6dWvAa3xut1s9e/ZU27Zt7ZlzH6dupu5xGrIWAABgtqCL0KlTp1ReXq7y8nJJ37wpuby8XIcPH1ZYWJjy8vL0zDPP6I9//KP27Nmjn/3sZ0pKStLIkSMlSb1799bw4cM1ceJE7dy5U++//75yc3M1ZswYJSUlSZJ+8pOfKCoqSuPHj9e+ffu0atUqLVmyJOBlqyeeeEJFRUVauHCh9u/fr1mzZumDDz5Qbm6uJDVoLQAAwGxBvzT2wQcfaOjQofbtunKSnZ2twsJCTZ06VVVVVXr00Ud1/Phx3X777SoqKlJMTIx9n9dff125ubm6++67FR4erlGjRumFF16w98fHx6u4uFg5OTlKTU1Vhw4dNGPGjIC/NXTrrbdq5cqVmj59un7xi1/o+9//vtatW6cbbrjBnmnIWgAAgLmCLkJDhgyRZV38I99hYWGaM2eO5syZc9GZdu3aaeXKlZd8nP79++vPf/7zJWceeOABPfDAA1e1FgAAYC7+rTEAAGAsihAAADAWRQgAABiLIgQAAIxFEQIAAMaiCAEAAGNRhAAAgLEoQgAAwFgUIQAAYCyKEAAAMBZFCAAAGIsiBAAAjEURAgAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBYFCEAAGAsihAAADAWRQgAABiLIgQAAIxFEQIAAMaiCAEAAGNRhAAAgLEoQgAAwFgUIQAAYCyKEAAAMBZFCAAAGIsiBAAAjEURAgAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBYIS9Cs2bNUlhYWMBXr1697P1nzpxRTk6O2rdvr2uuuUajRo1SRUVFwDEOHz6srKwsxcbGqmPHjpoyZYrOnj0bMFNaWqqbbrpJ0dHR6tGjhwoLC+utpaCgQN26dVNMTIzS0tK0c+fOUMcFAADfYY3yjFDfvn31+eef21/vvfeevW/y5Ml6++23tWbNGm3ZskVHjhzR/fffb++vqalRVlaWqqurtW3bNq1YsUKFhYWaMWOGPXPo0CFlZWVp6NChKi8vV15eniZMmKBNmzbZM6tWrVJ+fr5mzpypXbt2acCAAXK5XDp69GhjRAYAAN9BjVKEWrRoocTERPurQ4cOkqQTJ07o1Vdf1aJFi3TXXXcpNTVVy5cv17Zt27R9+3ZJUnFxsT766CP99re/1cCBAzVixAjNnTtXBQUFqq6uliQtXbpUKSkpWrhwoXr37q3c3Fz96Ec/0uLFi+01LFq0SBMnTtS4cePUp08fLV26VLGxsVq2bFljRAYAAN9BLRrjoJ988omSkpIUExOj9PR0zZs3T126dFFZWZn8fr8yMjLs2V69eqlLly7yeDy65ZZb5PF41K9fPyUkJNgzLpdLkyZN0r59+3TjjTfK4/EEHKNuJi8vT5JUXV2tsrIyTZs2zd4fHh6ujIwMeTyei67b5/PJ5/PZtysrKyVJfr9ffr//qs7J+eqOFx1uhfS4jS2Y81A3G+pz11w4PZ/k/IxOzyeR0Qmcnk8KfcZgjhPyIpSWlqbCwkL17NlTn3/+uWbPnq077rhDe/fuldfrVVRUlNq0aRNwn4SEBHm9XkmS1+sNKEF1++v2XWqmsrJSX3/9tb766ivV1NRccGb//v0XXfu8efM0e/bsetuLi4sVGxvbsBMQpLmDahvluI1l48aNQd/H7XY3wkqaD6fnk5yf0en5JDI6gdPzSaHLePr06QbPhrwIjRgxwv7v/v37Ky0tTV27dtXq1avVsmXLUD9cSE2bNk35+fn27crKSiUnJyszM1NxcXEhfSy/3y+3262nPwiXrzYspMduTHtnuRo8W5dx2LBhioyMbMRVNQ2n55Ocn9Hp+SQyOoHT80mhz1j3ik5DNMpLY+dq06aNrr/+en366acaNmyYqqurdfz48YBnhSoqKpSYmChJSkxMrPfprrpPlZ07c/4nzSoqKhQXF6eWLVsqIiJCERERF5ypO8aFREdHKzo6ut72yMjIRvvm89WGyVfz3SlCV3IeGvP8NQdOzyc5P6PT80lkdAKn55NClzGYYzT63xE6deqUDh48qE6dOik1NVWRkZEqKSmx9x84cECHDx9Wenq6JCk9PV179uwJ+HSX2+1WXFyc+vTpY8+ce4y6mbpjREVFKTU1NWCmtrZWJSUl9gwAAEDIi9DPf/5zbdmyRX/729+0bds2/fCHP1RERIQefPBBxcfHa/z48crPz9e7776rsrIyjRs3Tunp6brlllskSZmZmerTp4/Gjh2r//mf/9GmTZs0ffp05eTk2M/WPPbYY/rrX/+qqVOnav/+/XrppZe0evVqTZ482V5Hfn6+fvOb32jFihX6+OOPNWnSJFVVVWncuHGhjgwAAL6jQv7S2GeffaYHH3xQX375pa699lrdfvvt2r59u6699lpJ0uLFixUeHq5Ro0bJ5/PJ5XLppZdesu8fERGh9evXa9KkSUpPT1erVq2UnZ2tOXPm2DMpKSnasGGDJk+erCVLlqhz58565ZVX5HL93/tXRo8erS+++EIzZsyQ1+vVwIEDVVRUVO8N1AAAwFwhL0JvvvnmJffHxMSooKBABQUFF53p2rXrZT+dNGTIEO3evfuSM7m5ucrNzb3kDAAAMBf/1hgAADAWRQgAABiLIgQAAIxFEQIAAMaiCAEAAGNRhAAAgLEoQgAAwFgUIQAAYCyKEAAAMBZFCAAAGIsiBAAAjEURAgAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBYFCEAAGAsihAAADAWRQgAABiLIgQAAIxFEQIAAMaiCAEAAGNRhAAAgLEoQgAAwFgUIQAAYCyKEAAAMBZFCAAAGIsiBAAAjEURAgAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBYRhShgoICdevWTTExMUpLS9POnTubekkAAKAZcHwRWrVqlfLz8zVz5kzt2rVLAwYMkMvl0tGjR5t6aQAAoIk5vggtWrRIEydO1Lhx49SnTx8tXbpUsbGxWrZsWVMvDQAANLEWTb2AxlRdXa2ysjJNmzbN3hYeHq6MjAx5PJ568z6fTz6fz7594sQJSdKxY8fk9/tDuja/36/Tp0+rhT9cNbVhIT12Y/ryyy8bPFuX8csvv1RkZGQjrqppOD2f5PyMTs8nkdEJnJ5PCn3GkydPSpIsy7rsrKOL0L/+9S/V1NQoISEhYHtCQoL2799fb37evHmaPXt2ve0pKSmNtsbvmg4Lm3oFAAA0zMmTJxUfH3/JGUcXoWBNmzZN+fn59u3a2lodO3ZM7du3V1hYaJ+1qaysVHJysv7xj38oLi4upMduLpye0en5JOdndHo+iYxO4PR8UugzWpalkydPKikp6bKzji5CHTp0UEREhCoqKgK2V1RUKDExsd58dHS0oqOjA7a1adOmMZeouLg4x35j13F6Rqfnk5yf0en5JDI6gdPzSaHNeLlnguo4+s3SUVFRSk1NVUlJib2ttrZWJSUlSk9Pb8KVAQCA5sDRzwhJUn5+vrKzszVo0CANHjxYzz//vKqqqjRu3LimXhoAAGhiji9Co0eP1hdffKEZM2bI6/Vq4MCBKioqqvcG6m9bdHS0Zs6cWe+lOCdxekan55Ocn9Hp+SQyOoHT80lNmzHMashnywAAABzI0e8RAgAAuBSKEAAAMBZFCAAAGIsiBAAAjEURCpGCggJ169ZNMTExSktL086dOy85v2bNGvXq1UsxMTHq16+fNm7cGLDfsizNmDFDnTp1UsuWLZWRkaFPPvmkMSNcVjAZf/Ob3+iOO+5Q27Zt1bZtW2VkZNSbf/jhhxUWFhbwNXz48MaOcUnBZCwsLKy3/piYmICZ5nYdg8k3ZMiQevnCwsKUlZVlzzS3a7h161bde++9SkpKUlhYmNatW3fZ+5SWluqmm25SdHS0evToocLCwnozwf58N5Zg8/3hD3/QsGHDdO211youLk7p6enatGlTwMysWbPqXcNevXo1YopLCzZjaWnpBb9PvV5vwFxzuYZS8Bkv9HMWFhamvn372jPN6TrOmzdPN998s1q3bq2OHTtq5MiROnDgwGXv11S/FylCIbBq1Srl5+dr5syZ2rVrlwYMGCCXy6WjR49ecH7btm168MEHNX78eO3evVsjR47UyJEjtXfvXntm/vz5euGFF7R06VLt2LFDrVq1ksvl0pkzZ76tWAGCzVhaWqoHH3xQ7777rjwej5KTk5WZmal//vOfAXPDhw/X559/bn+98cYb30acCwo2o/TNX0E9d/1///vfA/Y3p+sYbL4//OEPAdn27t2riIgIPfDAAwFzzekaVlVVacCAASooKGjQ/KFDh5SVlaWhQ4eqvLxceXl5mjBhQkBZuJLvi8YSbL6tW7dq2LBh2rhxo8rKyjR06FDde++92r17d8Bc3759A67he++91xjLb5BgM9Y5cOBAQIaOHTva+5rTNZSCz7hkyZKAbP/4xz/Url27ej+LzeU6btmyRTk5Odq+fbvcbrf8fr8yMzNVVVV10fs06e9FC1dt8ODBVk5Ojn27pqbGSkpKsubNm3fB+R//+MdWVlZWwLa0tDTr3/7t3yzLsqza2lorMTHR+uUvf2nvP378uBUdHW298cYbjZDg8oLNeL6zZ89arVu3tlasWGFvy87Otu67775QL/WKBZtx+fLlVnx8/EWP19yu49Vew8WLF1utW7e2Tp06ZW9rbtfwXJKstWvXXnJm6tSpVt++fQO2jR492nK5XPbtqz1vjaUh+S6kT58+1uzZs+3bM2fOtAYMGBC6hYVQQzK+++67liTrq6++uuhMc72GlnVl13Ht2rVWWFiY9be//c3e1pyv49GjRy1J1pYtWy4605S/F3lG6CpVV1errKxMGRkZ9rbw8HBlZGTI4/Fc8D4ejydgXpJcLpc9f+jQIXm93oCZ+Ph4paWlXfSYjelKMp7v9OnT8vv9ateuXcD20tJSdezYUT179tSkSZP05ZdfhnTtDXWlGU+dOqWuXbsqOTlZ9913n/bt22fva07XMRTX8NVXX9WYMWPUqlWrgO3N5Rpeicv9LIbivDUntbW1OnnyZL2fw08++URJSUm67rrr9NBDD+nw4cNNtMIrN3DgQHXq1EnDhg3T+++/b2932jWUvvlZzMjIUNeuXQO2N9freOLECUmq9313rqb8vUgRukr/+te/VFNTU+8vVSckJNR7jbqO1+u95Hzd/w3mmI3pSjKe78knn1RSUlLAN/Hw4cP12muvqaSkRM8995y2bNmiESNGqKamJqTrb4grydizZ08tW7ZMb731ln7729+qtrZWt956qz777DNJzes6Xu013Llzp/bu3asJEyYEbG9O1/BKXOxnsbKyUl9//XVIvvebkwULFujUqVP68Y9/bG9LS0tTYWGhioqK9PLLL+vQoUO64447dPLkySZcacN16tRJS5cu1e9//3v9/ve/V3JysoYMGaJdu3ZJCs3/fjUnR44c0Z/+9Kd6P4vN9TrW1tYqLy9Pt912m2644YaLzjXl70XH/xMbaHrPPvus3nzzTZWWlga8mXjMmDH2f/fr10/9+/dX9+7dVVpaqrvvvrsplhqU9PT0gH+899Zbb1Xv3r31X//1X5o7d24Triz0Xn31VfXr10+DBw8O2P5dv4YmWblypWbPnq233nor4P0zI0aMsP+7f//+SktLU9euXbV69WqNHz++KZYalJ49e6pnz5727VtvvVUHDx7U4sWL9d///d9NuLLGsWLFCrVp00YjR44M2N5cr2NOTo727t3bpO87uxyeEbpKHTp0UEREhCoqKgK2V1RUKDEx8YL3SUxMvOR83f8N5piN6Uoy1lmwYIGeffZZFRcXq3///pecve6669ShQwd9+umnV73mYF1NxjqRkZG68cYb7fU3p+t4Nfmqqqr05ptvNuh/TJvyGl6Ji/0sxsXFqWXLliH5vmgO3nzzTU2YMEGrV6+u9/LD+dq0aaPrr7/+O3MNL2Tw4MH2+p1yDaVvPjW1bNkyjR07VlFRUZecbQ7XMTc3V+vXr9e7776rzp07X3K2KX8vUoSuUlRUlFJTU1VSUmJvq62tVUlJScCzBedKT08PmJckt9ttz6ekpCgxMTFgprKyUjt27LjoMRvTlWSUvnmH/9y5c1VUVKRBgwZd9nE+++wzffnll+rUqVNI1h2MK814rpqaGu3Zs8def3O6jleTb82aNfL5fPrpT3962cdpymt4JS73sxiK74um9sYbb2jcuHF64403Av70wcWcOnVKBw8e/M5cwwspLy+31++Ea1hny5Yt+vTTTxv0/5Q05XW0LEu5ublau3atNm/erJSUlMvep0l/L17VW61hWZZlvfnmm1Z0dLRVWFhoffTRR9ajjz5qtWnTxvJ6vZZlWdbYsWOtp556yp5///33rRYtWlgLFiywPv74Y2vmzJlWZGSktWfPHnvm2Weftdq0aWO99dZb1ocffmjdd999VkpKivX1119/6/ksK/iMzz77rBUVFWX97ne/sz7//HP76+TJk5ZlWdbJkyetn//855bH47EOHTpkvfPOO9ZNN91kff/737fOnDnzncg4e/Zsa9OmTdbBgwetsrIya8yYMVZMTIy1b98+e6Y5Xcdg89W5/fbbrdGjR9fb3hyv4cmTJ63du3dbu3fvtiRZixYtsnbv3m39/e9/tyzLsp566ilr7Nix9vxf//pXKzY21poyZYr18ccfWwUFBVZERIRVVFRkz1zuvDXnfK+//rrVokULq6CgIODn8Pjx4/bMv//7v1ulpaXWoUOHrPfff9/KyMiwOnToYB09evRbz2dZwWdcvHixtW7dOuuTTz6x9uzZYz3xxBNWeHi49c4779gzzekaWlbwGev89Kc/tdLS0i54zOZ0HSdNmmTFx8dbpaWlAd93p0+ftmea0+9FilCI/OpXv7K6dOliRUVFWYMHD7a2b99u7/vBD35gZWdnB8yvXr3auv76662oqCirb9++1oYNGwL219bWWk8//bSVkJBgRUdHW3fffbd14MCBbyPKRQWTsWvXrpakel8zZ860LMuyTp8+bWVmZlrXXnutFRkZaXXt2tWaOHFik/0PU51gMubl5dmzCQkJ1j333GPt2rUr4HjN7ToG+326f/9+S5JVXFxc71jN8RrWfZT6/K+6XNnZ2dYPfvCDevcZOHCgFRUVZV133XXW8uXL6x33Uuft2xRsvh/84AeXnLesb/5cQKdOnayoqCjre9/7njV69Gjr008//XaDnSPYjM8995zVvXt3KyYmxmrXrp01ZMgQa/PmzfWO21yuoWVd2ffp8ePHrZYtW1q//vWvL3jM5nQdL5RNUsDPVnP6vRj2/xcNAABgHN4jBAAAjEURAgAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAB867Zu3ap7771XSUlJCgsL07p164I+hmVZWrBgga6//npFR0fre9/7nv7zP/8zqGPwr88DAIBvXVVVlQYMGKBHHnlE999//xUd44knnlBxcbEWLFigfv366dixYzp27FhQx+AvSwMAgCYVFhamtWvXauTIkfY2n8+n//iP/9Abb7yh48eP64YbbtBzzz2nIUOGSJI+/vhj9e/fX3v37lXPnj2v+LF5aQwAADQ7ubm58ng8evPNN/Xhhx/qgQce0PDhw/XJJ59Ikt5++21dd911Wr9+vVJSUtStWzdNmDAh6GeEKEIAAKBZOXz4sJYvX641a9bojjvuUPfu3fXzn/9ct99+u5YvXy5J+utf/6q///3vWrNmjV577TUVFhaqrKxMP/rRj4J6LN4jBAAAmpU9e/aopqZG119/fcB2n8+n9u3bS5Jqa2vl8/n02muv2XOvvvqqUlNTdeDAgQa/XEYRAgAAzcqpU6cUERGhsrIyRUREBOy75pprJEmdOnVSixYtAspS7969JX3zjBJFCAAAfCfdeOONqqmp0dGjR3XHHXdccOa2227T2bNndfDgQXXv3l2S9L//+7+SpK5duzb4sfjUGAAA+NadOnVKn376qaRvis+iRYs0dOhQtWvXTl26dNFPf/pTvf/++1q4cKFuvPFGffHFFyopKVH//v2VlZWl2tpa3Xzzzbrmmmv0/PPPq7a2Vjk5OYqLi1NxcXGD10ERAgAA37rS0lINHTq03vbs7GwVFhbK7/frmWee0WuvvaZ//vOf6tChg2655RbNnj1b/fr1kyQdOXJEjz/+uIqLi9WqVSuNGDFCCxcuVLt27Rq8DooQAAAwFh+fBwAAxqIIAQAAY1GEAACAsShCAADAWBQhAABgLIoQAAAwFkUIAAAYiyIEAACMRRECAADGoggBAABjUYQAAICxKEIAAMBY/w8KcfRfIHEI/wAAAABJRU5ErkJggg==", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "df['tripduration'].hist()" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "cabf81db-6c49-4274-8460-770405d1a405", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'nan_count': 0,\n", + " 'distinct_count': 1615,\n", + " 'min': 60,\n", + " 'mean': 733.9689447403462,\n", + " 'max': 1990440,\n", + " 'dtype': dtype('int64')}" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def col_stats(ser):\n", + " l = len(ser)\n", + " values = ser.value_counts()\n", + " return dict(\n", + " nan_count = ser.isna().sum(),\n", + " distinct_count = values[values == 1].sum(),\n", + " min = ser.min(),\n", + " mean = ser.mean(),\n", + " max = ser.max(),\n", + " dtype = ser.dtype)\n", + "col_stats(df['tripduration'])" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "21d22855-7f52-41ab-b3a8-4e23b77f2e76", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "sampled_df = df.sample(50) # grab 50 random rows" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "15bdaf26-09c0-4350-bfec-0db1362a79f5", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "Could not convert string '2014-01-11 07:18:292014-01-17 22:35:122014-01-25 23:03:312014-01-07 13:06:052014-01-18 09:41:582014-01-27 14:58:362014-01-08 10:36:522014-01-02 19:19:522014-01-03 08:03:132014-01-20 16:58:002014-01-14 16:43:132014-01-17 06:27:252014-01-18 11:17:332014-01-15 17:08:142014-01-13 11:40:182014-01-30 17:19:182014-01-26 03:06:292014-01-29 17:51:082014-01-17 09:03:482014-01-19 13:09:322014-01-08 08:58:282014-01-15 12:35:342014-01-30 19:19:502014-01-23 08:49:162014-01-16 15:59:092014-01-10 20:00:442014-01-28 18:24:372014-01-01 18:58:342014-01-17 18:49:252014-01-16 11:56:452014-01-14 07:16:082014-01-12 09:43:542014-01-31 15:24:332014-01-22 18:25:162014-01-20 17:55:582014-01-06 17:52:012014-01-12 10:25:442014-01-26 19:37:262014-01-20 06:37:262014-01-11 00:22:172014-01-15 16:36:232014-01-06 17:39:112014-01-15 15:12:582014-01-10 09:13:292014-01-26 11:27:172014-01-27 07:40:552014-01-27 06:50:092014-01-31 16:31:512014-01-06 19:05:402014-01-27 18:30:28' to numeric", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[20], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m pd\u001b[38;5;241m.\u001b[39mDataFrame(\u001b[38;5;28mdict\u001b[39m(\u001b[43m[\u001b[49m\u001b[43m[\u001b[49m\u001b[43mcol\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcol_stats\u001b[49m\u001b[43m(\u001b[49m\u001b[43msampled_df\u001b[49m\u001b[43m[\u001b[49m\u001b[43mcol\u001b[49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\u001b[43m]\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mcol\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43msampled_df\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcolumns\u001b[49m\u001b[43m]\u001b[49m))\n", + "Cell \u001b[0;32mIn[20], line 1\u001b[0m, in \u001b[0;36m\u001b[0;34m(.0)\u001b[0m\n\u001b[0;32m----> 1\u001b[0m pd\u001b[38;5;241m.\u001b[39mDataFrame(\u001b[38;5;28mdict\u001b[39m([[col, \u001b[43mcol_stats\u001b[49m\u001b[43m(\u001b[49m\u001b[43msampled_df\u001b[49m\u001b[43m[\u001b[49m\u001b[43mcol\u001b[49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m] \u001b[38;5;28;01mfor\u001b[39;00m col \u001b[38;5;129;01min\u001b[39;00m sampled_df\u001b[38;5;241m.\u001b[39mcolumns]))\n", + "Cell \u001b[0;32mIn[18], line 8\u001b[0m, in \u001b[0;36mcol_stats\u001b[0;34m(ser)\u001b[0m\n\u001b[1;32m 2\u001b[0m l \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlen\u001b[39m(ser)\n\u001b[1;32m 3\u001b[0m values \u001b[38;5;241m=\u001b[39m ser\u001b[38;5;241m.\u001b[39mvalue_counts()\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mdict\u001b[39m(\n\u001b[1;32m 5\u001b[0m nan_count \u001b[38;5;241m=\u001b[39m ser\u001b[38;5;241m.\u001b[39misna()\u001b[38;5;241m.\u001b[39msum(),\n\u001b[1;32m 6\u001b[0m distinct_count \u001b[38;5;241m=\u001b[39m values[values \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m1\u001b[39m]\u001b[38;5;241m.\u001b[39msum(),\n\u001b[1;32m 7\u001b[0m \u001b[38;5;28mmin\u001b[39m \u001b[38;5;241m=\u001b[39m ser\u001b[38;5;241m.\u001b[39mmin(),\n\u001b[0;32m----> 8\u001b[0m mean \u001b[38;5;241m=\u001b[39m \u001b[43mser\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmean\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m,\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28mmax\u001b[39m \u001b[38;5;241m=\u001b[39m ser\u001b[38;5;241m.\u001b[39mmax(),\n\u001b[1;32m 10\u001b[0m dtype \u001b[38;5;241m=\u001b[39m ser\u001b[38;5;241m.\u001b[39mdtype)\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-1/lib/python3.11/site-packages/pandas/core/series.py:6221\u001b[0m, in \u001b[0;36mSeries.mean\u001b[0;34m(self, axis, skipna, numeric_only, **kwargs)\u001b[0m\n\u001b[1;32m 6213\u001b[0m \u001b[38;5;129m@doc\u001b[39m(make_doc(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmean\u001b[39m\u001b[38;5;124m\"\u001b[39m, ndim\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m))\n\u001b[1;32m 6214\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mmean\u001b[39m(\n\u001b[1;32m 6215\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 6219\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs,\n\u001b[1;32m 6220\u001b[0m ):\n\u001b[0;32m-> 6221\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mNDFrame\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmean\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mskipna\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnumeric_only\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-1/lib/python3.11/site-packages/pandas/core/generic.py:11978\u001b[0m, in \u001b[0;36mNDFrame.mean\u001b[0;34m(self, axis, skipna, numeric_only, **kwargs)\u001b[0m\n\u001b[1;32m 11971\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mmean\u001b[39m(\n\u001b[1;32m 11972\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 11973\u001b[0m axis: Axis \u001b[38;5;241m|\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 11976\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs,\n\u001b[1;32m 11977\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Series \u001b[38;5;241m|\u001b[39m \u001b[38;5;28mfloat\u001b[39m:\n\u001b[0;32m> 11978\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_stat_function\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 11979\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mmean\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnanops\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mnanmean\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mskipna\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnumeric_only\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\n\u001b[1;32m 11980\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-1/lib/python3.11/site-packages/pandas/core/generic.py:11935\u001b[0m, in \u001b[0;36mNDFrame._stat_function\u001b[0;34m(self, name, func, axis, skipna, numeric_only, **kwargs)\u001b[0m\n\u001b[1;32m 11931\u001b[0m nv\u001b[38;5;241m.\u001b[39mvalidate_func(name, (), kwargs)\n\u001b[1;32m 11933\u001b[0m validate_bool_kwarg(skipna, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mskipna\u001b[39m\u001b[38;5;124m\"\u001b[39m, none_allowed\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m)\n\u001b[0;32m> 11935\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_reduce\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 11936\u001b[0m \u001b[43m \u001b[49m\u001b[43mfunc\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mname\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mname\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mskipna\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mskipna\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnumeric_only\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnumeric_only\u001b[49m\n\u001b[1;32m 11937\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-1/lib/python3.11/site-packages/pandas/core/series.py:6129\u001b[0m, in \u001b[0;36mSeries._reduce\u001b[0;34m(self, op, name, axis, skipna, numeric_only, filter_type, **kwds)\u001b[0m\n\u001b[1;32m 6124\u001b[0m \u001b[38;5;66;03m# GH#47500 - change to TypeError to match other methods\u001b[39;00m\n\u001b[1;32m 6125\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mTypeError\u001b[39;00m(\n\u001b[1;32m 6126\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSeries.\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mname\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m does not allow \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mkwd_name\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mnumeric_only\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 6127\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mwith non-numeric dtypes.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 6128\u001b[0m )\n\u001b[0;32m-> 6129\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mop\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdelegate\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mskipna\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mskipna\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwds\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-1/lib/python3.11/site-packages/pandas/core/nanops.py:147\u001b[0m, in \u001b[0;36mbottleneck_switch.__call__..f\u001b[0;34m(values, axis, skipna, **kwds)\u001b[0m\n\u001b[1;32m 145\u001b[0m result \u001b[38;5;241m=\u001b[39m alt(values, axis\u001b[38;5;241m=\u001b[39maxis, skipna\u001b[38;5;241m=\u001b[39mskipna, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwds)\n\u001b[1;32m 146\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 147\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43malt\u001b[49m\u001b[43m(\u001b[49m\u001b[43mvalues\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mskipna\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mskipna\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwds\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 149\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m result\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-1/lib/python3.11/site-packages/pandas/core/nanops.py:404\u001b[0m, in \u001b[0;36m_datetimelike_compat..new_func\u001b[0;34m(values, axis, skipna, mask, **kwargs)\u001b[0m\n\u001b[1;32m 401\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m datetimelike \u001b[38;5;129;01mand\u001b[39;00m mask \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 402\u001b[0m mask \u001b[38;5;241m=\u001b[39m isna(values)\n\u001b[0;32m--> 404\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[43mvalues\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mskipna\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mskipna\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmask\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmask\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 406\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m datetimelike:\n\u001b[1;32m 407\u001b[0m result \u001b[38;5;241m=\u001b[39m _wrap_results(result, orig_values\u001b[38;5;241m.\u001b[39mdtype, fill_value\u001b[38;5;241m=\u001b[39miNaT)\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-1/lib/python3.11/site-packages/pandas/core/nanops.py:720\u001b[0m, in \u001b[0;36mnanmean\u001b[0;34m(values, axis, skipna, mask)\u001b[0m\n\u001b[1;32m 718\u001b[0m count \u001b[38;5;241m=\u001b[39m _get_counts(values\u001b[38;5;241m.\u001b[39mshape, mask, axis, dtype\u001b[38;5;241m=\u001b[39mdtype_count)\n\u001b[1;32m 719\u001b[0m the_sum \u001b[38;5;241m=\u001b[39m values\u001b[38;5;241m.\u001b[39msum(axis, dtype\u001b[38;5;241m=\u001b[39mdtype_sum)\n\u001b[0;32m--> 720\u001b[0m the_sum \u001b[38;5;241m=\u001b[39m \u001b[43m_ensure_numeric\u001b[49m\u001b[43m(\u001b[49m\u001b[43mthe_sum\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 722\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m axis \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mgetattr\u001b[39m(the_sum, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mndim\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mFalse\u001b[39;00m):\n\u001b[1;32m 723\u001b[0m count \u001b[38;5;241m=\u001b[39m cast(np\u001b[38;5;241m.\u001b[39mndarray, count)\n", + "File \u001b[0;32m~/anaconda3/envs/buckaroo-dev-1/lib/python3.11/site-packages/pandas/core/nanops.py:1693\u001b[0m, in \u001b[0;36m_ensure_numeric\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 1690\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (is_float(x) \u001b[38;5;129;01mor\u001b[39;00m is_integer(x) \u001b[38;5;129;01mor\u001b[39;00m is_complex(x)):\n\u001b[1;32m 1691\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(x, \u001b[38;5;28mstr\u001b[39m):\n\u001b[1;32m 1692\u001b[0m \u001b[38;5;66;03m# GH#44008, GH#36703 avoid casting e.g. strings to numeric\u001b[39;00m\n\u001b[0;32m-> 1693\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mTypeError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCould not convert string \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mx\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m to numeric\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 1694\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1695\u001b[0m x \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mfloat\u001b[39m(x)\n", + "\u001b[0;31mTypeError\u001b[0m: Could not convert string '2014-01-11 07:18:292014-01-17 22:35:122014-01-25 23:03:312014-01-07 13:06:052014-01-18 09:41:582014-01-27 14:58:362014-01-08 10:36:522014-01-02 19:19:522014-01-03 08:03:132014-01-20 16:58:002014-01-14 16:43:132014-01-17 06:27:252014-01-18 11:17:332014-01-15 17:08:142014-01-13 11:40:182014-01-30 17:19:182014-01-26 03:06:292014-01-29 17:51:082014-01-17 09:03:482014-01-19 13:09:322014-01-08 08:58:282014-01-15 12:35:342014-01-30 19:19:502014-01-23 08:49:162014-01-16 15:59:092014-01-10 20:00:442014-01-28 18:24:372014-01-01 18:58:342014-01-17 18:49:252014-01-16 11:56:452014-01-14 07:16:082014-01-12 09:43:542014-01-31 15:24:332014-01-22 18:25:162014-01-20 17:55:582014-01-06 17:52:012014-01-12 10:25:442014-01-26 19:37:262014-01-20 06:37:262014-01-11 00:22:172014-01-15 16:36:232014-01-06 17:39:112014-01-15 15:12:582014-01-10 09:13:292014-01-26 11:27:172014-01-27 07:40:552014-01-27 06:50:092014-01-31 16:31:512014-01-06 19:05:402014-01-27 18:30:28' to numeric" + ] + } + ], + "source": [ + "pd.DataFrame(dict([[col, col_stats(sampled_df[col])] for col in sampled_df.columns]))" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "30b99e5c-c8b2-496c-822b-b15198e22616", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    tripdurationstarttimestoptimestart station idstart station namestart station latitudestart station longitudeend station idend station nameend station latitudeend station longitudebikeidusertypebirth yeargender
    nan_count000000000000000
    distinct_count4850462323232328282828480170
    dtypeint64objectobjectint64objectfloat64float64int64objectfloat64float64int64objectobjectint64
    min128NaNNaN83NaN40.683125-74.015756127NaN40.682166-74.01234214650NaNNaN0
    mean720.24NaNNaN572.3NaN40.73296-73.98873400.14NaN40.730918-73.99000317363.68NaNNaN0.98
    max1957NaNNaN3002NaN40.770513-73.9678442022NaN40.763707-73.9539921183NaNNaN2
    \n", + "
    " + ], + "text/plain": [ + " tripduration starttime stoptime start station id \\\n", + "nan_count 0 0 0 0 \n", + "distinct_count 48 50 46 23 \n", + "dtype int64 object object int64 \n", + "min 128 NaN NaN 83 \n", + "mean 720.24 NaN NaN 572.3 \n", + "max 1957 NaN NaN 3002 \n", + "\n", + " start station name start station latitude \\\n", + "nan_count 0 0 \n", + "distinct_count 23 23 \n", + "dtype object float64 \n", + "min NaN 40.683125 \n", + "mean NaN 40.73296 \n", + "max NaN 40.770513 \n", + "\n", + " start station longitude end station id end station name \\\n", + "nan_count 0 0 0 \n", + "distinct_count 23 28 28 \n", + "dtype float64 int64 object \n", + "min -74.015756 127 NaN \n", + "mean -73.98873 400.14 NaN \n", + "max -73.967844 2022 NaN \n", + "\n", + " end station latitude end station longitude bikeid usertype \\\n", + "nan_count 0 0 0 0 \n", + "distinct_count 28 28 48 0 \n", + "dtype float64 float64 int64 object \n", + "min 40.682166 -74.012342 14650 NaN \n", + "mean 40.730918 -73.990003 17363.68 NaN \n", + "max 40.763707 -73.95399 21183 NaN \n", + "\n", + " birth year gender \n", + "nan_count 0 0 \n", + "distinct_count 17 0 \n", + "dtype object int64 \n", + "min NaN 0 \n", + "mean NaN 0.98 \n", + "max NaN 2 " + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "def col_stats(ser):\n", + " l = len(ser)\n", + " values = ser.value_counts()\n", + " base_stats = dict(\n", + " nan_count = ser.isna().sum(),\n", + " distinct_count = values[values == 1].sum(),\n", + " dtype = ser.dtype)\n", + " if pd.api.types.is_numeric_dtype(ser):\n", + " base_stats.update(dict(\n", + " min = ser.min(),\n", + " mean = ser.mean(),\n", + " max = ser.max()))\n", + " return base_stats\n", + "def summary(df):\n", + " #we'll start with the first 50 rows as a smoke test\n", + " small_df = df.iloc[:50]\n", + " return pd.DataFrame(dict([[col, col_stats(small_df[col])] for col in small_df.columns]))\n", + "summary(df)" + ] + }, + { + "cell_type": "markdown", + "id": "243d392e-1820-446a-80ae-8552da26d6b1", + "metadata": {}, + "source": [ + "# ok let's add mode" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "0c9c5725-212f-4186-b863-ac403ef7b4a9", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    tripdurationstarttimestoptimestart station idstart station namestart station latitudestart station longitudeend station idend station nameend station latitudeend station longitudebikeidusertypebirth yeargender
    nan_count000000000000000
    distinct_count4850462323232328282828480170
    dtypeint64objectobjectint64objectfloat64float64int64objectfloat64float64int64objectobjectint64
    min128NaNNaN83NaN40.683125-74.015756127NaN40.682166-74.01234214650NaNNaN0
    mean720.24NaNNaN572.3NaN40.73296-73.98873400.14NaN40.730918-73.99000317363.68NaNNaN0.98
    max1957NaNNaN3002NaN40.770513-73.9678442022NaN40.763707-73.9539921183NaNNaN2
    mode513NaNNaN422NaN40.770513-73.988038380NaN40.734011-74.00550915693NaNNaN1
    \n", + "
    " + ], + "text/plain": [ + " tripduration starttime stoptime start station id \\\n", + "nan_count 0 0 0 0 \n", + "distinct_count 48 50 46 23 \n", + "dtype int64 object object int64 \n", + "min 128 NaN NaN 83 \n", + "mean 720.24 NaN NaN 572.3 \n", + "max 1957 NaN NaN 3002 \n", + "mode 513 NaN NaN 422 \n", + "\n", + " start station name start station latitude \\\n", + "nan_count 0 0 \n", + "distinct_count 23 23 \n", + "dtype object float64 \n", + "min NaN 40.683125 \n", + "mean NaN 40.73296 \n", + "max NaN 40.770513 \n", + "mode NaN 40.770513 \n", + "\n", + " start station longitude end station id end station name \\\n", + "nan_count 0 0 0 \n", + "distinct_count 23 28 28 \n", + "dtype float64 int64 object \n", + "min -74.015756 127 NaN \n", + "mean -73.98873 400.14 NaN \n", + "max -73.967844 2022 NaN \n", + "mode -73.988038 380 NaN \n", + "\n", + " end station latitude end station longitude bikeid usertype \\\n", + "nan_count 0 0 0 0 \n", + "distinct_count 28 28 48 0 \n", + "dtype float64 float64 int64 object \n", + "min 40.682166 -74.012342 14650 NaN \n", + "mean 40.730918 -73.990003 17363.68 NaN \n", + "max 40.763707 -73.95399 21183 NaN \n", + "mode 40.734011 -74.005509 15693 NaN \n", + "\n", + " birth year gender \n", + "nan_count 0 0 \n", + "distinct_count 17 0 \n", + "dtype object int64 \n", + "min NaN 0 \n", + "mean NaN 0.98 \n", + "max NaN 2 \n", + "mode NaN 1 " + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def col_stats(ser):\n", + " l = len(ser)\n", + " values = ser.value_counts()\n", + " base_stats = dict(\n", + " nan_count = ser.isna().sum(),\n", + " distinct_count = values[values == 1].sum(),\n", + " dtype = ser.dtype)\n", + " if pd.api.types.is_numeric_dtype(ser):\n", + " base_stats.update(dict(\n", + " min = ser.min(),\n", + " mean = ser.mean(),\n", + " max = ser.max(),\n", + " mode = ser.mode()[0]\n", + " ))\n", + " return base_stats\n", + "\n", + "def summary(df):\n", + " #we'll start with the first 50 rows as a smoke test\n", + " small_df = df.iloc[:50]\n", + " return pd.DataFrame(dict([[col, col_stats(small_df[col])] for col in small_df.columns]))\n", + "summary(df)" + ] + }, + { + "cell_type": "markdown", + "id": "e6d4592c-a71e-464f-9c53-2143025c3cdf", + "metadata": {}, + "source": [ + "# Now lets add distinct_percentage\n", + "we just want to divide distinct_count by length\n", + "but we have no decent way to insert that calculation, we have to rewrite the entire function" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "c7dc1ed8-1382-448c-bdec-e740052c6458", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    tripdurationstarttimestoptimestart station idstart station namestart station latitudestart station longitudeend station idend station nameend station latitudeend station longitudebikeidusertypebirth yeargender
    nan_count000000000000000
    distinct_count4850462323232328282828480170
    distinct_percentage0.961.00.920.460.460.460.460.560.560.560.560.960.00.340.0
    dtypeint64objectobjectint64objectfloat64float64int64objectfloat64float64int64objectobjectint64
    min128NaNNaN83NaN40.683125-74.015756127NaN40.682166-74.01234214650NaNNaN0
    mean720.24NaNNaN572.3NaN40.73296-73.98873400.14NaN40.730918-73.99000317363.68NaNNaN0.98
    max1957NaNNaN3002NaN40.770513-73.9678442022NaN40.763707-73.9539921183NaNNaN2
    mode513NaNNaN422NaN40.770513-73.988038380NaN40.734011-74.00550915693NaNNaN1
    \n", + "
    " + ], + "text/plain": [ + " tripduration starttime stoptime start station id \\\n", + "nan_count 0 0 0 0 \n", + "distinct_count 48 50 46 23 \n", + "distinct_percentage 0.96 1.0 0.92 0.46 \n", + "dtype int64 object object int64 \n", + "min 128 NaN NaN 83 \n", + "mean 720.24 NaN NaN 572.3 \n", + "max 1957 NaN NaN 3002 \n", + "mode 513 NaN NaN 422 \n", + "\n", + " start station name start station latitude \\\n", + "nan_count 0 0 \n", + "distinct_count 23 23 \n", + "distinct_percentage 0.46 0.46 \n", + "dtype object float64 \n", + "min NaN 40.683125 \n", + "mean NaN 40.73296 \n", + "max NaN 40.770513 \n", + "mode NaN 40.770513 \n", + "\n", + " start station longitude end station id end station name \\\n", + "nan_count 0 0 0 \n", + "distinct_count 23 28 28 \n", + "distinct_percentage 0.46 0.56 0.56 \n", + "dtype float64 int64 object \n", + "min -74.015756 127 NaN \n", + "mean -73.98873 400.14 NaN \n", + "max -73.967844 2022 NaN \n", + "mode -73.988038 380 NaN \n", + "\n", + " end station latitude end station longitude bikeid \\\n", + "nan_count 0 0 0 \n", + "distinct_count 28 28 48 \n", + "distinct_percentage 0.56 0.56 0.96 \n", + "dtype float64 float64 int64 \n", + "min 40.682166 -74.012342 14650 \n", + "mean 40.730918 -73.990003 17363.68 \n", + "max 40.763707 -73.95399 21183 \n", + "mode 40.734011 -74.005509 15693 \n", + "\n", + " usertype birth year gender \n", + "nan_count 0 0 0 \n", + "distinct_count 0 17 0 \n", + "distinct_percentage 0.0 0.34 0.0 \n", + "dtype object object int64 \n", + "min NaN NaN 0 \n", + "mean NaN NaN 0.98 \n", + "max NaN NaN 2 \n", + "mode NaN NaN 1 " + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def col_stats(ser):\n", + " \n", + " l = len(ser)\n", + " values = ser.value_counts()\n", + " distinct_count = values[values == 1].sum()\n", + "\n", + " base_stats = dict(\n", + " nan_count = ser.isna().sum(),\n", + " distinct_count = distinct_count,\n", + " distinct_percentage = distinct_count / l,\n", + " dtype = ser.dtype)\n", + " if pd.api.types.is_numeric_dtype(ser):\n", + " base_stats.update(dict(\n", + " min = ser.min(),\n", + " mean = ser.mean(),\n", + " max = ser.max(),\n", + " mode = ser.mode()[0]\n", + " ))\n", + " return base_stats\n", + "\n", + "def summary(df, size=50):\n", + " #we'll start with the first 50 rows as a smoke test\n", + " if size > 0:\n", + " small_df = df.iloc[:size]\n", + " else:\n", + " #use the whole thing\n", + " small_df = df\n", + " return pd.DataFrame(dict([[col, col_stats(small_df[col])] for col in small_df.columns]))\n", + "\n", + "summary(df)" + ] + }, + { + "cell_type": "markdown", + "id": "f480a73f-072c-4480-8d60-6c7929ed6c0f", + "metadata": {}, + "source": [ + "# What about individual stats functions\n", + "summary is modified to recieve a list of functions to apply in order" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "98b252c6-a5c2-4f5f-b7e2-2f046154327b", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    tripdurationstarttimestoptimestart station idstart station namestart station latitudestart station longitudeend station idend station nameend station latitudeend station longitudebikeidusertypebirth yeargender
    nan_count000000000000000
    distinct_count4850462323232328282828480170
    dtypeint64objectobjectint64objectfloat64float64int64objectfloat64float64int64objectobjectint64
    min128NaNNaN83NaN40.683125-74.015756127NaN40.682166-74.01234214650NaNNaN0
    mean720.24NaNNaN572.3NaN40.73296-73.98873400.14NaN40.730918-73.99000317363.68NaNNaN0.98
    max1957NaNNaN3002NaN40.770513-73.9678442022NaN40.763707-73.9539921183NaNNaN2
    mode513NaNNaN422NaN40.770513-73.988038380NaN40.734011-74.00550915693NaNNaN1
    distinct_percentage0.961.00.920.460.460.460.460.560.560.560.560.960.00.340.0
    \n", + "
    " + ], + "text/plain": [ + " tripduration starttime stoptime start station id \\\n", + "nan_count 0 0 0 0 \n", + "distinct_count 48 50 46 23 \n", + "dtype int64 object object int64 \n", + "min 128 NaN NaN 83 \n", + "mean 720.24 NaN NaN 572.3 \n", + "max 1957 NaN NaN 3002 \n", + "mode 513 NaN NaN 422 \n", + "distinct_percentage 0.96 1.0 0.92 0.46 \n", + "\n", + " start station name start station latitude \\\n", + "nan_count 0 0 \n", + "distinct_count 23 23 \n", + "dtype object float64 \n", + "min NaN 40.683125 \n", + "mean NaN 40.73296 \n", + "max NaN 40.770513 \n", + "mode NaN 40.770513 \n", + "distinct_percentage 0.46 0.46 \n", + "\n", + " start station longitude end station id end station name \\\n", + "nan_count 0 0 0 \n", + "distinct_count 23 28 28 \n", + "dtype float64 int64 object \n", + "min -74.015756 127 NaN \n", + "mean -73.98873 400.14 NaN \n", + "max -73.967844 2022 NaN \n", + "mode -73.988038 380 NaN \n", + "distinct_percentage 0.46 0.56 0.56 \n", + "\n", + " end station latitude end station longitude bikeid \\\n", + "nan_count 0 0 0 \n", + "distinct_count 28 28 48 \n", + "dtype float64 float64 int64 \n", + "min 40.682166 -74.012342 14650 \n", + "mean 40.730918 -73.990003 17363.68 \n", + "max 40.763707 -73.95399 21183 \n", + "mode 40.734011 -74.005509 15693 \n", + "distinct_percentage 0.56 0.56 0.96 \n", + "\n", + " usertype birth year gender \n", + "nan_count 0 0 0 \n", + "distinct_count 0 17 0 \n", + "dtype object object int64 \n", + "min NaN NaN 0 \n", + "mean NaN NaN 0.98 \n", + "max NaN NaN 2 \n", + "mode NaN NaN 1 \n", + "distinct_percentage 0.0 0.34 0.0 " + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "def base_col_stats(ser):\n", + " \n", + " l = len(ser)\n", + " values = ser.value_counts()\n", + " distinct_count = values[values == 1].sum()\n", + "\n", + " base_stats = dict(\n", + " nan_count = ser.isna().sum(),\n", + " distinct_count = distinct_count,\n", + " dtype = ser.dtype)\n", + " if pd.api.types.is_numeric_dtype(ser):\n", + " base_stats.update(dict(\n", + " min = ser.min(),\n", + " mean = ser.mean(),\n", + " max = ser.max(),\n", + " mode = ser.mode()[0]\n", + " ))\n", + " return base_stats\n", + "\n", + "def distinct_percentage(ser):\n", + " \n", + " l = len(ser)\n", + " values = ser.value_counts()\n", + " distinct_count = values[values == 1].sum()\n", + "\n", + " return dict(\n", + " distinct_percentage = distinct_count / l)\n", + " return base_stats\n", + "\n", + "def summary_funcs(df, funcs, size=50):\n", + " if size > 0:\n", + " small_df = df.iloc[:size]\n", + " else:\n", + " #use the whole thing\n", + " small_df = df\n", + " \n", + " facts_dict = {}\n", + " for col in small_df.columns:\n", + " facts = {}\n", + " for func in funcs:\n", + " facts.update(func(small_df[col]))\n", + " facts_dict[col] = facts\n", + " return pd.DataFrame(facts_dict)\n", + "\n", + "summary_funcs(df, [base_col_stats, distinct_percentage])" + ] + }, + { + "cell_type": "markdown", + "id": "064e381b-acd6-42fd-88e2-787286fae0ef", + "metadata": {}, + "source": [ + "# It works\n", + "But there's a problem. The call to value_counts is slow. watch the following timings with sampling turned off" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "d1b96a21-b721-460e-871d-3ae881fe8fdc", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "237 ms ± 26.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%timeit summary(df, -1)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "c4f95f09-f149-4934-92ae-5424ce3065f4", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "374 ms ± 7.99 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%timeit summary_funcs(df, [base_col_stats, distinct_percentage], -1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a23805fe-b8de-4ecf-bf68-27312a664943", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/requirements-ui-test.txt b/requirements-ui-test.txt new file mode 100644 index 000000000..8f4b3d595 --- /dev/null +++ b/requirements-ui-test.txt @@ -0,0 +1,465 @@ +# +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: +# +# pip-compile --extra=ui-test --output-file=requirements-ui-test.txt setup.py +# +aiofiles==22.1.0 + # via ypy-websocket +aiosqlite==0.19.0 + # via ypy-websocket +anyio==3.7.0 + # via + # jupyter-server + # starlette + # watchgod +appnope==0.1.3 + # via + # ipykernel + # ipython +argon2-cffi==21.3.0 + # via + # jupyter-server + # nbclassic + # notebook +argon2-cffi-bindings==21.2.0 + # via argon2-cffi +arrow==1.2.3 + # via isoduration +asttokens==2.2.1 + # via stack-data +attrs==23.1.0 + # via jsonschema +babel==2.12.1 + # via jupyterlab-server +backcall==0.2.0 + # via ipython +beautifulsoup4==4.12.2 + # via nbconvert +bleach==6.0.0 + # via nbconvert +cachetools==5.3.1 + # via solara +certifi==2023.5.7 + # via requests +cffi==1.15.1 + # via argon2-cffi-bindings +charset-normalizer==3.1.0 + # via requests +click==8.1.3 + # via + # rich-click + # solara + # uvicorn +comm==0.1.3 + # via ipykernel +debugpy==1.6.7 + # via ipykernel +decorator==5.1.1 + # via ipython +defusedxml==0.7.1 + # via nbconvert +entrypoints==0.4 + # via jupyter-client +exceptiongroup==1.1.1 + # via + # anyio + # pytest +executing==1.2.0 + # via stack-data +fastjsonschema==2.17.1 + # via nbformat +filelock==3.12.2 + # via solara +fqdn==1.5.1 + # via jsonschema +greenlet==2.0.1 + # via playwright +h11==0.14.0 + # via uvicorn +humanize==4.6.0 + # via solara +idna==3.4 + # via + # anyio + # jsonschema + # requests +iniconfig==2.0.0 + # via pytest +ipykernel==6.23.2 + # via + # ipywidgets + # nbclassic + # notebook + # solara +ipython==8.12.2 + # via + # ipykernel + # ipywidgets + # jupyterlab +ipython-genutils==0.2.0 + # via + # nbclassic + # notebook +ipyvue==1.9.2 + # via + # ipyvuetify + # solara +ipyvuetify==1.8.10 + # via solara +ipywidgets==8.0.6 + # via + # ipyaggrid (setup.py) + # ipyvue + # reacton + # solara +isoduration==20.11.0 + # via jsonschema +jedi==0.18.2 + # via ipython +jinja2==3.1.2 + # via + # jupyter-server + # jupyterlab + # jupyterlab-server + # nbclassic + # nbconvert + # notebook + # solara +json5==0.9.14 + # via jupyterlab-server +jsonpointer==2.3 + # via jsonschema +jsonschema[format-nongpl]==4.17.3 + # via + # jupyter-events + # jupyterlab-server + # nbformat +jupyter-client==7.4.1 + # via + # ipykernel + # jupyter-server + # nbclassic + # nbclient + # notebook + # solara + # voila +jupyter-core==5.3.1 + # via + # ipykernel + # jupyter-client + # jupyter-server + # jupyterlab + # nbclassic + # nbclient + # nbconvert + # nbformat + # notebook + # voila +jupyter-events==0.6.3 + # via jupyter-server-fileid +jupyter-server==1.24.0 + # via + # ipyaggrid (setup.py) + # jupyter-server-fileid + # jupyterlab + # jupyterlab-server + # nbclassic + # notebook-shim + # solara + # voila +jupyter-server-fileid==0.9.0 + # via jupyter-server-ydoc +jupyter-server-ydoc==0.8.0 + # via jupyterlab +jupyter-ydoc==0.2.4 + # via + # jupyter-server-ydoc + # jupyterlab +jupyterlab==3.6.3 + # via + # ipyaggrid (setup.py) + # solara +jupyterlab-pygments==0.2.2 + # via nbconvert +jupyterlab-server==2.23.0 + # via + # jupyterlab + # voila +jupyterlab-widgets==3.0.7 + # via ipywidgets +markdown==3.4.3 + # via + # pymdown-extensions + # solara +markdown-it-py==3.0.0 + # via + # mdit-py-plugins + # rich + # solara +markupsafe==2.0.1 + # via + # jinja2 + # nbconvert + # solara +matplotlib-inline==0.1.6 + # via + # ipykernel + # ipython +mdit-py-plugins==0.4.0 + # via solara +mdurl==0.1.2 + # via markdown-it-py +mistune==2.0.5 + # via nbconvert +nbclassic==1.0.0 + # via + # jupyterlab + # notebook +nbclient==0.7.4 + # via + # nbconvert + # voila +nbconvert==7.5.0 + # via + # jupyter-server + # nbclassic + # notebook + # solara + # voila +nbformat==5.9.0 + # via + # jupyter-server + # nbclassic + # nbclient + # nbconvert + # notebook + # solara +nest-asyncio==1.5.6 + # via + # ipykernel + # jupyter-client + # nbclassic + # notebook +notebook-shim==0.2.3 + # via nbclassic +numpy==1.24.3 + # via + # pandas + # solara +packaging==23.1 + # via + # ipykernel + # jupyter-server + # jupyterlab + # jupyterlab-server + # nbconvert + # pytest +pandas==2.0.2 + # via ipyaggrid (setup.py) +pandocfilters==1.5.0 + # via nbconvert +parso==0.8.3 + # via jedi +pexpect==4.8.0 + # via ipython +pickleshare==0.7.5 + # via ipython +pillow==9.5.0 + # via solara +pixelmatch==0.3.0 + # via solara +platformdirs==3.5.3 + # via jupyter-core +playwright==1.32.1 + # via + # ipyaggrid (setup.py) + # pytest-playwright + # solara +pluggy==1.0.0 + # via pytest +prometheus-client==0.17.0 + # via + # jupyter-server + # nbclassic + # notebook +prompt-toolkit==3.0.38 + # via ipython +psutil==5.9.5 + # via ipykernel +ptyprocess==0.7.0 + # via + # pexpect + # terminado +pure-eval==0.2.2 + # via stack-data +pycparser==2.21 + # via cffi +pydantic==1.10.9 + # via solara +pyee==9.0.4 + # via playwright +pygments==2.15.1 + # via + # ipython + # nbconvert + # rich + # solara +pymdown-extensions==10.0.1 + # via solara +pyrsistent==0.19.3 + # via jsonschema +pytest==7.3.2 + # via + # pytest-base-url + # pytest-playwright + # solara +pytest-base-url==2.0.0 + # via pytest-playwright +pytest-playwright==0.3.3 + # via solara +python-dateutil==2.8.2 + # via + # arrow + # jupyter-client + # pandas +python-json-logger==2.0.7 + # via jupyter-events +python-slugify==8.0.1 + # via pytest-playwright +pytz==2023.3 + # via pandas +pyyaml==6.0.1 + # via + # jupyter-events + # pymdown-extensions +pyzmq==25.1.0 + # via + # ipykernel + # jupyter-client + # jupyter-server + # nbclassic + # notebook +reacton==1.7.1 + # via solara +requests==2.31.0 + # via + # jupyterlab-server + # pytest-base-url + # solara +rfc3339-validator==0.1.4 + # via + # jsonschema + # jupyter-events +rfc3986-validator==0.1.1 + # via + # jsonschema + # jupyter-events +rich==13.4.2 + # via rich-click +rich-click==1.6.1 + # via solara +send2trash==1.8.2 + # via + # jupyter-server + # nbclassic + # notebook +simplejson==3.19.1 + # via ipyaggrid (setup.py) +six==1.16.0 + # via + # asttokens + # bleach + # python-dateutil + # rfc3339-validator +sniffio==1.3.0 + # via anyio +solara[pytest]==1.16.3 + # via ipyaggrid (setup.py) +soupsieve==2.4.1 + # via beautifulsoup4 +stack-data==0.6.2 + # via ipython +starlette==0.28.0 + # via solara +terminado==0.17.1 + # via + # jupyter-server + # nbclassic + # notebook +text-unidecode==1.3 + # via python-slugify +tinycss2==1.2.1 + # via nbconvert +tomli==2.0.1 + # via + # jupyterlab + # pytest +tornado==6.3.2 + # via + # ipykernel + # jupyter-client + # jupyter-server + # jupyterlab + # nbclassic + # notebook + # terminado +traitlets==5.9.0 + # via + # comm + # ipykernel + # ipython + # ipywidgets + # jupyter-client + # jupyter-core + # jupyter-events + # jupyter-server + # matplotlib-inline + # nbclassic + # nbclient + # nbconvert + # nbformat + # notebook + # voila +typing-extensions==4.6.3 + # via + # pydantic + # pyee + # reacton +tzdata==2023.3 + # via pandas +uri-template==1.2.0 + # via jsonschema +urllib3==2.0.3 + # via requests +uvicorn==0.22.0 + # via solara +voila==0.4.0 + # via solara +watchdog==3.0.0 + # via solara +watchgod==0.8.2 + # via solara +wcwidth==0.2.6 + # via prompt-toolkit +webcolors==1.13 + # via jsonschema +webencodings==0.5.1 + # via + # bleach + # tinycss2 +websocket-client==1.5.3 + # via jupyter-server +websockets==11.0.3 + # via + # solara + # voila +widgetsnbextension==4.0.7 + # via ipywidgets +y-py==0.5.9 + # via + # jupyter-ydoc + # ypy-websocket +ypy-websocket==0.8.2 + # via jupyter-server-ydoc + diff --git a/static/images/Buckaroo-screenshot.png b/static/images/Buckaroo-screenshot.png new file mode 100644 index 000000000..0476a79b9 Binary files /dev/null and b/static/images/Buckaroo-screenshot.png differ diff --git a/static/images/dcf-jupyter.png b/static/images/dcf-jupyter.png deleted file mode 100644 index 806e888f2..000000000 Binary files a/static/images/dcf-jupyter.png and /dev/null differ diff --git a/style/widget.css b/style/widget.css deleted file mode 100644 index 1b6558848..000000000 --- a/style/widget.css +++ /dev/null @@ -1,8 +0,0 @@ -.col-enum table { - margin-bottom:9px; -} - -.ag-theme-alpine-dark { - --ag-grid-size:3px; - --ag-list-item-height: 20px; - } diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ts/gridUtils.test.ts b/tests/ts/gridUtils.test.ts new file mode 100644 index 000000000..8be2ef2e5 --- /dev/null +++ b/tests/ts/gridUtils.test.ts @@ -0,0 +1,69 @@ +//import { add, multiply } from "../src/math"; + +import { extractSDFT, getHistoIndex, } from '../../js/components/DFViewerParts/gridUtils'; +import { DFData } from "../../js/components/DFViewerParts/DFWhole"; +import { getFloatFormatter } from '../../js/components/DFViewerParts/Displayer'; +import { ValueFormatterParams } from 'ag-grid-community'; + +describe("testing utility functions in gridUtils ", () => { + // mostly sanity checks to help develop gridUtils + +it("should test getFormater", () => { +// expect(getFormatter({displayer: 'string'})).toBe(stringFormatter) + // expect(getFormatter({displayer: 'obj'})).toBe(objFormatter); + + +}); + +it("should format floats with a consistently spaced decimal pont", + () => { + const floatFormatter = getFloatFormatter( + {'displayer':'float', 'min_fraction_digits':0, 'max_fraction_digits':3}) + const res1 = floatFormatter({'value': 1.997} as ValueFormatterParams); + expect(res1).toBe("1.997"); + const res2 = floatFormatter({'value': 1.000} as ValueFormatterParams); + expect(res2).toBe("1 "); + const res3 = floatFormatter({'value': 1} as ValueFormatterParams); + expect(res3).toBe("1 "); + const res4 = floatFormatter({'value': 31} as ValueFormatterParams); + expect(res4).toBe("31 "); + + const res5 = floatFormatter({'value': 1.5} as ValueFormatterParams); + expect(res5).toBe("1.5 "); + + } +) + it("should convert to expected format", () => { + const basicSDF:DFData = [ + {'index': 'histogram_bins', 'a':[2,3]}, + {'index': 'histogram_log_bins', 'a':[20,30], 'b': [10, 20] + }, + ]; + const expected = { + 'a': {'histogram_bins': [2,3], 'histogram_log_bins': [20, 30]}, + 'b': {'histogram_bins': [], 'histogram_log_bins': [10, 20]} + }; + const result = extractSDFT(basicSDF); + expect(result).toEqual(expected); + }); + it("color mapper should pick from ranges properly", () => { + /* +np.histogram([1, 2, 3, 4, 10, 20, 30, 40, 300, 300, 400, 500], bins=5) +( [ 8, 0, 2, 1, 1], +[ 1. , 100.8, 200.6, 300.4, 400.2, 500. ]) +The bottom matters for us, those are the endge + +this means that 8 values are between 1 and 100.8 and 2 values are between 200.6 and 300.4 + */ + const edges = [2, 4, 10, 30]; + expect(getHistoIndex(1, [])).toBe(0); + expect(getHistoIndex(1, edges)).toBe(0); + expect(getHistoIndex(3, edges)).toBe(1); + expect(getHistoIndex(5, edges)).toBe(2); + expect(getHistoIndex(10, edges)).toBe(2); + expect(getHistoIndex(11, edges)).toBe(3); + expect(getHistoIndex(11000, edges)).toBe(4); + + }); +}); + diff --git a/tests/ui/jupyter_test.py b/tests/ui/jupyter_test.py new file mode 100644 index 000000000..d1e310863 --- /dev/null +++ b/tests/ui/jupyter_test.py @@ -0,0 +1,44 @@ +import playwright.sync_api +from IPython.display import display + + +''' +def test_widget_aggrid(ipywidgets_runner, page_session: playwright.sync_api.Page, assert_solara_snapshot): + def kernel_code(): + import ipyaggrid + cars = [ + {"carName": "Chevelle", "origin": "US", "make": "Chevrolet", "price": 30415}, + {"carName": "Skylark 320", "origin": "US", "make": "Buick", "price": 21042}, + {"carName": "PL411", "origin": "Asia", "make": "Datsun", "price": 27676}, + ] + column_defs = [{"field": c} for c in cars[0]] + + grid_options = { + "columnDefs": column_defs, + } + g = ipyaggrid.Grid(grid_data=cars, grid_options=grid_options) + + display(g) + ipywidgets_runner(kernel_code) + cell = page_session.locator(".ag-root-wrapper >> text=Chevrolet") + cell.click() + cell.wait_for() + assert_solara_snapshot(page_session.locator(".ag-root-wrapper").screenshot()) +''' +def test_widget_buckaroo(ipywidgets_runner, page_session: playwright.sync_api.Page, assert_solara_snapshot): + def kernel_code(): + import buckaroo + import pandas as pd + df = pd.DataFrame({"carName": ["Chevelle", "Skylark", "PL411"], + "origin": ["US", "US", "asia"], + "make": ["Chevrolet", "Buick", "Datsun"] + }) + bw = buckaroo.BuckarooWidget(df) + display(bw) + ipywidgets_runner(kernel_code) + cell = page_session.locator(".df-viewer >> text=Chevrolet") + cell.click() + cell.wait_for() + page_session.locator(".df-viewer").screenshot() + #assert_solara_snapshot(page_session.locator(".df-viewer").screenshot()) + diff --git a/tests/ui/snapshots/tests/ui/jupyter_test.py/test_widget_buckaroo-jupyter_lab-chromium-darwin-reference.png b/tests/ui/snapshots/tests/ui/jupyter_test.py/test_widget_buckaroo-jupyter_lab-chromium-darwin-reference.png new file mode 100644 index 000000000..742519f4a Binary files /dev/null and b/tests/ui/snapshots/tests/ui/jupyter_test.py/test_widget_buckaroo-jupyter_lab-chromium-darwin-reference.png differ diff --git a/tests/ui/snapshots/tests/ui/jupyter_test.py/test_widget_buckaroo-solara-chromium-darwin-reference.png b/tests/ui/snapshots/tests/ui/jupyter_test.py/test_widget_buckaroo-solara-chromium-darwin-reference.png new file mode 100644 index 000000000..4643545b4 Binary files /dev/null and b/tests/ui/snapshots/tests/ui/jupyter_test.py/test_widget_buckaroo-solara-chromium-darwin-reference.png differ diff --git a/tests/ui/snapshots/tests/ui/jupyter_test.py/test_widget_buckaroo-voila-chromium-darwin-reference.png b/tests/ui/snapshots/tests/ui/jupyter_test.py/test_widget_buckaroo-voila-chromium-darwin-reference.png new file mode 100644 index 000000000..3df3dbe26 Binary files /dev/null and b/tests/ui/snapshots/tests/ui/jupyter_test.py/test_widget_buckaroo-voila-chromium-darwin-reference.png differ diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/analysis_management_test.py b/tests/unit/analysis_management_test.py new file mode 100644 index 000000000..8746284a3 --- /dev/null +++ b/tests/unit/analysis_management_test.py @@ -0,0 +1,198 @@ +import unittest + +from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import ( + ColAnalysis) + +from buckaroo.pluggable_analysis_framework.analysis_management import ( + AnalysisPipeline, DfStats, + #full_produce_summary_df, + produce_series_df) + +from buckaroo.pluggable_analysis_framework.safe_summary_df import (output_full_reproduce) + + +from buckaroo.customizations.analysis import (TypingStats, DefaultSummaryStats) +from .fixtures import (test_df, df, DistinctCount, Len, DistinctPer, word_only_df, + empty_df, empty_df_with_columns) + +class DumbTableHints(ColAnalysis): + provides_summary = [ + 'is_numeric', 'is_integer', 'min_digits', 'max_digits', 'histogram'] + + provides_defaults = { + 'is_numeric':False, 'is_integer':False, 'histogram':[]} + @staticmethod + def computed_summary(summary_dict): + return {'is_numeric':True, + 'is_integer':False, + 'histogram': []} + +class AlwaysErr(ColAnalysis): + provides_defaults = {'foo':0} + + @staticmethod + def computed_summary(summary_dict): + 1/0 + +class TestAnalysisPipeline(unittest.TestCase): + + def test_produce_series_df(self): + """just make sure this doesn't fail""" + + sdf, errs = produce_series_df( + test_df, [Len], 'test_df', debug=True) + ld = {'len':4} + #dict(**sdf) makes the types equal and leads to better error messages if there is a problem + assert dict(**sdf) == {'normal_int_series': ld, 'empty_na_ser': ld, 'float_nan_ser': ld, 'index':ld} + + sdf2, errs = produce_series_df( + test_df, [DistinctCount], 'test_df', debug=True) + assert dict(**sdf2) == { + 'normal_int_series': {'distinct_count': 4}, + 'index': {'distinct_count': 4}, + 'empty_na_ser': {'distinct_count':0}, 'float_nan_ser': {'distinct_count':2}} + + sdf3, errs = produce_series_df( + test_df, [DistinctCount, DistinctPer], 'test_df', debug=True) + assert dict(**sdf3) == { + 'normal_int_series': {'distinct_count': 4, 'distinct_per':0}, + 'index': {'distinct_count': 4, 'distinct_per':0}, + 'empty_na_ser': {'distinct_count': 0, 'distinct_per':0}, + 'float_nan_ser': {'distinct_count': 2, 'distinct_per':0}} + + def test_full_produce_summary_df(self): + """just make sure this doesn't fail""" + sdf, errs = AnalysisPipeline.full_produce_summary_df( + test_df, [DistinctCount, Len, DistinctPer], 'test_df', debug=True) + assert errs == {} + + def test_full_produce_summary_df_empy(self): + """just make sure this doesn't fail""" + + sdf, errs = AnalysisPipeline.full_produce_summary_df( + empty_df, [DistinctCount, Len, DistinctPer], 'test_df', debug=True) + assert errs == {} + + def test_full_produce_summary_df_empy2(self): + """just make sure this doesn't fail""" + + sdf, errs = AnalysisPipeline.full_produce_summary_df( + empty_df_with_columns, [DistinctCount, Len, DistinctPer], 'test_df', debug=True) + assert errs == {} + + def test_full_produce_summary_df_errs(self): + """just make sure this doesn't fail""" + single_col_df = test_df[['empty_na_ser']] + sdf, errs = AnalysisPipeline.full_produce_summary_df( + single_col_df, [AlwaysErr], 'test_df', debug=False) + + err_key = list(errs.keys())[0] + err_val = list(errs.values())[0] + assert err_key == ('index', 'computed_summary') + assert err_val[1] == AlwaysErr + #can't compare instances of Exception classes + # assert errs == { + # ('empty_na_ser', 'computed_summary'): (ZeroDivisionError('division by zero'), AlwaysErr)} + + def test_output_full_reproduce(self): + errs = { + ('empty_na_ser', 'computed_summary'): (ZeroDivisionError('division by zero'), AlwaysErr)} + output_full_reproduce(errs, {'bar':8}, 'testing_df') + + def test_pipeline_base(self): + ap = AnalysisPipeline([TypingStats, DefaultSummaryStats]) + #just verify that there are no errors + ap.process_df(df) + + def test_add_aobj(self): + ap = AnalysisPipeline([TypingStats, DefaultSummaryStats]) + class Foo(ColAnalysis): + provides_defaults = {'foo':0} + requires_summary = ['length'] + + @staticmethod + def computed_summary(summary): + return dict(foo=8) + assert ap.add_analysis(Foo) == (True, []) #verify no errors thrown + sdf, _unused_errs = ap.process_df(df) + self.assertEqual(sdf['tripduration']['foo'], 8) + + def test_add_buggy_aobj(self): + ap = AnalysisPipeline([TypingStats, DefaultSummaryStats]) + class Foo(ColAnalysis): + provides_defaults = {'foo':0} + requires_summary = ['length'] + + @staticmethod + def computed_summary(summary_dict): + 1/0 #throw an error + return dict(foo=8) + unit_test_results, errs = ap.add_analysis(Foo) + + assert unit_test_results is False + + def test_replace_aobj(self): + ap = AnalysisPipeline([TypingStats, DefaultSummaryStats]) + class Foo(ColAnalysis): + provides_defaults = {'foo':0} + requires_summary = ['length'] + + @staticmethod + def computed_summary(bar): + return dict(foo=8) + ap.add_analysis(Foo) + sdf, _unused_errs = ap.process_df(df) + self.assertEqual(sdf['tripduration']['foo'], 8) + #18 facts returned about tripduration + #FIXME + #self.assertEqual(len(sdf['tripduration']), 18) + #Create an updated Foo that returns 9 + class Foo(ColAnalysis): + provides_defaults = {'foo':0} + requires_summary = ['length'] + + @staticmethod + def computed_summary(bar): + return dict(foo=9) + ap.add_analysis(Foo) + sdf2, _unused_errs = ap.process_df(df) + self.assertEqual(sdf2['tripduration']['foo'], 9) + #still 18 facts returned about tripduration + #self.assertEqual(len(sdf2['tripduration']), 18) + #Create an updated Foo that returns 9 + + +class SometimesProvides(ColAnalysis): + provides_defaults = {'conditional_on_dtype':'xcvz'} + + summary_stats_display = ['conditional_on_dtype'] + + @staticmethod + def series_summary(ser, ser2): + import pandas as pd + is_numeric = pd.api.types.is_numeric_dtype(ser) + if is_numeric: + return dict(conditional_on_dtype=True) + return {} + +class TestDfStats(unittest.TestCase): + def test_dfstats_sometimes_present(self): + """many ColAnalysis objects are written such that they only + provide stats for certain dtypes. This used to cause + instantiation failures. This test verifies that there are no + stack traces. The alternative would be to have ColAnalyis + objects always return every key, even if NA. That's a less + natural style to write analyis code. + + Possible future improvement is to run through PERVERSE_DF and + verify that each ColAnalyis provides its specified value as + non NA at least once + + """ + #dfs = DfStats(word_only_df, [SometimesProvides]) + #ab = dfs.presentation_sdf + + #triggers a getter? + DfStats(word_only_df, [SometimesProvides]).sdf + + diff --git a/tests/unit/analysis_test.py b/tests/unit/analysis_test.py new file mode 100644 index 000000000..1863431f5 --- /dev/null +++ b/tests/unit/analysis_test.py @@ -0,0 +1,173 @@ +from datetime import datetime as dtdt +import numpy as np +import pandas as pd +from buckaroo.customizations.analysis import DefaultSummaryStats +from buckaroo.customizations.histogram import Histogram +from buckaroo.pluggable_analysis_framework.analysis_management import PERVERSE_DF + +def without(dct, *keys): + cleaned_result = dct.copy() + for k in keys: + cleaned_result = {i:cleaned_result[i] for i in cleaned_result if i!= k } + return cleaned_result + +text_ser = pd.Series(["foo", "bar", "baz"]) +datelike_ser = pd.Series([ + "2014-01-01 00:00:06", + "2014-01-01 00:00:38", + "2014-01-01 00:03:59" + +]) +datetime_ser = pd.Series([dtdt(2000, 1, 1), dtdt(2001, 1, 1), pd.NaT]) +all_nan_ser = pd.Series([np.nan, np.nan]) +int_ser = pd.Series([10, 30, -10, 33]) +fp_ser = pd.Series([33.2, 83.2, -1.0, 0]) + +nan_text_ser = pd.Series([np.nan, np.nan, 'y', 'y']) +nan_mixed_type_ser = pd.Series([np.nan, np.nan, 'y', 'y', 8.0]) +unhashable_ser = pd.Series([['a'], ['b']]) + +fifty_int_ser = pd.Series([ + 5, 1, 6, 8, 3, 5, 9, 2, 4, 2, 4, 4, 9, 3, 5, 1, 4, 2, 2, 9, 2, 5, + 3, 8, 3, 9, 4, 2, 5, 6, 2, 3, 8, 1, 1, 4, 5, 9, 6, 5, 6, 7, 6, 1, + 7, 5, 8, 7, 3, 1]) + + +all_sers = [ + text_ser, datelike_ser, all_nan_ser, + int_ser, fp_ser, nan_text_ser, nan_mixed_type_ser, unhashable_ser] + +def test_text_ser(): + DefaultSummaryStats.series_summary(nan_text_ser, nan_text_ser) + DefaultSummaryStats.series_summary(nan_mixed_type_ser, nan_mixed_type_ser) + +def test_unhashable(): + result = DefaultSummaryStats.series_summary(unhashable_ser, unhashable_ser) + #print(result) + cleaned_result = {i:result[i] for i in result if i!='value_counts'} + assert {'length': 2, 'nan_count': 0, + 'mode': ['a'], 'min': np.nan, 'max': np.nan} == cleaned_result + +def test_unhashable3(): + ser = pd.Series([{'a':1, 'b':2}, {'b':10, 'c': 5}]) + DefaultSummaryStats.series_summary(ser, ser) # 'nan_per' + +def test_default_summary_stats(): + for ser in all_sers: + print(DefaultSummaryStats.series_summary(ser, ser)) + +def test_datetime_histogram(): + series_result = Histogram.series_summary( + datetime_ser, datetime_ser) + assert series_result == {'histogram_args':{}} + + summary_result = Histogram.computed_summary( + dict(histogram_args={}, + length=3, + value_counts=pd.Series( + [1,1], + index=pd.DatetimeIndex([ + dtdt(2000, 1, 1), + dtdt(2001, 1, 1)])), + + min=dtdt(2000, 1, 1), + max=dtdt(2001, 1, 1), + is_numeric=False, + nan_per=.33 + )) + + assert { + 'histogram': [{'cat_pop': 33.0, + 'name': pd.Timestamp('2000-01-01 00:00:00')}, + {'cat_pop': 33.0, + 'name': pd.Timestamp('2001-01-01 00:00:00')}, + {'name': 'longtail', 'unique': 67.0}, + {'NA': 33.0, 'name': 'NA'} + ], + } == summary_result + +def test_numeric_histogram(): + assert {'a':[1,2,3]} == {'a':[1,2,3]} + series_result = Histogram.series_summary( + fifty_int_ser, fifty_int_ser) + + actual_histogram_args = series_result['histogram_args'] + + rest_ha = without(actual_histogram_args, 'meat_histogram', 'normalized_populations') + assert rest_ha == {'high_tail': 9.0, 'low_tail': 1.0} + + + expected_meat_histogram = [[7, 6, 0, 6, 0, 8, 5, 0, 3, 4], + [2. , 2.6, 3.2, 3.8, 4.4, 5. , 5.6, 6.2, 6.8, 7.3999999999999995, 8. ]] + meat_histogram = [x.tolist() for x in actual_histogram_args['meat_histogram']] + assert meat_histogram == expected_meat_histogram + Histogram.computed_summary( + {'histogram_args': actual_histogram_args, + 'value_counts': fifty_int_ser.value_counts(), + 'length':50, + 'min': 1, + 'max': 9, + 'is_numeric':True, + 'nan_per':0}) + +def test_perverse_on_histogram(): + + series_result = Histogram.series_summary( + PERVERSE_DF['all_false'], PERVERSE_DF['all_false']) + assert series_result == {'histogram_args':{}} + Histogram.computed_summary( + dict(histogram_args={}, + length=10, + value_counts=pd.Series( + [10], + index=[False]), + min=False, + max=False, + is_numeric=True, + nan_per=0 + )) + +def test_perverse_on_histogram2(): + + series_result = Histogram.series_summary( + PERVERSE_DF['UInt8None'], PERVERSE_DF['UInt8None']) + assert series_result == {'histogram_args':{}} + Histogram.computed_summary( + dict(histogram_args={}, + length=10, + value_counts=pd.Series( + [10], + index=[False]), + min=False, + max=False, + is_numeric=True, + nan_per=0 + )) + + + +def test_weird_grouper(): + """fails on + + File "/Users/paddy/buckaroo/buckaroo/customizations/analysis.py", line 86, in series_summary + value_counts = ser.value_counts() + ^^^^^^^^^^^^^^^^^^ + File "/Users/paddy/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/pandas/core/frame.py", line 7264, in value_counts + counts = self.groupby(subset, dropna=dropna, observed=False).grouper.size() + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/paddy/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/pandas/core/frame.py", line 8869, in groupby + return DataFrameGroupBy( + ^^^^^^^^^^^^^^^^^ + File "/Users/paddy/anaconda3/envs/buckaroo-dev-5/lib/python3.11/site-packages/pandas/core/groupby/groupby.py", line 1278, in __init__ + grouper, exclusions, obj = get_grouper( + # """ + # df = pd.DataFrame({'a':np.random.randint(1,50,200), 'b': np.random.randint(1,30,200)}) + # a_ser = df['a'].value_counts() + # b_ser = df['b'].value_counts() + # a_df = pd.DataFrame({ + # 'a': a_ser.index.values, 'a_counts': a_ser.values}) + # b_df = pd.DataFrame({ 'b': b_ser.index.values, 'a_counts': b_ser.values}) + # merged_df = pd.concat([a_df, b_df], axis=1) + + #ahh "a_counts" is repeated, hmmm + diff --git a/tests/unit/auto_clean_test.py b/tests/unit/auto_clean_test.py new file mode 100644 index 000000000..cfbcd6269 --- /dev/null +++ b/tests/unit/auto_clean_test.py @@ -0,0 +1,117 @@ + +import pandas as pd +from buckaroo.auto_clean import auto_clean as ac +from pandas import NA as NA +from numpy import nan +from pandas.testing import assert_series_equal + + +DATETIME_META = {'datetime': 0.75, 'datetime_error': 0.25, 'int': 0.25, 'int_error': 0.75, 'float': 0.25, 'float_error': 0.75, 'bool': 0, 'bool_error':1} + +INT_META = {'datetime': 0.0, 'datetime_error': 1.0, 'int': 0.75, 'int_error': 0.25, 'float': 0.75, 'float_error': 0.25, 'bool': 0.0, 'bool_error': 1.0} + +FULL_INT_META = {'datetime': 0.0, 'datetime_error': 0, 'int': 1, 'int_error': 0, 'float': 0, 'float_error': 0, 'bool': 0.0, 'bool_error': 0, 'exact_type': 'UInt32', 'general_type':'int'} + +FLOAT_META = {'datetime': 0.0, 'datetime_error': 1.0, 'int': 0.25, 'int_error': 0.75, 'float': 0.75, 'float_error': 0.25, 'bool': 0.0, 'bool_error': 1.0} + +STRING_META = {'datetime': 0.0, 'datetime_error': 1.0, 'int': 0.0, 'int_error': 1.0, 'float': 0.25, 'float_error': 0.75, 'bool': 0.0, 'bool_error': 1.0} + +DATETIME_EDGECASE_META = {'datetime': 1.0, 'datetime_error': 1.0, 'int': 0.0, 'int_error': 1.0, 'float': 0.0, 'float_error': 1, 'bool': 0.0, 'bool_error': 1.0} + +BOOL_META = {'bool': .6, 'bool_error': 0.4, + 'datetime': 0.0, 'datetime_error': 1.0, + 'float': 0.6, 'float_error': 0.4, + 'int': 0.6, 'int_error': 0.4} + + +MIXED_NUMERIC_META = {'bool': 0.0, 'bool_error': 1.0, + 'datetime': 0.0, 'datetime_error': 1.0, + 'float': (2/3), 'float_error': (1/3), + 'int': (2/3), 'int_error': (1/3)} + +def assign_values(d, new_values): + d2 = d.copy() + d2.update(new_values) + return d2 + +DATETIME_DTYPE_META = assign_values(ac.default_type_dict, + {'general_type':'datetime', 'exact_type': 'datetime64[ns]'}) + +MIXED_EXACT = assign_values(ac.default_type_dict, {'exact_type': 'Int64', 'general_type': 'int', 'int':1}) + +ONLY_NANS_META = {'datetime': 0, 'datetime_error': 0, 'int': 0, 'int_error': 0, 'float': 0, 'float_error': 0, 'bool': 0, 'bool_error': 0} + +# WEIRD_INT = {'bool': 0.0, 'bool_error': 1.0, +# 'datetime': 0.0, 'datetime_error': 1.0, +# 'float': (2/3), 'float_error': (1/3), +# 'int': (2/3), 'int_error': (1/3)} + + +def test_get_typing_metadata(): + if int(pd.__version__[0]) < 2: + return + # assert WEIRD_INT == ac.get_typing_metadata(pd.Series([5, 2, 3.1, None, NA])) + assert INT_META == ac.get_typing_metadata(pd.Series(['181', '182', '183', 'a'])) + assert FLOAT_META == ac.get_typing_metadata(pd.Series(['181.1', '182.2', '183', 'a'])) + assert STRING_META == ac.get_typing_metadata(pd.Series(['181.1', 'b', 'c', 'a'])) + assert DATETIME_META == ac.get_typing_metadata(pd.Series(['1981-05-11', '1982-05-11', '1983', 'a'])) + assert DATETIME_EDGECASE_META == ac.get_typing_metadata(pd.Series(['00:01.6', '00:01.6', '00:01.6', None])) + assert DATETIME_DTYPE_META == ac.get_typing_metadata(pd.date_range('2010-01-01', '2010-01-31')) + + assert MIXED_EXACT == ac.get_typing_metadata(pd.Series([NA, 2, 3, NA, NA], dtype='Int64')) + assert MIXED_NUMERIC_META == ac.get_typing_metadata(pd.Series(['a', 2.0, 3.0, None, NA])) + + #there are still problems here, the code isn't properly distinguishing bools from ints and bools + assert BOOL_META == ac.get_typing_metadata(pd.Series(['a', 'b', False, True, False])) + assert FULL_INT_META == ac.get_typing_metadata(pd.Series([5]*10, dtype='UInt32')) + + # what does the typing code do on "dtype" objects + ac.get_typing_metadata(pd.Series([pd.Series([5], dtype='UInt32').dtype]*3)) + + + + #only nans + assert ac.get_typing_metadata(pd.Series([None])) == ONLY_NANS_META + assert ac.get_typing_metadata(pd.Series([NA, NA])) == ONLY_NANS_META + assert ac.get_typing_metadata(pd.Series([])) == ONLY_NANS_META + assert ac.get_typing_metadata(pd.Series([nan, NA])) == ONLY_NANS_META + #assert ac.get_typing_metadata(pd.Series([nan, nan])) == ONLY_NANS_META + +def test_recommend_type(): + assert ac.recommend_type(DATETIME_META) == 'datetime' + assert ac.recommend_type(INT_META) == 'int' + assert ac.recommend_type(FLOAT_META) == 'float' + assert ac.recommend_type(STRING_META) == 'string' + assert ac.recommend_type(DATETIME_DTYPE_META) == 'datetime' + + WEIRD_INT_SER = pd.Series(['a', 2, 3, 4, None]) + assert ac.recommend_type( ac.get_typing_metadata(WEIRD_INT_SER)) == 'int' + +def test_smart_to_int(): + assert_series_equal( + ac.smart_to_int(pd.Series(['a', 2, 3, 4, None])), + pd.Series([NA, 2,3,4, NA], dtype='UInt8')) + + + # this should throw an error + # assert_series_equal( + # ac.smart_to_int(pd.Series(['a', 2.0, 3.1, None, NA])), + # pd.Series([NA, 2,3,4, NA], dtype='UInt8')) + + +def test_coerce_series(): + assert_series_equal( + ac.coerce_series(pd.Series(['a', 2, 3, 4, None]), 'int'), + pd.Series([NA, 2,3,4, NA], dtype='UInt8')) + + assert_series_equal( + ac.coerce_series(pd.Series(['a', False, True, None]), 'bool'), + pd.Series([NA, False, True, NA], dtype='boolean')) + + assert_series_equal( + ac.coerce_series(pd.Series(['a', 2.0, 3.0, None, NA]), 'int'), + pd.Series([NA, 2, 3, NA, NA], dtype='UInt8')) + + assert_series_equal( + ac.coerce_series(pd.Series(['a', 2.0, 3.1, None, NA]), 'float'), + pd.Series([nan, 2, 3.1, nan, nan], dtype='float')) diff --git a/tests/unit/basic_widget_test.py b/tests/unit/basic_widget_test.py new file mode 100644 index 000000000..e2a08f839 --- /dev/null +++ b/tests/unit/basic_widget_test.py @@ -0,0 +1,80 @@ +import pandas as pd +from IPython.display import display +from buckaroo.buckaroo_widget import BuckarooWidget +from buckaroo.pluggable_analysis_framework.analysis_management import PERVERSE_DF +from .fixtures import (word_only_df) + +simple_df = pd.DataFrame({'int_col':[1, 2, 3], 'str_col':['a', 'b', 'c']}) + + + +def test_basic_instantiation(): + w = BuckarooWidget(simple_df) + assert w.df_meta['total_rows'] == 3 + +def test_perverse_instantiation(): + w = BuckarooWidget(PERVERSE_DF) + assert w.df_meta['total_rows'] == 10 + +def test_word_only_instantiation(): + BuckarooWidget(word_only_df) + +def test_basic_display(): + df = simple_df + w = BuckarooWidget(df) + display(w) + +def test_debug_true(): + df = simple_df + w = BuckarooWidget(df, debug=True) + display(w) + +def xtest_interpreter(): + #df = pd.read_csv('./examples/data/2014-01-citibike-tripdata.csv') + + w = BuckarooWidget(simple_df, auto_clean=True) + assert w.operation_results['generated_py_code'] == '''def clean(df): + df['int_col'] = smart_to_int(df['int_col']) + df['str_col'] = df['str_col'].fillna(value='').astype('string').replace('', None) + return df''' + + temp_ops = w.operations.copy() + temp_ops.append([{"symbol":"dropcol"},{"symbol":"df"},"str_col"]) + w.operations = temp_ops + + tdf = w.operation_results['transformed_df'] + assert w.operation_results['transform_error'] is False + field_names = [ f['col_name'] for f in tdf['dfviewer_config']['column_config'] ] + assert 'str_col' not in field_names + assert w.operation_results['generated_py_code'] == """def clean(df): + df['int_col'] = smart_to_int(df['int_col']) + df['str_col'] = df['str_col'].fillna(value='').astype('string').replace('', None) + df.drop('str_col', axis=1, inplace=True) + return df""" + +def atest_symbol_meta(): + """verifies that a symbol with a meta key can be added and + properly interpretted. This should probably be a lower level + parser test + + """ + + df = pd.read_csv('./docs/examples/data/2014-01-citibike-tripdata.csv') + w = BuckarooWidget(df) + assert w.operation_results['generated_py_code'] == '# instantiation, unused' + w.operations = [[{"symbol":"dropcol", "meta":{}},{"symbol":"df"},"starttime"]] + + tdf = w.operation_results['transformed_df'] + assert w.operation_results['transform_error'] is False + field_names = [ f['name'] for f in tdf['schema']['fields'] ] + assert 'starttime' not in field_names + + +def xtest_interpreter_errors(): + w = BuckarooWidget(simple_df) + w.operations = [ + [{"symbol":"dropcol"},{"symbol":"df"},"int_col"], + #dropping the same column will result in an error + [{"symbol":"dropcol"},{"symbol":"df"},"int_col"]] + assert w.operation_results['transform_error'] == '''"['int_col'] not found in axis"''' + diff --git a/tests/unit/commands/__init__.py b/tests/unit/commands/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/commands/cleaning_command_test.py b/tests/unit/commands/cleaning_command_test.py new file mode 100644 index 000000000..03ed63c57 --- /dev/null +++ b/tests/unit/commands/cleaning_command_test.py @@ -0,0 +1,58 @@ +import pandas as pd +import numpy as np + +from buckaroo.jlisp.lispy import s +from .command_tests import assert_to_py_same_transform_df +from buckaroo.auto_clean.cleaning_commands import ( + to_bool, to_datetime, to_int, to_float, + to_string) + +same = assert_to_py_same_transform_df + +def test_to_bool(): + base_df = pd.DataFrame({ + 'mixed_bool':[True, False, 0, 1, pd.NA], 'b': [pd.NA] * 5}) + + output_df = same(to_bool, [[s('to_bool'), s('df'), "mixed_bool"]], base_df) + assert isinstance(output_df['mixed_bool'].dtype , pd.core.arrays.boolean.BooleanDtype) + assert output_df['mixed_bool'].to_list() == [True, False, False, True, pd.NA] + +def test_to_datetime(): + base_df = pd.DataFrame({ + 'mixed_dates':['2021-02-03', '2022-05-07', 'asdf', pd.NA], 'b': [pd.NA] * 4}) + + output_df = same(to_datetime, [[s('to_datetime'), s('df'), "mixed_dates"]], base_df) + assert pd.api.types.is_datetime64_any_dtype(output_df['mixed_dates']) + assert output_df['mixed_dates'].to_list() == [ + pd.Timestamp('2021-02-03'), pd.Timestamp('2022-05-07'), pd.NaT, pd.NaT] + +def test_to_int(): + base_df = pd.DataFrame({ + 'mixed_ints':['3', '4', '3.', 'asdf', pd.NA], 'b': [pd.NA] * 5}) + + output_df = same(to_int, [[s('to_int'), s('df'), "mixed_ints"]], base_df) + pd.testing.assert_series_equal( + output_df['mixed_ints'], + pd.Series([3,4,3, pd.NA, pd.NA], dtype='UInt8', name='mixed_ints')) + +def test_to_float(): + base_df = pd.DataFrame({ + 'mixed_floats':['3', '4', '7.1', 'asdf', np.nan], 'b': [pd.NA] * 5}) + + output_df = same(to_float, [[s('to_float'), s('df'), "mixed_floats"]], base_df) + pd.testing.assert_series_equal( + output_df['mixed_floats'], + pd.Series([3, 4, 7.1, np.nan, np.nan], dtype='float64', name='mixed_floats')) + +def _test_to_string(): + """ + skipping for now. works on my machine against pandas 2.1.1 fails in CI against pandas 1.3.5 + """ + base_df = pd.DataFrame({ + 'mixed_strings':['a', 'b', pd.NA], 'b': [pd.NA] * 3}) + + output_df = same(to_string, [[s('to_string'), s('df'), "mixed_strings"]], base_df) + pd.testing.assert_series_equal( + output_df['mixed_strings'], + pd.Series(['a', 'b', pd.NA], dtype='string', name='mixed_strings')) + diff --git a/tests/unit/commands/command_tests.py b/tests/unit/commands/command_tests.py new file mode 100644 index 000000000..f7fbffa6a --- /dev/null +++ b/tests/unit/commands/command_tests.py @@ -0,0 +1,71 @@ +import pandas as pd +import numpy as np + +from buckaroo.jlisp.lispy import s +from buckaroo.jlisp.configure_utils import configure_buckaroo +from buckaroo.customizations.all_transforms import ( + DropCol, FillNA, OneHot, GroupBy, reindex ) + + +def result_from_exec(code_str, df_input): + CODE_PREAMBLE = "import pandas as pd\nimport numpy as np\n" + CODE_PREAMBLE += "from buckaroo.auto_clean.auto_clean import smart_to_int\n" + RETRIEVE_RESULT_STR = '\n__ret_closure[0] = clean(__test_df)' + outer_scope_result = [0] + full_code_str = CODE_PREAMBLE + code_str + RETRIEVE_RESULT_STR + try: + exec(full_code_str, {'__test_df':df_input, '__ret_closure':outer_scope_result}) + except: + print("Failure calling exec with following code string") + print(full_code_str) + #print(full_code_str) + return outer_scope_result[0] + +def assert_to_py_same_transform_df(command_kls, operations, test_df): + _a, _b, transform_df, transform_to_py = configure_buckaroo([command_kls]) + tdf_ops = [{'symbol': 'begin'}] + tdf_ops.extend(operations) + tdf = transform_df(tdf_ops, test_df.copy()) + py_code_string = transform_to_py(operations) + + edf = result_from_exec(py_code_string, test_df.copy()) + pd.testing.assert_frame_equal(tdf, edf) + return tdf +same = assert_to_py_same_transform_df + +def test_fillna(): + base_df = pd.DataFrame({ + 'a':[1,2,3,4,5], 'b': [pd.NA, 2, 2, 2, pd.NA]}) + + output_df = same(FillNA, [[s('fillna'), s('df'), "b", 100]], base_df) + assert output_df.iloc[0]['b'] == 100 + +def test_dropcol(): + base_df = pd.DataFrame({ + 'a':np.random.randint(1, 10, 5), 'b':np.random.randint(1, 10, 5), + 'c':np.random.randint(1, 10, 5)}) + + same(DropCol, [[s('dropcol'), s('df'), "a"]], base_df) + +def test_onehot(): + base_df = pd.DataFrame({ + 'a':['cc', 'cc', 'dd', 'ee', 'ff'], 'b': [pd.NA, 2, 2, 2, pd.NA]}) + + output_df = same(OneHot, [[s('onehot'), s('df'), "a"]], base_df) + assert output_df.columns.to_list() == ['b', 'cc', 'dd', 'ee', 'ff'] + +def test_groupby(): + base_df = pd.DataFrame({ + 'a':['cc', 'cc', 'cc', 'ee', 'ff'], 'b': [pd.NA, 2, 2, 2, pd.NA]}) + + output_df = same(GroupBy, [[s('groupby'), s('df'), "a", {'b':'count'}]], base_df) + expected_output = pd.DataFrame({'b': {'cc': 2, 'ee': 1, 'ff': 0}}, + index=pd.Index(['cc', 'ee', 'ff'], dtype='object', name='a')) + pd.testing.assert_frame_equal(output_df, expected_output) + +def test_reindex(): + base_df = pd.DataFrame({ + 'a':['ca', 'cb', 'cd', 'ee', 'ff'], 'b': [pd.NA, 2, 2, 2, pd.NA]}) + + output_df = same(reindex, [[s('reindex'), s('df'), "a"]], base_df) + assert output_df.index.to_list() == ['ca', 'cb', 'cd', 'ee', 'ff'] diff --git a/tests/unit/commands/polars_command_tests.py b/tests/unit/commands/polars_command_tests.py new file mode 100644 index 000000000..81b9602a7 --- /dev/null +++ b/tests/unit/commands/polars_command_tests.py @@ -0,0 +1,85 @@ +from collections import OrderedDict +import polars as pl +import numpy as np + +from buckaroo.jlisp.lispy import s +from polars.testing import assert_frame_equal +from buckaroo.jlisp.configure_utils import configure_buckaroo +from buckaroo.customizations.polars_commands import ( + DropCol, FillNA, GroupBy #, OneHot, GroupBy, reindex +) + + +def result_from_exec(code_str, df_input): + CODE_PREAMBLE = "import polars as pl\nimport numpy as np\n" + CODE_PREAMBLE += "from buckaroo.auto_clean.auto_clean import smart_to_int\n" + RETRIEVE_RESULT_STR = '\n__ret_closure[0] = clean(__test_df)' + outer_scope_result = [0] + full_code_str = CODE_PREAMBLE + code_str + RETRIEVE_RESULT_STR + try: + exec(full_code_str, {'__test_df':df_input, '__ret_closure':outer_scope_result}) + except: + print("Failure calling exec with following code string") + print(full_code_str) + print(full_code_str) + return outer_scope_result[0] + +def assert_to_py_same_transform_df(command_kls, operations, test_df): + _a, _b, transform_df, transform_to_py = configure_buckaroo([command_kls]) + tdf_ops = [{'symbol': 'begin'}] + tdf_ops.extend(operations) + tdf = transform_df(tdf_ops, test_df.clone()) + py_code_string = transform_to_py(operations) + + edf = result_from_exec(py_code_string, test_df.clone()) + assert_frame_equal(tdf, edf) + return tdf +same = assert_to_py_same_transform_df + +def test_fillna(): + base_df = pl.DataFrame({ + 'a':[1,2,3,4,5], 'b': [None, 2, 2, 2, None]}) + + output_df = same(FillNA, [[s('fillna'), s('df'), "b", 100]], base_df) + assert output_df[0, 'b'] == 100 + +def test_dropcol(): + base_df = pl.DataFrame({ + 'a':np.random.randint(1, 10, 5), 'b':np.random.randint(1, 10, 5), + 'c':np.random.randint(1, 10, 5)}) + + same(DropCol, [[s('dropcol'), s('df'), "a"]], base_df) + +def test_groupby(): + base_df = pl.DataFrame({ + 'a':['cc', 'cc', 'cc', 'ee', 'ff'], 'b': [None, 2, 2, 2, None], + 'c': [10, 20, 30, 40, 50]}) + + output_df = same(GroupBy, [[s('groupby'), s('df'), "a", {'b':'count', 'c': 'sum'}]], base_df) + expected = pl.DataFrame( + {'a': ["ff", "ee", "cc"], + 'b(count)': [ 0, 1, 2], + 'c(sum)': [ 50, 40, 60]}, + schema=OrderedDict([('a', pl.Utf8), ('b(count)', pl.UInt32), ('c(sum)', pl.Int64)]) + ) + assert_frame_equal(output_df, expected) + + +''' + + +def test_onehot(): + base_df = pd.DataFrame({ + 'a':['cc', 'cc', 'dd', 'ee', 'ff'], 'b': [pd.NA, 2, 2, 2, pd.NA]}) + + output_df = same(OneHot, [[s('onehot'), s('df'), "a"]], base_df) + assert output_df.columns.to_list() == ['b', 'cc', 'dd', 'ee', 'ff'] + + +def test_reindex(): + base_df = pd.DataFrame({ + 'a':['ca', 'cb', 'cd', 'ee', 'ff'], 'b': [pd.NA, 2, 2, 2, pd.NA]}) + + output_df = same(reindex, [[s('reindex'), s('df'), "a"]], base_df) + assert output_df.index.to_list() == ['ca', 'cb', 'cd', 'ee', 'ff'] +''' diff --git a/tests/unit/dataflow/__init__.py b/tests/unit/dataflow/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/dataflow/autocleaning_test.py b/tests/unit/dataflow/autocleaning_test.py new file mode 100644 index 000000000..fa161ed19 --- /dev/null +++ b/tests/unit/dataflow/autocleaning_test.py @@ -0,0 +1,166 @@ +import polars as pl +from buckaroo.customizations.polars_analysis import ( + VCAnalysis, PLCleaningStats, BasicAnalysis) +from buckaroo.pluggable_analysis_framework.polars_analysis_management import PlDfStats +from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import (ColAnalysis) +from buckaroo.dataflow.autocleaning import merge_ops, format_ops, make_origs, AutocleaningConfig +from buckaroo.polars_buckaroo import PolarsAutocleaning +from buckaroo.customizations.polars_commands import ( + PlSafeInt, DropCol, FillNA, GroupBy, NoOp +) + + + +dirty_df = pl.DataFrame({ + 'a':[10, 20, 30, 40, 10, 20.3, 5, None, None, None], + 'b':["3", "4", "a", "5", "5", "b", "b", None, None, None]}) + + +def make_default_analysis(**kwargs): + class DefaultAnalysis(ColAnalysis): + requires_summary = [] + provides_defaults = kwargs + return DefaultAnalysis + +class CleaningGenOps(ColAnalysis): + requires_summary = ['int_parse_fail', 'int_parse'] + provides_defaults = {'cleaning_ops': []} + + int_parse_threshhold = .3 + @classmethod + def computed_summary(kls, column_metadata): + if column_metadata['int_parse'] > kls.int_parse_threshhold: + return {'cleaning_ops': [{'symbol': 'safe_int', 'meta':{'auto_clean': True}}, {'symbol': 'df'}]} + else: + return {'cleaning_ops': []} + + +def test_cleaning_stats(): + dfs = PlDfStats(dirty_df, [VCAnalysis, PLCleaningStats, BasicAnalysis]) + + # "3", "4", "5", "5" 4 out of 10 + assert dfs.sdf['b']['int_parse'] == 0.4 + assert dfs.sdf['b']['int_parse_fail'] == 0.6 + + +SAFE_INT_TOKEN = [{'symbol': 'safe_int', 'meta':{'auto_clean': True}}, {'symbol': 'df'}] +def test_ops_gen(): + + dfs = PlDfStats(dirty_df, [make_default_analysis(int_parse=.4, int_parse_fail=.6), + CleaningGenOps], debug=True) + assert dfs.sdf['b']['cleaning_ops'] == SAFE_INT_TOKEN + dfs = PlDfStats(dirty_df, [make_default_analysis(int_parse=.2, int_parse_fail=.8), + CleaningGenOps]) + assert dfs.sdf['b']['cleaning_ops'] == [] + + + +def test_format_ops(): + column_meta = { + 'a': {'cleaning_ops':SAFE_INT_TOKEN }, + 'b': {'cleaning_ops': [ + {'symbol': 'replace_dirty', 'meta':{'auto_clean': True}}, + {'symbol': 'df'}, '\n', None]}} + + expected_ops = [ + [{'symbol': 'safe_int', 'meta':{'auto_clean': True}}, {'symbol': 'df'}, 'a'], + [{'symbol': 'replace_dirty', 'meta':{'auto_clean': True}}, {'symbol': 'df'}, 'b', '\n', None]] + assert format_ops(column_meta) == expected_ops + + +def test_merge_ops(): + existing_ops = [ + [{'symbol': 'safe_int', 'meta':{'auto_clean': True}}, 'a'], + [{'symbol': 'usergen'}, 'foo_column'] + ] + + cleaning_ops = [ + [{'symbol': 'new_cleaning', 'meta':{'auto_clean': True}}, 'a']] + + expected_merged = [ + [{'symbol': 'new_cleaning', 'meta':{'auto_clean': True}}, 'a'], + [{'symbol': 'usergen'}, 'foo_column'] + ] + print( merge_ops(existing_ops, cleaning_ops)) + print("@"*80) + assert merge_ops(existing_ops, cleaning_ops) == expected_merged + +class ACConf(AutocleaningConfig): + autocleaning_analysis_klasses = [VCAnalysis, PLCleaningStats, BasicAnalysis, CleaningGenOps] + command_klasses = [PlSafeInt, DropCol, FillNA, GroupBy, NoOp] + name="default" + + + +def test_handle_user_ops(): + + ac = PolarsAutocleaning([ACConf]) + df = pl.DataFrame({'a': [10, 20, 30]}) + cleaning_result = ac.handle_ops_and_clean(df, cleaning_method='default', existing_operations=[]) + cleaned_df, cleaning_sd, generated_code, merged_operations = cleaning_result + assert merged_operations == [ + [{'symbol': 'safe_int', 'meta':{'auto_clean': True}}, {'symbol': 'df'}, 'a']] + + existing_ops = [ + [{'symbol': 'old_safe_int', 'meta':{'auto_clean': True}}, {'symbol': 'df'}, 'a']] + cleaning_result2 = ac.handle_ops_and_clean( + df, cleaning_method='default', existing_operations=existing_ops) + cleaned_df, cleaning_sd, generated_code, merged_operations2 = cleaning_result2 + assert merged_operations2 == [ + [{'symbol': 'safe_int', 'meta':{'auto_clean': True}}, {'symbol': 'df'}, 'a']] + + user_ops = [ + [{'symbol': 'noop'}, {'symbol': 'df'}, 'b']] + cleaning_result3 = ac.handle_ops_and_clean( + df, cleaning_method='default', existing_operations=user_ops) + cleaned_df, cleaning_sd, generated_code, merged_operations3 = cleaning_result3 + assert merged_operations3 == [ + [{'symbol': 'safe_int', 'meta':{'auto_clean': True}}, {'symbol': 'df'}, 'a'], + [{'symbol': 'noop'}, {'symbol': 'df'}, 'b'] + ] + + +def desired_test_make_origs(): + # I can't make this work in a sensible way because it is not + # possible to quickly run comparisons against different dtype + # columns, and object dtypes are serverely limited + df_a = pl.DataFrame({'a': [10, 20, 30, 40], 'b': [1, 2, 3, 4]}) + df_b = pl.DataFrame({'a': [10, 20, 0, 40], 'b': [1, 2, 3, 4]}) + + expected = pl.DataFrame( + [pl.Series("a", [ 10, 20, 0, 40], dtype=pl.Int64), + pl.Series("a_orig", [None, None, 30, None], dtype=pl.Int64), + pl.Series("b", [ 1, 2, 3, 4], dtype=pl.Int64), + pl.Series("b_orig", [None, None, None, None], dtype=pl.Int64)]) + + assert make_origs(df_a, df_b).to_dicts() == expected.to_dicts() + +def test_make_origs_different_dtype(): + raw = pl.DataFrame({'a': [30, "40"]}) + cleaned = pl.DataFrame({'a': [30, 40]}) + expected = pl.DataFrame({ + 'a': [30, 40], + 'a_orig': [30, "40"]}) + assert make_origs(raw, cleaned).to_dicts() == expected.to_dicts() + +def test_handle_clean_df(): + ac = PolarsAutocleaning([ACConf]) + df = pl.DataFrame({'a': ["30", "40"]}) + cleaning_result = ac.handle_ops_and_clean(df, cleaning_method='default', existing_operations=[]) + cleaned_df, cleaning_sd, generated_code, merged_operations = cleaning_result + expected = pl.DataFrame({ + 'a': [30, 40], + 'a_orig': ["30", "40"]}) + assert cleaned_df.to_dicts() == expected.to_dicts() + +EXPECTED_GEN_CODE = """def clean(df): + df = df.with_columns(pl.col('a').cast(pl.Int64, strict=False)) + return df""" + +def test_autoclean_codegen(): + ac = PolarsAutocleaning([ACConf]) + df = pl.DataFrame({'a': ["30", "40"]}) + cleaning_result = ac.handle_ops_and_clean(df, cleaning_method='default', existing_operations=[]) + cleaned_df, cleaning_sd, generated_code, merged_operations = cleaning_result + + assert generated_code == EXPECTED_GEN_CODE diff --git a/tests/unit/dataflow/customizable_dataflow_test.py b/tests/unit/dataflow/customizable_dataflow_test.py new file mode 100644 index 000000000..197153bcc --- /dev/null +++ b/tests/unit/dataflow/customizable_dataflow_test.py @@ -0,0 +1,204 @@ +import numpy as np +import pandas as pd +import pytest +from ..fixtures import (DistinctCount) +from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import (ColAnalysis) +from buckaroo.dataflow.dataflow import CustomizableDataflow, StylingAnalysis +from buckaroo.buckaroo_widget import BuckarooWidget + + +EMPTY_DF_JSON = { + 'dfviewer_config': { + 'pinned_rows': [], + 'column_config': []}, + 'data': []} + +BASIC_DF = pd.DataFrame({'a': [10, 20, 20], 'b':['foo', 'bar', 'baz']}) +BASIC_DF_JSON_DATA = [{'index':0, 'a':10, 'b':'foo'}, + {'index':1, 'a':20, 'b':'bar'}, + {'index':2, 'a':20, 'b':'baz'}] +DFVIEWER_CONFIG_DEFAULT = { + 'pinned_rows': [], + 'column_config': [ + {'col_name':'index', 'displayer_args': {'displayer': 'obj'}}, + {'col_name':'a', 'displayer_args': {'displayer': 'obj'}}, + {'col_name':'b', 'displayer_args': {'displayer': 'obj'}}], + 'component_config': {}, + 'extra_grid_config': {}, +} + +def test_widget_instatiation(): + dfc = CustomizableDataflow(BASIC_DF) + assert dfc.widget_args_tuple[1] is BASIC_DF + assert dfc.df_data_dict['main'] == BASIC_DF_JSON_DATA + assert dfc.df_display_args['main']['df_viewer_config'] == DFVIEWER_CONFIG_DEFAULT + +def test_custom_dataflow(): + + class IntStyling(StylingAnalysis): + provides_defaults = {} + @staticmethod + def style_column(col, sd): + return {'col_name':col, 'displayer_args': {'displayer': 'int'}} + + df_display_name = "int_styles" + data_key = "main" + summary_stats_key= '555555555' + + + class TwoStyleDFC(CustomizableDataflow): + analysis_klasses = [StylingAnalysis, IntStyling] + #analysis_klasses = [IntStyling] + + cdfc = TwoStyleDFC(BASIC_DF) + assert cdfc.widget_args_tuple[1] is BASIC_DF + assert cdfc.df_display_args['main']['df_viewer_config'] == DFVIEWER_CONFIG_DEFAULT + DFVIEWER_CONFIG_INT = { + 'pinned_rows': [], + 'column_config': [ + {'col_name':'index', 'displayer_args': {'displayer': 'int'}}, + {'col_name':'a', 'displayer_args': {'displayer': 'int'}}, + {'col_name':'b', 'displayer_args': {'displayer': 'int'}}], + 'component_config': {}, + 'extra_grid_config': {}, + } + + assert cdfc.df_display_args['int_styles']['df_viewer_config'] == DFVIEWER_CONFIG_INT + + + +def test_custom_summary_stats(): + class DCDFC(CustomizableDataflow): + analysis_klasses = [DistinctCount, StylingAnalysis] + + dc_dfc = DCDFC(BASIC_DF) + + summary_sd = dc_dfc.widget_args_tuple[2] + print(summary_sd) + print("^"*80) + assert summary_sd == {'index': {'distinct_count': 3}, + 'a': {'distinct_count':2}, 'b': {'distinct_count':3}} + assert list(summary_sd.keys()) == ['index', 'a', 'b'] + +SENTINEL_DF = pd.DataFrame({'sent_int_col':[11, 22, 33], 'sent_str_col':['ka', 'b', 'c']}) + + +class PostProcessingAnalysis(ColAnalysis): + provides_defaults = {} + post_processing_method = "post1" + + @classmethod + def post_process_df(kls, cleaned_df): + return [SENTINEL_DF, {'sent_int_col': {'sentinel_prop':5}}] + + +def test_custom_post_processing(): + class PostDCFC(CustomizableDataflow): + analysis_klasses = [PostProcessingAnalysis, StylingAnalysis] + + p_dfc = PostDCFC(BASIC_DF) + + assert p_dfc.buckaroo_options['post_processing'] == ['', 'post1'] + assert p_dfc.post_processing_method == '' + p_dfc.post_processing_method = 'post1' + + assert p_dfc.processed_df is SENTINEL_DF + +class AlwaysFailAnalysis(ColAnalysis): + provides_defaults = {} + + @staticmethod + def computed_summary(foo): + 1/0 +def test_error_analysis(): + class ErrorCustomDataflow(CustomizableDataflow): + analysis_klasses = [AlwaysFailAnalysis] + + ErrorCustomDataflow(BASIC_DF) + #basically asserting that it doesn't throw an error + with pytest.raises(Exception): + ErrorCustomDataflow(BASIC_DF, debug=True) + +class AlwaysFailPostProcessingAnalysis(ColAnalysis): + provides_defaults = {} + post_processing_method = "always_fail" + + @classmethod + def post_process_df(kls, cleaned_df): + 1/0 + + +def test_error_post_processing(): + class ErrorCFC(CustomizableDataflow): + analysis_klasses = [AlwaysFailPostProcessingAnalysis, StylingAnalysis] + + e_dfc = ErrorCFC(BASIC_DF) + + assert e_dfc.buckaroo_options['post_processing'] == ['', 'always_fail'] + e_dfc.post_processing_method = 'always_fail' + assert e_dfc.processed_df.values == [["division by zero"]] + +def test_column_config_override_widget(): + ROWS = 200 + typed_df = pd.DataFrame( + {'int_col': [1] * ROWS, + 'float_col': [.5] * ROWS, + "str_col": ["foobar"]* ROWS}) + bw2 = BuckarooWidget( + typed_df, + column_config_overrides={ + 'float_col': + {'displayer_args': { 'displayer': 'integer', 'min_digits': 3, 'max_digits': 5 }}}) + float_col_config = bw2.df_display_args['main']['df_viewer_config']['column_config'][2] + assert float_col_config == {'col_name': 'float_col', 'displayer_args': { 'displayer': 'integer', 'min_digits': 3, 'max_digits': 5 }} + + + +def test_pinned_rows_override_widget(): + ROWS = 200 + typed_df = pd.DataFrame( + {'int_col': [1] * ROWS, + 'float_col': [.5] * ROWS, + "str_col": ["foobar"]* ROWS}) + HIST_ROW = {'primary_key_val': 'histogram', 'displayer_args': { 'displayer': 'histogram' }} + bw2 = BuckarooWidget(typed_df, pinned_rows=[HIST_ROW]) + pinned_rows = bw2.df_display_args['main']['df_viewer_config']['pinned_rows'] + assert pinned_rows[0] == HIST_ROW + + + +class TransposeProcessing(ColAnalysis): + provides_defaults = {} + @classmethod + def post_process_df(kls, df): + return [df.T, {}] + post_processing_method = "transpose" + + +def test_transpose_error(): + ROWS = 5 + typed_df = pd.DataFrame( + {'int_col': [1] * ROWS, + 'float_col': [.5] * ROWS, + "str_col": ["foobar"]* ROWS}) + + base_a_klasses = BuckarooWidget.analysis_klasses.copy() + base_a_klasses.extend([TransposeProcessing]) + + class VCBuckarooWidget(BuckarooWidget): + analysis_klasses = base_a_klasses + + vcb = VCBuckarooWidget(typed_df, debug=False) + temp_buckaroo_state = vcb.buckaroo_state.copy() + temp_buckaroo_state['post_processing'] = 'transpose' + vcb.buckaroo_state = temp_buckaroo_state + assert vcb.processed_df.values.tolist() == [ + [1, 1, 1, 1, 1], + [0.5, 0.5, 0.5, 0.5, 0.5], + ['foobar', 'foobar', 'foobar', 'foobar', 'foobar']] +def test_sample(): + big_df = pd.DataFrame({'a': np.arange(105_000)}) + bw = CustomizableDataflow(big_df) + assert len(bw.processed_df) == 100_000 + print(list(bw.df_data_dict.keys())) + assert len(bw.df_data_dict['main']) == 10_000 diff --git a/tests/unit/dataflow/dataflow_polars_test.py b/tests/unit/dataflow/dataflow_polars_test.py new file mode 100644 index 000000000..4b298448e --- /dev/null +++ b/tests/unit/dataflow/dataflow_polars_test.py @@ -0,0 +1,221 @@ +from buckaroo.dataflow.dataflow import StylingAnalysis +from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import (ColAnalysis) +from buckaroo.polars_buckaroo import PolarsBuckarooWidget +import polars as pl +import numpy as np + +simple_df = pl.DataFrame({'int_col':[1, 2, 3], 'str_col':['a', 'b', 'c']}) +BASIC_DF_JSON_DATA = [{'index':0, 'a':10, 'b':'foo'}, + {'index':1, 'a':20, 'b':'bar'}, + {'index':2, 'a':20, 'b':'baz'}] + +BASIC_DF = pl.DataFrame({'a': [10, 20, 20], 'b':['foo', 'bar', 'baz']}) + + +DFVIEWER_CONFIG_DEFAULT = { + 'pinned_rows': [], + 'column_config': [ + {'col_name':'index', 'displayer_args': {'displayer': 'obj'}}, + {'col_name':'a', 'displayer_args': {'displayer': 'obj'}}, + {'col_name':'b', 'displayer_args': {'displayer': 'obj'}}], + 'component_config' : {}, + 'extra_grid_config': {}, +} + + +class BasicStyling(StylingAnalysis): + provides_defaults = {} + df_display_name = "basic" + + +def test_widget_instatiation(): + dfc = PolarsBuckarooWidget(BASIC_DF) + #the BasicStyling is simple and predictable, it writes to 'basic' which nothing else should + dfc.add_analysis(BasicStyling) + + assert dfc.widget_args_tuple[1] is BASIC_DF + assert dfc.df_data_dict['main'] == BASIC_DF_JSON_DATA + + actual_column_config = dfc.df_display_args['basic']['df_viewer_config']['column_config'] + expected_column_config = DFVIEWER_CONFIG_DEFAULT['column_config'] + + #this test is brittle because styling is rapidly changing in development + assert actual_column_config == expected_column_config + +def test_custom_dataflow(): + """Tests that a styling method can be added BuckarooWidget and + that it properly modifies column_config. This Styling analysis + should be identical between polars and pandas + + """ + class IntStyling(StylingAnalysis): + @staticmethod + def style_column(col, sd): + return {'col_name':col, 'displayer_args': {'displayer': 'int'}} + + df_display_name = "int_styles" + data_key = "main" + summary_stats_key= '555555555' + + + class TwoStyleDFC(PolarsBuckarooWidget): + analysis_klasses = [StylingAnalysis, IntStyling] + + cdfc = TwoStyleDFC(BASIC_DF) + assert cdfc.widget_args_tuple[1] is BASIC_DF + assert cdfc.df_display_args['main']['df_viewer_config'] == DFVIEWER_CONFIG_DEFAULT + DFVIEWER_CONFIG_INT = { + 'pinned_rows': [], + 'column_config': [ + {'col_name':'index', 'displayer_args': {'displayer': 'obj'}}, + {'col_name':'a', 'displayer_args': {'displayer': 'int'}}, + {'col_name':'b', 'displayer_args': {'displayer': 'int'}}], + 'component_config' : {}, + 'extra_grid_config': {}, + } + + assert cdfc.df_display_args['int_styles']['df_viewer_config'] == DFVIEWER_CONFIG_INT + + +SENTINEL_DF = pl.DataFrame({'sent_int_col':[11, 22, 33], 'sent_str_col':['ka', 'b', 'c']}) + + +class PostProcessingAnalysis(ColAnalysis): + provides_defaults = {} + post_processing_method = "post1" + + @classmethod + def post_process_df(kls, cleaned_df): + return [SENTINEL_DF, {'sent_int_col': {'sentinel_prop':5}}] + + +def test_custom_post_processing(): + """This test demonstrates that a post processing method can be + added to BuckarooWidget through an analysis class. It further + checks that BuckarooWidget responds to changes in buckaroo_state + that activate the actual post_processing function + + """ + class PostDCFC(PolarsBuckarooWidget): + analysis_klasses = [PostProcessingAnalysis, StylingAnalysis] + + p_dfc = PostDCFC(BASIC_DF) + + assert p_dfc.buckaroo_options['post_processing'] == ['', 'post1'] + assert p_dfc.buckaroo_state['post_processing'] == '' + + temp_buckaroo_state = p_dfc.buckaroo_state.copy() + temp_buckaroo_state['post_processing'] = 'post1' + p_dfc.buckaroo_state = temp_buckaroo_state + + assert p_dfc.processed_df is SENTINEL_DF + + +class TransposeProcessing(ColAnalysis): + provides_defaults = {} + @classmethod + def post_process_df(kls, df): + return [df.transpose(), {}] + post_processing_method = "transpose" + + +def test_transpose_error(): + ROWS = 5 + typed_df = pl.DataFrame( + {'int_col': [1] * ROWS, + 'float_col': [.5] * ROWS, + "str_col": ["foobar"]* ROWS}) + + base_a_klasses = PolarsBuckarooWidget.analysis_klasses.copy() + base_a_klasses.extend([TransposeProcessing]) + + class VCBuckarooWidget(PolarsBuckarooWidget): + analysis_klasses = base_a_klasses + + vcb = VCBuckarooWidget(typed_df, debug=False) + assert type(vcb.processed_df) == pl.DataFrame + assert vcb.processed_df.to_numpy().tolist() ==[ + [1, 0.5, 'foobar'], + [1, 0.5, 'foobar'], + [1, 0.5, 'foobar'], + [1, 0.5, 'foobar'], + [1, 0.5, 'foobar']] + + temp_buckaroo_state = vcb.buckaroo_state.copy() + temp_buckaroo_state['post_processing'] = 'transpose' + vcb.buckaroo_state = temp_buckaroo_state + assert type(vcb.processed_df) == pl.DataFrame + #note that Polars doesn'transpose to objects, but to strings instead + assert vcb.processed_df.to_numpy().tolist() == [ + ['1', '1', '1', '1', '1'], + ['0.5', '0.5', '0.5', '0.5', '0.5'], + ['foobar', 'foobar', 'foobar', 'foobar', 'foobar']] + + +class AlwaysErrorPostProcessing(ColAnalysis): + provides_defaults = {} + @classmethod + def post_process_df(kls, df): + 1/0 + post_processing_method = "always_error" + +def test_always_error_post_processing(): + ROWS = 5 + typed_df = pl.DataFrame( + {'int_col': [1] * ROWS, + 'float_col': [.5] * ROWS, + "str_col": ["foobar"]* ROWS}) + bw = PolarsBuckarooWidget(typed_df, debug=False) + + bw.add_analysis(AlwaysErrorPostProcessing) + + temp_buckaroo_state = bw.buckaroo_state.copy() + temp_buckaroo_state['post_processing'] = 'always_error' + bw.buckaroo_state = temp_buckaroo_state + + print(bw.processed_df.to_numpy().tolist()) + assert bw.processed_df.to_numpy().tolist() == [['division by zero']] + +ROWS = 5 +typed_df = pl.DataFrame( + {'int_col': [1] * ROWS, + 'float_col': [.5] * ROWS, + "str_col": ["foobar"]* ROWS}) + +EXPECTED_OVERRIDE = {'color_map_config': {'color_rule': 'color_from_column', 'col_name': 'Volume_colors'}} +class ColumnConfigOverride(ColAnalysis): + provides_defaults = {} + @classmethod + def post_process_df(kls, df): + return [df, { + 'int_col':{ + 'column_config_override': EXPECTED_OVERRIDE}}] + post_processing_method = "override" + +def test_column_config_override(): + + bw = PolarsBuckarooWidget(typed_df, debug=False) + + bw.add_analysis(ColumnConfigOverride) + + assert 'column_config_override' not in bw.merged_sd['int_col'] + cc_initial = bw.df_display_args['main']['df_viewer_config']['column_config'] + int_cc_initial = cc_initial[1] + assert int_cc_initial['col_name'] == 'int_col' #make sure we found the right row + assert 'color_map_config' not in int_cc_initial + + temp_buckaroo_state = bw.buckaroo_state.copy() + temp_buckaroo_state['post_processing'] = 'override' + bw.buckaroo_state = temp_buckaroo_state + + assert bw.merged_sd['int_col']['column_config_override'] == EXPECTED_OVERRIDE + cc_after = bw.df_display_args['main']['df_viewer_config']['column_config'] + int_cc_after = cc_after[1] + assert int_cc_after['col_name'] == 'int_col' #make sure we found the right row + assert int_cc_after['color_map_config'] == EXPECTED_OVERRIDE['color_map_config'] + +def test_sample(): + big_df = pl.DataFrame({'a': np.arange(30_000)}) + bw = PolarsBuckarooWidget(big_df) + assert len(bw.processed_df) == len(big_df) + assert len(bw.df_data_dict['main']) == 10_000 diff --git a/tests/unit/dataflow/dataflow_test.py b/tests/unit/dataflow/dataflow_test.py new file mode 100644 index 000000000..36c1d1a65 --- /dev/null +++ b/tests/unit/dataflow/dataflow_test.py @@ -0,0 +1,210 @@ +import sys +import pandas as pd +from buckaroo.dataflow.dataflow import DataFlow +from buckaroo.dataflow import dataflow as dft +from buckaroo.dataflow.autocleaning import SENTINEL_DF_1, SENTINEL_DF_2 + +simple_df = pd.DataFrame({'int_col':[1, 2, 3], 'str_col':['a', 'b', 'c']}) + + +def test_dataflow_operating_df(): + d_flow = DataFlow(simple_df) + d_flow.raw_df = simple_df + assert d_flow.sampled_df is simple_df + d_flow.sample_method = "first" + assert len(d_flow.sampled_df) == 1 + d_flow.sample_method = "default" + assert d_flow.sampled_df is simple_df + + +def test_dataflow_cleaned(): + d_flow = DataFlow(simple_df) + assert d_flow.cleaned_df is simple_df + d_flow.existing_operations = ["one"] + assert d_flow.cleaned_df is SENTINEL_DF_1 + d_flow.cleaning_method = "one op" + assert d_flow.cleaned_df is SENTINEL_DF_2 + +def test_dataflow_processed(): + + d_flow = DataFlow(simple_df) + assert d_flow.processed_df is simple_df + #processed is currently a no-op, so I'm skipping actual tests for now + +def test_summary_sd(): + d_flow = DataFlow(simple_df) + assert d_flow.summary_sd == {'index': {}, 'int_col': {}, 'str_col': {}} + d_flow.analysis_klasses = "foo" + d_flow.cleaning_method = "one op" + assert d_flow.summary_sd == {'some-col': {'foo':8}} + +def test_merged_sd(): + d_flow = DataFlow(simple_df) + assert d_flow.merged_sd == {'index': {}, 'int_col': {}, 'str_col': {}} + d_flow.analysis_klasses = "foo" + d_flow.cleaning_method = "one op" + assert d_flow.summary_sd == {'some-col': {'foo':8}} + assert d_flow.merged_sd == {'some-col': {'foo':8}} + + +def test_column_config(): + basic_df = pd.DataFrame({'a': [10, 20, 30], 'b':['foo', 'bar', 'baz']}) + d_flow = DataFlow(basic_df) + _unused, df, merged_sd = d_flow.widget_args_tuple + + #dfviewer_config = d_flow.df_display_args['main'] + assert merged_sd == {'index' : {}, 'a': {}, 'b': {}} + +def test_merge_sds(): + + sd_base = { + 'Volume' : { + 'a':10, + 'column_config_override': { + 'color_map_config' : {'color_rule': 'color_from_column', + 'col_name': 'Volume_colors'}}}, + 'Volume_colors' : { + 'a': 30, + 'column_config_override': { 'displayer': 'hidden'}}, + 'only_in_base': {'f':77}} + + sd_second = { + 'Volume' : { + 'a': 999, + 'b': "foo", + 'column_config_override': { + 'tooltip_config': {'tooltip_type' : 'summary_series'}}}, + 'Volume_colors' : { + 'd':111, + 'column_config_override': { 'displayer': 'string'}}, + 'completely_new_column': {'k':90}} + + expected = { + 'Volume' : { + 'a': 999, + 'b': "foo", + 'column_config_override': { + 'color_map_config' : {'color_rule': 'color_from_column', + 'col_name': 'Volume_colors'}, + #note that column_config_override is merged, not just overwritten + 'tooltip_config': {'tooltip_type' : 'summary_series'}}}, + 'Volume_colors' : { + 'a': 30, + 'd': 111, + #sd_second has a different value for 'displayer then sd_base + 'column_config_override': { 'displayer': 'string'}}, + #only in base, needs to be present + 'only_in_base': {'f':77}, + #only found in second should show up here + 'completely_new_column': {'k':90}} + + result = dft.merge_sds(sd_base, sd_second) + + assert result == expected + + +def test_merge_column_config(): + overrides = { + 'bar' : {'displayer_args': {'displayer': 'int'}}, + 'foo' : {'color_map_config' : {'color_rule': 'color_from_column', + 'col_name': 'Volume_colors'}}} + + computed_column_config = [ + {'col_name':'index', 'displayer_args': {'displayer': 'obj'}}, + {'col_name':'foo', 'displayer_args': {'displayer': 'obj'}}, + {'col_name':'bar', 'displayer_args': {'displayer': 'obj'}}] + + merged = dft.merge_column_config( + computed_column_config, overrides) + + expected = [ + {'col_name':'index', 'displayer_args': {'displayer': 'obj'}}, + {'col_name':'foo', 'displayer_args': {'displayer': 'obj'}, + 'color_map_config' : {'color_rule': 'color_from_column', + 'col_name': 'Volume_colors'}}, + {'col_name':'bar', 'displayer_args': {'displayer': 'int'}}] + assert expected == merged + + +def test_merge_column_config_hide(): + overrides = { + 'bar' : {'merge_rule':'hidden'}} + computed_column_config = [ + + {'col_name':'index', 'displayer_args': {'displayer': 'obj'}}, + {'col_name':'foo', 'displayer_args': {'displayer': 'obj'}}, + {'col_name':'bar', 'displayer_args': {'displayer': 'obj'}}] + + merged = dft.merge_column_config( + computed_column_config, overrides) + + expected = [ + {'col_name':'index', 'displayer_args': {'displayer': 'obj'}}, + {'col_name':'foo', 'displayer_args': {'displayer': 'obj'}}] + + assert expected == merged + + + +class ExpectedFail(Exception): + pass + + + +def tb_depth(tb, depth=1): + """ + returns the depth of a traceback + """ + if tb.tb_next is None: + return depth + else: + return tb_depth(tb.tb_next, depth+1) + +def exc_depth(exc): + """ + returns the depth of an exception + """ + return tb_depth(exc.__traceback__) + + + +def test_exc_depth(): + def level_3(): + 1/0 + def level_2(): + level_3() + def level_1(): + level_2() + try: + level_1() + except Exception: + l1_exc = sys.exc_info()[1] + assert tb_depth(l1_exc.__traceback__) == 4 + + try: + level_2() + except Exception: + l2_exc = sys.exc_info()[1] + assert tb_depth(l2_exc.__traceback__) == 3 + + +class SampleFailDataFlow(DataFlow): + def _compute_sampled_df(self, raw_df, sample_method): + raise ExpectedFail("_compute_sampled_df") + +def test_error_handling(): + """ + + when something fails in DataFlow, we get stack traces of traitlets.change + there should be shorter stacktraces, the errors should be written to "data_flow_errors" + + I get 300 line stacktraces, aint nobody got time for that + https://pymotw.com/3/traceback/ + """ + try: + SampleFailDataFlow(simple_df) + except Exception: + sf_exc = sys.exc_info()[1] #eption() + print(exc_depth(sf_exc)) + + assert exc_depth(sf_exc) < 7 diff --git a/tests/unit/dataflow/widget_extension_tests.py b/tests/unit/dataflow/widget_extension_tests.py new file mode 100644 index 000000000..58025c502 --- /dev/null +++ b/tests/unit/dataflow/widget_extension_tests.py @@ -0,0 +1,92 @@ +import pytest +from buckaroo.dataflow.widget_extension_utils import ( + find_most_specific_styling, analysis_extend, get_styling_analysis, + InvalidArgumentException, + configure_buckaroo) +from buckaroo.customizations.styling import (DefaultMainStyling, obj_) +from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import (ColAnalysis) +from buckaroo.buckaroo_widget import BuckarooWidget + +def foo(): + print(analysis_extend, get_styling_analysis, configure_buckaroo) + +class Custom_1(ColAnalysis): + pass + +class CustomStyling(DefaultMainStyling): + pinned_rows= ['foo'] + +class ExtendedCustomStyling(CustomStyling): + pinned_rows= ['foo', 'bar'] + +def test_find_most_specific_styling(): + # Custom_1 doesn't extend DefaultMain, it looses + assert find_most_specific_styling([Custom_1, DefaultMainStyling]) == DefaultMainStyling + #order shouldn't matter + assert find_most_specific_styling([DefaultMainStyling, Custom_1]) == DefaultMainStyling + + assert find_most_specific_styling([CustomStyling, DefaultMainStyling]) == CustomStyling + assert find_most_specific_styling([DefaultMainStyling, CustomStyling]) == CustomStyling + + assert find_most_specific_styling([ExtendedCustomStyling, CustomStyling, DefaultMainStyling]) == ExtendedCustomStyling + assert find_most_specific_styling([DefaultMainStyling, CustomStyling, ExtendedCustomStyling]) == ExtendedCustomStyling + +def test_analysis_extend(): + #Custom_1 doesn't extend BaseStylingKlass, so it won't work + assert [Custom_1] == analysis_extend(BuckarooWidget, analysis_klasses=[Custom_1]) + + base_len = len(BuckarooWidget.analysis_klasses) + extra_kls_lst = analysis_extend(BuckarooWidget, extra_analysis_klasses=[Custom_1]) + assert Custom_1 in extra_kls_lst + assert len(extra_kls_lst) == (base_len) + 1 + + with pytest.raises(InvalidArgumentException): + analysis_extend(BuckarooWidget, extra_analysis_klasses=[Custom_1], analysis_klasses=[ExtendedCustomStyling]) + + +foo_row = obj_('foo') + +def test_get_styling_analysis(): + base_pinned_row_len = len(DefaultMainStyling.pinned_rows) + ExtraFooStyling = get_styling_analysis( + DefaultMainStyling, + extra_pinned_rows=[foo_row]) + + assert foo_row in ExtraFooStyling.pinned_rows + assert len(ExtraFooStyling.pinned_rows) == (base_pinned_row_len + 1) + + ReplacePinnedStyling = get_styling_analysis(DefaultMainStyling, pinned_rows=[foo_row]) + assert ReplacePinnedStyling.pinned_rows == [foo_row] + with pytest.raises(InvalidArgumentException): + get_styling_analysis(DefaultMainStyling, extra_pinned_rows=[1], pinned_rows=[2]) + +def test_configure_buckaroo_extra(): + + ExtraBuckaroo = configure_buckaroo( + BuckarooWidget, extra_pinned_rows=[foo_row], extra_analysis_klasses=[Custom_1]) + SyntheticStyling = [kls for kls in ExtraBuckaroo.analysis_klasses if kls.__name__ == 'SyntheticStyling'][0] + + base_pinned_row_len = len(DefaultMainStyling.pinned_rows) + + assert foo_row in SyntheticStyling.pinned_rows + assert len(SyntheticStyling.pinned_rows) == (base_pinned_row_len + 1) + + assert Custom_1 in ExtraBuckaroo.analysis_klasses + + +def test_configure_buckaroo_replace(): + + ReplaceBuckaroo = configure_buckaroo( + BuckarooWidget, analysis_klasses=[Custom_1, DefaultMainStyling], + pinned_rows=[foo_row]) + + #bad things will happen if there isn't a Styling, but I'd caveat empetor for that + + SyntheticStyling = [kls for kls in ReplaceBuckaroo.analysis_klasses if kls.__name__ == 'SyntheticStyling'][0] + + assert SyntheticStyling.pinned_rows == [foo_row] + + assert len(ReplaceBuckaroo.analysis_klasses) == 3 + assert Custom_1 in ReplaceBuckaroo.analysis_klasses + + diff --git a/tests/unit/experimental_pydantic.py b/tests/unit/experimental_pydantic.py new file mode 100644 index 000000000..b68ababf1 --- /dev/null +++ b/tests/unit/experimental_pydantic.py @@ -0,0 +1,236 @@ +import time +import json +import pytest +from pydantic import ValidationError +import pandas as pd +import numpy as np +from buckaroo.serialization_utils import df_to_obj +import pydantic + +# import typing +# if typing.TYPE_CHECKING: +# from . import AnyComponent + + +from typing import Optional, List, Literal, Union, Dict + + + +Formatter = Union[Literal["histogram"], Literal["float"], Literal["string"]] + + +class HistogramFormatterConfig(pydantic.BaseModel): + formatter = Literal["histogram"] + #histograms aren't formatters they are renderers, but that's a frontend problem + +class IntegerFormatterConfig(pydantic.BaseModel): + formatter: Literal["integer"] + min_digits:int + max_digits:int + +FormatterConfig = Union[HistogramFormatterConfig, IntegerFormatterConfig] + +class PinnedRowConfig(pydantic.BaseModel): + primary_key_val : str #value of primary key for this row + displayer_args: FormatterConfig + +class ColumnConfig(pydantic.BaseModel): + col_name : str #value of primary key for this row + displayer_args: FormatterConfig + +class DFViewerConfig(pydantic.BaseModel): + pinned_rows: List[PinnedRowConfig] + column_config: List[ColumnConfig] + + #//extra_config: Dict[str, Any] #height, width + +class DfViewer(pydantic.BaseModel): + df:pd.DataFrame + summary_stats_df: pd.DataFrame + dfviewer_config: DFViewerConfig + + +""" +DFViewer is responsible for picking through summary_stats_df and ordering rows in the order of pinned_rows + +Otherwise, there would be two specification of the order of summary_stats_rows +---- + +When actually displaying summary_stats, the df argument will be empty. Only summary_stats_df will be populated +and every displayed row must have a pinned_row config + + + + + +""" + +class HistogramModel(pydantic.BaseModel): + name: str + population: float + +HT = Optional[List[HistogramModel]] + + + +class ColumnStringHint(pydantic.BaseModel): + type: Literal["string"] + histogram: HT + +class ColumnObjHint(pydantic.BaseModel): + type: Literal["obj"] + histogram: HT + + +class ColumnBooleanHint(pydantic.BaseModel): + type: Literal["boolean"] + histogram: HT + +class ColumnIntegerHint(pydantic.BaseModel): + type: Literal["integer"] + min_digits:int + max_digits:int + histogram: HT + +class DFColumn(pydantic.BaseModel): + name: str + type: str #should be a union + +ColumnHint = Union[ColumnStringHint, ColumnObjHint, ColumnBooleanHint, ColumnIntegerHint] + +class DFSchema(pydantic.BaseModel): + fields: List[DFColumn] + primaryKey: list[str] #; //['index'] + pandas_version: str #; //'1.4.0', + + +DFData = List[Dict[str, Union[str, int, float, None]]] + + + +class DFWhole(pydantic.BaseModel): + schema__ :DFSchema = pydantic.Field(alias='schema') + table_hints: Dict[str, ColumnHint] + data: DFData + +# class DfViewer(pydantic.BaseModel): +# type: 'DFViewer' +# df: DFWhole + +# #Ilike the serialization_alias... but luckily I avoid the need +# #because I don't have any snake cased fields + + +def test_column_hints(): + ColumnStringHint(type="string", histogram=[]) + ColumnStringHint(type="string", histogram=[{'name':'foo', 'population':3500}]) + with pytest.raises(ValidationError) as exc_info: + errant_histogram_entry = {'name':'foo', 'no_population':3500} + ColumnStringHint(type="string", histogram=[errant_histogram_entry]) + assert exc_info.value.errors(include_url=False) == [ + {'type': 'missing', 'loc': ('histogram', 0, 'population'), + 'msg': 'Field required','input': errant_histogram_entry}] + + ColumnBooleanHint(type="boolean", histogram=[]) + +def test_column_hint_extra(): + """verify that we can pass in extra unexpected keys""" + ColumnStringHint(type="string", histogram=[], foo=8) + +def test_dfwhole(): + temp = {'schema': {'fields':[{'name':'foo', 'type':'integer'}], + 'primaryKey':['foo'], 'pandas_version':'1.4.0'}, + 'table_hints': {'foo':{'type':'string', 'histogram':[]}, + 'bar':{'type':'integer', 'min_digits':2, 'max_digits':4, 'histogram':[]}, + 'baz':{'type':'obj', 'histogram':[]}, + }, + 'data': [{'foo': 'hello', 'bar':8}, + {'foo': 'world', 'bar':10}]} + DFWhole(**temp) + +def test_df_to_obj_pydantic(): + named_index_df = pd.DataFrame( + dict(foo=['one', 'two', 'three'], + bar=[1, 2, 3])) + + serialized_df = df_to_obj(named_index_df) + print(json.dumps(serialized_df, indent=4)) + DFWhole(**serialized_df) + +def bimodal(mean_1, mean_2, N, sigma=5): + X1 = np.random.normal(mean_1, sigma, int(N/2)) + X2 = np.random.normal(mean_2, sigma, int(N/2)) + X = np.concatenate([X1, X2]) + return X + +def rand_cat(named_p, na_per, N): + choices, p = [], [] + named_total_per = sum(named_p.values()) + na_per + total_len = int(np.floor(named_total_per * N)) + if named_total_per > 0: + for k, v in named_p.items(): + choices.append(k) + p.append(v/named_total_per) + choices.append(pd.NA) + p.append(na_per/named_total_per) + return [np.random.choice(choices, p=p) for k in range(total_len)] + return [] + +def random_categorical(named_p, unique_per, na_per, longtail_per, N): + choice_arr = rand_cat(named_p, na_per, N) + discrete_choice_len = len(choice_arr) + + longtail_count = int(np.floor(longtail_per * N))//2 + extra_arr = [] + for i in range(longtail_count): + extra_arr.append("long_%d" % i) + extra_arr.append("long_%d" % i) + + unique_len = N - (len(extra_arr) + discrete_choice_len) + for i in range(unique_len): + extra_arr.append("unique_%d" % i) + all_arr = np.concatenate([choice_arr, extra_arr]) + np.random.shuffle(all_arr) + try: + return pd.Series(all_arr, dtype='UInt64') + except Exception: # this is test fixture code + return pd.Series(all_arr, dtype=pd.StringDtype()) + + +def _test_df_to_obj_timing(): + N = 100_000 + df = pd.DataFrame({ + 'normal': np.random.normal(25, .3, N), + 'exponential' : np.random.exponential(1.0, N) * 10 , + 'increasing':[i for i in range(N)], + 'one': [1]*N, + 'dominant_categories': random_categorical({'foo': .6, 'bar': .25, 'baz':.15}, unique_per=0, na_per=0, longtail_per=0, N=N), + 'all_unique_cat': random_categorical({}, unique_per=1, na_per=0, longtail_per=0, N=N), + 'all_NA' : pd.Series([pd.NA] * N, dtype='UInt8'), + 'half_NA' : random_categorical({1: .55}, unique_per=0, na_per=.45, longtail_per=.0, N=N), + 'longtail' : random_categorical({}, unique_per=0, na_per=.2, longtail_per=.8, N=N), + 'longtail_unique' : random_categorical({}, unique_per=0.5, na_per=.0, longtail_per=.5, N=N)}) + + + start_serialize = time.time() + serialized_df = df_to_obj(df) + end_serialize = time.time() + DFWhole(**serialized_df) + end_pydantic = time.time() + + json.dumps(serialized_df) + end_json_time = time.time() + + serialize_time = end_serialize - start_serialize + pydantic_time = end_pydantic - end_serialize + json_time = end_json_time - end_pydantic + + print("serialize_time ", serialize_time) + print("pydantic_time ", pydantic_time) + print("json_time ", json_time) + + #pydantic time was about 1/5th of serialization time + #json.dumps time was around 2/5ths of serialization time + + #the following line triggers an error which will force printing + #1/0 diff --git a/tests/unit/fixtures.py b/tests/unit/fixtures.py new file mode 100644 index 000000000..66da47b94 --- /dev/null +++ b/tests/unit/fixtures.py @@ -0,0 +1,63 @@ +import numpy as np +import pandas as pd +from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import (ColAnalysis) + +test_df = pd.DataFrame({ + 'normal_int_series' : pd.Series([1,2,3,4]), + 'empty_na_ser' : pd.Series([], dtype="Int64"), + 'float_nan_ser' : pd.Series([3.5, np.nan, 4.8]) + }) + +word_only_df = pd.DataFrame({'letters': 'h o r s e'.split(' ')}) + +df = pd.read_csv('./docs/examples/data/2014-01-citibike-tripdata.csv') + +empty_df = pd.DataFrame({}) +empty_df_with_columns = pd.DataFrame({}, columns=[0]) + + + +class DistinctCount(ColAnalysis): + provides_defaults = {'distinct_count':0} + requires_raw = True + provides_series_stats = ["distinct_count"] + + @staticmethod + def series_summary(sampled_ser, raw_ser): + val_counts = raw_ser.value_counts() + distinct_count= len(val_counts) + return {'distinct_count': distinct_count} + +class Len(ColAnalysis): + provides_defaults = {'len':0} + provides_series_stats = ["len"] + requires_raw = True + + @staticmethod + def series_summary(sampled_ser, ser): + return {'len': len(ser)} + +class DCLen(ColAnalysis): + provides_defaults = {'len':0, 'distinct_count':0} + provides_series_stats = ["len", "distinct_count"] + requires_raw = True + + @staticmethod + def series_summary(sampled_ser, raw_ser): + val_counts = raw_ser.value_counts() + distinct_count= len(val_counts) + return {'distinct_count': distinct_count} + + +class DistinctPer(ColAnalysis): + provides_defaults = {'distinct_per':0} + requires_summary = ["len", "distinct_count"] + + @staticmethod + def computed_summary(summary_dict): + print("summary_dict", summary_dict) + return {'distinct_per': summary_dict['distinct_count'] / summary_dict['len']} + +class DependsNoProvides(ColAnalysis): + provides_defaults = {} + requires_summary = ["len"] diff --git a/tests/unit/geopandas_test.py b/tests/unit/geopandas_test.py new file mode 100644 index 000000000..e5ddcfa4c --- /dev/null +++ b/tests/unit/geopandas_test.py @@ -0,0 +1,33 @@ +from buckaroo.geopandas_buckaroo import GeopandasSVGBuckarooWidget, GeopandasBuckarooWidget +from .fixtures import (DistinctCount) +import geopandas + +world_df = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres')) + + +def test_basic_instantiation(): + """ test that GeopandasBuckarooWidget can instantiate without an error""" + GeopandasBuckarooWidget(world_df) + +def test_summary_stats(): + """ + test that summary stats serialize properly + """ + class SimpleGeoBW(GeopandasBuckarooWidget): + analysis_klasses = [DistinctCount] + pinned_rows = [] + + w = SimpleGeoBW(world_df[:3]) + assert w.df_data_dict['all_stats'] == [ + {'continent': 2, + 'gdp_md_est': 3, + 'geometry': 3, + 'index': 'distinct_count', + 'iso_a3': 3, + 'name': 3, + 'pop_est': 3}, + ] + +def test_svg(): + """ test that GeopandasSVGBuckarooWidget can instantiate without an error""" + GeopandasSVGBuckarooWidget(world_df[:10]) diff --git a/tests/unit/histogram_test.py b/tests/unit/histogram_test.py new file mode 100644 index 000000000..f97987537 --- /dev/null +++ b/tests/unit/histogram_test.py @@ -0,0 +1,78 @@ +import pandas as pd +from buckaroo.pluggable_analysis_framework.analysis_management import ( + DfStats, produce_series_df, AnalysisPipeline) +from buckaroo.customizations.histogram import Histogram +from buckaroo.customizations.analysis import ( + TypingStats, ComputedDefaultSummaryStats, DefaultSummaryStats) + +INT_ARR = [33, 41, 11, 46, 42, 44, 31, 25, 16, 24, 26, 7, 19, 23, 20, 46, 10, + 4, 31, 45, 40, 37, 48, 21, 19, 20, 19, 14, 14, 26, 36, 24, 21, 41, + 19, 17, 24, 27, 32, 30, 19, 49, 22, 20, 16, 7, 45, 10, 23, 44, 28, + 44, 15, 29, 34, 3, 44, 19, 20, 27, 1, 35, 34, 42, 12, 9, 21, 32, + 40, 41, 49, 47, 16, 25, 20, 11, 28, 13, 30, 6, 34, 16, 37, 21, 7, + 34, 34, 29, 24, 2, 7, 17, 13, 22, 13, 32, 11, 24, 24, 31, 11, 9, + 39, 40, 36, 20, 46, 31, 37, 27, 25, 9, 27, 41, 13, 35, 33, 24, 8, + 25, 12, 28, 26, 17, 7, 18, 12, 6, 45, 42, 32, 38, 31, 25, 33, 13, + 24, 23, 40, 18, 33, 42, 7, 40, 48, 29, 27, 13, 38, 35, 33, 24, 40, + 19, 47, 38, 8, 3, 6, 48, 9, 17, 13, 46, 6, 3, 34, 43, 6, 9, + 28, 4, 49, 10, 14, 36, 48, 39, 1, 37, 41, 37, 43, 43, 6, 23, 6, + 30, 27, 11, 19, 19, 34, 14, 37, 42, 15, 6, 48, 32] + +test_df = pd.DataFrame({'a': INT_ARR}) + +def _assert_ha(ha): + assert ha['low_tail'] == 1.99 + assert ha['high_tail'] == 49.0 + + assert ha['normalized_populations'] == [ + 0.07179487179487179, 0.1076923076923077, 0.08205128205128205, 0.1282051282051282, + 0.09743589743589744, 0.1076923076923077, 0.1282051282051282, 0.07692307692307693, + 0.1076923076923077, 0.09230769230769231] + #numpy arrays need special comparison that I will look at later + + # assert ha['meat_histogram'] == ( + # np.array([14, 21, 16, 25, 19, 21, 25, 15, 21, 18]), + # np.array([ 2. , 6.6, 11.2, 15.8, 20.4, 25. , 29.6, 34.2, 38.8, 43.4, 48. ])) + + +def test_produce_series_df(): + """just make sure this doesn't fail""" + sdf, errs = produce_series_df( + test_df, [Histogram], 'test_df', debug=True) + ha = sdf['a']['histogram_args'] + _assert_ha(ha) + +def test_no_meat(): + """just make sure this doesn't fail based on + Nearly-constant column with outliers fails to display #264 + https://github.com/paddymul/buckaroo/issues/264 + """ + df = pd.DataFrame({'no_meat': [1] * 400 + [10, 20, 30, 40, 50]}) + sdf, errs = AnalysisPipeline.full_produce_summary_df(df, + [TypingStats, ComputedDefaultSummaryStats, Histogram, DefaultSummaryStats], + debug=True) + assert errs == {} + +def test_full_produce_summary_df(): + sdf, errs = AnalysisPipeline.full_produce_summary_df(test_df, [Histogram], debug=True) + ha = sdf['a']['histogram_args'] + _assert_ha(ha) + +def test_full_produce_summary_df2(): + sdf, errs = AnalysisPipeline.full_produce_summary_df( + test_df, + [TypingStats, ComputedDefaultSummaryStats, Histogram, DefaultSummaryStats], + debug=True) + ha = sdf['a']['histogram_args'] + _assert_ha(ha) + +def test_dfstats_histogram(): + stats = DfStats( + test_df, + [TypingStats, ComputedDefaultSummaryStats, Histogram, DefaultSummaryStats], + 'test_df', debug=True) + sdf = stats.sdf + + print(sdf['a']) + ha = sdf['a']['histogram_args'] + _assert_ha(ha) diff --git a/tests/unit/hypothesis_buckaroo.py b/tests/unit/hypothesis_buckaroo.py new file mode 100644 index 000000000..693322a7b --- /dev/null +++ b/tests/unit/hypothesis_buckaroo.py @@ -0,0 +1,44 @@ +import hypothesis + +import buckaroo +from hypothesis import strategies as st +from hypothesis.extra.pandas import data_frames, column + + +@hypothesis.settings(deadline=10_000) +@hypothesis.given( + # TODO: write strategy to support n-Columns + df=st.one_of(data_frames(columns=[column(elements=st.integers())]), + data_frames(columns=[column(elements=st.floats())]), + data_frames(columns=[column(elements=st.text())]), + data_frames(columns=[column(elements= + st.dictionaries(st.text(), st.integers()))]), + data_frames(columns=[column(elements= + st.lists(st.text()))])), + sampled=st.booleans(), + summaryStats=st.booleans(), + reorderdColumns=st.booleans(), + showCommands=st.booleans(), + postProcessingF=st.none(), +) +def test_fuzz_BuckarooWidget( + df, + sampled, + summaryStats, + reorderdColumns, + showCommands, + postProcessingF, +): + + #debug=True will cause an analysis error to throw an error, + #auto_clean is tempermental and not turned on by default + buckaroo.BuckarooWidget( + df=df, + sampled=sampled, + summaryStats=summaryStats, + reorderdColumns=reorderdColumns, + showCommands=showCommands, + auto_clean=False, + postProcessingF=postProcessingF, + debug=True + ) diff --git a/tests/unit/lispy_test.py b/tests/unit/lispy_test.py new file mode 100644 index 000000000..16711d468 --- /dev/null +++ b/tests/unit/lispy_test.py @@ -0,0 +1,27 @@ +from buckaroo.jlisp.lisp_utils import split_operations, lists_match + +def test_split_operations(): + + full_ops = [ + [{"symbol":"dropcol", "meta":{"precleaning":True}},{"symbol":"df"},"starttime"], + [{"symbol":"dropcol"},{"symbol":"df"},"starttime"], + ] + + EXPECTED_cleaning_ops = [ + [{"symbol":"dropcol", "meta":{"precleaning":True}},{"symbol":"df"},"starttime"]] + + EXPECTED_user_gen_ops = [ + [{"symbol":"dropcol"},{"symbol":"df"},"starttime"]] + + cleaning_ops, user_gen_ops = split_operations(full_ops) + + assert EXPECTED_cleaning_ops == cleaning_ops + assert EXPECTED_user_gen_ops == user_gen_ops + +def test_lists_match(): + + assert lists_match(["a", "b"], ["a", "b"]) + assert lists_match([["a", "b"]], [["a", "b"]]) + assert not lists_match(["a", "b"], ["a", "b", "c"]) + assert not lists_match([["a", "b"]], [["a", "b", "c"]]) + diff --git a/tests/unit/perf_regression_test.py b/tests/unit/perf_regression_test.py new file mode 100644 index 000000000..94a4dcee2 --- /dev/null +++ b/tests/unit/perf_regression_test.py @@ -0,0 +1,53 @@ +import pandas as pd +import numpy as np +import buckaroo +import time + +def float_df(N_rows, K_columns): + return pd.DataFrame( + {chr(i+97): np.random.random_sample(N_rows) for i in range(K_columns)}) + + +""" +The idea of this is to make a relative timing comparison between just insantiating a dataframe and the full buckaroo testing. it's crude but should alert to major performance regressions. particularly with json serialization + +""" +# %timeit float_df(100_000,20) 9ms on my laptop + +def bw_do_stuff(df, **kwargs): + buckaroo.buckaroo_widget.BuckarooWidget(df, **kwargs) + +#%timeit bw_do_stuff(float_df(100_000, 20)) 500 ms on my laptop + + +# the slow part is serialization to json, not summary stats +# %timeit bw_do_stuff2(float_df(10_000, 5)) 140 ms on my laptop +# %timeit bw_do_stuff2(float_df(100_000, 5)) 150ms on my laptop + + +def test_basic_instantiation(): + t_start = time.time() + float_df(100_000, 20) + t_end = time.time() + + np_time = t_end - t_start + assert np_time < 10 + + bw_start = time.time() + bw_do_stuff(float_df(10_000,5)) + bw_end = time.time() + bw_time_1 = bw_end - bw_start + + assert bw_time_1 < np_time * 50 + + + bw_start2 = time.time() + bw_do_stuff(float_df(100_000,5)) + bw_end2 = time.time() + bw_time_2 = bw_end2 - bw_start2 + + assert bw_time_2 < np_time * 60 + + + + diff --git a/tests/unit/pluggable_analysis_framework_test.py b/tests/unit/pluggable_analysis_framework_test.py new file mode 100644 index 000000000..f05c67e83 --- /dev/null +++ b/tests/unit/pluggable_analysis_framework_test.py @@ -0,0 +1,74 @@ +import unittest +import graphlib +from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import ( + ColAnalysis, order_analysis, check_solvable, NotProvidedException) + + + +from .fixtures import (DistinctCount, Len, DistinctPer, DCLen, DependsNoProvides) + +class NoRoute(ColAnalysis): + provides_defaults = {'not_used': False} + requires_summary = ["does_not_exist"] + +class CycleA(ColAnalysis): + provides_defaults = {'cycle_a': 'asdf'} + requires_summary = ["cycle_b"] + +class CycleB(ColAnalysis): + provides_defaults = {'cycle_b': 'foo'} + requires_summary = ["cycle_a"] + +class CA_AB(ColAnalysis): + provides_summary = {"a":0, "b":99} + +class CA_CD(ColAnalysis): + provides_summary = {"c":3, "d":1} + +class CA_EF(ColAnalysis): + provides_defaults = {"e":9, "f":2} + requires_summary = ["a", "b", "c", "d"] + +class CA_G(ColAnalysis): + provides_defaults = {"g":3} + requires_summary = ["e"] + + +class TestOrderAnalysis(unittest.TestCase): + + def test_default_order(self): + self.assertEqual( + order_analysis([DistinctCount, Len, DistinctPer]), + [DistinctCount, Len, DistinctPer]) + self.assertEqual( + order_analysis([DistinctPer, DistinctCount, Len]), + [DistinctCount, Len, DistinctPer]) + + def test_multiple_provides(self): + self.assertEqual( + order_analysis([DCLen, DistinctPer]), + [DCLen, DistinctPer]) + self.assertEqual( + order_analysis([DistinctPer, DCLen]), + [DCLen, DistinctPer]) + self.assertEqual( + order_analysis([CA_G, CA_CD, CA_AB, CA_EF]), + [CA_CD, CA_AB, CA_EF, CA_G ]) + #note the order between CA_CD and CA_AB doesn't matter - + # as long as they occur before other classes + + def test_no_provides(self): + # order_analysis should work properly with ColAnalysis objects that don't provide any summary_stats + + self.assertEqual( + order_analysis([DCLen, DistinctPer, DependsNoProvides]), + [DCLen, DependsNoProvides, DistinctPer]) + + def test_cycle(self): + with self.assertRaises(graphlib.CycleError): + order_analysis([CycleA, CycleB]) + + def test_no_route(self): + check_solvable([Len]) + with self.assertRaises(NotProvidedException): + check_solvable([NoRoute]) diff --git a/tests/unit/polars_analysis_management_test.py b/tests/unit/polars_analysis_management_test.py new file mode 100644 index 000000000..247ea6c16 --- /dev/null +++ b/tests/unit/polars_analysis_management_test.py @@ -0,0 +1,187 @@ +import polars as pl +import numpy as np +from polars import functions as F +import polars.selectors as cs +from buckaroo.customizations.polars_analysis import ( + VCAnalysis, PlTyping, BasicAnalysis, HistogramAnalysis, + ComputedDefaultSummaryStats) + +from buckaroo.pluggable_analysis_framework.utils import (json_postfix, replace_in_dict) + +from buckaroo.pluggable_analysis_framework.polars_analysis_management import ( + PolarsAnalysisPipeline, polars_produce_series_df, PolarsAnalysis, PlDfStats) + +test_df = pl.DataFrame({ + 'normal_int_series' : pl.Series([1,2,3,4]), + #'empty_na_ser' : pl.Series([pl.Null] * 4, dtype="Int64"), + 'float_nan_ser' : pl.Series([3.5, np.nan, 4.8, 2.2])}) + +word_only_df = pl.DataFrame({'letters': 'h o r s e'.split(' ')}) + +df = pl.read_csv('./docs/examples/data/2014-01-citibike-tripdata.csv') + +empty_df = pl.DataFrame({}) +#empty_df_with_columns = pl.DataFrame({}, columns=[0]) + + + +class SelectOnlyAnalysis(PolarsAnalysis): + provides_defaults = {} + select_clauses = [ + F.all().null_count().name.map(json_postfix('null_count')), + F.all().mean().name.map(json_postfix('mean')), + F.all().quantile(.99).name.map(json_postfix('quin99'))] + + +def test_non_full_analysis(): + class MixedAnalysis(PolarsAnalysis): + provides_defaults = dict( + empty_count=0, sum=0) + + select_clauses = [ + F.col(pl.Utf8).str.count_matches("^$").sum().name.map(json_postfix('empty_count')), + cs.numeric().sum().name.map(json_postfix('sum'))] + + df = pl.DataFrame({'a': [10, 20], 'b': ['', 'bar']}) + + pdf = PlDfStats(df, [MixedAnalysis]) + assert pdf.sdf == {'a': dict(empty_count=0, sum=30), + 'b': dict(empty_count=1, sum=0)} + + +def test_produce_series_df(): + """just make sure this doesn't fail""" + + sdf, errs = polars_produce_series_df( + test_df, [SelectOnlyAnalysis], 'test_df', debug=True) + expected = { + 'float_nan_ser': {'mean': None, 'null_count': 0, 'quin99': None}, + 'normal_int_series': {'mean': 2.5, 'null_count': 0, 'quin99': 4.0}} + dsdf = replace_in_dict(sdf, [(np.nan, None)]) + assert dsdf == expected + +class MaxAnalysis(PolarsAnalysis): + provides_defaults = {} + select_clauses = [F.all().max().name.map(json_postfix('max'))] + +def test_produce_series_combine_df(): + """just make sure this doesn't fail""" + + sdf, errs = polars_produce_series_df( + test_df, [SelectOnlyAnalysis, MaxAnalysis], 'test_df', debug=True) + expected = { + 'float_nan_ser': {'mean': None, 'null_count': 0, 'quin99': None, 'max': 4.8}, + 'normal_int_series': {'mean': 2.5, 'null_count': 0, 'quin99': 4.0, 'max': 4.0}, + } + dsdf = replace_in_dict(sdf, [(np.nan, None)]) + assert dsdf == expected + + + +def test_produce_series_column_ops(): + mixed_df = pl.DataFrame( + {'string_col': ["foo", "bar", "baz"] + [""]*2, + 'int_col':[1,2,3,30, 100], + 'float_col':[1.1, 1.1, 3, 3, 5]}) + + summary_df, _unused = polars_produce_series_df(mixed_df, [HistogramAnalysis]) + assert summary_df["string_col"] == {'categorical_histogram': [], 'histogram': [], 'histogram_bins': []} + + assert summary_df["int_col"]["histogram_args"]["meat_histogram"] == ( + [2, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1.0, 4.0, 7.0, 10.0, 13.0, 16.0, 19.0, 22.0, 25.0, 28.0, 100.0],) + + + +HA_CLASSES = [VCAnalysis, PlTyping, BasicAnalysis, ComputedDefaultSummaryStats, HistogramAnalysis] +def test_histogram_analysis(): + cats = [chr(x) for x in range(97, 102)] * 2 + cats += [chr(x) for x in range(103,113)] + cats += ['foo']*30 + ['bar'] * 50 + + df = pl.DataFrame({'categories': cats, 'numerical_categories': [3]*30 + [7] * 70}) + + summary_df, errs = PolarsAnalysisPipeline.full_produce_summary_df(df, HA_CLASSES, debug=True) + + actual_cats = summary_df["categories"]["categorical_histogram"] + expected_cats = {'bar': 0.5, 'foo': 0.3, 'longtail': 0.1, 'unique': 0.1} + assert actual_cats == expected_cats + + actual_numcats = summary_df["numerical_categories"]["categorical_histogram"] + rounded_actual_numcats = dict([(k, np.round(v,2)) for k,v in actual_numcats.items()]) + expected_categorical_histogram = {3:.3, 7:.7, 'longtail': 0.0, 'unique': 0.0} + assert rounded_actual_numcats == expected_categorical_histogram + + +def test_numeric_histograms(): + #np.random.standard_normal(50) + #note the negative numbers + float_arr = np.array( + [ 0.15866514, 1.17068755, -0.33565104, 0.65639612, -1.82228383, + -0.31636192, 1.15528901, 0.51853447, -2.46400234, -0.43549045, + 0.00352285, 0.81172013, -0.72803939, -1.00862492, -0.22710132, + -0.3175636 , 0.75857194, -1.78286566, -1.34886293, 0.13987727, + 0.38449789, -1.40855498, 1.87998263, 0.67376218, 0.35140324, + 0.57988045, -0.88552517, -1.89412544, -0.93349705, -0.79151579, + -1.43998107, 0.44633053, 0.46607586, -0.28883213, -0.16766607, + 1.49832905, 0.56894383, 0.66272376, 0.89071271, -2.03593151, + -0.52559652, -1.87226564, -0.55629666, -0.56985112, 0.06456509, + -0.44142502, -2.09803033, 0.51801718, -1.56189092, -1.17083831]) + #make them all positive numbers + float_arr2 = float_arr + 2.46400234 + + #np.round(np.random.standard_normal(50) * 100).astype('int16') + int_arr = np.array( + [-272, 107, -85, 5, -6, 19, 38, -102, -84, 79, 106, + 59, -132, 81, -122, -62, -34, 80, 14, 19, -20, -155, + 1, -9, 82, 37, 114, 76, -90, -2, 63, 169, -239, + -225, 71, 55, 174, 30, -69, 99, 62, -116, 51, -45, + 57, 64, 8, -20, -130, -83]) + int_arr2 = int_arr + 272 + df = pl.DataFrame({ + 'float_col': float_arr, + 'float_col2': float_arr2, + 'int_col': int_arr, + 'int_col2': int_arr2 + }) + + summary_df, errs = PolarsAnalysisPipeline.full_produce_summary_df(df, HA_CLASSES, debug=True) + print(summary_df['int_col']['histogram']) + + expected_float_histogram = [ + {'name': '-2.46400234 - -2.46400234', 'tail': 1}, + {'name': '-2--3', 'population': 0.0}, {'name': '-3--3', 'population': 0.0}, + {'name': '-3--2', 'population': 4.0}, {'name': '-2--1', 'population': 17.0}, + {'name': '-1--0', 'population': 19.0}, {'name': '-0-0', 'population': 25.0}, + {'name': '0-1', 'population': 29.0}, {'name': '1-2', 'population': 6.0}, + {'name': '2-2', 'population': 0.0}, {'name': '2-2', 'population': 0.0}, + {'name': '1.87998263 - 1.87998263', 'tail': 1}] + assert summary_df['float_col']['histogram'] == expected_float_histogram + + assert summary_df["int_col"]["histogram_bins"] == [ + -272.0, -199.0, -158.0, -117.0, -76.0, + -35.0, 6.0, 47.0, 88.0, 129.0, 174.0] + + expected_int_histogram = [ + {'name': '-272 - -272.0', 'tail': 1}, + {'name': '-272--199', 'population': 4.0}, {'name': '-199--158', 'population': 0.0}, + {'name': '-158--117', 'population': 8.0}, {'name': '-117--76', 'population': 12.0}, + {'name': '-76--35', 'population': 6.0}, {'name': '-35-6', 'population': 17.0}, + {'name': '6-47', 'population': 15.0}, {'name': '47-88', 'population': 27.0}, + {'name': '88-129', 'population': 8.0}, {'name': '129-174', 'population': 2.0}, + {'name': '174.0 - 174', 'tail': 1}] + assert summary_df['int_col']['histogram'] == expected_int_histogram + + + +def test_pl_typing(): + + class AdaptingStylingAnalysis(PolarsAnalysis): + provides_defaults = {} + requires_summary = ["histogram", "is_numeric", "dtype", "is_integer"] + + PlDfStats(df, + [AdaptingStylingAnalysis, PlTyping, HistogramAnalysis, + BasicAnalysis, VCAnalysis, + ComputedDefaultSummaryStats]) + diff --git a/tests/unit/polars_analysis_tests.py b/tests/unit/polars_analysis_tests.py new file mode 100644 index 000000000..e76fc45bc --- /dev/null +++ b/tests/unit/polars_analysis_tests.py @@ -0,0 +1,59 @@ + +import polars as pl +import numpy as np +from polars import functions as F + +from buckaroo.pluggable_analysis_framework.utils import (json_postfix, replace_in_dict) + +from buckaroo.pluggable_analysis_framework.polars_analysis_management import ( + polars_produce_series_df, PolarsAnalysis) + +from buckaroo.pluggable_analysis_framework.polars_analysis_management import PlDfStats +from buckaroo.customizations.polars_analysis import BasicAnalysis, VCAnalysis + + +class SelectOnlyAnalysis(PolarsAnalysis): + + select_clauses = [ + F.all().null_count().name.map(json_postfix('null_count')), + F.all().mean().name.map(json_postfix('mean')), + F.all().quantile(.99).name.map(json_postfix('quin99'))] + + +def test_produce_series_df(): + """just make sure this doesn't fail""" + test_df = pl.DataFrame({ + 'normal_int_series' : pl.Series([1,2,3,4]), + #'empty_na_ser' : pl.Series([pl.Null] * 4, dtype="Int64"), + 'float_nan_ser' : pl.Series([3.5, np.nan, 4.8, 2.2]) + }) + + sdf, errs = polars_produce_series_df( + test_df, [SelectOnlyAnalysis], 'test_df', debug=True) + expected = { + 'float_nan_ser': {'mean': None, 'null_count': 0, 'quin99': None}, + 'normal_int_series': {'mean': 2.5, 'null_count': 0, 'quin99': 4.0}} + dsdf = replace_in_dict(sdf, [(np.nan, None)]) + assert dsdf == expected + + +def test_struct(): + """ + structs have caused hard to debug errors. Make sure they are properly tested + """ + ser = pl.Series([{'a':5}]) + df = pl.DataFrame({'b': ser, 'normal': [4]}) + dfs = PlDfStats(df, [VCAnalysis, BasicAnalysis], debug=True) + print(dfs.sdf) + assert dfs.errs == {} + + +''' + +word_only_df = pl.DataFrame({'letters': 'h o r s e'.split(' ')}) + +df = pl.read_csv('./examples/data/2014-01-citibike-tripdata.csv') + +empty_df = pl.DataFrame({}) +#empty_df_with_columns = pl.DataFrame({}, columns=[0]) +''' diff --git a/tests/unit/polars_basic_widget_test.py b/tests/unit/polars_basic_widget_test.py new file mode 100644 index 000000000..5fdc6935d --- /dev/null +++ b/tests/unit/polars_basic_widget_test.py @@ -0,0 +1,227 @@ +import polars as pl +from polars import functions as F +import numpy as np +from buckaroo.pluggable_analysis_framework.polars_analysis_management import ( + PolarsAnalysis, polars_produce_series_df) +from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import ( + ColAnalysis) +from buckaroo.pluggable_analysis_framework.utils import (json_postfix) +from buckaroo.polars_buckaroo import PolarsBuckarooWidget +from buckaroo.dataflow.dataflow import StylingAnalysis + +def test_basic_instantiation(): + PolarsBuckarooWidget( + pl.DataFrame({'a':[1,2,3]})) + + +EXPECTED_DF_VIEWER_CONFIG = { + 'pinned_rows': [], + 'column_config': [ + {'col_name': 'index', 'displayer_args': {'displayer': 'obj'}}, + {'col_name': 'normal_int_series', 'displayer_args': {'displayer': 'obj'}}], + 'component_config': {}, + 'extra_grid_config': {}, +} + +class SelectOnlyAnalysis(PolarsAnalysis): + + select_clauses = [ + F.all().null_count().name.map(json_postfix('null_count')), + F.all().mean().name.map(json_postfix('mean')), + F.all().quantile(.99).name.map(json_postfix('quin99'))] + +test_df = pl.DataFrame({ + 'normal_int_series' : pl.Series([1,2,3,4]), +}) + + + +def test_polars_all_stats(): + """ + FIXME temporarily disabled to test other build stuff + the all_stats verify that PolarsBuckarooWidget produces the + same summary_stats shape tatha pandas does. + + Since polars doesn't have an index concept, some things are a little different, but the summary_stats display essentiall depends on the index being present and displayed + + """ + + sdf, errs = polars_produce_series_df( + test_df, [SelectOnlyAnalysis], 'test_df', debug=True) + expected = { + 'normal_int_series': {'mean': 2.5, 'null_count': 0, 'quin99': 4.0}} + #dsdf = replace_in_dict(sdf, [(np.nan, None)]) + class SimplePolarsBuckaroo(PolarsBuckarooWidget): + analysis_klasses= [SelectOnlyAnalysis, StylingAnalysis] + + spbw = SimplePolarsBuckaroo(test_df) + assert spbw.merged_sd == expected + + assert spbw.df_data_dict['all_stats'] == [ + {'index': 'null_count', 'normal_int_series': 0.0}, + {'index': 'mean', 'normal_int_series': 2.5}, + {'index': 'quin99', 'normal_int_series': 4.0}] + assert spbw.df_display_args['main']['df_viewer_config'] == EXPECTED_DF_VIEWER_CONFIG + + + +def test_pandas_all_stats(): + """ + + just make sure this doesn't fail""" + from buckaroo.buckaroo_widget import BuckarooWidget + from buckaroo.pluggable_analysis_framework.pluggable_analysis_framework import (ColAnalysis) + import pandas as pd + + pd_test_df = pd.DataFrame({ + 'normal_int_series' : pl.Series([1,2,3,4]), + #'empty_na_ser' : pl.Series([pl.Null] * 4, dtype="Int64"), + #'float_nan_ser' : pl.Series([3.5, np.nan, 4.8, 2.2]) + }) + + + class SimpleAnalysis(ColAnalysis): + provides_defaults = {} + requires_raw = True + provides_series_stats = ["distinct_count"] + + @staticmethod + def series_summary(sampled_ser, raw_ser): + return dict( + null_count=0, + mean=2.5, + quin99=4.0) + + class SimpleBuckaroo(BuckarooWidget): + analysis_klasses= [SimpleAnalysis, StylingAnalysis] + + sbw = SimpleBuckaroo(pd_test_df) + assert sbw.merged_sd == { + 'index': {'mean': 2.5, 'null_count': 0, 'quin99': 4.0}, + 'normal_int_series': {'mean': 2.5, 'null_count': 0, 'quin99': 4.0}} + assert sbw.df_display_args['main']['df_viewer_config'] == EXPECTED_DF_VIEWER_CONFIG + + + +def test_object_dtype1(): + """ + originally I thought that these errors with objects in polars were caused by just doing something dumb with polars... + But the first two lines run fine, something happens inside of PolarsBuckarooWidget + + I think the problme is related to type coercion or serialization + """ + ser = pl.Series([{'a':5}]) + df = pl.DataFrame({'b': ser}) + PolarsBuckarooWidget(df) + +def Xtest_object_dtype2(): + + ser = pl.Series([{'a':5}], dtype=pl.Object) + df = pl.DataFrame({'b': ser}) + PolarsBuckarooWidget(df) + + + # I eventually wanted to test non regular object like this + # ser = pl.Series([ + # {'level_1': {'a':10}}, None], dtype=pl.Object) + # df = pl.DataFrame({'nested_dicts2': ser}) + +def test_weird(): +# RAW = { +# 'names': ['all_NA', 'half_NA','longtail', 'longtail_unique'], +# 'histo': [ +# [{'name': 'NA', 'NA': 100.0}], +# [{'name': 1, 'cat_pop': 46.0}, {'name': 'NA', 'NA': 54.0}], +# [{'name': 'long_30', 'cat_pop': 0.0}, {'name': 'long_15', 'cat_pop': 0.0}, +# {'name': 'long_29', 'cat_pop': 0.0}, {'name': 'long_184', 'cat_pop': 0.0}, +# {'name': 'long_101', 'cat_pop': 0.0}, {'name': 'long_48', 'cat_pop': 0.0}, +# {'name': 'long_123', 'cat_pop': 0.0}, {'name': 'longtail', 'longtail': 77.0}, +# {'name': 'NA', 'NA': 20.0}], +# [ +# {'name': 'long_120', 'cat_pop': 0.0}, {'name': 'long_41', 'cat_pop': 0.0}, +# {'name': 'long_0', 'cat_pop': 0.0}, {'name': 'long_32', 'cat_pop': 0.0}, +# {'name': 'long_44', 'cat_pop': 0.0}, {'name': 'long_113', 'cat_pop': 0.0}, +# {'name': 'long_22', 'cat_pop': 0.0}, +# {'name': 'longtail', 'unique': 50.0, 'longtail': 47.0}]]} + +# pl_histo = pl.DataFrame(RAW) +# pl_histo + +# RAW = ​ { +# 'all_NA': [{'name': 'NA', 'NA': 100.0}], +# 'half_NA': [{'name': 1, 'cat_pop': 46.0}, {'name': 'NA', 'NA': 54.0}], +# 'longtail': [{'name': 'long_30', 'cat_pop': 0.0}, {'name': 'long_15', 'cat_pop': 0.0}, +# {'name': 'long_29', 'cat_pop': 0.0}, {'name': 'long_184', 'cat_pop': 0.0}, +# {'name': 'long_101', 'cat_pop': 0.0}, {'name': 'long_48', 'cat_pop': 0.0}, +# {'name': 'long_123', 'cat_pop': 0.0}, {'name': 'longtail', 'longtail': 77.0}, +# {'name': 'NA', 'NA': 20.0}], +# 'longtail_unique': [ +# {'name': 'long_120', 'cat_pop': 0.0}, {'name': 'long_41', 'cat_pop': 0.0}, +# {'name': 'long_0', 'cat_pop': 0.0}, {'name': 'long_32', 'cat_pop': 0.0}, +# {'name': 'long_44', 'cat_pop': 0.0}, {'name': 'long_113', 'cat_pop': 0.0}, +# {'name': 'long_22', 'cat_pop': 0.0}, +# {'name': 'longtail', 'unique': 50.0, 'longtail': 47.0}]} + + RAW = {'names': ['all_NA', 'half_NA'], + 'histo': [ + [{'name': 'NA', 'NA': 100.0}], + [{'name': 1, 'cat_pop': 46.0}, {'name': 'NA', 'NA': 54.0}]]} + pl_histo = pl.DataFrame(RAW, strict=False) + + PolarsBuckarooWidget(pl_histo) + +class ValueCountPostProcessing(PolarsAnalysis): + provides_defaults = {} + @classmethod + def post_process_df(kls, df): + result_df = df.select( + F.all().value_counts().implode().list.gather(pl.arange(0, 10), null_on_oob=True).explode().struct.rename_fields(['val', 'unused_count']).struct.field('val').prefix('val_'), + F.all().value_counts().implode().list.gather(pl.arange(0, 10), null_on_oob=True).explode().struct.field('count').prefix('count_')) + return [result_df, {}] + post_processing_method = "value_counts" + + +class TransposeProcessing(ColAnalysis): + provides_defaults = {} + @classmethod + def post_process_df(kls, df): + return [df.transpose(), {}] + post_processing_method = "transpose" + +class ShowErrorsPostProcessing(PolarsAnalysis): + provides_defaults = {} + @classmethod + def post_process_df(kls, df): + print("^"*80) + print(type(df)) + df.select + result_df = df.select( + F.all(), + pl.col('float_col').lt(5).replace(True, "foo").replace(False, None).alias('errored_float')) + return [result_df, {}] + + post_processing_method = "show_errors" + +ROWS = 5 +typed_df = pl.DataFrame( + {'int_col':np.random.randint(1,50, ROWS), 'float_col': np.random.randint(1,30, ROWS)/.7, + 'timestamp':["2020-01-01 01:00Z", "2020-01-01 02:00Z", + "2020-02-28 02:00Z", "2020-03-15 02:00Z", None], + "str_col": ["foobar", "Realllllly long string", "", None, "normal"]}) +typed_df = typed_df.with_columns(timestamp=pl.col('timestamp').str.to_datetime() ) +column_config_overrides={'float_col': {'color_map_config': { + 'color_rule': 'color_not_null', + 'conditional_color': 'red', 'exist_column': 'errored_float'}}} + +def test_polars_to_pandas(): + bw = PolarsBuckarooWidget(typed_df) + bw.add_analysis(ShowErrorsPostProcessing) + + temp_buckaroo_state = bw.buckaroo_state.copy() + temp_buckaroo_state['post_processing'] = 'show_errors' + bw.buckaroo_state = temp_buckaroo_state + + +''' +FIXME:test a large dataframe that forces sampling +''' diff --git a/tests/unit/safe_summary_test.py b/tests/unit/safe_summary_test.py new file mode 100644 index 000000000..b54cc4ad3 --- /dev/null +++ b/tests/unit/safe_summary_test.py @@ -0,0 +1,12 @@ +import pandas as pd +import numpy as np +import polars as pl + + +from buckaroo.pluggable_analysis_framework.safe_summary_df import pd_py_serialize + +def test_py_serialize(): + assert pd_py_serialize({'a': pd.NA, 'b': np.nan}) == "{'a': pd.NA, 'b': np.nan, }" + assert pd_py_serialize({'a': None, 'b': "string", 'c': 4, 'd': 10.3 }) ==\ + "{'a': None, 'b': 'string', 'c': 4, 'd': 10.3, }" + assert pd_py_serialize({'a': pl.Series([1,2])}) == "{'a': pl.Series(), }" diff --git a/tests/unit/serialization_pydantic_tests.py b/tests/unit/serialization_pydantic_tests.py new file mode 100644 index 000000000..ec5717828 --- /dev/null +++ b/tests/unit/serialization_pydantic_tests.py @@ -0,0 +1,338 @@ +import time +import json +import pandas as pd +import numpy as np +from buckaroo.serialization_utils import df_to_obj +import pydantic + +# import typing +# if typing.TYPE_CHECKING: +# from . import AnyComponent + + +from typing import Optional, List, Literal, Union, Dict + + + +class HistogramModel(pydantic.BaseModel): + name: str + population: float + +HT = Optional[List[HistogramModel]] + + +class ObjDisplayerA(pydantic.BaseModel): + displayer: Literal["obj"] + +class BooleanDisplayerA(pydantic.BaseModel): + displayer: Literal["boolean"] + +class StringDisplayerA(pydantic.BaseModel): + displayer: Literal["string"] + #max_length: int + +class FloatDisplayerA(pydantic.BaseModel): + displayer: Literal["float"] + +class DatetimeDefaultDisplayerA(pydantic.BaseModel): + displayer: Literal["datetimeDefault"] + +class IntegerDisplayerA(pydantic.BaseModel): + displayer: Literal["integer"] + min_digits: int + max_digits: int + +class DatetimeLocaleDisplayerA(pydantic.BaseModel): + displayer: Literal["datetimeLocaleString"] + locale: Union[ + *map(lambda x: Literal[x], + ['en-US', 'en-GB', 'en-CA', 'fr-FR', 'es-ES', 'de-DE', 'ja-JP'])] + args: str # start with a dictionary, not sure of full typing + #args: Intl.DateTimeFormatOptions; + +#End FormatterArgs + +# Begin CellRenderArgs +class HistogramDisplayerA(pydantic.BaseModel): + displayer: Literal["histogram"] + +class LinkifyDisplayerA(pydantic.BaseModel): + displayer: Literal["linkify"] + + +# Internally DfViewer distinguishes between FormatterArgs and +# CellRendererArgs because they are sent to different functions, but to +# the python side, that is just an implmentation detail + +DisplayerArgs = Union[ + #formatters + ObjDisplayerA, BooleanDisplayerA, StringDisplayerA, FloatDisplayerA, DatetimeDefaultDisplayerA, + IntegerDisplayerA, DatetimeLocaleDisplayerA, + #Cell Renderers + HistogramDisplayerA, LinkifyDisplayerA] + +class ColorMapRules(pydantic.BaseModel): + color_rule: Literal['color_map'] + map_name: Union[Literal['BLUE_TO_YELLOW'], Literal['DIVERGING_RED_WHITE_BLUE']] + val_column: Optional[str] + +class ColorWhenNotNullRules(pydantic.BaseModel): + color_rule: Literal['color_not_null'] + conditional_color: Union[str, Literal['red']] + exist_column: str + +class ColorFromColumn(pydantic.BaseModel): + color_rule: Literal['color_from_column'] + col_name: str + +ColorMappingConfig = Union[ColorMapRules, ColorWhenNotNullRules, ColorFromColumn] + +class SimpleToolTip(pydantic.BaseModel): + tooltip_type: Literal['simple'] + val_column: str + +class SummarySeriesTooltip(pydantic.BaseModel): + tooltip_type: Literal['summary_series'] + +TooltipConfig = Union[SimpleToolTip, SummarySeriesTooltip] + + +class ColumnConfig(pydantic.BaseModel): + col_name: str + displayer_args: DisplayerArgs + color_map_config: Optional[ColorMappingConfig] + tooltip_config: Optional[TooltipConfig] + +class ColorMapRules(pydantic.BaseModel): + color_rule: Literal['color_map'] + map_name: Union[Literal['BLUE_TO_YELLOW'], Literal['DIVERGING_RED_WHITE_BLUE']] + val_column: Optional[str] + +class LinkifyDisplayerA(pydantic.BaseModel): + displayer: Literal["linkify"] + + +class PinnedRowConfig(pydantic.BaseModel): + primary_key_val: str + displayer_args: DisplayerArgs + + +class DFViewerConfig(pydantic.BaseModel): + pinned_rows: List[PinnedRowConfig] + column_config: List[ColumnConfig] + +DFData = List[Dict[str, Union[str, int, float, None]]] + +class DFWhole(pydantic.BaseModel): + dfviewer_config: DFViewerConfig + data: DFData + + +class DFMeta(pydantic.BaseModel): + """ + stats as calculated about the underlying dataframe. + Static, these don't change regardless of modification to the dataframe via styling or cleaning + """ + total_rows: int + columns: int + rows_shown: int + +class BuckarooOptions(pydantic.BaseModel): + """ + Buckaroo is opinionated. Each of these represent an opinion about an aspect of buckaroo. + The idea being that different opinions can be swapped through by the frontend + """ + df_list: List[str] #defaults to "base_df" + sampled: List[str] # sampling strategies + #maybe add "base_df" as an always present option... but also maybe + #not. PL_Compare won't really use it + summary_stats: List[str] + auto_clean: List[str] # which cleaning strategy + #reorderd_columns: List[str] #strategy for reordering cloumns + #styling: List[str] # which column ordering strategy + +class BuckarooState(pydantic.BaseModel): + """ + Given BuckarooOptions, the current state of the frontend. each str + will be one of the list from BuckarooOptions + """ + displayed_df: Union[str, Literal['base_df']] + sampled: Union[str, False] + summary_stats: Union[str, False] + show_commands: bool + auto_clean: Union[str, False] + #reorderd_columns: Union[str, False] + #styling: Union[str, False] + +class WidgetOptions(pydantic.BaseModel): + + + #How is summary_dict['all'] pulled out from df_dict. DFViewer gets a dfwhole and a summary_df + df_dict: Dict[str, DFWhole] + df_meta: DFMeta + operations: List[any] # don't think I have typing yet + operation_results: any # don't have typing yet + commandConfig: any # casing, fix. not typing + buckaroo_state: BuckarooState + buckaroo_options: BuckarooOptions + + +""" +auto_clean, reorderd_columns and styling all poke at the same things, and I'm not sure the best way to pull it apart. + +The trickiest example is lat/long. + +imagine a dataframe with a lat column and a long column. + +This should be a 'location' tuple that combines the two columns and is displayed as a map or link to a map... +But editting/combining columns is a whole dataframe operation. Which currently slots it into auto_clean. + +For display only, this makes sense as a post processing step. + +For autocleaning, it makes sense as a 'foreign key recognition step'. for citibike data, start_station name, start_station_id, start_station_latitude, start_station_longitude should be replaced with a categorical linking to a 'station enum'. They should be displayed as either "start station name", a map, or a link to the map geo coordinates. + +For now, I will leave it ambiguous. I will also consider a post_processing_step that has the same interface as auto_clean (df in, df out). + +This same attribute could be manipulated via styling like so. +separate lat/long columns -> display separately +tuple column tagged lat/long in summary stats -> display as link to map +tuple column tagged lat/long in summary stats -> display as inline map +categorical to 3 valued tuple (name, lat/long, id) -> display name +categorical to 3 valued tuple (name, lat/long, id) -> display tuple inline nested +categorical to 3 valued tuple (name, lat/long, id) -> display as link to map +categorical to 3 valued tuple (name, lat/long, id) -> display as map + + +Given the above data processing should go +raw -> auto_clean (pre-processing) -> summary_stats -> post_processing -> styling -> overrides + +I would also like to be able to write partial processing classes that can be combined. So you could just write the lat/long combination into tuple, without having to rewrite a whole auto cleaning command. These could be composed by programmers (not end users initially). + + +""" + + + +# class DfViewer(pydantic.BaseModel): +# type: 'DFViewer' +# df: DFWhole + +# #Ilike the serialization_alias... but luckily I avoid the need +# #because I don't have any snake cased fields + + + + +# def test_column_hints(): +# ColumnStringHint(type="string", histogram=[]) +# ColumnStringHint(type="string", histogram=[{'name':'foo', 'population':3500}]) +# with pytest.raises(ValidationError) as exc_info: +# errant_histogram_entry = {'name':'foo', 'no_population':3500} +# ColumnStringHint(type="string", histogram=[errant_histogram_entry]) +# assert exc_info.value.errors(include_url=False) == [ +# {'type': 'missing', 'loc': ('histogram', 0, 'population'), +# 'msg': 'Field required','input': errant_histogram_entry}] + +# ColumnBooleanHint(type="boolean", histogram=[]) + +# def test_column_hint_extra(): +# """verify that we can pass in extra unexpected keys""" +# ColumnStringHint(type="string", histogram=[], foo=8) + +# def test_dfwhole(): +# temp = {'schema': {'fields':[{'name':'foo', 'type':'integer'}], +# 'primaryKey':['foo'], 'pandas_version':'1.4.0'}, +# 'table_hints': {'foo':{'type':'string', 'histogram':[]}, +# 'bar':{'type':'integer', 'min_digits':2, 'max_digits':4, 'histogram':[]}, +# 'baz':{'type':'obj', 'histogram':[]}, +# }, +# 'data': [{'foo': 'hello', 'bar':8}, +# {'foo': 'world', 'bar':10}]} +# DFWhole(**temp) + +# def test_df_to_obj_pydantic(): +# named_index_df = pd.DataFrame( +# dict(foo=['one', 'two', 'three'], +# bar=[1, 2, 3])) + +# serialized_df = df_to_obj(named_index_df) +# print(json.dumps(serialized_df, indent=4)) +# DFWhole(**serialized_df) + +def bimodal(mean_1, mean_2, N, sigma=5): + X1 = np.random.normal(mean_1, sigma, int(N/2)) + X2 = np.random.normal(mean_2, sigma, int(N/2)) + X = np.concatenate([X1, X2]) + return X + +def rand_cat(named_p, na_per, N): + choices, p = [], [] + named_total_per = sum(named_p.values()) + na_per + total_len = int(np.floor(named_total_per * N)) + if named_total_per > 0: + for k, v in named_p.items(): + choices.append(k) + p.append(v/named_total_per) + choices.append(pd.NA) + p.append(na_per/named_total_per) + return [np.random.choice(choices, p=p) for k in range(total_len)] + return [] + +def random_categorical(named_p, unique_per, na_per, longtail_per, N): + choice_arr = rand_cat(named_p, na_per, N) + discrete_choice_len = len(choice_arr) + + longtail_count = int(np.floor(longtail_per * N))//2 + extra_arr = [] + for i in range(longtail_count): + extra_arr.append("long_%d" % i) + extra_arr.append("long_%d" % i) + + unique_len = N - (len(extra_arr) + discrete_choice_len) + for i in range(unique_len): + extra_arr.append("unique_%d" % i) + all_arr = np.concatenate([choice_arr, extra_arr]) + np.random.shuffle(all_arr) + try: + return pd.Series(all_arr, dtype='UInt64') + except Exception: # this is test fixture code + return pd.Series(all_arr, dtype=pd.StringDtype()) + + +def _test_df_to_obj_timing(): + N = 100_000 + df = pd.DataFrame({ + 'normal': np.random.normal(25, .3, N), + 'exponential' : np.random.exponential(1.0, N) * 10 , + 'increasing':[i for i in range(N)], + 'one': [1]*N, + 'dominant_categories': random_categorical({'foo': .6, 'bar': .25, 'baz':.15}, unique_per=0, na_per=0, longtail_per=0, N=N), + 'all_unique_cat': random_categorical({}, unique_per=1, na_per=0, longtail_per=0, N=N), + 'all_NA' : pd.Series([pd.NA] * N, dtype='UInt8'), + 'half_NA' : random_categorical({1: .55}, unique_per=0, na_per=.45, longtail_per=.0, N=N), + 'longtail' : random_categorical({}, unique_per=0, na_per=.2, longtail_per=.8, N=N), + 'longtail_unique' : random_categorical({}, unique_per=0.5, na_per=.0, longtail_per=.5, N=N)}) + + + start_serialize = time.time() + serialized_df = df_to_obj(df) + end_serialize = time.time() + DFWhole(**serialized_df) + end_pydantic = time.time() + + json.dumps(serialized_df) + end_json_time = time.time() + + serialize_time = end_serialize - start_serialize + pydantic_time = end_pydantic - end_serialize + json_time = end_json_time - end_pydantic + + print("serialize_time ", serialize_time) + print("pydantic_time ", pydantic_time) + print("json_time ", json_time) + + #pydantic time was about 1/5th of serialization time + #json.dumps time was around 2/5ths of serialization time + + #the following line triggers an error which will force printing + #1/0 diff --git a/tests/unit/serialization_utils_test.py b/tests/unit/serialization_utils_test.py new file mode 100644 index 000000000..1d20d7a8b --- /dev/null +++ b/tests/unit/serialization_utils_test.py @@ -0,0 +1,22 @@ +import pandas as pd +from buckaroo.serialization_utils import df_to_obj + +def test_df_to_obj(): + named_index_df = pd.DataFrame( + dict(names=['one', 'two', 'three'], + values=[1, 2, 3])).set_index('names') + + serialized_df = df_to_obj(named_index_df, {}) + assert serialized_df['data'][0]['names'] == 'one' + +# def test_int_overflow_validation(): +# value=float('nan') +# class Model(BaseModel): +# a: int +# Model(a=3) +# with pytest.raises(ValidationError) as exc_info: +# Model(a=value) +# assert exc_info.value.errors(include_url=False) == [ +# {'type': 'finite_number', 'loc': ('a',), 'msg': 'Input should be a finite number', +# 'input': value +# }] diff --git a/tsconfig.json b/tsconfig.json index 781206139..6c65b16c1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,8 @@ "compilerOptions": { "declaration": true, "esModuleInterop": true, - "lib": ["es2015", "dom"], + "allowSyntheticDefaultImports": true, + "lib": ["es2019", "dom", "dom.iterable"], "module": "commonjs", "moduleResolution": "node", "noEmitOnError": true, @@ -13,9 +14,19 @@ "skipLibCheck": true, "sourceMap": true, "strict": true, + "experimentalDecorators": true, // This allows us to initialize members in the "initialize" method "strictPropertyInitialization": false, - "target": "es2015" + "target": "es2015", + "jsx": "react", + "baseUrl": "." }, - "include": ["js/*.ts", "js/*.tsx", "js/core/*.ts", "js/core/*.tsx"] + "typeRoots": [ + "./js/typings", + "./node_modules/@types/" + ], + "include": ["js/*.ts", "js/*.tsx", "js/core/*.ts", "js/core/*.tsx", ], + "ts-node": { + "transpileOnly": true + } } diff --git a/webpack-local-dev.config.js b/webpack-local-dev.config.js new file mode 100644 index 000000000..5f17375b3 --- /dev/null +++ b/webpack-local-dev.config.js @@ -0,0 +1,184 @@ +const path = require('path'); +const version = require('./package.json').version; +//import {TsconfigPathsPlugin} from 'tsconfig-paths-webpack-plugin'; +const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); + +//import HtmlWebpackPlugin from 'html-webpack-plugin'; +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const luminoThemeImages = /^.*@lumino\/default-theme.*.png$/; + +const crypto = require('crypto'); + +// Workaround for loaders using "md4" by default, which is not supported in FIPS-compliant OpenSSL +const cryptoOrigCreateHash = crypto.createHash; +crypto.createHash = (algorithm) => + cryptoOrigCreateHash(algorithm == 'md4' ? 'sha256' : algorithm); + +const performance = { + maxAssetSize: 100_000_000, +}; + +// Custom webpack rules +const baseRules = [ + + { test: /\.js$/, loader: 'source-map-loader' }, + { test: /\.css$/, use: ['style-loader', 'css-loader'] }, + { + test: /\.scss$/, + use: [ + // We're in dev and want HMR, SCSS is handled in JS + // In production, we want our css as files + "style-loader", + "css-loader", + { + loader: "postcss-loader", + options: { + postcssOptions: { + plugins: [ + ["postcss-preset-env"], + ], + }, + }, + }, + "sass-loader" + ], + }, + { + test: luminoThemeImages, + issuer: /\.css$/, + use: { + loader: 'url-loader', + }, + }, + { + test: /\.(jpg|png|gif|woff|woff2)$/, + exclude: luminoThemeImages, + use: ['file-loader'], + }, + { + test: /\.md$/, + use: ['html-loader', 'markdown-loader'] + }, + { + test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, + issuer: /\.css$/, + use: { + loader: 'svg-url-loader', + options: { encoding: 'none', limit: 10000 }, + }, + }, +]; + + +const rules = [...baseRules, { test: /\.tsx?$/, loader: 'ts-loader' }]; +const demoRules = [...baseRules, + { + test: /\.tsx?$/, + loader: 'ts-loader', + options: { + transpileOnly: true, + configFile: 'examples/tsconfig.json' + } + }] + + +// Packages that shouldn't be bundled but loaded at runtime +const externals = ['@jupyter-widgets/base']; + +const resolve = { + // Add '.ts' and '.tsx' as resolvable extensions. + extensions: ['.webpack.js', '.web.js', '.ts', '.js', '.tsx'], + plugins: [new TsconfigPathsPlugin()], + fallback: { crypto: false }, +}; + +module.exports = [ +// the following section must be commented out for the nbextension to work +// I think it must be enabled for the dev mode of the react app to work + + { + entry: './examples/index-react18.tsx', + output: { + path: path.join(__dirname, '/examples/dist'), + filename: 'bundle.js' + }, + module: { + rules: demoRules, + }, + devtool: 'source-map', + externals, + resolve, + plugins: [new HtmlWebpackPlugin({ + //template: './examples/index.html' + template: './examples/index.html' + }), + new HtmlWebpackPlugin({ + filename: path.join(__dirname, '/examples/dist', 'index-iframe.html'), + template: 'examples/index-iframe.html', + // chunks: ['exampleEntry'] + }) + ], + performance + }, + + + /** + * Notebook extension + * + * This bundle only contains the part of the JavaScript that is run on load of + * the notebook. + */ + { + entry: './js/extension.ts', + output: { + filename: 'index.js', + path: path.resolve(__dirname, 'buckaroo', 'nbextension'), + libraryTarget: 'amd', + }, + module: { + rules: rules, + }, + devtool: 'source-map', + externals, + resolve, + // plugins: [new HtmlWebpackPlugin({ + // template: './examples/index.html' + // })] + performance + + + }, + + /** + * Embeddable buckaroo bundle + * + * This bundle is almost identical to the notebook extension bundle. The only + * difference is in the configuration of the webpack public path for the + * static assets. + * + * The target bundle is always `dist/index.js`, which is the path required by + * the custom widget embedder. + */ + { + entry: './js/index.ts', + output: { + filename: 'index.js', + path: path.resolve(__dirname, 'dist'), + libraryTarget: 'amd', + library: 'buckaroo', + publicPath: 'https://unpkg.com/buckaroo@' + version + '/dist/', + }, + devtool: 'source-map', + module: { + rules: rules, + }, + externals, + resolve, + devServer: { + port: 8030 + }, + performance + + }, + +]; diff --git a/webpack.config.js b/webpack.config.js index 1091c1b51..d55587cd6 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,10 @@ const path = require('path'); const version = require('./package.json').version; +//import {TsconfigPathsPlugin} from 'tsconfig-paths-webpack-plugin'; +const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); +//import HtmlWebpackPlugin from 'html-webpack-plugin'; +const HtmlWebpackPlugin = require('html-webpack-plugin'); const luminoThemeImages = /^.*@lumino\/default-theme.*.png$/; const crypto = require('crypto'); @@ -10,12 +14,35 @@ const cryptoOrigCreateHash = crypto.createHash; crypto.createHash = (algorithm) => cryptoOrigCreateHash(algorithm == 'md4' ? 'sha256' : algorithm); +const performance = { + maxAssetSize: 100_000_000, +}; // Custom webpack rules -const rules = [ - { test: /\.ts$/, loader: 'ts-loader' }, +const baseRules = [ + { test: /\.js$/, loader: 'source-map-loader' }, { test: /\.css$/, use: ['style-loader', 'css-loader'] }, + { + test: /\.scss$/, + use: [ + // We're in dev and want HMR, SCSS is handled in JS + // In production, we want our css as files + "style-loader", + "css-loader", + { + loader: "postcss-loader", + options: { + postcssOptions: { + plugins: [ + ["postcss-preset-env"], + ], + }, + }, + }, + "sass-loader" + ], + }, { test: luminoThemeImages, issuer: /\.css$/, @@ -24,10 +51,14 @@ const rules = [ }, }, { - test: /\.(jpg|png|gif)$/, + test: /\.(jpg|png|gif|woff|woff2)$/, exclude: luminoThemeImages, use: ['file-loader'], }, + { + test: /\.md$/, + use: ['html-loader', 'markdown-loader'] + }, { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, issuer: /\.css$/, @@ -38,12 +69,26 @@ const rules = [ }, ]; + +const rules = [...baseRules, { test: /\.tsx?$/, loader: 'ts-loader' }]; +const demoRules = [...baseRules, + { + test: /\.tsx?$/, + loader: 'ts-loader', + options: { + transpileOnly: true, + configFile: 'examples/tsconfig.json' + } + }] + + // Packages that shouldn't be bundled but loaded at runtime const externals = ['@jupyter-widgets/base']; const resolve = { // Add '.ts' and '.tsx' as resolvable extensions. - extensions: ['.webpack.js', '.web.js', '.ts', '.js'], + extensions: ['.webpack.js', '.web.js', '.ts', '.js', '.tsx'], + plugins: [new TsconfigPathsPlugin()], fallback: { crypto: false }, }; @@ -58,7 +103,7 @@ module.exports = [ entry: './js/extension.ts', output: { filename: 'index.js', - path: path.resolve(__dirname, 'ipydatagrid', 'nbextension'), + path: path.resolve(__dirname, 'buckaroo', 'nbextension'), libraryTarget: 'amd', }, module: { @@ -67,10 +112,16 @@ module.exports = [ devtool: 'source-map', externals, resolve, + // plugins: [new HtmlWebpackPlugin({ + // template: './examples/index.html' + // })] + performance + + }, /** - * Embeddable ipydatagrid bundle + * Embeddable buckaroo bundle * * This bundle is almost identical to the notebook extension bundle. The only * difference is in the configuration of the webpack public path for the @@ -85,8 +136,8 @@ module.exports = [ filename: 'index.js', path: path.resolve(__dirname, 'dist'), libraryTarget: 'amd', - library: 'ipydatagrid', - publicPath: 'https://unpkg.com/ipydatagrid@' + version + '/dist/', + library: 'buckaroo', + publicPath: 'https://unpkg.com/buckaroo@' + version + '/dist/', }, devtool: 'source-map', module: { @@ -94,6 +145,11 @@ module.exports = [ }, externals, resolve, + devServer: { + port: 8030 + }, + performance + }, /** @@ -106,7 +162,7 @@ module.exports = [ output: { filename: 'embed-bundle.js', path: path.resolve(__dirname, 'docs', 'source', '_static'), - library: 'ipydatagrid', + library: 'buckaroo', libraryTarget: 'amd', }, module: { @@ -115,5 +171,7 @@ module.exports = [ devtool: 'source-map', externals, resolve, + performance + }, ]; diff --git a/yarn.lock b/yarn.lock index 49fecfde6..78495acb3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,34 +2,27 @@ # yarn lockfile v1 -"@ag-grid-community/client-side-row-model@^29.2.0": - version "29.2.0" - resolved "https://registry.yarnpkg.com/@ag-grid-community/client-side-row-model/-/client-side-row-model-29.2.0.tgz#edb0184431c407ee7cca17d48c7e5bd2fa707919" - integrity sha512-GkLkwhGh1reV34MNuhv0it8M00/aV62Xjd/5qbMNan2oYZnEHOrn2I7OBDEHKHMjajWyV5lTOGTcKBmh/HXUMQ== - dependencies: - "@ag-grid-community/core" "~29.2.0" - -"@ag-grid-community/core@~29.2.0": - version "29.2.0" - resolved "https://registry.yarnpkg.com/@ag-grid-community/core/-/core-29.2.0.tgz#03a0f214448a64444b6a6d943f1c5962c4564c2c" - integrity sha512-1G0X3DrCCfH/vngBXz5rKRhlNmb/WPy/kTtfy/Yo+XOAChs+lgMGG/dgurY/blRyCaMQsUO3aZoJmcckYG4/eQ== +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@ampproject/remapping@^2.1.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" - integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== +"@ampproject/remapping@^2.2.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== dependencies: - "@jridgewell/gen-mapping" "^0.1.0" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" "@babel/cli@^7.6.3": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.19.3.tgz#55914ed388e658e0b924b3a95da1296267e278e2" - integrity sha512-643/TybmaCAe101m2tSVHi9UKpETXP9c/Ff4mD2tAwkdP6esKIfaauZFc67vGEM6r9fekbEGid+sZhbEnSe3dg== + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.24.1.tgz#2e11e071e32fe82850b4fe514f56b9c9e1c44911" + integrity sha512-HbmrtxyFUr34LwAlV9jS+sSIjUp4FpdtIMGwgufY3AsxrIfsh/HxlMTywsONAZsU0RMYbZtbZFpUCrSGs7o0EA== dependencies: - "@jridgewell/trace-mapping" "^0.3.8" + "@jridgewell/trace-mapping" "^0.3.25" commander "^4.0.1" - convert-source-map "^1.1.0" + convert-source-map "^2.0.0" fs-readdir-recursive "^1.1.0" glob "^7.2.0" make-dir "^2.1.0" @@ -38,414 +31,290 @@ "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3" chokidar "^3.4.0" -"@babel/code-frame@7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" - integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== - dependencies: - "@babel/highlight" "^7.10.4" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2", "@babel/code-frame@^7.8.3": + version "7.24.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" + integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== dependencies: - "@babel/highlight" "^7.18.6" + "@babel/highlight" "^7.24.2" + picocolors "^1.0.0" -"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.19.3", "@babel/compat-data@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.4.tgz#95c86de137bf0317f3a570e1b6e996b427299747" - integrity sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw== +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.5", "@babel/compat-data@^7.24.4": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a" + integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ== "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.6.3": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.6.tgz#7122ae4f5c5a37c0946c066149abd8e75f81540f" - integrity sha512-D2Ue4KHpc6Ys2+AxpIx1BZ8+UegLLLE2p3KJEuJRKmokHOtl49jQ5ny1773KsGLZs8MQvBidAF6yWUJxRqtKtg== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.19.6" - "@babel/helper-compilation-targets" "^7.19.3" - "@babel/helper-module-transforms" "^7.19.6" - "@babel/helpers" "^7.19.4" - "@babel/parser" "^7.19.6" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.6" - "@babel/types" "^7.19.4" - convert-source-map "^1.7.0" + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.4.tgz#1f758428e88e0d8c563874741bc4ffc4f71a4717" + integrity sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.24.2" + "@babel/generator" "^7.24.4" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.24.4" + "@babel/parser" "^7.24.4" + "@babel/template" "^7.24.0" + "@babel/traverse" "^7.24.1" + "@babel/types" "^7.24.0" + convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.2.1" - semver "^6.3.0" + json5 "^2.2.3" + semver "^6.3.1" -"@babel/generator@^7.19.6", "@babel/generator@^7.7.2": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.6.tgz#9e481a3fe9ca6261c972645ae3904ec0f9b34a1d" - integrity sha512-oHGRUQeoX1QrKeJIKVe0hwjGqNnVYsM5Nep5zo0uE0m42sLH+Fsd2pStJ5sRM1bNyTUUoz0pe2lTeMJrb/taTA== +"@babel/generator@^7.24.1", "@babel/generator@^7.24.4", "@babel/generator@^7.7.2": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.4.tgz#1fc55532b88adf952025d5d2d1e71f946cb1c498" + integrity sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw== dependencies: - "@babel/types" "^7.19.4" - "@jridgewell/gen-mapping" "^0.3.2" + "@babel/types" "^7.24.0" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" -"@babel/helper-annotate-as-pure@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" - integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" - integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.18.6" - "@babel/types" "^7.18.9" - -"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.19.0", "@babel/helper-compilation-targets@^7.19.3": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz#a10a04588125675d7c7ae299af86fa1b2ee038ca" - integrity sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg== - dependencies: - "@babel/compat-data" "^7.19.3" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.21.3" - semver "^6.3.0" - -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz#bfd6904620df4e46470bae4850d66be1054c404b" - integrity sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-member-expression-to-functions" "^7.18.9" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-replace-supers" "^7.18.9" - "@babel/helper-split-export-declaration" "^7.18.6" - -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" - integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - regexpu-core "^5.1.0" - -"@babel/helper-define-polyfill-provider@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" - integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== +"@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz#5426b109cf3ad47b91120f8328d8ab1be8b0b956" + integrity sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== + dependencies: + "@babel/compat-data" "^7.23.5" + "@babel/helper-validator-option" "^7.23.5" + browserslist "^4.22.2" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.24.1", "@babel/helper-create-class-features-plugin@^7.24.4": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz#c806f73788a6800a5cfbbc04d2df7ee4d927cce3" + integrity sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-member-expression-to-functions" "^7.23.0" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.24.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.15", "@babel/helper-create-regexp-features-plugin@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz#5ee90093914ea09639b01c711db0d6775e558be1" + integrity sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + regexpu-core "^5.3.1" + semver "^6.3.1" + +"@babel/helper-define-polyfill-provider@^0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz#fadc63f0c2ff3c8d02ed905dcea747c5b0fb74fd" + integrity sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA== dependencies: - "@babel/helper-compilation-targets" "^7.17.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" debug "^4.1.1" lodash.debounce "^4.0.8" resolve "^1.14.2" - semver "^6.1.2" -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== -"@babel/helper-explode-assignable-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" - integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== +"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== dependencies: - "@babel/types" "^7.18.6" + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" -"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" - integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== dependencies: - "@babel/template" "^7.18.10" - "@babel/types" "^7.19.0" + "@babel/types" "^7.22.5" -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== +"@babel/helper-member-expression-to-functions@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" + integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.23.0" + +"@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.24.1": + version "7.24.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128" + integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg== + dependencies: + "@babel/types" "^7.24.0" -"@babel/helper-member-expression-to-functions@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" - integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== - dependencies: - "@babel/types" "^7.18.9" - -"@babel/helper-module-imports@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.6": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.6.tgz#6c52cc3ac63b70952d33ee987cbee1c9368b533f" - integrity sha512-fCmcfQo/KYr/VXXDIyd3CBGZ6AFhPFy1TfSEJ+PilGVlQT6jcbqtHAM4C1EciRqMza7/TpOUZliuSH+U6HAhJw== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.19.4" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.19.1" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.6" - "@babel/types" "^7.19.4" - -"@babel/helper-optimise-call-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" - integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" - integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== - -"@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" - integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-wrap-function" "^7.18.9" - "@babel/types" "^7.18.9" - -"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.18.9": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" - integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-member-expression-to-functions" "^7.18.9" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/traverse" "^7.19.1" - "@babel/types" "^7.19.0" - -"@babel/helper-simple-access@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.19.4.tgz#be553f4951ac6352df2567f7daa19a0ee15668e7" - integrity sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg== - dependencies: - "@babel/types" "^7.19.4" - -"@babel/helper-skip-transparent-expression-wrappers@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz#778d87b3a758d90b471e7b9918f34a9a02eb5818" - integrity sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw== - dependencies: - "@babel/types" "^7.18.9" - -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-string-parser@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" - integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== - -"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== - -"@babel/helper-validator-option@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" - integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== - -"@babel/helper-wrap-function@^7.18.9": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1" - integrity sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg== - dependencies: - "@babel/helper-function-name" "^7.19.0" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.0" - "@babel/types" "^7.19.0" - -"@babel/helpers@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.4.tgz#42154945f87b8148df7203a25c31ba9a73be46c5" - integrity sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw== - dependencies: - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.4" - "@babel/types" "^7.19.4" - -"@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" +"@babel/helper-module-transforms@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" + integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/helper-optimise-call-expression@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" + integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a" + integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== + +"@babel/helper-remap-async-to-generator@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0" + integrity sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-wrap-function" "^7.22.20" + +"@babel/helper-replace-supers@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz#7085bd19d4a0b7ed8f405c1ed73ccb70f323abc1" + integrity sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-member-expression-to-functions" "^7.23.0" + "@babel/helper-optimise-call-expression" "^7.22.5" + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" + integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.23.4": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e" + integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/helper-validator-option@^7.16.7", "@babel/helper-validator-option@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" + integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== + +"@babel/helper-wrap-function@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz#15352b0b9bfb10fc9c76f79f6342c00e3411a569" + integrity sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw== + dependencies: + "@babel/helper-function-name" "^7.22.5" + "@babel/template" "^7.22.15" + "@babel/types" "^7.22.19" + +"@babel/helpers@^7.24.4": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.4.tgz#dc00907fd0d95da74563c142ef4cd21f2cb856b6" + integrity sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw== + dependencies: + "@babel/template" "^7.24.0" + "@babel/traverse" "^7.24.1" + "@babel/types" "^7.24.0" + +"@babel/highlight@^7.24.2": + version "7.24.2" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.2.tgz#3f539503efc83d3c59080a10e6634306e0370d26" + integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" js-tokens "^4.0.0" + picocolors "^1.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.18.10", "@babel/parser@^7.19.6": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.6.tgz#b923430cb94f58a7eae8facbffa9efd19130e7f8" - integrity sha512-h1IUp81s2JYJ3mRkdxJgs4UvmSsRvDrx5ICSJbPvtWYv5i1nTBGcBpnog+89rAFMwvvru6E5NUHdBe01UeSzYA== - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" - integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50" - integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" - "@babel/plugin-proposal-optional-chaining" "^7.18.9" - -"@babel/plugin-proposal-async-generator-functions@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz#34f6f5174b688529342288cd264f80c9ea9fb4a7" - integrity sha512-0yu8vNATgLy4ivqMNBIwb1HebCelqN7YX8SL3FDXORv/RqT0zEEWUCH4GH44JsSrvCu6GqnAdR5EBFAPeNBB4Q== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/helper-remap-async-to-generator" "^7.18.9" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-proposal-class-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" - integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-proposal-class-static-block@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" - integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - -"@babel/plugin-proposal-dynamic-import@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" - integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - -"@babel/plugin-proposal-export-namespace-from@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" - integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-proposal-json-strings@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" - integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-json-strings" "^7.8.3" - -"@babel/plugin-proposal-logical-assignment-operators@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23" - integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" - integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - -"@babel/plugin-proposal-numeric-separator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" - integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-object-rest-spread@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.19.4.tgz#a8fc86e8180ff57290c91a75d83fe658189b642d" - integrity sha512-wHmj6LDxVDnL+3WhXteUBaoM1aVILZODAUjg11kHqG4cOlfgMQGxw6aCgvrXrmaJR3Bn14oZhImyCPZzRpC93Q== - dependencies: - "@babel/compat-data" "^7.19.4" - "@babel/helper-compilation-targets" "^7.19.3" - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.18.8" +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.24.0", "@babel/parser@^7.24.1", "@babel/parser@^7.24.4": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.4.tgz#234487a110d89ad5a3ed4a8a566c36b9453e8c88" + integrity sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg== -"@babel/plugin-proposal-optional-catch-binding@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" - integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.4": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.4.tgz#6125f0158543fb4edf1c22f322f3db67f21cb3e1" + integrity sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-proposal-optional-chaining@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993" - integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz#b645d9ba8c2bc5b7af50f0fe949f9edbeb07c8cf" + integrity sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-proposal-private-methods@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" - integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz#da8261f2697f0f41b0855b91d3a20a1fbfd271d3" + integrity sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-transform-optional-chaining" "^7.24.1" -"@babel/plugin-proposal-private-property-in-object@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503" - integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw== +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz#1181d9685984c91d657b8ddf14f0487a6bab2988" + integrity sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw== dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" - integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -489,14 +358,21 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-import-assertions@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz#cd6190500a4fa2fe31990a963ffab4b63e4505e4" - integrity sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ== +"@babel/plugin-syntax-import-assertions@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz#db3aad724153a00eaac115a3fb898de544e34971" + integrity sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-syntax-import-meta@^7.8.3": +"@babel/plugin-syntax-import-attributes@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz#c66b966c63b714c4eec508fcf5763b1f2d381093" + integrity sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + +"@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== @@ -566,304 +442,440 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.18.6", "@babel/plugin-syntax-typescript@^7.7.2": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz#1c09cd25795c7c2b8a4ba9ae49394576d4133285" - integrity sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA== +"@babel/plugin-syntax-typescript@^7.24.1", "@babel/plugin-syntax-typescript@^7.7.2": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz#b3bcc51f396d15f3591683f90239de143c076844" + integrity sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-arrow-functions@^7.18.6": +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" - integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-async-to-generator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" - integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== +"@babel/plugin-transform-arrow-functions@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz#2bf263617060c9cc45bcdbf492b8cc805082bf27" + integrity sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw== dependencies: - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-remap-async-to-generator" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-block-scoped-functions@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" - integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== +"@babel/plugin-transform-async-generator-functions@^7.24.3": + version "7.24.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz#8fa7ae481b100768cc9842c8617808c5352b8b89" + integrity sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-remap-async-to-generator" "^7.22.20" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-transform-async-to-generator@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz#0e220703b89f2216800ce7b1c53cb0cf521c37f4" + integrity sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw== + dependencies: + "@babel/helper-module-imports" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-remap-async-to-generator" "^7.22.20" + +"@babel/plugin-transform-block-scoped-functions@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz#1c94799e20fcd5c4d4589523bbc57b7692979380" + integrity sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + +"@babel/plugin-transform-block-scoping@^7.24.4": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.4.tgz#28f5c010b66fbb8ccdeef853bef1935c434d7012" + integrity sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + +"@babel/plugin-transform-class-properties@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz#bcbf1aef6ba6085cfddec9fc8d58871cf011fc29" + integrity sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-block-scoping@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.19.4.tgz#315d70f68ce64426db379a3d830e7ac30be02e9b" - integrity sha512-934S2VLLlt2hRJwPf4MczaOr4hYF0z+VKPwqTNxyKX7NthTiPfhuKFWQZHXRM0vh/wo/VyXB3s4bZUNA08l+tQ== - dependencies: - "@babel/helper-plugin-utils" "^7.19.0" - -"@babel/plugin-transform-classes@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz#0e61ec257fba409c41372175e7c1e606dc79bb20" - integrity sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-compilation-targets" "^7.19.0" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/helper-replace-supers" "^7.18.9" - "@babel/helper-split-export-declaration" "^7.18.6" +"@babel/plugin-transform-class-static-block@^7.24.4": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz#1a4653c0cf8ac46441ec406dece6e9bc590356a4" + integrity sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.4" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-transform-classes@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz#5bc8fc160ed96378184bc10042af47f50884dcb1" + integrity sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-replace-supers" "^7.24.1" + "@babel/helper-split-export-declaration" "^7.22.6" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" - integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw== +"@babel/plugin-transform-computed-properties@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz#bc7e787f8e021eccfb677af5f13c29a9934ed8a7" + integrity sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/template" "^7.24.0" -"@babel/plugin-transform-destructuring@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.19.4.tgz#46890722687b9b89e1369ad0bd8dc6c5a3b4319d" - integrity sha512-t0j0Hgidqf0aM86dF8U+vXYReUgJnlv4bZLsyoPnwZNrGY+7/38o8YjaELrvHeVfTZao15kjR0PVv0nju2iduA== +"@babel/plugin-transform-destructuring@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz#b1e8243af4a0206841973786292b8c8dd8447345" + integrity sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw== dependencies: - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" - integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== +"@babel/plugin-transform-dotall-regex@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz#d56913d2f12795cc9930801b84c6f8c47513ac13" + integrity sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-duplicate-keys@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" - integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== +"@babel/plugin-transform-duplicate-keys@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz#5347a797fe82b8d09749d10e9f5b83665adbca88" + integrity sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-exponentiation-operator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" - integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== +"@babel/plugin-transform-dynamic-import@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz#2a5a49959201970dd09a5fca856cb651e44439dd" + integrity sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-transform-for-of@^7.18.8": - version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" - integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== +"@babel/plugin-transform-exponentiation-operator@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz#6650ebeb5bd5c012d5f5f90a26613a08162e8ba4" + integrity sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.15" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-function-name@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" - integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== +"@babel/plugin-transform-export-namespace-from@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz#f033541fc036e3efb2dcb58eedafd4f6b8078acd" + integrity sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ== dependencies: - "@babel/helper-compilation-targets" "^7.18.9" - "@babel/helper-function-name" "^7.18.9" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-transform-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" - integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== +"@babel/plugin-transform-for-of@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz#67448446b67ab6c091360ce3717e7d3a59e202fd" + integrity sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" -"@babel/plugin-transform-member-expression-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" - integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== +"@babel/plugin-transform-function-name@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz#8cba6f7730626cc4dfe4ca2fa516215a0592b361" + integrity sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-modules-amd@^7.18.6": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.19.6.tgz#aca391801ae55d19c4d8d2ebfeaa33df5f2a2cbd" - integrity sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg== +"@babel/plugin-transform-json-strings@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz#08e6369b62ab3e8a7b61089151b161180c8299f7" + integrity sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ== dependencies: - "@babel/helper-module-transforms" "^7.19.6" - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-transform-modules-commonjs@^7.18.6": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.19.6.tgz#25b32feef24df8038fc1ec56038917eacb0b730c" - integrity sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ== +"@babel/plugin-transform-literals@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz#0a1982297af83e6b3c94972686067df588c5c096" + integrity sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g== dependencies: - "@babel/helper-module-transforms" "^7.19.6" - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/helper-simple-access" "^7.19.4" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-modules-systemjs@^7.19.0": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.6.tgz#59e2a84064b5736a4471b1aa7b13d4431d327e0d" - integrity sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ== +"@babel/plugin-transform-logical-assignment-operators@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz#719d8aded1aa94b8fb34e3a785ae8518e24cfa40" + integrity sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w== dependencies: - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-module-transforms" "^7.19.6" - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/helper-validator-identifier" "^7.19.1" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-transform-modules-umd@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" - integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== +"@babel/plugin-transform-member-expression-literals@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz#896d23601c92f437af8b01371ad34beb75df4489" + integrity sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg== dependencies: - "@babel/helper-module-transforms" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888" - integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw== +"@babel/plugin-transform-modules-amd@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz#b6d829ed15258536977e9c7cc6437814871ffa39" + integrity sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.19.0" - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-new-target@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" - integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== +"@babel/plugin-transform-modules-commonjs@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz#e71ba1d0d69e049a22bf90b3867e263823d3f1b9" + integrity sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-simple-access" "^7.22.5" -"@babel/plugin-transform-object-super@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" - integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== +"@babel/plugin-transform-modules-systemjs@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz#2b9625a3d4e445babac9788daec39094e6b11e3e" + integrity sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-validator-identifier" "^7.22.20" -"@babel/plugin-transform-parameters@^7.18.8": - version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz#ee9f1a0ce6d78af58d0956a9378ea3427cccb48a" - integrity sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg== +"@babel/plugin-transform-modules-umd@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz#69220c66653a19cf2c0872b9c762b9a48b8bebef" + integrity sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-property-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" - integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== +"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f" + integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-regenerator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73" - integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ== +"@babel/plugin-transform-new-target@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz#29c59988fa3d0157de1c871a28cd83096363cc34" + integrity sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - regenerator-transform "^0.15.0" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-reserved-words@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" - integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== +"@babel/plugin-transform-nullish-coalescing-operator@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz#0cd494bb97cb07d428bd651632cb9d4140513988" + integrity sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-transform-shorthand-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" - integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== +"@babel/plugin-transform-numeric-separator@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz#5bc019ce5b3435c1cadf37215e55e433d674d4e8" + integrity sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-transform-spread@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" - integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== +"@babel/plugin-transform-object-rest-spread@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz#5a3ce73caf0e7871a02e1c31e8b473093af241ff" + integrity sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA== dependencies: - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.24.1" -"@babel/plugin-transform-sticky-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" - integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== +"@babel/plugin-transform-object-super@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz#e71d6ab13483cca89ed95a474f542bbfc20a0520" + integrity sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-replace-supers" "^7.24.1" -"@babel/plugin-transform-template-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" - integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== +"@babel/plugin-transform-optional-catch-binding@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz#92a3d0efe847ba722f1a4508669b23134669e2da" + integrity sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-transform-typeof-symbol@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" - integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== +"@babel/plugin-transform-optional-chaining@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz#26e588acbedce1ab3519ac40cc748e380c5291e6" + integrity sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-transform-typescript@^7.18.6": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.3.tgz#4f1db1e0fe278b42ddbc19ec2f6cd2f8262e35d6" - integrity sha512-z6fnuK9ve9u/0X0rRvI9MY0xg+DOUaABDYOe+/SQTxtlptaBB/V9JIUxJn6xp3lMBeb9qe8xSFmHU35oZDXD+w== +"@babel/plugin-transform-parameters@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz#983c15d114da190506c75b616ceb0f817afcc510" + integrity sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.19.0" - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/plugin-syntax-typescript" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-unicode-escapes@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" - integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== +"@babel/plugin-transform-private-methods@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz#a0faa1ae87eff077e1e47a5ec81c3aef383dc15a" + integrity sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-create-class-features-plugin" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-unicode-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" - integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== +"@babel/plugin-transform-private-property-in-object@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz#756443d400274f8fb7896742962cc1b9f25c1f6a" + integrity sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-transform-property-literals@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz#d6a9aeab96f03749f4eebeb0b6ea8e90ec958825" + integrity sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + +"@babel/plugin-transform-regenerator@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz#625b7545bae52363bdc1fbbdc7252b5046409c8c" + integrity sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + regenerator-transform "^0.15.2" + +"@babel/plugin-transform-reserved-words@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz#8de729f5ecbaaf5cf83b67de13bad38a21be57c1" + integrity sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + +"@babel/plugin-transform-shorthand-properties@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz#ba9a09144cf55d35ec6b93a32253becad8ee5b55" + integrity sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + +"@babel/plugin-transform-spread@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz#a1acf9152cbf690e4da0ba10790b3ac7d2b2b391" + integrity sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + +"@babel/plugin-transform-sticky-regex@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz#f03e672912c6e203ed8d6e0271d9c2113dc031b9" + integrity sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + +"@babel/plugin-transform-template-literals@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz#15e2166873a30d8617e3e2ccadb86643d327aab7" + integrity sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + +"@babel/plugin-transform-typeof-symbol@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz#6831f78647080dec044f7e9f68003d99424f94c7" + integrity sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/preset-env@^7.6.3": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.19.4.tgz#4c91ce2e1f994f717efb4237891c3ad2d808c94b" - integrity sha512-5QVOTXUdqTCjQuh2GGtdd7YEhoRXBMVGROAtsBeLGIbIz3obCBIfRMT1I3ZKkMgNzwkyCkftDXSSkHxnfVf4qg== - dependencies: - "@babel/compat-data" "^7.19.4" - "@babel/helper-compilation-targets" "^7.19.3" - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/helper-validator-option" "^7.18.6" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9" - "@babel/plugin-proposal-async-generator-functions" "^7.19.1" - "@babel/plugin-proposal-class-properties" "^7.18.6" - "@babel/plugin-proposal-class-static-block" "^7.18.6" - "@babel/plugin-proposal-dynamic-import" "^7.18.6" - "@babel/plugin-proposal-export-namespace-from" "^7.18.9" - "@babel/plugin-proposal-json-strings" "^7.18.6" - "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6" - "@babel/plugin-proposal-numeric-separator" "^7.18.6" - "@babel/plugin-proposal-object-rest-spread" "^7.19.4" - "@babel/plugin-proposal-optional-catch-binding" "^7.18.6" - "@babel/plugin-proposal-optional-chaining" "^7.18.9" - "@babel/plugin-proposal-private-methods" "^7.18.6" - "@babel/plugin-proposal-private-property-in-object" "^7.18.6" - "@babel/plugin-proposal-unicode-property-regex" "^7.18.6" +"@babel/plugin-transform-typescript@^7.16.7": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.4.tgz#03e0492537a4b953e491f53f2bc88245574ebd15" + integrity sha512-79t3CQ8+oBGk/80SQ8MN3Bs3obf83zJ0YZjDmDaEZN8MqhMI760apl5z6a20kFeMXBwJX99VpKT8CKxEBp5H1g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.24.4" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-typescript" "^7.24.1" + +"@babel/plugin-transform-unicode-escapes@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz#fb3fa16676549ac7c7449db9b342614985c2a3a4" + integrity sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + +"@babel/plugin-transform-unicode-property-regex@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz#56704fd4d99da81e5e9f0c0c93cabd91dbc4889e" + integrity sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.24.0" + +"@babel/plugin-transform-unicode-regex@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz#57c3c191d68f998ac46b708380c1ce4d13536385" + integrity sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.24.0" + +"@babel/plugin-transform-unicode-sets-regex@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz#c1ea175b02afcffc9cf57a9c4658326625165b7f" + integrity sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.24.0" + +"@babel/preset-env@^7.6.11": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.4.tgz#46dbbcd608771373b88f956ffb67d471dce0d23b" + integrity sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A== + dependencies: + "@babel/compat-data" "^7.24.4" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-validator-option" "^7.23.5" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.4" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.1" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.1" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.1" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.18.6" + "@babel/plugin-syntax-import-assertions" "^7.24.1" + "@babel/plugin-syntax-import-attributes" "^7.24.1" + "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" @@ -873,105 +885,124 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.18.6" - "@babel/plugin-transform-async-to-generator" "^7.18.6" - "@babel/plugin-transform-block-scoped-functions" "^7.18.6" - "@babel/plugin-transform-block-scoping" "^7.19.4" - "@babel/plugin-transform-classes" "^7.19.0" - "@babel/plugin-transform-computed-properties" "^7.18.9" - "@babel/plugin-transform-destructuring" "^7.19.4" - "@babel/plugin-transform-dotall-regex" "^7.18.6" - "@babel/plugin-transform-duplicate-keys" "^7.18.9" - "@babel/plugin-transform-exponentiation-operator" "^7.18.6" - "@babel/plugin-transform-for-of" "^7.18.8" - "@babel/plugin-transform-function-name" "^7.18.9" - "@babel/plugin-transform-literals" "^7.18.9" - "@babel/plugin-transform-member-expression-literals" "^7.18.6" - "@babel/plugin-transform-modules-amd" "^7.18.6" - "@babel/plugin-transform-modules-commonjs" "^7.18.6" - "@babel/plugin-transform-modules-systemjs" "^7.19.0" - "@babel/plugin-transform-modules-umd" "^7.18.6" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1" - "@babel/plugin-transform-new-target" "^7.18.6" - "@babel/plugin-transform-object-super" "^7.18.6" - "@babel/plugin-transform-parameters" "^7.18.8" - "@babel/plugin-transform-property-literals" "^7.18.6" - "@babel/plugin-transform-regenerator" "^7.18.6" - "@babel/plugin-transform-reserved-words" "^7.18.6" - "@babel/plugin-transform-shorthand-properties" "^7.18.6" - "@babel/plugin-transform-spread" "^7.19.0" - "@babel/plugin-transform-sticky-regex" "^7.18.6" - "@babel/plugin-transform-template-literals" "^7.18.9" - "@babel/plugin-transform-typeof-symbol" "^7.18.9" - "@babel/plugin-transform-unicode-escapes" "^7.18.10" - "@babel/plugin-transform-unicode-regex" "^7.18.6" - "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.19.4" - babel-plugin-polyfill-corejs2 "^0.3.3" - babel-plugin-polyfill-corejs3 "^0.6.0" - babel-plugin-polyfill-regenerator "^0.4.1" - core-js-compat "^3.25.1" - semver "^6.3.0" - -"@babel/preset-modules@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" - integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.24.1" + "@babel/plugin-transform-async-generator-functions" "^7.24.3" + "@babel/plugin-transform-async-to-generator" "^7.24.1" + "@babel/plugin-transform-block-scoped-functions" "^7.24.1" + "@babel/plugin-transform-block-scoping" "^7.24.4" + "@babel/plugin-transform-class-properties" "^7.24.1" + "@babel/plugin-transform-class-static-block" "^7.24.4" + "@babel/plugin-transform-classes" "^7.24.1" + "@babel/plugin-transform-computed-properties" "^7.24.1" + "@babel/plugin-transform-destructuring" "^7.24.1" + "@babel/plugin-transform-dotall-regex" "^7.24.1" + "@babel/plugin-transform-duplicate-keys" "^7.24.1" + "@babel/plugin-transform-dynamic-import" "^7.24.1" + "@babel/plugin-transform-exponentiation-operator" "^7.24.1" + "@babel/plugin-transform-export-namespace-from" "^7.24.1" + "@babel/plugin-transform-for-of" "^7.24.1" + "@babel/plugin-transform-function-name" "^7.24.1" + "@babel/plugin-transform-json-strings" "^7.24.1" + "@babel/plugin-transform-literals" "^7.24.1" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.1" + "@babel/plugin-transform-member-expression-literals" "^7.24.1" + "@babel/plugin-transform-modules-amd" "^7.24.1" + "@babel/plugin-transform-modules-commonjs" "^7.24.1" + "@babel/plugin-transform-modules-systemjs" "^7.24.1" + "@babel/plugin-transform-modules-umd" "^7.24.1" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" + "@babel/plugin-transform-new-target" "^7.24.1" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.1" + "@babel/plugin-transform-numeric-separator" "^7.24.1" + "@babel/plugin-transform-object-rest-spread" "^7.24.1" + "@babel/plugin-transform-object-super" "^7.24.1" + "@babel/plugin-transform-optional-catch-binding" "^7.24.1" + "@babel/plugin-transform-optional-chaining" "^7.24.1" + "@babel/plugin-transform-parameters" "^7.24.1" + "@babel/plugin-transform-private-methods" "^7.24.1" + "@babel/plugin-transform-private-property-in-object" "^7.24.1" + "@babel/plugin-transform-property-literals" "^7.24.1" + "@babel/plugin-transform-regenerator" "^7.24.1" + "@babel/plugin-transform-reserved-words" "^7.24.1" + "@babel/plugin-transform-shorthand-properties" "^7.24.1" + "@babel/plugin-transform-spread" "^7.24.1" + "@babel/plugin-transform-sticky-regex" "^7.24.1" + "@babel/plugin-transform-template-literals" "^7.24.1" + "@babel/plugin-transform-typeof-symbol" "^7.24.1" + "@babel/plugin-transform-unicode-escapes" "^7.24.1" + "@babel/plugin-transform-unicode-property-regex" "^7.24.1" + "@babel/plugin-transform-unicode-regex" "^7.24.1" + "@babel/plugin-transform-unicode-sets-regex" "^7.24.1" + "@babel/preset-modules" "0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.4" + babel-plugin-polyfill-regenerator "^0.6.1" + core-js-compat "^3.31.0" + semver "^6.3.1" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-typescript@^7.6.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" - integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== +"@babel/preset-typescript@7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" + integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-validator-option" "^7.18.6" - "@babel/plugin-transform-typescript" "^7.18.6" - -"@babel/runtime@^7.1.2", "@babel/runtime@^7.8.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.4.tgz#a42f814502ee467d55b38dd1c256f53a7b885c78" - integrity sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.18.10", "@babel/template@^7.3.3": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" - integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.10" - "@babel/types" "^7.18.10" - -"@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.19.4", "@babel/traverse@^7.19.6", "@babel/traverse@^7.7.2": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.6.tgz#7b4c865611df6d99cb131eec2e8ac71656a490dc" - integrity sha512-6l5HrUCzFM04mfbG09AagtYyR2P0B71B1wN7PfSPiksDPz2k5H9CBC1tcZpz2M8OxbKTPccByoOJ22rUKbpmQQ== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.19.6" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.19.6" - "@babel/types" "^7.19.4" - debug "^4.1.0" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-option" "^7.16.7" + "@babel/plugin-transform-typescript" "^7.16.7" + +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== + +"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd" + integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.22.15", "@babel/template@^7.24.0", "@babel/template@^7.3.3": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" + integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/parser" "^7.24.0" + "@babel/types" "^7.24.0" + +"@babel/traverse@^7.24.1", "@babel/traverse@^7.7.2": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.1.tgz#d65c36ac9dd17282175d1e4a3c49d5b7988f530c" + integrity sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ== + dependencies: + "@babel/code-frame" "^7.24.1" + "@babel/generator" "^7.24.1" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.24.1" + "@babel/types" "^7.24.0" + debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.19.4", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.4.tgz#0dd5c91c573a202d600490a35b33246fed8a41c7" - integrity sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw== +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.24.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf" + integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w== dependencies: - "@babel/helper-string-parser" "^7.19.4" - "@babel/helper-validator-identifier" "^7.19.1" + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" "@bcoe/v8-coverage@^0.2.3": @@ -979,92 +1010,167 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@blueprintjs/colors@^4.0.0-alpha.3": - version "4.1.7" - resolved "https://registry.yarnpkg.com/@blueprintjs/colors/-/colors-4.1.7.tgz#3ccac41eabc3245da20669e6aafafe6c0271d264" - integrity sha512-4qmwwNabzJ6TbdWLjfVFqoCz6OPZpPDV6xvSmnEnS6tWSQ+bepi/ybzx3kKOGtNk1lu0tFDU6tnVti7uz23XaQ== - -"@blueprintjs/core@^3.36.0", "@blueprintjs/core@^3.54.0": - version "3.54.0" - resolved "https://registry.yarnpkg.com/@blueprintjs/core/-/core-3.54.0.tgz#7269f34eccdf0d2874377c5ad973ca2a31562221" - integrity sha512-u2c1s6MNn0ocxhnC6CuiG5g3KV6b4cKUvSobznepA9SC3/AL1s3XOvT7DLWoHRv2B/vBOHFYEDzLw2/vlcGGZg== - dependencies: - "@blueprintjs/colors" "^4.0.0-alpha.3" - "@blueprintjs/icons" "^3.33.0" - "@juggle/resize-observer" "^3.3.1" - "@types/dom4" "^2.0.1" - classnames "^2.2" - dom4 "^2.1.5" - normalize.css "^8.0.1" - popper.js "^1.16.1" - react-lifecycles-compat "^3.0.4" - react-popper "^1.3.7" - react-transition-group "^2.9.0" - tslib "~2.3.1" +"@csstools/postcss-cascade-layers@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz#8a997edf97d34071dd2e37ea6022447dd9e795ad" + integrity sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA== + dependencies: + "@csstools/selector-specificity" "^2.0.2" + postcss-selector-parser "^6.0.10" + +"@csstools/postcss-color-function@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz#2bd36ab34f82d0497cfacdc9b18d34b5e6f64b6b" + integrity sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw== + dependencies: + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" + +"@csstools/postcss-font-format-keywords@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz#677b34e9e88ae997a67283311657973150e8b16a" + integrity sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg== + dependencies: + postcss-value-parser "^4.2.0" + +"@csstools/postcss-hwb-function@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz#ab54a9fce0ac102c754854769962f2422ae8aa8b" + integrity sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w== + dependencies: + postcss-value-parser "^4.2.0" + +"@csstools/postcss-ic-unit@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz#28237d812a124d1a16a5acc5c3832b040b303e58" + integrity sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw== + dependencies: + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" + +"@csstools/postcss-is-pseudo-class@^2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz#846ae6c0d5a1eaa878fce352c544f9c295509cd1" + integrity sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA== + dependencies: + "@csstools/selector-specificity" "^2.0.0" + postcss-selector-parser "^6.0.10" + +"@csstools/postcss-nested-calc@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz#d7e9d1d0d3d15cf5ac891b16028af2a1044d0c26" + integrity sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ== + dependencies: + postcss-value-parser "^4.2.0" + +"@csstools/postcss-normalize-display-values@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz#15da54a36e867b3ac5163ee12c1d7f82d4d612c3" + integrity sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw== + dependencies: + postcss-value-parser "^4.2.0" + +"@csstools/postcss-oklab-function@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz#88cee0fbc8d6df27079ebd2fa016ee261eecf844" + integrity sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA== + dependencies: + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" + +"@csstools/postcss-progressive-custom-properties@^1.1.0", "@csstools/postcss-progressive-custom-properties@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz#542292558384361776b45c85226b9a3a34f276fa" + integrity sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA== + dependencies: + postcss-value-parser "^4.2.0" -"@blueprintjs/icons@^3.33.0": - version "3.33.0" - resolved "https://registry.yarnpkg.com/@blueprintjs/icons/-/icons-3.33.0.tgz#4dacdb7731abdf08d1ab240f3a23a185df60918b" - integrity sha512-Q6qoSDIm0kRYQZISm59UUcDCpV3oeHulkLuh3bSlw0HhcSjvEQh2PSYbtaifM60Q4aK4PCd6bwJHg7lvF1x5fQ== +"@csstools/postcss-stepped-value-functions@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz#f8772c3681cc2befed695e2b0b1d68e22f08c4f4" + integrity sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ== + dependencies: + postcss-value-parser "^4.2.0" + +"@csstools/postcss-text-decoration-shorthand@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz#ea96cfbc87d921eca914d3ad29340d9bcc4c953f" + integrity sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw== dependencies: - classnames "^2.2" - tslib "~2.3.1" + postcss-value-parser "^4.2.0" -"@blueprintjs/select@^3.15.0": - version "3.19.1" - resolved "https://registry.yarnpkg.com/@blueprintjs/select/-/select-3.19.1.tgz#b5e8baa6f182a0647651a57fde8d1d97eaa1e997" - integrity sha512-8UJIZMaWXRMQHr14wbmzJc/CklcSKxOU5JUux0xXKQz/hDW/g1a650tlwJmnxufvRdShbGinlVfHupCs0EL6sw== +"@csstools/postcss-trigonometric-functions@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz#94d3e4774c36d35dcdc88ce091336cb770d32756" + integrity sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og== dependencies: - "@blueprintjs/core" "^3.54.0" - classnames "^2.2" - tslib "~2.3.1" + postcss-value-parser "^4.2.0" + +"@csstools/postcss-unset-value@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz#c99bb70e2cdc7312948d1eb41df2412330b81f77" + integrity sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g== + +"@csstools/selector-specificity@^2.0.0", "@csstools/selector-specificity@^2.0.2": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz#2cbcf822bf3764c9658c4d2e568bd0c0cb748016" + integrity sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw== "@discoveryjs/json-ext@^0.5.0": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@eslint/eslintrc@^0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" - integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== + +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== dependencies: ajv "^6.12.4" - debug "^4.1.1" - espree "^7.3.0" - globals "^13.9.0" - ignore "^4.0.6" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" import-fresh "^3.2.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" + js-yaml "^4.1.0" + minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@gar/promisify@^1.0.1": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" - integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== +"@eslint/js@8.57.0": + version "8.57.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" + integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== -"@humanwhocodes/config-array@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" - integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== +"@humanwhocodes/config-array@^0.11.14": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== dependencies: - "@humanwhocodes/object-schema" "^1.2.0" - debug "^4.1.1" - minimatch "^3.0.4" + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" + minimatch "^3.0.5" -"@humanwhocodes/object-schema@^1.2.0": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@hypnosphi/create-react-context@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz#f8bfebdc7665f5d426cba3753e0e9c7d3154d7c6" - integrity sha512-V1klUed202XahrWJLLOT3EXNeCpFHCcJntdFGI15ntCwau+jfT386w7OFTMaCqOgXUH1fa0w/I1oZs+i/Rfr0A== - dependencies: - gud "^1.0.0" - warning "^4.0.3" +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" @@ -1275,285 +1381,312 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jridgewell/gen-mapping@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" - integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== dependencies: - "@jridgewell/set-array" "^1.0.1" + "@jridgewell/set-array" "^1.2.1" "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/source-map@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" - integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.13", "@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.8", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.17" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" - integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== - dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@juggle/resize-observer@^3.3.1": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" - integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA== +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== -"@jupyter-widgets/base@^2 || ^3 || ^4 || ^6.0.0": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@jupyter-widgets/base/-/base-6.0.1.tgz#1a9237694fd8290084c5e9dfc696452ccf85d054" - integrity sha512-EDuEaM10WtLYvqAaC8nXl0lmss8P+pDPtFIsCmRiodZNg3xyXAxTHDJM9Gl5gtXk31ny62Y+C7l275uir1/0sw== - dependencies: - "@jupyterlab/services" "^6.0.0" - "@lumino/coreutils" "^1.11.1" - "@lumino/messaging" "^1.10.1" - "@lumino/widgets" "^1.30.0" +"@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.13", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@jupyter-widgets/base@6.0.6": + version "6.0.6" + resolved "https://registry.yarnpkg.com/@jupyter-widgets/base/-/base-6.0.6.tgz#1e6746c897085ab7a9aea6d2890b10833011b66d" + integrity sha512-oafc4mZfH2r7VP15fPTmonwYg9onPsO8To4ip/p4fxRB3aBGIDDev5hou0dk2XfOpZLFgYAASEf3x6ze6KLnrQ== + dependencies: + "@jupyterlab/services" "^6.0.0 || ^7.0.0" + "@lumino/coreutils" "^1.11.1 || ^2.1" + "@lumino/messaging" "^1.10.1 || ^2.1" + "@lumino/widgets" "^1.30.0 || ^2.1" "@types/backbone" "1.4.14" "@types/lodash" "^4.14.134" backbone "1.4.0" jquery "^3.1.1" lodash "^4.17.4" -"@jupyterlab/apputils@^3.0.2": - version "3.4.8" - resolved "https://registry.yarnpkg.com/@jupyterlab/apputils/-/apputils-3.4.8.tgz#09126a7628958ab2409379d3b691a00d144eee90" - integrity sha512-b7vvPQUdkXcrZnfPUXJVYw4vpKl5HmPqFtFTGmatY+F734FSLYkZeIrNxByinI2DJg35I1p1NfSQW/3DVVwpog== - dependencies: - "@jupyterlab/coreutils" "^5.4.8" - "@jupyterlab/observables" "^4.4.8" - "@jupyterlab/services" "^6.4.8" - "@jupyterlab/settingregistry" "^3.4.8" - "@jupyterlab/statedb" "^3.4.8" - "@jupyterlab/translation" "^3.4.8" - "@jupyterlab/ui-components" "^3.4.8" - "@lumino/algorithm" "^1.9.0" - "@lumino/commands" "^1.19.0" - "@lumino/coreutils" "^1.11.0" - "@lumino/disposable" "^1.10.0" - "@lumino/domutils" "^1.8.0" - "@lumino/messaging" "^1.10.0" - "@lumino/polling" "^1.9.0" - "@lumino/properties" "^1.8.0" - "@lumino/signaling" "^1.10.0" - "@lumino/virtualdom" "^1.14.0" - "@lumino/widgets" "^1.33.0" - "@types/react" "^17.0.0" - react "^17.0.1" - react-dom "^17.0.1" - sanitize-html "~2.5.3" - url "^0.11.0" - -"@jupyterlab/builder@^3.0.1": - version "3.4.8" - resolved "https://registry.yarnpkg.com/@jupyterlab/builder/-/builder-3.4.8.tgz#68877818d327d98087e2029a360314cffe0f0c9f" - integrity sha512-PjSpzcVFVyk6u2EENX9JrTdXelL+a90n668pkns8NoEKZVRE3KjZoBUO6WMLS/c4mI7h3TWQhByghKpmjxflAQ== - dependencies: - "@jupyterlab/buildutils" "^3.4.8" - "@lumino/algorithm" "^1.9.0" - "@lumino/application" "^1.27.0" - "@lumino/commands" "^1.19.0" - "@lumino/coreutils" "^1.11.0" - "@lumino/disposable" "^1.10.0" - "@lumino/domutils" "^1.8.0" - "@lumino/dragdrop" "^1.13.0" - "@lumino/messaging" "^1.10.0" - "@lumino/properties" "^1.8.0" - "@lumino/signaling" "^1.10.0" - "@lumino/virtualdom" "^1.14.0" - "@lumino/widgets" "^1.33.0" - ajv "^6.12.3" - commander "~6.0.0" - css-loader "^5.0.1" +"@jupyter/react-components@^0.15.2": + version "0.15.3" + resolved "https://registry.yarnpkg.com/@jupyter/react-components/-/react-components-0.15.3.tgz#891b2cb8457cd9b06079e2937795f8d7d0e319ba" + integrity sha512-u85j88lxMSQ+2iVWuHPpMtFxek7nQnQsLh2eVJQFVv0ECX6H4s2WzIa4Ha1VRu4gjAXDtI/9wec9qUW6nezUnw== + dependencies: + "@jupyter/web-components" "^0.15.3" + "@microsoft/fast-react-wrapper" "^0.3.22" + react ">=17.0.0 <19.0.0" + +"@jupyter/web-components@^0.15.2", "@jupyter/web-components@^0.15.3": + version "0.15.3" + resolved "https://registry.yarnpkg.com/@jupyter/web-components/-/web-components-0.15.3.tgz#5491b5f6bc4e12f9b9c85bac63cd19514abedef1" + integrity sha512-ZrbyXr9mcYowXZ0Ic09ee6W2T3+t7+HP7yYwd2u7wHmQ0etWq5r8+DNdp8uFHiAeTV1kFm6aogNufR9fH34MCw== + dependencies: + "@microsoft/fast-colors" "^5.3.1" + "@microsoft/fast-element" "^1.12.0" + "@microsoft/fast-foundation" "^2.49.4" + "@microsoft/fast-web-utilities" "^5.4.1" + +"@jupyter/ydoc@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@jupyter/ydoc/-/ydoc-1.1.1.tgz#4405b1ad093ef3c14aa6960acc3cf78427bcfab9" + integrity sha512-fXx9CbUwUlXBsJo83tBQL3T0MgWT4YYz2ozcSFj0ymZSohAnI1uo7N9CPpVe4/nmc9uG1lFdlXC4XQBevi2jSA== + dependencies: + "@jupyterlab/nbformat" "^3.0.0 || ^4.0.0-alpha.21 || ^4.0.0" + "@lumino/coreutils" "^1.11.0 || ^2.0.0" + "@lumino/disposable" "^1.10.0 || ^2.0.0" + "@lumino/signaling" "^1.10.0 || ^2.0.0" + y-protocols "^1.0.5" + yjs "^13.5.40" + +"@jupyterlab/apputils@^3 || ^4": + version "4.2.6" + resolved "https://registry.yarnpkg.com/@jupyterlab/apputils/-/apputils-4.2.6.tgz#bdf994ffbf28cefb43969bfb3501bcc9bbcb324e" + integrity sha512-Sg+HbZTSL9C6/Fi/EbPMrAopriMbLRnx5SOndWt9rvFkkdfI7MmLmZGmrpQE7eUC6mVJWpms37PnqFvbZOo/ww== + dependencies: + "@jupyterlab/coreutils" "^6.1.6" + "@jupyterlab/observables" "^5.1.6" + "@jupyterlab/rendermime-interfaces" "^3.9.6" + "@jupyterlab/services" "^7.1.6" + "@jupyterlab/settingregistry" "^4.1.6" + "@jupyterlab/statedb" "^4.1.6" + "@jupyterlab/statusbar" "^4.1.6" + "@jupyterlab/translation" "^4.1.6" + "@jupyterlab/ui-components" "^4.1.6" + "@lumino/algorithm" "^2.0.1" + "@lumino/commands" "^2.2.0" + "@lumino/coreutils" "^2.1.2" + "@lumino/disposable" "^2.1.2" + "@lumino/domutils" "^2.0.1" + "@lumino/messaging" "^2.0.1" + "@lumino/signaling" "^2.1.2" + "@lumino/virtualdom" "^2.0.1" + "@lumino/widgets" "^2.3.1" + "@types/react" "^18.0.26" + react "^18.2.0" + sanitize-html "~2.7.3" + +"@jupyterlab/builder@^4.0.5": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@jupyterlab/builder/-/builder-4.1.6.tgz#55fa469ff504947b3637b51a203b000d3bed44b3" + integrity sha512-sZQY59qyj3gju1bmjfWGB3Xir/7X5XXR6IBceJjW+dfya9DWxssI7nfyguD6MEDjl7dTX2ITTeYYbO/dzpB6Bg== + dependencies: + "@lumino/algorithm" "^2.0.1" + "@lumino/application" "^2.3.0" + "@lumino/commands" "^2.2.0" + "@lumino/coreutils" "^2.1.2" + "@lumino/disposable" "^2.1.2" + "@lumino/domutils" "^2.0.1" + "@lumino/dragdrop" "^2.1.4" + "@lumino/messaging" "^2.0.1" + "@lumino/properties" "^2.0.1" + "@lumino/signaling" "^2.1.2" + "@lumino/virtualdom" "^2.0.1" + "@lumino/widgets" "^2.3.1" + ajv "^8.12.0" + commander "^9.4.1" + css-loader "^6.7.1" duplicate-package-checker-webpack-plugin "^3.0.0" - file-loader "~6.0.0" - fs-extra "^9.0.1" + fs-extra "^10.1.0" glob "~7.1.6" license-webpack-plugin "^2.3.14" - mini-css-extract-plugin "~1.3.2" + mini-css-extract-plugin "^2.7.0" + mini-svg-data-uri "^1.4.4" path-browserify "^1.0.0" process "^0.11.10" - raw-loader "~4.0.0" - style-loader "~2.0.0" + source-map-loader "~1.0.2" + style-loader "~3.3.1" supports-color "^7.2.0" - svg-url-loader "~6.0.0" - terser-webpack-plugin "^4.1.0" - to-string-loader "^1.1.6" - url-loader "~4.1.0" - webpack "^5.41.1" - webpack-cli "^4.1.0" - webpack-merge "^5.1.2" + terser-webpack-plugin "^5.3.7" + webpack "^5.76.1" + webpack-cli "^5.0.1" + webpack-merge "^5.8.0" worker-loader "^3.0.2" -"@jupyterlab/buildutils@^3.4.8": - version "3.4.8" - resolved "https://registry.yarnpkg.com/@jupyterlab/buildutils/-/buildutils-3.4.8.tgz#97b9c123021ba0f35ba6b3c5f2227fb2465bcecf" - integrity sha512-1+OyQaheW+ZWiUS8SBeZ+TB9Iowx7gqxFGIL9jd3yYK2D5UkdZNPc4NEs9BmOTUnhUD3rySNTSCu3gZU0hRQYw== - dependencies: - "@lumino/coreutils" "^1.11.0" - "@yarnpkg/lockfile" "^1.1.0" - child_process "~1.0.2" - commander "~6.0.0" - crypto "~1.0.1" - dependency-graph "^0.9.0" - fs-extra "^9.0.1" - glob "~7.1.6" - inquirer "^7.1.0" - minimatch "~3.0.4" - os "~0.1.1" - package-json "^6.5.0" - prettier "~2.1.1" - process "^0.11.10" - semver "^7.3.2" - sort-package-json "~1.44.0" - typescript "~4.1.3" - verdaccio "^5.13.3" - -"@jupyterlab/coreutils@^5.4.8": - version "5.4.8" - resolved "https://registry.yarnpkg.com/@jupyterlab/coreutils/-/coreutils-5.4.8.tgz#e3a81a8edb51c9a8d40f9baf4149f86c5e5109d0" - integrity sha512-UICv9nBCL+thSSOFlLWGjPm+UTT1ioPq+pOMjgn0E/DPliUMAMKtrAU5viAbRhITGAU55uL2KH9ijMUIc6o3xA== - dependencies: - "@lumino/coreutils" "^1.11.0" - "@lumino/disposable" "^1.10.0" - "@lumino/signaling" "^1.10.0" +"@jupyterlab/coreutils@^6.1.6": + version "6.1.6" + resolved "https://registry.yarnpkg.com/@jupyterlab/coreutils/-/coreutils-6.1.6.tgz#71acd617500ac318375fafcc3598cd0ba749e559" + integrity sha512-4rTO/O2zZNRCY28+cA4wv0/mp3/KWl4kKbOUObsH2elzO9FLjPEtKOxWm/WCn/VtlkQG+/XF2J0bS5Qz/WeW7w== + dependencies: + "@lumino/coreutils" "^2.1.2" + "@lumino/disposable" "^2.1.2" + "@lumino/signaling" "^2.1.2" minimist "~1.2.0" - moment "^2.24.0" path-browserify "^1.0.0" - url-parse "~1.5.1" - -"@jupyterlab/nbformat@^3.4.8": - version "3.4.8" - resolved "https://registry.yarnpkg.com/@jupyterlab/nbformat/-/nbformat-3.4.8.tgz#8552c9d32e8f04bd3e9be468be57662f0c5307c2" - integrity sha512-RcyITAagwXMIWqehpctb43mVB1H3LrTfikGvykLICmA5AfT+byhooCDN4d+ipg4rkeioUmEgX+2uTfForCsJWQ== - dependencies: - "@lumino/coreutils" "^1.11.0" - -"@jupyterlab/observables@^4.4.8": - version "4.4.8" - resolved "https://registry.yarnpkg.com/@jupyterlab/observables/-/observables-4.4.8.tgz#a73833e4f33b3d7e9c2a59306e8f526e13c043d9" - integrity sha512-TT7YQNxvLnfuzbHQjoovfVN02dXDG/zxfWiA1RkycAJnQ/aTgRtEMlLMs7dUqNCh6ej6zNQOUEduJInro/OL4A== - dependencies: - "@lumino/algorithm" "^1.9.0" - "@lumino/coreutils" "^1.11.0" - "@lumino/disposable" "^1.10.0" - "@lumino/messaging" "^1.10.0" - "@lumino/signaling" "^1.10.0" - -"@jupyterlab/services@^6.0.0", "@jupyterlab/services@^6.4.8": - version "6.4.8" - resolved "https://registry.yarnpkg.com/@jupyterlab/services/-/services-6.4.8.tgz#2da20fd5a5c94ab8f8200da633a252792927318a" - integrity sha512-/acj4d1A1V9KDN+k4CUokOA8e/IxaoJW2B+FJxVnTZvVOBh7093EIG+HYL1SQuQ8CUc2T4DNiq9mG3skiSe2fQ== - dependencies: - "@jupyterlab/coreutils" "^5.4.8" - "@jupyterlab/nbformat" "^3.4.8" - "@jupyterlab/observables" "^4.4.8" - "@jupyterlab/settingregistry" "^3.4.8" - "@jupyterlab/statedb" "^3.4.8" - "@lumino/algorithm" "^1.9.0" - "@lumino/coreutils" "^1.11.0" - "@lumino/disposable" "^1.10.0" - "@lumino/polling" "^1.9.0" - "@lumino/signaling" "^1.10.0" - node-fetch "^2.6.0" - ws "^7.4.6" - -"@jupyterlab/settingregistry@^3.4.8": - version "3.4.8" - resolved "https://registry.yarnpkg.com/@jupyterlab/settingregistry/-/settingregistry-3.4.8.tgz#10f52898b8553639ed4d9d786294617ac599c4a9" - integrity sha512-w9MNFivKXUOLrEvWckpcYm3XAZr0sbcKQ33SkftaLSQODsFlUwkcsjCPJJATVyxiWXAsCAgUlOKdNcqWxYXvOA== - dependencies: - "@jupyterlab/statedb" "^3.4.8" - "@lumino/commands" "^1.19.0" - "@lumino/coreutils" "^1.11.0" - "@lumino/disposable" "^1.10.0" - "@lumino/signaling" "^1.10.0" - ajv "^6.12.3" - json5 "^2.1.1" - -"@jupyterlab/statedb@^3.4.8": - version "3.4.8" - resolved "https://registry.yarnpkg.com/@jupyterlab/statedb/-/statedb-3.4.8.tgz#78654b5563f97e8f63683c54403bdc391f4c8df3" - integrity sha512-PMlo+x4R8uXPH1BgCJUVVIj/H8SY9scGJU0pqHhYa6mm3R2EHNAwr8JxyqGjAqT3C0VCCCIDzHtQ3f9inW+OXg== - dependencies: - "@lumino/commands" "^1.19.0" - "@lumino/coreutils" "^1.11.0" - "@lumino/disposable" "^1.10.0" - "@lumino/properties" "^1.8.0" - "@lumino/signaling" "^1.10.0" - -"@jupyterlab/translation@^3.4.8": - version "3.4.8" - resolved "https://registry.yarnpkg.com/@jupyterlab/translation/-/translation-3.4.8.tgz#9958bbbcabdcf913e96fcb267b223dccfa4d1151" - integrity sha512-5hIdMcA33qQpa2jR2Ho+bslfrf+feMyZbu37eCV58kHZjG3BsW47PWe5M0PCCe8WEIkTDu9z7BAmIUtbfwaZgA== - dependencies: - "@jupyterlab/coreutils" "^5.4.8" - "@jupyterlab/services" "^6.4.8" - "@jupyterlab/statedb" "^3.4.8" - "@lumino/coreutils" "^1.11.0" - -"@jupyterlab/ui-components@^3.4.8": - version "3.4.8" - resolved "https://registry.yarnpkg.com/@jupyterlab/ui-components/-/ui-components-3.4.8.tgz#1aec1b7c6a07abe8d84424d8b3085d8f5627b360" - integrity sha512-mkbJnllKCHaKEtUAtCwQAHrJjoD13njlcaDM2Ml9x8vF7PQB8bwRfp/ml4d6n1jOEJjd+a8HRrpzD2X1mTneZQ== - dependencies: - "@blueprintjs/core" "^3.36.0" - "@blueprintjs/select" "^3.15.0" - "@jupyterlab/coreutils" "^5.4.8" - "@jupyterlab/translation" "^3.4.8" - "@lumino/algorithm" "^1.9.0" - "@lumino/commands" "^1.19.0" - "@lumino/coreutils" "^1.11.0" - "@lumino/disposable" "^1.10.0" - "@lumino/signaling" "^1.10.0" - "@lumino/virtualdom" "^1.14.0" - "@lumino/widgets" "^1.33.0" - "@rjsf/core" "^3.1.0" - react "^17.0.1" - react-dom "^17.0.1" + url-parse "~1.5.4" + +"@jupyterlab/nbformat@^3.0.0 || ^4.0.0-alpha.21 || ^4.0.0", "@jupyterlab/nbformat@^4.1.6": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@jupyterlab/nbformat/-/nbformat-4.1.6.tgz#8ae366a3e74392cddb4633625ee5e0777b997149" + integrity sha512-wh/lw8+WciC/8kB25A8Ma27VvR6aR/TcrO4pL4nqCRI61YV0s/HbVL/0xug+qnGLRCNu6AfVYNEWPY2yTQguAw== + dependencies: + "@lumino/coreutils" "^2.1.2" + +"@jupyterlab/observables@^5.1.6": + version "5.1.6" + resolved "https://registry.yarnpkg.com/@jupyterlab/observables/-/observables-5.1.6.tgz#d5ef4f800a108c2faa93c6b97e3a40da541063dc" + integrity sha512-92S9EUZT47PA5YIW/Wwv+P1kbFipvOKOAg63z9NY9nqZ1X/EY3Gq3VEeARRIqMD8HdnS2HLl10F3bY5tu8t1Pw== + dependencies: + "@lumino/algorithm" "^2.0.1" + "@lumino/coreutils" "^2.1.2" + "@lumino/disposable" "^2.1.2" + "@lumino/messaging" "^2.0.1" + "@lumino/signaling" "^2.1.2" + +"@jupyterlab/rendermime-interfaces@^3.9.6": + version "3.9.6" + resolved "https://registry.yarnpkg.com/@jupyterlab/rendermime-interfaces/-/rendermime-interfaces-3.9.6.tgz#16662615b277056890cd9a76baf4204706448672" + integrity sha512-w6F4s4jMx1IM1HmRY+AoeceGuW6qJrWRXy0XREDy8/NPFLdMwtkv+Brbol4T4LzGarOVX5dFVs0udegeSCjW6w== + dependencies: + "@lumino/coreutils" "^1.11.0 || ^2.1.2" + "@lumino/widgets" "^1.37.2 || ^2.3.1" + +"@jupyterlab/services@^6.0.0 || ^7.0.0", "@jupyterlab/services@^7.1.6": + version "7.1.6" + resolved "https://registry.yarnpkg.com/@jupyterlab/services/-/services-7.1.6.tgz#a9fa5cb07f0461795bcf2457045e5a6ecd8841ee" + integrity sha512-7i/Cp03qmjQ4cS2DGe8QMTFMGnhxxty5UHEywiov+qBKB45tGnFiT830hc+ncOMR3LMOmmzyfF9t3SxMbjvTlw== + dependencies: + "@jupyter/ydoc" "^1.1.1" + "@jupyterlab/coreutils" "^6.1.6" + "@jupyterlab/nbformat" "^4.1.6" + "@jupyterlab/settingregistry" "^4.1.6" + "@jupyterlab/statedb" "^4.1.6" + "@lumino/coreutils" "^2.1.2" + "@lumino/disposable" "^2.1.2" + "@lumino/polling" "^2.1.2" + "@lumino/properties" "^2.0.1" + "@lumino/signaling" "^2.1.2" + ws "^8.11.0" + +"@jupyterlab/settingregistry@^4.1.6": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@jupyterlab/settingregistry/-/settingregistry-4.1.6.tgz#845217ab6c6829ec48f66fab6dd4c2ba18e0fbfd" + integrity sha512-hxUM1n3O5F4/10XU6r9MnIw6Q06dWiXzWqsGCbaWaPrjiXZALV9ATBgG7ygeXK69x3KnyCq282uyT2woDtL5Fg== + dependencies: + "@jupyterlab/nbformat" "^4.1.6" + "@jupyterlab/statedb" "^4.1.6" + "@lumino/commands" "^2.2.0" + "@lumino/coreutils" "^2.1.2" + "@lumino/disposable" "^2.1.2" + "@lumino/signaling" "^2.1.2" + "@rjsf/utils" "^5.13.4" + ajv "^8.12.0" + json5 "^2.2.3" + +"@jupyterlab/statedb@^4.1.6": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@jupyterlab/statedb/-/statedb-4.1.6.tgz#73c27c83ac651c371500be327db088ce8a7c4eab" + integrity sha512-pFFmdHWARYX/s2Uv/pz16UMQwLwrAaGqXzdTa58Z7J8V9Uwu9V6aTJmew8I1LudM/3GSJJ0Lo31/TP60V2bbwg== + dependencies: + "@lumino/commands" "^2.2.0" + "@lumino/coreutils" "^2.1.2" + "@lumino/disposable" "^2.1.2" + "@lumino/properties" "^2.0.1" + "@lumino/signaling" "^2.1.2" + +"@jupyterlab/statusbar@^4.1.6": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@jupyterlab/statusbar/-/statusbar-4.1.6.tgz#3ae81ad356d38cdc1813b1e000726b4c661591e4" + integrity sha512-KmQCrWf7Towh789KiR2WlTF/4LtLM2C0QRLvw9nQhyb5t1VmiFVoAFNY+7blWbPCrwd/rSIbUQnOQnAyEh070w== + dependencies: + "@jupyterlab/ui-components" "^4.1.6" + "@lumino/algorithm" "^2.0.1" + "@lumino/coreutils" "^2.1.2" + "@lumino/disposable" "^2.1.2" + "@lumino/messaging" "^2.0.1" + "@lumino/signaling" "^2.1.2" + "@lumino/widgets" "^2.3.1" + react "^18.2.0" + +"@jupyterlab/translation@^4.1.6": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@jupyterlab/translation/-/translation-4.1.6.tgz#89e984ac4a05aa5fe2d9a429e762d0ca3a7b1a4a" + integrity sha512-aCy2nWC2Kn9pVOK0ls/vjDU+S9t6oneV2K3dxR+oF5IybLG0XYoIQ/W7cATWAjlVidpv2JvJ6sAaGiSHhBtvfg== + dependencies: + "@jupyterlab/coreutils" "^6.1.6" + "@jupyterlab/rendermime-interfaces" "^3.9.6" + "@jupyterlab/services" "^7.1.6" + "@jupyterlab/statedb" "^4.1.6" + "@lumino/coreutils" "^2.1.2" + +"@jupyterlab/ui-components@^4.1.6": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@jupyterlab/ui-components/-/ui-components-4.1.6.tgz#626bd6e41c4f0351a58bcbd9c2c56c1b679df61e" + integrity sha512-7kioNLAW5i2dsSIJwwZcA/nF96pDoBaoO1SfOtX29/JHpFvCWiirh0URmEo3qyLr7Bkpnrq9Usgyh/QalWKi3w== + dependencies: + "@jupyter/react-components" "^0.15.2" + "@jupyter/web-components" "^0.15.2" + "@jupyterlab/coreutils" "^6.1.6" + "@jupyterlab/observables" "^5.1.6" + "@jupyterlab/rendermime-interfaces" "^3.9.6" + "@jupyterlab/translation" "^4.1.6" + "@lumino/algorithm" "^2.0.1" + "@lumino/commands" "^2.2.0" + "@lumino/coreutils" "^2.1.2" + "@lumino/disposable" "^2.1.2" + "@lumino/messaging" "^2.0.1" + "@lumino/polling" "^2.1.2" + "@lumino/properties" "^2.0.1" + "@lumino/signaling" "^2.1.2" + "@lumino/virtualdom" "^2.0.1" + "@lumino/widgets" "^2.3.1" + "@rjsf/core" "^5.13.4" + "@rjsf/utils" "^5.13.4" + react "^18.2.0" + react-dom "^18.2.0" typestyle "^2.0.4" -"@lumino/algorithm@^1.9.0", "@lumino/algorithm@^1.9.2": +"@leichtgewicht/ip-codec@^2.0.1": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz#4fc56c15c580b9adb7dc3c333a134e540b44bfb1" + integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw== + +"@lumino/algorithm@^1.9.2": version "1.9.2" resolved "https://registry.yarnpkg.com/@lumino/algorithm/-/algorithm-1.9.2.tgz#b95e6419aed58ff6b863a51bfb4add0f795141d3" integrity sha512-Z06lp/yuhz8CtIir3PNTGnuk7909eXt4ukJsCzChsGuot2l5Fbs96RJ/FOHgwCedaX74CtxPjXHXoszFbUA+4A== -"@lumino/application@^1.27.0": - version "1.29.4" - resolved "https://registry.yarnpkg.com/@lumino/application/-/application-1.29.4.tgz#4ee5aedb424c2dd0eade52c45c42a11a153aeecc" - integrity sha512-yCBkG7Fk2tJ9OBwbzDzZyJUySGqzSGG+Fn/kQJ8kiPcEA7ajpoGrtI8/pd0TzASrih3A5PZnuoR8bRV6Dt2UbA== +"@lumino/algorithm@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@lumino/algorithm/-/algorithm-2.0.1.tgz#1045f4629f96076b431fc1a8c0005e13d8b95a56" + integrity sha512-iA+uuvA7DeNFB0/cQpIWNgO1c6z4pOSigifjstLy+rxf1U5ZzxIq+xudnEuTbWgKSTviG02j4cKwCyx1PO6rzA== + +"@lumino/application@^1 || ^2", "@lumino/application@^2.3.0": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@lumino/application/-/application-2.3.1.tgz#1b27b34af496dc8125af17ccb0ee8b99555248b2" + integrity sha512-f13alXxzJpQwkprF9NLFqS46FCKfElbL7rM7g+aJX4bf39l5Eia2isxhaDoUxtSi3D5zkHeajgp+s1tX4aDp8A== dependencies: - "@lumino/commands" "^1.20.1" - "@lumino/coreutils" "^1.12.1" - "@lumino/widgets" "^1.34.1" + "@lumino/commands" "^2.3.0" + "@lumino/coreutils" "^2.1.2" + "@lumino/widgets" "^2.3.2" "@lumino/collections@^1.9.3": version "1.9.3" @@ -1562,51 +1695,57 @@ dependencies: "@lumino/algorithm" "^1.9.2" -"@lumino/commands@^1.19.0", "@lumino/commands@^1.20.1": - version "1.20.1" - resolved "https://registry.yarnpkg.com/@lumino/commands/-/commands-1.20.1.tgz#8a4e4840528e8009c5472dc6b5bb0970d7f27a5f" - integrity sha512-7u0vc3qWVAyI3CHGmQ+MXP5bvmj5dtnU5J4u2aRrodtlysU3nLjGhD57bbTq2VUqpmS1bkfBqNFhO1e4PFKSaQ== +"@lumino/collections@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@lumino/collections/-/collections-2.0.1.tgz#cfb9afa9837eddb72d1939e73dcd5256feaf37ef" + integrity sha512-8TbAU/48XVPKc/FOhGHLuugf2Gmx6vhVEx867KGG5fLwDOI8EW4gTno78yJUk8G0QpgNa+sdpB/LwbJFNIratg== dependencies: - "@lumino/algorithm" "^1.9.2" - "@lumino/coreutils" "^1.12.1" - "@lumino/disposable" "^1.10.2" - "@lumino/domutils" "^1.8.2" - "@lumino/keyboard" "^1.8.2" - "@lumino/signaling" "^1.10.2" - "@lumino/virtualdom" "^1.14.2" - -"@lumino/coreutils@^1.11.0", "@lumino/coreutils@^1.11.1", "@lumino/coreutils@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@lumino/coreutils/-/coreutils-1.12.1.tgz#79860c9937483ddf6cda87f6c2b9da8eb1a5d768" - integrity sha512-JLu3nTHzJk9N8ohZ85u75YxemMrmDzJdNgZztfP7F7T7mxND3YVNCkJG35a6aJ7edu1sIgCjBxOvV+hv27iYvQ== + "@lumino/algorithm" "^2.0.1" -"@lumino/disposable@^1.10.0", "@lumino/disposable@^1.10.2": - version "1.10.2" - resolved "https://registry.yarnpkg.com/@lumino/disposable/-/disposable-1.10.2.tgz#8a7e74320f51a48419d92672fe8abcf8cec04818" - integrity sha512-jwt8bCw3OU65wJMOCJUZAfVVUdxZdEufRDrDkoG91aSW+/R/VBzt33AqZX81/B0KxddL6R3PdNWI+0fRJBaeYw== +"@lumino/commands@^2.2.0", "@lumino/commands@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@lumino/commands/-/commands-2.3.0.tgz#b30d46cb529171d896d8e0aa6b0e359beeb7b310" + integrity sha512-qOF9p9W54IWjyXrbd9QKr0d5XIn5ZTh6PBFO4UBGvEJJPO477tDm0f36HUxMMRtdJvp5ArgTj5/Khd3L3BFayg== + dependencies: + "@lumino/algorithm" "^2.0.1" + "@lumino/coreutils" "^2.1.2" + "@lumino/disposable" "^2.1.2" + "@lumino/domutils" "^2.0.1" + "@lumino/keyboard" "^2.0.1" + "@lumino/signaling" "^2.1.2" + "@lumino/virtualdom" "^2.0.1" + +"@lumino/coreutils@2.1.2", "@lumino/coreutils@^1.11.0 || ^2.0.0", "@lumino/coreutils@^1.11.0 || ^2.1.2", "@lumino/coreutils@^1.11.1 || ^2.1", "@lumino/coreutils@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@lumino/coreutils/-/coreutils-2.1.2.tgz#354e658353e99969329c9ee33b0692ecd97abe1f" + integrity sha512-vyz7WzchTO4HQ8iVAxvSUmb5o/8t3cz1vBo8V4ZIaPGada0Jx0xe3tKQ8bXp4pjHc+AEhMnkCnlUyVYMWbnj4A== + +"@lumino/disposable@^1.10.0 || ^2.0.0", "@lumino/disposable@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@lumino/disposable/-/disposable-2.1.2.tgz#a4df34a50d23e577051eee27c000fc9ad37f35bb" + integrity sha512-0qmB6zPt9+uj4SVMTfISn0wUOjYHahtKotwxDD5flfcscj2gsXaFCXO4Oqot1zcsZbg8uJmTUhEzAvFW0QhFNA== dependencies: - "@lumino/algorithm" "^1.9.2" - "@lumino/signaling" "^1.10.2" + "@lumino/signaling" "^2.1.2" -"@lumino/domutils@^1.8.0", "@lumino/domutils@^1.8.2": - version "1.8.2" - resolved "https://registry.yarnpkg.com/@lumino/domutils/-/domutils-1.8.2.tgz#d15cdbae12bea52852bbc13c4629360f9f05b7f5" - integrity sha512-QIpMfkPJrs4GrWBuJf2Sn1fpyVPmvqUUAeD8xAQo8+4V5JAT0vUDLxZ9HijefMgNCi3+Bs8Z3lQwRCrz+cFP1A== +"@lumino/domutils@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@lumino/domutils/-/domutils-2.0.1.tgz#1852eadd2658cf754e17f2d0e5c18d1737a91530" + integrity sha512-tbcfhsdKH04AMjSgYAYGD2xE80YcjrqKnfMTeU2NHt4J294Hzxs1GvEmSMk5qJ3Bbgwx6Z4BbQ7apnFg8Gc6cA== -"@lumino/dragdrop@^1.13.0", "@lumino/dragdrop@^1.14.2": - version "1.14.2" - resolved "https://registry.yarnpkg.com/@lumino/dragdrop/-/dragdrop-1.14.2.tgz#5e877496921f9a8ef57c7eb8aec884035cf0d051" - integrity sha512-wXsungIpgNSLmV23f61UPhDlxr0VUBX4xQY2gHq0ps1dDL9BNQnec9q0dbeYRa0n27gKEJ81efAgCV4a/+xJ3A== +"@lumino/dragdrop@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@lumino/dragdrop/-/dragdrop-2.1.4.tgz#b5c90cdb27cc4d7c57e34cbe40897acadb59323f" + integrity sha512-/ckaYPHIZC1Ff0pU2H3WDI/Xm7V3i0XnyYG4PeZvG1+ovc0I0zeZtlb6qZXne0Vi2r8L2a0624FjF2CwwgNSnA== dependencies: - "@lumino/coreutils" "^1.12.1" - "@lumino/disposable" "^1.10.2" + "@lumino/coreutils" "^2.1.2" + "@lumino/disposable" "^2.1.2" -"@lumino/keyboard@^1.8.2": - version "1.8.2" - resolved "https://registry.yarnpkg.com/@lumino/keyboard/-/keyboard-1.8.2.tgz#714dbe671f0718f516d1ec23188b31a9ccd82fb2" - integrity sha512-Dy+XqQ1wXbcnuYtjys5A0pAqf4SpAFl9NY6owyIhXAo0Va7w3LYp3jgiP1xAaBAwMuUppiUAfrbjrysZuZ625g== +"@lumino/keyboard@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@lumino/keyboard/-/keyboard-2.0.1.tgz#a16db961e29a94f87b2669c989b2b358590ce1f6" + integrity sha512-R2mrH9HCEcv/0MSAl7bEUbjCNOnhrg49nXZBEVckg//TEG+sdayCsyrbJNMPcZ07asIPKc6mq3v7DpAmDKqh+w== -"@lumino/messaging@^1.10.0", "@lumino/messaging@^1.10.1", "@lumino/messaging@^1.10.3": +"@lumino/messaging@^1.10.1 || ^2.1": version "1.10.3" resolved "https://registry.yarnpkg.com/@lumino/messaging/-/messaging-1.10.3.tgz#b6227bdfc178a8542571625ecb68063691b6af3c" integrity sha512-F/KOwMCdqvdEG8CYAJcBSadzp6aI7a47Fr60zAKGqZATSRRRV41q53iXU7HjFPqQqQIvdn9Z7J32rBEAyQAzww== @@ -1614,50 +1753,94 @@ "@lumino/algorithm" "^1.9.2" "@lumino/collections" "^1.9.3" -"@lumino/polling@^1.9.0": - version "1.11.2" - resolved "https://registry.yarnpkg.com/@lumino/polling/-/polling-1.11.2.tgz#a1f5e0749be0a661f0da1a06d1d590edf946ae08" - integrity sha512-/1neRyLdRt62teEwi/wKmyaqaU+H8e4SvvFzrIXITX0shb72um+kv2vOAkj7wSImsIo21PWweRsTbzJ97f6J3w== +"@lumino/messaging@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@lumino/messaging/-/messaging-2.0.1.tgz#5ef321ed090b74b821d2a0de02493a2f9f3c21f7" + integrity sha512-Z1b9Sq7i2yw7BN/u9ezoBUMYK06CsQXO7BqpczSnEO0PfwFf9dWi7y9VcIySOBz9uogsT1uczZMIMtLefk+xPQ== dependencies: - "@lumino/coreutils" "^1.12.1" - "@lumino/disposable" "^1.10.2" - "@lumino/signaling" "^1.10.2" + "@lumino/algorithm" "^2.0.1" + "@lumino/collections" "^2.0.1" -"@lumino/properties@^1.8.0", "@lumino/properties@^1.8.2": - version "1.8.2" - resolved "https://registry.yarnpkg.com/@lumino/properties/-/properties-1.8.2.tgz#91131f2ca91a902faa138771eb63341db78fc0fd" - integrity sha512-EkjI9Cw8R0U+xC9HxdFSu7X1tz1H1vKu20cGvJ2gU+CXlMB1DvoYJCYxCThByHZ+kURTAap4SE5x8HvKwNPbig== +"@lumino/polling@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@lumino/polling/-/polling-2.1.2.tgz#f641710b29b83d40b3c93ff6ed385abd734c7a2b" + integrity sha512-hv6MT7xuSrw2gW4VIoiz3L366ZdZz4oefht+7HIW/VUB6seSDp0kVyZ4P9P4I4s/LauuzPqru3eWr7QAsFZyGA== + dependencies: + "@lumino/coreutils" "^2.1.2" + "@lumino/disposable" "^2.1.2" + "@lumino/signaling" "^2.1.2" -"@lumino/signaling@^1.10.0", "@lumino/signaling@^1.10.2": - version "1.10.2" - resolved "https://registry.yarnpkg.com/@lumino/signaling/-/signaling-1.10.2.tgz#da30a84b8820f2b29e0c176450059711913392d9" - integrity sha512-LvnLRb2ngOZbRtFHRcKkMdPSXm0bzfVv/5mbx/hpT1DWHihMtBpGQ+bIfFvnARmFJoI11Wt+DMX77MWPw6tpig== +"@lumino/properties@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@lumino/properties/-/properties-2.0.1.tgz#349407042df99d94943798078454dc11a327684b" + integrity sha512-RPtHrp8cQqMnTC915lOIdrmsbPDCC7PhPOZb2YY7/Jj6dEdwmGhoMthc2tBEYWoHP+tU/hVm8UR/mEQby22srQ== + +"@lumino/signaling@^1.10.0 || ^2.0.0", "@lumino/signaling@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@lumino/signaling/-/signaling-2.1.2.tgz#b5f127463165884174f1446e8364794af831a852" + integrity sha512-KtwKxx+xXkLOX/BdSqtvnsqBTPKDIENFBKeYkMTxstQc3fHRmyTzmaVoeZES+pr1EUy3e8vM4pQFVQpb8VsDdA== dependencies: - "@lumino/algorithm" "^1.9.2" + "@lumino/algorithm" "^2.0.1" + "@lumino/coreutils" "^2.1.2" -"@lumino/virtualdom@^1.14.0", "@lumino/virtualdom@^1.14.2": - version "1.14.2" - resolved "https://registry.yarnpkg.com/@lumino/virtualdom/-/virtualdom-1.14.2.tgz#bee4fd3cf78c1aa003d9c208f6825969b4321573" - integrity sha512-iF20v6s4gP/hAH4VjmBtv2dexr18W4vL/Y5Rx4+U3kS/ZIFU7987NsM+0Yr6W9kdBQ1w6+pJjRBS9sWYnohdoQ== +"@lumino/virtualdom@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@lumino/virtualdom/-/virtualdom-2.0.1.tgz#335e0e8758f21908a67f66b43f8dec177bcd6133" + integrity sha512-WNM+uUZX7vORhlDRN9NmhEE04Tz1plDjtbwsX+i/51pQj2N2r7+gsVPY/gR4w+I5apmC3zG8/BojjJYIwi8ogA== dependencies: - "@lumino/algorithm" "^1.9.2" + "@lumino/algorithm" "^2.0.1" + +"@lumino/widgets@2.3.2", "@lumino/widgets@^1.30.0 || ^2.1", "@lumino/widgets@^1.37.2 || ^2.3.1", "@lumino/widgets@^2.3.1", "@lumino/widgets@^2.3.2": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@lumino/widgets/-/widgets-2.3.2.tgz#305314317383fa98031f94a2452709f31cf5eb02" + integrity sha512-IUx4VNplRS9V+6RqG7K46QAnf5OzhcjZ3Us6WcZzcEO9K5FD73BK914rnFAat4BnWScdTAdZGUGKOvLPT9kuNA== + dependencies: + "@lumino/algorithm" "^2.0.1" + "@lumino/commands" "^2.3.0" + "@lumino/coreutils" "^2.1.2" + "@lumino/disposable" "^2.1.2" + "@lumino/domutils" "^2.0.1" + "@lumino/dragdrop" "^2.1.4" + "@lumino/keyboard" "^2.0.1" + "@lumino/messaging" "^2.0.1" + "@lumino/properties" "^2.0.1" + "@lumino/signaling" "^2.1.2" + "@lumino/virtualdom" "^2.0.1" + +"@microsoft/fast-colors@^5.3.1": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@microsoft/fast-colors/-/fast-colors-5.3.1.tgz#defc59874176e42316be7e6d24c31885ead8ca56" + integrity sha512-72RZXVfCbwQzvo5sXXkuLXLT7rMeYaSf5r/6ewQiv/trBtqpWRm4DEH2EilHw/iWTBKOXs1qZNQndgUMa5n4LA== + +"@microsoft/fast-element@^1.12.0", "@microsoft/fast-element@^1.13.0": + version "1.13.0" + resolved "https://registry.yarnpkg.com/@microsoft/fast-element/-/fast-element-1.13.0.tgz#d390ff13697064a48dc6ad6bb332a5f5489f73f8" + integrity sha512-iFhzKbbD0cFRo9cEzLS3Tdo9BYuatdxmCEKCpZs1Cro/93zNMpZ/Y9/Z7SknmW6fhDZbpBvtO8lLh9TFEcNVAQ== -"@lumino/widgets@^1.30.0", "@lumino/widgets@^1.33.0", "@lumino/widgets@^1.34.1": - version "1.34.1" - resolved "https://registry.yarnpkg.com/@lumino/widgets/-/widgets-1.34.1.tgz#46272677876caea02a8d197c6d0cfc0afd5061bd" - integrity sha512-DNpqg7TgAQROOVytGNgFs8oBET/UrTjXYEls/S/GSzr0qcoiDHfrX+LOyaXxOO08ijvq9NhqYfYvmM5AFGTNuA== +"@microsoft/fast-foundation@^2.49.4", "@microsoft/fast-foundation@^2.49.6": + version "2.49.6" + resolved "https://registry.yarnpkg.com/@microsoft/fast-foundation/-/fast-foundation-2.49.6.tgz#0bdee7d28dcf93918075618359b083a676d2891c" + integrity sha512-DZVr+J/NIoskFC1Y6xnAowrMkdbf2d5o7UyWK6gW5AiQ6S386Ql8dw4KcC4kHaeE1yL2CKvweE79cj6ZhJhTvA== dependencies: - "@lumino/algorithm" "^1.9.2" - "@lumino/commands" "^1.20.1" - "@lumino/coreutils" "^1.12.1" - "@lumino/disposable" "^1.10.2" - "@lumino/domutils" "^1.8.2" - "@lumino/dragdrop" "^1.14.2" - "@lumino/keyboard" "^1.8.2" - "@lumino/messaging" "^1.10.3" - "@lumino/properties" "^1.8.2" - "@lumino/signaling" "^1.10.2" - "@lumino/virtualdom" "^1.14.2" + "@microsoft/fast-element" "^1.13.0" + "@microsoft/fast-web-utilities" "^5.4.1" + tabbable "^5.2.0" + tslib "^1.13.0" + +"@microsoft/fast-react-wrapper@^0.3.22": + version "0.3.24" + resolved "https://registry.yarnpkg.com/@microsoft/fast-react-wrapper/-/fast-react-wrapper-0.3.24.tgz#caed362a95fac88f9715a4b82425c395fba550c2" + integrity sha512-sRnSBIKaO42p4mYoYR60spWVkg89wFxFAgQETIMazAm2TxtlsnsGszJnTwVhXq2Uz+XNiD8eKBkfzK5c/i6/Kw== + dependencies: + "@microsoft/fast-element" "^1.13.0" + "@microsoft/fast-foundation" "^2.49.6" + +"@microsoft/fast-web-utilities@^5.4.1": + version "5.4.1" + resolved "https://registry.yarnpkg.com/@microsoft/fast-web-utilities/-/fast-web-utilities-5.4.1.tgz#8e3082ee2ff2b5467f17e7cb1fb01b0e4906b71f" + integrity sha512-ReWYncndjV3c8D8iq9tp7NcFNc1vbVHvcBFPME2nNFKNbS1XCesYZGlIlf3ot5EmuOXPlrzUHOWzQ2vFpIkqDg== + dependencies: + exenv-es6 "^1.1.1" "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": version "2.1.8-no-fsevents.3" @@ -1677,7 +1860,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3": +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -1685,51 +1868,76 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@npmcli/fs@^1.0.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" - integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== - dependencies: - "@gar/promisify" "^1.0.1" - semver "^7.3.5" +"@popperjs/core@^2.11.6": + version "2.11.8" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" + integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== + +"@react-aria/ssr@^3.5.0": + version "3.9.2" + resolved "https://registry.yarnpkg.com/@react-aria/ssr/-/ssr-3.9.2.tgz#01b756965cd6e32b95217f968f513eb3bd6ee44b" + integrity sha512-0gKkgDYdnq1w+ey8KzG9l+H5Z821qh9vVjztk55rUg71vTk/Eaebeir+WtzcLLwTjw3m/asIjx8Y59y1lJZhBw== + dependencies: + "@swc/helpers" "^0.5.0" + +"@remix-run/router@1.15.3": + version "1.15.3" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.15.3.tgz#d2509048d69dbb72d5389a14945339f1430b2d3c" + integrity sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w== + +"@restart/hooks@^0.4.9": + version "0.4.16" + resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.4.16.tgz#95ae8ac1cc7e2bd4fed5e39800ff85604c6d59fb" + integrity sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w== + dependencies: + dequal "^2.0.3" + +"@restart/ui@^1.6.8": + version "1.6.8" + resolved "https://registry.yarnpkg.com/@restart/ui/-/ui-1.6.8.tgz#61b73503d4690e2f0f58992d4d6ae1e89c276791" + integrity sha512-6ndCv3oZ7r9vuP1Ok9KH55TM1/UkdBnP/fSraW0DFDMbPMzWKhVKeFAIEUCRCSdzayjZDcFYK6xbMlipN9dmMA== + dependencies: + "@babel/runtime" "^7.21.0" + "@popperjs/core" "^2.11.6" + "@react-aria/ssr" "^3.5.0" + "@restart/hooks" "^0.4.9" + "@types/warning" "^3.0.0" + dequal "^2.0.3" + dom-helpers "^5.2.0" + uncontrollable "^8.0.1" + warning "^4.0.3" -"@npmcli/move-file@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" - integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== +"@rjsf/core@^5.13.4": + version "5.18.2" + resolved "https://registry.yarnpkg.com/@rjsf/core/-/core-5.18.2.tgz#618175e6ef96ed62ebe23c80cea47ba27bf03a17" + integrity sha512-dqS8E70DJSnTpJ8tdQi4flTffJ3fr/G1Jro7Bhx/eKiB2UbYII1tR536HfZqwe8p1NvJ26DViJclOAghHPmJog== dependencies: - mkdirp "^1.0.4" - rimraf "^3.0.2" + lodash "^4.17.21" + lodash-es "^4.17.21" + markdown-to-jsx "^7.4.1" + nanoid "^3.3.7" + prop-types "^15.8.1" -"@rjsf/core@^3.1.0": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@rjsf/core/-/core-3.2.1.tgz#8a7b24c9a6f01f0ecb093fdfc777172c12b1b009" - integrity sha512-dk8ihvxFbcuIwU7G+HiJbFgwyIvaumPt5g5zfnuC26mwTUPlaDGFXKK2yITp8tJ3+hcwS5zEXtAN9wUkfuM4jA== - dependencies: - "@types/json-schema" "^7.0.7" - ajv "^6.7.0" - core-js-pure "^3.6.5" - json-schema-merge-allof "^0.6.0" - jsonpointer "^5.0.0" - lodash "^4.17.15" - nanoid "^3.1.23" - prop-types "^15.7.2" - react-is "^16.9.0" +"@rjsf/utils@^5.13.4": + version "5.18.2" + resolved "https://registry.yarnpkg.com/@rjsf/utils/-/utils-5.18.2.tgz#7a4af6a4dfe3c11ac2305d970855bbbbb140eeb2" + integrity sha512-iDqwBTispZ7mAgwBuHIM0emK+Ft2xRgKD9TzB68VEUhr2hqlDRpwtH6/AgAWUKmJl4kUj3cRKVqqhIvamGLpXw== + dependencies: + json-schema-merge-allof "^0.8.1" + jsonpointer "^5.0.1" + lodash "^4.17.21" + lodash-es "^4.17.21" + react-is "^18.2.0" "@sinclair/typebox@^0.24.1": - version "0.24.47" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.47.tgz#530b67163714356f93e82bdb871e7db4b7bc564e" - integrity sha512-J4Xw0xYK4h7eC34MNOPQi6IkNxGRck6n4VJpWDzXIFVTW8I/D43Gf+NfWz/v/7NHlzWOPd3+T4PJ4OqklQ2u7A== - -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + version "0.24.51" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" + integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== "@sinonjs/commons@^1.7.0": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" - integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + version "1.8.6" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" + integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== dependencies: type-detect "4.0.8" @@ -1740,50 +1948,45 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== +"@swc/helpers@^0.5.0": + version "0.5.9" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.9.tgz#ce69b9a821c6f266358ec5107be36996550c465f" + integrity sha512-XI76sLwMJoLjJTOK5RblBZkouOJG3X3hjxLCzLnyN1ifAiKQc6Hck3uvnU4Z/dV/Dyk36Ffj8FLvDLV2oWvKTw== dependencies: - defer-to-connect "^1.0.1" - -"@tootallnate/once@1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" - integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + tslib "^2.4.0" "@types/babel__core@^7.1.14": - version "7.1.19" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460" - integrity sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw== + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" "@types/babel__generator" "*" "@types/babel__template" "*" "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.4" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" - integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== + version "7.6.8" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== dependencies: "@babel/types" "^7.0.0" "@types/babel__template@*": - version "7.4.1" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" - integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.2.tgz#235bf339d17185bdec25e024ca19cce257cc7309" - integrity sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg== + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.5.tgz#7b7502be0aa80cc4ef22978846b983edaafcd4dd" + integrity sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ== dependencies: - "@babel/types" "^7.3.0" + "@babel/types" "^7.20.7" "@types/backbone@1.4.14": version "1.4.14" @@ -1793,115 +1996,227 @@ "@types/jquery" "*" "@types/underscore" "*" -"@types/dom4@^2.0.1": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/dom4/-/dom4-2.0.2.tgz#6495303f049689ce936ed328a3e5ede9c51408ee" - integrity sha512-Rt4IC1T7xkCWa0OG1oSsPa0iqnxlDeQqKXZAHrQGLb7wFGncWm85MaxKUjAGejOrUynOgWlFi4c6S6IyJwoK4g== +"@types/backbone@^1.4.19": + version "1.4.19" + resolved "https://registry.yarnpkg.com/@types/backbone/-/backbone-1.4.19.tgz#f6e8406fed40ca3fe224f6e59115142b62be76d6" + integrity sha512-byyn236JymGByOajKA7mi1k+/jKn162TIvArOB4SHgOGbVlFj8CSfJH4jekP0qo0vJwW5khrrsiiO1Jsos6ZvA== + dependencies: + "@types/jquery" "*" + "@types/underscore" "*" + +"@types/body-parser@*": + version "1.19.5" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" + integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/bonjour@^3.5.9": + version "3.5.13" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.13.tgz#adf90ce1a105e81dd1f9c61fdc5afda1bfb92956" + integrity sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ== + dependencies: + "@types/node" "*" + +"@types/connect-history-api-fallback@*", "@types/connect-history-api-fallback@^1.3.5": + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz#7de71645a103056b48ac3ce07b3520b819c1d5b3" + integrity sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.38" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== + dependencies: + "@types/node" "*" + +"@types/d3-array@^3.0.3": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5" + integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg== + +"@types/d3-color@*": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2" + integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A== + +"@types/d3-ease@^3.0.0": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b" + integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA== + +"@types/d3-interpolate@^3.0.1": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c" + integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA== + dependencies: + "@types/d3-color" "*" + +"@types/d3-path@*": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.1.0.tgz#2b907adce762a78e98828f0b438eaca339ae410a" + integrity sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ== + +"@types/d3-scale@^4.0.2": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb" + integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ== + dependencies: + "@types/d3-time" "*" + +"@types/d3-shape@^3.1.0": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.6.tgz#65d40d5a548f0a023821773e39012805e6e31a72" + integrity sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA== + dependencies: + "@types/d3-path" "*" + +"@types/d3-time@*", "@types/d3-time@^3.0.0": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be" + integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw== + +"@types/d3-timer@^3.0.0": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70" + integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw== "@types/eslint-scope@^3.7.3": - version "3.7.4" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" - integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== dependencies: "@types/eslint" "*" "@types/estree" "*" -"@types/eslint-visitor-keys@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" - integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== - "@types/eslint@*": - version "8.4.7" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.7.tgz#0f05a2677d1a394ff70c21a964a32d3efa05f966" - integrity sha512-ehM7cCt2RSFs42mb+lcmhFT9ouIlV92PuaeRGn8N8c98oMjG4Z5pJHA9b1QiCcuqnbPSHcyfiD3mlhqMaHsQIw== + version "8.56.9" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.9.tgz#403e9ced04a34e63f1c383c5b8ee1a94442c8cc4" + integrity sha512-W4W3KcqzjJ0sHg2vAq9vfml6OhsJ53TcUjUqfzzZf/EChUtwspszj/S0pzMxnfRcO55/iGq47dscXw71Fxc4Zg== dependencies: "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" - integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== - -"@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== +"@types/estree@*", "@types/estree@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== -"@types/glob@^7.1.1": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" - integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.0.tgz#3ae8ab3767d98d0b682cda063c3339e1e86ccfaa" + integrity sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ== dependencies: - "@types/minimatch" "*" "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/send" "*" + +"@types/express@*", "@types/express@^4.17.13": + version "4.17.21" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" "@types/graceful-fs@^4.1.3": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" - integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + version "4.1.9" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" + integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== dependencies: "@types/node" "*" -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": +"@types/html-minifier-terser@^6.0.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" + integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + +"@types/http-errors@*": version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" - integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" + integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== + +"@types/http-proxy@^1.17.5", "@types/http-proxy@^1.17.8": + version "1.17.14" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.14.tgz#57f8ccaa1c1c3780644f8a94f9c6b5000b5e2eec" + integrity sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== "@types/istanbul-lib-report@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" - integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" - integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^27.4.1": - version "27.5.2" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.5.2.tgz#ec49d29d926500ffb9fd22b84262e862049c026c" - integrity sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA== +"@types/jest@^28": + version "28.1.8" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-28.1.8.tgz#6936409f3c9724ea431efd412ea0238a0f03b09b" + integrity sha512-8TJkV++s7B6XqnDrzR1m/TT0A0h948Pnl/097veySPN67VRAgQ4gZ7n2KfJo2rVq6njQjdxU3GCCyDvAeuHoiw== dependencies: - jest-matcher-utils "^27.0.0" - pretty-format "^27.0.0" + expect "^28.0.0" + pretty-format "^28.0.0" "@types/jquery@*": - version "3.5.14" - resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.14.tgz#ac8e11ee591e94d4d58da602cb3a5a8320dee577" - integrity sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg== + version "3.5.29" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.29.tgz#3c06a1f519cd5fc3a7a108971436c00685b5dcea" + integrity sha512-oXQQC9X9MOPRrMhPHHOsXqeQDnWeCDT3PelUIg/Oy8FAbzSZtFHRjc7IpbfFVmpLtJ+UOoywpRsuO5Jxjybyeg== dependencies: "@types/sizzle" "*" -"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== +"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== -"@types/lodash@^4.14.134": - version "4.14.186" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.186.tgz#862e5514dd7bd66ada6c70ee5fce844b06c8ee97" - integrity sha512-eHcVlLXP0c2FlMPm56ITode2AgLMSa6aJ05JTTbYbI+7EMkCEE5qk2E41d5g2lCVTqRe0GnnRFurmlCsDODrPw== +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/lodash@^4.14.191": - version "4.14.192" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.192.tgz#5790406361a2852d332d41635d927f1600811285" - integrity sha512-km+Vyn3BYm5ytMO13k9KTp27O75rbQ0NFw+U//g+PX7VZyjCioXaRFisqSIJRECljcTv73G3i6BpglNGHgUQ5A== +"@types/lodash@^4.14.134", "@types/lodash@^4.17.0": + version "4.17.0" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.0.tgz#d774355e41f372d5350a4d0714abb48194a489c3" + integrity sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA== -"@types/minimatch@*": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" - integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== +"@types/mime@^1": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== + +"@types/node-forge@^1.3.0": + version "1.3.11" + resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da" + integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ== + dependencies: + "@types/node" "*" "@types/node@*": - version "18.11.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.2.tgz#c59b7641832531264fda3f1ba610362dc9a7dfc8" - integrity sha512-BWN3M23gLO2jVG8g/XHIRFWiiV4/GckeFIqbU/C4V3xpoBBWSMk4OZomouN0wCkfQFPqgZikyLr7DOYDysIkkw== + version "20.12.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.7.tgz#04080362fa3dd6c5822061aa3124f5c152cff384" + integrity sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg== + dependencies: + undici-types "~5.26.4" "@types/node@^10.11.6": version "10.17.60" @@ -1909,323 +2224,403 @@ integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== "@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" + integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== "@types/prettier@^2.1.5": - version "2.7.1" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e" - integrity sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow== + version "2.7.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" + integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== "@types/prop-types@*": - version "15.7.5" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" - integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== + version "15.7.12" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" + integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== + +"@types/qs@*": + version "6.9.14" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.14.tgz#169e142bfe493895287bee382af6039795e9b75b" + integrity sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA== + +"@types/range-parser@*": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== "@types/react-dom@^18.0.0": - version "18.0.11" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.11.tgz#321351c1459bc9ca3d216aefc8a167beec334e33" - integrity sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw== + version "18.2.25" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.25.tgz#2946a30081f53e7c8d585eb138277245caedc521" + integrity sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA== dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^18.0.0": - version "18.0.33" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.33.tgz#a1575160cb4376787c2f5fe0312302f824baa61e" - integrity sha512-sHxzVxeanvQyQ1lr8NSHaj0kDzcNiGpILEVt69g9S31/7PfMvNCKLKcsHw4lYKjs3cGNJjXSP4mYzX43QlnjNA== +"@types/react-transition-group@^4.4.6": + version "4.4.10" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.10.tgz#6ee71127bdab1f18f11ad8fb3322c6da27c327ac" + integrity sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q== dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" + "@types/react" "*" -"@types/react@^17.0.0": - version "17.0.50" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.50.tgz#39abb4f7098f546cfcd6b51207c90c4295ee81fc" - integrity sha512-ZCBHzpDb5skMnc1zFXAXnL3l1FAdi+xZvwxK+PkglMmBrwjpp9nKaWuEvrGnSifCJmBFGxZOOFuwC6KH/s0NuA== +"@types/react@*", "@types/react@>=16.9.11", "@types/react@^18.0.0", "@types/react@^18.0.26": + version "18.2.78" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.78.tgz#94aec453d0ccca909998a2b4b2fd78af15a7d2fe" + integrity sha512-qOwdPnnitQY4xKlKayt42q5W5UQrSHjgoXNVEtxeqdITJ99k4VXJOP3vt8Rkm9HmgJpH50UNU+rlqfkfWOqp0A== dependencies: "@types/prop-types" "*" - "@types/scheduler" "*" csstype "^3.0.2" -"@types/scheduler@*": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== +"@types/retry@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" + integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== + +"@types/semver@^7.3.12": + version "7.5.8" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" + integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== + +"@types/send@*": + version "0.17.4" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@types/serve-index@^1.9.1": + version "1.9.4" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.4.tgz#e6ae13d5053cb06ed36392110b4f9a49ac4ec898" + integrity sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug== + dependencies: + "@types/express" "*" + +"@types/serve-static@*", "@types/serve-static@^1.13.10": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== + dependencies: + "@types/http-errors" "*" + "@types/node" "*" + "@types/send" "*" "@types/sizzle@*": - version "2.3.3" - resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef" - integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ== + version "2.3.8" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.8.tgz#518609aefb797da19bf222feb199e8f653ff7627" + integrity sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg== + +"@types/sockjs@^0.3.33": + version "0.3.36" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535" + integrity sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q== + dependencies: + "@types/node" "*" "@types/source-list-map@*": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" - integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== + version "0.1.6" + resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.6.tgz#164e169dd061795b50b83c19e4d3be09f8d3a454" + integrity sha512-5JcVt1u5HDmlXkwOD2nslZVllBBc7HDuOICfiZah2Z0is8M8g+ddAEawbmd3VjedfDHBzxCaXLs07QEmb7y54g== "@types/stack-utils@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" - integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + +"@types/tapable@^1": + version "1.0.12" + resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.12.tgz#bc2cab12e87978eee89fb21576b670350d6d86ab" + integrity sha512-bTHG8fcxEqv1M9+TD14P8ok8hjxoOCkfKc8XXLaaD05kI7ohpeI956jtDOD3XHKBQrlyPughUtzm1jtVhHpA5Q== + +"@types/uglify-js@*": + version "3.17.5" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.17.5.tgz#905ce03a3cbbf2e31cbefcbc68d15497ee2e17df" + integrity sha512-TU+fZFBTBcXj/GpDpDaBmgWk/gn96kMZ+uocaFUlV2f8a6WdMzzI44QBCmGcCiYR0Y6ZlNRiyUyKKt5nl/lbzQ== + dependencies: + source-map "^0.6.1" "@types/underscore@*": - version "1.11.4" - resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.4.tgz#62e393f8bc4bd8a06154d110c7d042a93751def3" - integrity sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg== + version "1.11.15" + resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.15.tgz#29c776daecf6f1935da9adda17509686bf979947" + integrity sha512-HP38xE+GuWGlbSRq9WrZkousaQ7dragtZCruBVMi0oX1migFZavZ3OROKHSkNp/9ouq82zrWtZpg18jFnVN96g== + +"@types/warning@^3.0.0": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.3.tgz#d1884c8cc4a426d1ac117ca2611bf333834c6798" + integrity sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q== + +"@types/webpack-dev-server@^3.11.1": + version "3.11.6" + resolved "https://registry.yarnpkg.com/@types/webpack-dev-server/-/webpack-dev-server-3.11.6.tgz#d8888cfd2f0630203e13d3ed7833a4d11b8a34dc" + integrity sha512-XCph0RiiqFGetukCTC3KVnY1jwLcZ84illFRMbyFzCcWl90B/76ew0tSqF46oBhnLC4obNDG7dMO0JfTN0MgMQ== + dependencies: + "@types/connect-history-api-fallback" "*" + "@types/express" "*" + "@types/serve-static" "*" + "@types/webpack" "^4" + http-proxy-middleware "^1.0.0" "@types/webpack-env@^1.13.6": - version "1.18.0" - resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.18.0.tgz#ed6ecaa8e5ed5dfe8b2b3d00181702c9925f13fb" - integrity sha512-56/MAlX5WMsPVbOg7tAxnYvNYMMWr/QJiIp6BxVSW3JJXUVzzOn64qW8TzQyMSqSUFM2+PVI4aUHcHOzIz/1tg== + version "1.18.4" + resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.18.4.tgz#62879b0a9c653f9b1172d403b882f2045ecce032" + integrity sha512-I6e+9+HtWADAWeeJWDFQtdk4EVSAbj6Rtz4q8fJ7mSr1M0jzlFcs8/HZ+Xb5SHzVm1dxH7aUiI+A8kA8Gcrm0A== + +"@types/webpack-sources@*": + version "3.2.3" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-3.2.3.tgz#b667bd13e9fa15a9c26603dce502c7985418c3d8" + integrity sha512-4nZOdMwSPHZ4pTEZzSp0AsTM4K7Qmu40UKW4tJDiOVs20UzYF9l+qUe4s0ftfN0pin06n+5cWWDJXH+sbhAiDw== + dependencies: + "@types/node" "*" + "@types/source-list-map" "*" + source-map "^0.7.3" "@types/webpack-sources@^0.1.5": - version "0.1.9" - resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.9.tgz#da69b06eb34f6432e6658acb5a6893c55d983920" - integrity sha512-bvzMnzqoK16PQIC8AYHNdW45eREJQMd6WG/msQWX5V2+vZmODCOPb4TJcbgRljTZZTwTM4wUMcsI8FftNA7new== + version "0.1.12" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.12.tgz#9beb82c5dc5483c0fb947da1723f4044b07f6204" + integrity sha512-+vRVqE3LzMLLVPgZHUeI8k1YmvgEky+MOir5fQhKvFxpB8uZ0CFnGqxkRAmf8jvNhUBQzhuGZpIMNWZDeEyDIA== dependencies: "@types/node" "*" "@types/source-list-map" "*" source-map "^0.6.1" +"@types/webpack@^4": + version "4.41.38" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.38.tgz#5a40ac81bdd052bf405e8bdcf3e1236f6db6dc26" + integrity sha512-oOW7E931XJU1mVfCnxCVgv8GLFL768pDO5u2Gzk82i8yTIgX6i7cntyZOkZYb/JtYM8252SN9bQp9tgkVDSsRw== + dependencies: + "@types/node" "*" + "@types/tapable" "^1" + "@types/uglify-js" "*" + "@types/webpack-sources" "*" + anymatch "^3.0.0" + source-map "^0.6.0" + +"@types/ws@^8.5.5": + version "8.5.10" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" + integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== + dependencies: + "@types/node" "*" + "@types/yargs-parser@*": - version "21.0.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" - integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== "@types/yargs@^17.0.8": - version "17.0.13" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.13.tgz#34cced675ca1b1d51fcf4d34c3c6f0fa142a5c76" - integrity sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg== + version "17.0.32" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" + integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^3.5.0": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz#7e061338a1383f59edc204c605899f93dc2e2c8f" - integrity sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ== +"@typescript-eslint/eslint-plugin@^5.9.1": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" + integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== + dependencies: + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/type-utils" "5.62.0" + "@typescript-eslint/utils" "5.62.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.9.1": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" + integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== + dependencies: + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" + integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + +"@typescript-eslint/type-utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" + integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== + dependencies: + "@typescript-eslint/typescript-estree" "5.62.0" + "@typescript-eslint/utils" "5.62.0" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" + integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== + +"@typescript-eslint/typescript-estree@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + eslint-scope "^5.1.1" + semver "^7.3.7" + +"@typescript-eslint/visitor-keys@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" + integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== dependencies: - "@typescript-eslint/experimental-utils" "3.10.1" - debug "^4.1.1" - functional-red-black-tree "^1.0.1" - regexpp "^3.0.0" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/experimental-utils@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686" - integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/typescript-estree" "3.10.1" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - -"@typescript-eslint/parser@^3.5.0": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" - integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== - dependencies: - "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "3.10.1" - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/typescript-estree" "3.10.1" - eslint-visitor-keys "^1.1.0" - -"@typescript-eslint/types@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" - integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== - -"@typescript-eslint/typescript-estree@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" - integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== - dependencies: - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/visitor-keys" "3.10.1" - debug "^4.1.1" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" + "@typescript-eslint/types" "5.62.0" + eslint-visitor-keys "^3.3.0" + +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@typescript-eslint/visitor-keys@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" - integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== dependencies: - eslint-visitor-keys "^1.1.0" + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" -"@verdaccio/commons-api@10.2.0": - version "10.2.0" - resolved "https://registry.yarnpkg.com/@verdaccio/commons-api/-/commons-api-10.2.0.tgz#3b684c31749837b0574375bb2e10644ecea9fcca" - integrity sha512-F/YZANu4DmpcEV0jronzI7v2fGVWkQ5Mwi+bVmV+ACJ+EzR0c9Jbhtbe5QyLUuzR97t8R5E/Xe53O0cc2LukdQ== +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== + +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== + +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== + +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== dependencies: - http-errors "2.0.0" - http-status-codes "2.2.0" - -"@verdaccio/file-locking@10.3.0": - version "10.3.0" - resolved "https://registry.yarnpkg.com/@verdaccio/file-locking/-/file-locking-10.3.0.tgz#a4342665c549163817c267bfa451e32ed3009767" - integrity sha512-FE5D5H4wy/nhgR/d2J5e1Na9kScj2wMjlLPBHz7XF4XZAVSRdm45+kL3ZmrfA6b2HTADP/uH7H05/cnAYW8bhw== - dependencies: - lockfile "1.0.4" - -"@verdaccio/local-storage@10.3.1": - version "10.3.1" - resolved "https://registry.yarnpkg.com/@verdaccio/local-storage/-/local-storage-10.3.1.tgz#8cbdc6390a0eb532577ae217729cb0a4e062f299" - integrity sha512-f3oArjXPOAwUAA2dsBhfL/rSouqJ2sfml8k97RtnBPKOzisb28bgyAQW0mqwQvN4MTK5S/2xudmobFpvJAIatg== - dependencies: - "@verdaccio/commons-api" "10.2.0" - "@verdaccio/file-locking" "10.3.0" - "@verdaccio/streams" "10.2.0" - async "3.2.4" - debug "4.3.4" - lodash "4.17.21" - lowdb "1.0.0" - mkdirp "1.0.4" - -"@verdaccio/readme@10.4.1": - version "10.4.1" - resolved "https://registry.yarnpkg.com/@verdaccio/readme/-/readme-10.4.1.tgz#c568d158c36ca7dd742b1abef890383918f621b2" - integrity sha512-OZ6R+HF2bIU3WFFdPxgUgyglaIfZzGSqyUfM2m1TFNfDCK84qJvRIgQJ1HG/82KVOpGuz/nxVyw2ZyEZDkP1vA== - dependencies: - dompurify "2.3.9" - jsdom "16.7.0" - marked "4.0.18" - -"@verdaccio/streams@10.2.0": - version "10.2.0" - resolved "https://registry.yarnpkg.com/@verdaccio/streams/-/streams-10.2.0.tgz#e01d2bfdcfe8aa2389f31bc6b72a602628bd025b" - integrity sha512-FaIzCnDg0x0Js5kSQn1Le3YzDHl7XxrJ0QdIw5LrDUmLsH3VXNi4/NMlSHnw5RiTTMs4UbEf98V3RJRB8exqJA== - -"@verdaccio/ui-theme@6.0.0-6-next.48": - version "6.0.0-6-next.48" - resolved "https://registry.yarnpkg.com/@verdaccio/ui-theme/-/ui-theme-6.0.0-6-next.48.tgz#23bbc8037bf9e1b27600f5160a0ff716982db48b" - integrity sha512-1jls+cpfEXqXc1ZzqLGGNs6YCyG6B6QwDCezEkSvgKm+9A49FnSJ2n2dNIGcQYOszwHmd8EvwN98OEIx3Bbtrw== - -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== - dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== - -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== - -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== - -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== - dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== - -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" - -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== - dependencies: - "@webassemblyjs/ast" "1.11.1" +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== + dependencies: + "@webassemblyjs/ast" "1.12.1" "@xtuc/long" "4.2.2" "@webpack-cli/configtest@^1.2.0": @@ -2233,6 +2628,11 @@ resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== +"@webpack-cli/configtest@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" + integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== + "@webpack-cli/info@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" @@ -2240,11 +2640,21 @@ dependencies: envinfo "^7.7.3" +"@webpack-cli/info@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" + integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== + "@webpack-cli/serve@^1.7.0": version "1.7.0" resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== +"@webpack-cli/serve@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" + integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -2255,25 +2665,12 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -"@yarnpkg/lockfile@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" - integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== - -JSONStream@1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" - integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== - dependencies: - jsonparse "^1.2.0" - through ">=2.2.7 <3" - -abab@^2.0.3, abab@^2.0.5: +abab@^2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== -accepts@~1.3.5, accepts@~1.3.8: +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -2281,63 +2678,39 @@ accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-globals@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" - integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== - dependencies: - acorn "^7.1.1" - acorn-walk "^7.1.1" - -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== -acorn-jsx@^5.3.1: +acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn-walk@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" - integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== - acorn@^6.2.0: version "6.4.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== -acorn@^7.1.1, acorn@^7.4.0: - version "7.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" - integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== - -acorn@^8.2.4, acorn@^8.5.0, acorn@^8.7.1: - version "8.8.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" - integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== +acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== -ag-grid-community@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/ag-grid-community/-/ag-grid-community-29.2.0.tgz#ce29357464f50bbafa00aaa2adbd8b275310f44d" - integrity sha512-1xP1fpM8gXp2ALzBLONejZNul9hA3//ddszSlhq79QZ1FskQ1Z7E2WvvFeCeLJTJZrfhQkT1q1LO5DGfGeiBvg== +ag-grid-community@31.2.1, ag-grid-community@^31.0.3: + version "31.2.1" + resolved "https://registry.yarnpkg.com/ag-grid-community/-/ag-grid-community-31.2.1.tgz#6031c91baa5caebccfa58a5131efc13339643e50" + integrity sha512-D+gnUQ4dHZ/EQJmupQnDqcEKiCEeuK5ZxlsIpdPKgHg/23dmW+aEdivtB9nLpSc2IEK0RUpchcSxeUT37Boo5A== -ag-grid-react@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/ag-grid-react/-/ag-grid-react-29.2.0.tgz#512f41e98cfd7ec291832aae8601f76b52c366c8" - integrity sha512-FZEWhbe51KNkvu+MohGXxXixIJdakJrs5XDdJ/h1jqmCX9WZzHNT2OvoYHIXB7gcKKj5pf47YJB8eaEqsRlpbg== +ag-grid-react@^31.0.3: + version "31.2.1" + resolved "https://registry.yarnpkg.com/ag-grid-react/-/ag-grid-react-31.2.1.tgz#21be0703225e4c7ad88b1b6ca13491a6d9a072c1" + integrity sha512-9UH3xxXRwZfW97oz58KboyCJl4t+zdetopieeHVcttsXX1DvGFDUIEz7A1sQaG8e1DAXLMf3IxoIPrfWheH4XA== dependencies: + ag-grid-community "31.2.1" prop-types "^15.8.1" -agent-base@6: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -2346,17 +2719,26 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv-errors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" - integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" -ajv-keywords@^3.1.0, ajv-keywords@^3.5.2: +ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.7.0: +ajv-keywords@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2366,10 +2748,10 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.7.0: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.1: - version "8.11.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" - integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== +ajv@^8.0.0, ajv@^8.12.0, ajv@^8.9.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -2388,6 +2770,11 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: dependencies: type-fest "^0.21.3" +ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -2422,18 +2809,18 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -anymatch@^3.0.3, anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== +anymatch@^3.0.0, anymatch@^3.0.3, anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" -apache-md5@1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/apache-md5/-/apache-md5-1.1.7.tgz#dcef1802700cc231d60c5e08fd088f2f9b36375a" - integrity sha512-JtHjzZmJxtzfTSjsCyHgPR155HBe5WGyUyHTaEkfy46qhwCFKx1Epm6nAxgUG3WfUZP1dWhGqj9Z2NOBeZ+uBw== +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== argparse@^1.0.7: version "1.0.10" @@ -2447,38 +2834,108 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +array-buffer-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" + integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== + dependencies: + call-bind "^1.0.5" + is-array-buffer "^3.0.4" + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== +array-includes@^3.1.6, array-includes@^3.1.7: + version "3.1.8" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" + integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" + is-string "^1.0.7" + array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -asn1@~0.2.3: - version "0.2.6" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" - integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== +array.prototype.findlast@^1.2.4: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" + integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== dependencies: - safer-buffer "~2.1.0" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-shim-unscopables "^1.0.2" -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== +array.prototype.flat@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.toreversed@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz#b989a6bf35c4c5051e1dc0325151bf8088954eba" + integrity sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.tosorted@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz#c8c89348337e51b8a3c48a9227f9ce93ceedcba8" + integrity sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg== + dependencies: + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.1.0" + es-shim-unscopables "^1.0.2" + +arraybuffer.prototype.slice@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" + integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== + dependencies: + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.2.1" + get-intrinsic "^1.2.3" + is-array-buffer "^3.0.4" + is-shared-array-buffer "^1.0.2" astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== -async@3.2.4: - version "3.2.4" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" - integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== - async@^2.5.0: version "2.6.4" resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" @@ -2486,30 +2943,29 @@ async@^2.5.0: dependencies: lodash "^4.17.14" -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - at-least-node@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== -atomic-sleep@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" - integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== +autoprefixer@^10.4.13: + version "10.4.19" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.19.tgz#ad25a856e82ee9d7898c59583c1afeb3fa65f89f" + integrity sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew== + dependencies: + browserslist "^4.23.0" + caniuse-lite "^1.0.30001599" + fraction.js "^4.3.7" + normalize-range "^0.1.2" + picocolors "^1.0.0" + postcss-value-parser "^4.2.0" -aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" babel-code-frame@^6.26.0: version "6.26.0" @@ -2520,7 +2976,7 @@ babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-jest@^28.1.3: +babel-jest@^28, babel-jest@^28.1.3: version "28.1.3" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-28.1.3.tgz#c1187258197c099072156a0a121c11ee1e3917d5" integrity sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q== @@ -2561,29 +3017,29 @@ babel-plugin-jest-hoist@^28.1.3: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" -babel-plugin-polyfill-corejs2@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" - integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.10" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz#276f41710b03a64f6467433cab72cbc2653c38b1" + integrity sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ== dependencies: - "@babel/compat-data" "^7.17.7" - "@babel/helper-define-polyfill-provider" "^0.3.3" - semver "^6.1.1" + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.6.1" + semver "^6.3.1" -babel-plugin-polyfill-corejs3@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" - integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== +babel-plugin-polyfill-corejs3@^0.10.4: + version "0.10.4" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz#789ac82405ad664c20476d0233b485281deb9c77" + integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" - core-js-compat "^3.25.1" + "@babel/helper-define-polyfill-provider" "^0.6.1" + core-js-compat "^3.36.1" -babel-plugin-polyfill-regenerator@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" - integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz#4f08ef4c62c7a7f66a35ed4c0d75e30506acc6be" + integrity sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" + "@babel/helper-define-polyfill-provider" "^0.6.1" babel-plugin-transform-es2015-modules-commonjs@^6.26.2: version "6.26.2" @@ -2690,17 +3146,10 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== - dependencies: - tweetnacl "^0.14.3" - -bcryptjs@2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" - integrity sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ== +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== big.js@^5.2.2: version "5.2.2" @@ -2708,28 +3157,46 @@ big.js@^5.2.2: integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== -body-parser@1.20.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" - integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== +body-parser@1.20.2: + version "1.20.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" + integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== dependencies: bytes "3.1.2" - content-type "~1.0.4" + content-type "~1.0.5" debug "2.6.9" depd "2.0.0" destroy "1.2.0" http-errors "2.0.0" iconv-lite "0.4.24" on-finished "2.4.1" - qs "6.10.3" - raw-body "2.5.1" + qs "6.11.0" + raw-body "2.5.2" type-is "~1.6.18" unpipe "1.0.0" +bonjour-service@^1.0.11: + version "1.2.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02" + integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw== + dependencies: + fast-deep-equal "^3.1.3" + multicast-dns "^7.2.5" + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +bootstrap@^5.1.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.3.tgz#de35e1a765c897ac940021900fcbb831602bac38" + integrity sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2738,13 +3205,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -2752,20 +3212,15 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browser-process-hrtime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" - integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== - -browserslist@^4.14.5, browserslist@^4.21.3, browserslist@^4.21.4: - version "4.21.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" - integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== +browserslist@^4.21.10, browserslist@^4.21.4, browserslist@^4.22.2, browserslist@^4.23.0: + version "4.23.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" + integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== dependencies: - caniuse-lite "^1.0.30001400" - electron-to-chromium "^1.4.251" - node-releases "^2.0.6" - update-browserslist-db "^1.0.9" + caniuse-lite "^1.0.30001587" + electron-to-chromium "^1.4.668" + node-releases "^2.0.14" + update-browserslist-db "^1.0.13" bs-logger@0.x: version "0.2.6" @@ -2781,11 +3236,6 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -buffer-equal-constant-time@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== - buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -2801,56 +3251,30 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -cacache@^15.0.5: - version "15.3.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" - integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== - dependencies: - "@npmcli/fs" "^1.0.0" - "@npmcli/move-file" "^1.0.1" - chownr "^2.0.0" - fs-minipass "^2.0.0" - glob "^7.1.4" - infer-owner "^1.0.4" - lru-cache "^6.0.0" - minipass "^3.1.1" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.2" - mkdirp "^1.0.3" - p-map "^4.0.0" - promise-inflight "^1.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.0.2" - unique-filename "^1.1.1" - -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== +call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camel-case@^4.1.1, camel-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== + dependencies: + pascal-case "^3.1.2" + tslib "^2.0.3" + camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -2861,15 +3285,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001400: - version "1.0.30001422" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001422.tgz#f2d7c6202c49a8359e6e35add894d88ef93edba1" - integrity sha512-hSesn02u1QacQHhaxl/kNMZwqVG35Sz/8DgvmgedxSH8z9UUpcDYSPYgsj3x5dQNRcNp6BwpSfQfVzYUTm+fog== - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== +caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001599: + version "1.0.30001609" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001609.tgz#fc34fad75c0c6d6d6303bdbceec2da8f203dabd6" + integrity sha512-JFPQs34lHKx1B5t1EpQpWH4c+29zIyn/haGsbpfq3suuV9v56enjFt23zqijxGTMwy1p/4H2tjnQMY+p1WoAyA== chalk@^1.1.3: version "1.1.3" @@ -2882,7 +3301,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1: +chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2904,20 +3323,10 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - -child_process@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/child_process/-/child_process-1.0.2.tgz#b1f7e7fc73d25e7fd1d455adc94e143830182b5a" - integrity sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g== - -chokidar@^3.4.0: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.0, chokidar@^3.4.2, chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -2929,30 +3338,39 @@ chokidar@^3.4.0: optionalDependencies: fsevents "~2.3.2" -chownr@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" - integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== - chrome-trace-event@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== ci-info@^3.2.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.5.0.tgz#bfac2a29263de4c829d806b1ab478e35091e171f" - integrity sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw== + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== cjs-module-lexer@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" - integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== -classnames@^2.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" - integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== +classnames@^2.3.2: + version "2.5.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" + integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== + +clean-css@^4.2.3: + version "4.2.4" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.4.tgz#733bf46eba4e607c6891ea57c24a989356831178" + integrity sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A== + dependencies: + source-map "~0.6.0" + +clean-css@^5.2.2: + version "5.3.3" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd" + integrity sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg== + dependencies: + source-map "~0.6.0" clean-stack@^2.0.0: version "2.2.0" @@ -2974,18 +3392,6 @@ cli-truncate@^2.1.0: slice-ansi "^3.0.0" string-width "^4.2.0" -cli-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" - integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== - -clipanion@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/clipanion/-/clipanion-3.1.0.tgz#3e217dd6476bb9236638b07eb4673f7309839819" - integrity sha512-v025Hz+IDQ15FpOyK8p02h5bFznMu6rLFsJSyOPR+7WrbSnZ1Ek6pblPukV7K5tC/dsWfncQPIrJ4iUy2PXkbw== - dependencies: - typanion "^3.3.1" - cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -3004,12 +3410,10 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" -clone-response@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" - integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== - dependencies: - mimic-response "^1.0.0" +clsx@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.0.tgz#e851283bcb5c80ee7608db18487433f7b23f77cb" + integrity sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg== co@^4.6.0: version "4.6.0" @@ -3017,9 +3421,9 @@ co@^4.6.0: integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== collect-v8-coverage@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" - integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== color-convert@^1.9.0: version "1.9.3" @@ -3045,24 +3449,22 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^2.0.14, colorette@^2.0.16: - version "2.0.19" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" - integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== +colorette@^2.0.10, colorette@^2.0.14, colorette@^2.0.16: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== -combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^4.0.1: +commander@^4.0.1, commander@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== @@ -3077,15 +3479,15 @@ commander@^7.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@~6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-6.0.0.tgz#2b270da94f8fb9014455312f829a1129dbf8887e" - integrity sha512-s7EA+hDtTYNhuXkTlhqew4txMZVdszBmKWSPEMxGr8ru8JXR7bLUFIAtPhcSuFdJQ0ILMxnJi8GkQL0yvDy/YA== +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== +commander@^9.4.1: + version "9.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== compressible@~2.0.16: version "2.0.18" @@ -3094,7 +3496,7 @@ compressible@~2.0.16: dependencies: mime-db ">= 1.43.0 < 2" -compression@1.7.4: +compression@^1.7.4: version "1.7.4" resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== @@ -3116,7 +3518,7 @@ compute-gcd@^1.2.1: validate.io-function "^1.0.2" validate.io-integer-array "^1.0.0" -compute-lcm@^1.1.0: +compute-lcm@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/compute-lcm/-/compute-lcm-1.1.2.tgz#9107c66b9dca28cefb22b4ab4545caac4034af23" integrity sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ== @@ -3131,6 +3533,11 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +connect-history-api-fallback@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" + integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== + content-disposition@0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" @@ -3138,73 +3545,63 @@ content-disposition@0.5.4: dependencies: safe-buffer "5.2.1" -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +content-type@~1.0.4, content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== -convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.4.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== - -cookies@0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90" - integrity sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow== - dependencies: - depd "~2.0.0" - keygrip "~1.1.0" +cookie@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== -core-js-compat@^3.25.1: - version "3.25.5" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.25.5.tgz#0016e8158c904f7b059486639e6e82116eafa7d9" - integrity sha512-ovcyhs2DEBUIE0MGEKHP4olCUW/XYte3Vroyxuh38rD1wAO4dHohsovUC4eAOuzFxE6b+RXvBU3UZ9o0YhUTkA== +core-js-compat@^3.31.0, core-js-compat@^3.36.1: + version "3.36.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.36.1.tgz#1818695d72c99c25d621dca94e6883e190cea3c8" + integrity sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA== dependencies: - browserslist "^4.21.4" - -core-js-pure@^3.6.5: - version "3.25.5" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.25.5.tgz#79716ba54240c6aa9ceba6eee08cf79471ba184d" - integrity sha512-oml3M22pHM+igfWHDfdLVq2ShWmjM2V4L+dQEBs0DWVIqEm9WHCwGAlZ6BmyBQGy5sFrJmcx+856D9lVKyGWYg== + browserslist "^4.23.0" core-js@^2.4.0: version "2.6.12" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== - core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cors@2.8.5: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== +cosmiconfig@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" + integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== dependencies: - object-assign "^4" - vary "^1" + "@types/parse-json" "^4.0.0" + import-fresh "^3.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.7.2" cosmiconfig@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" - integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== + version "7.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== dependencies: "@types/parse-json" "^4.0.0" import-fresh "^3.2.1" @@ -3212,6 +3609,21 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" +cosmiconfig@^8.3.5: + version "8.3.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== + dependencies: + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + path-type "^4.0.0" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -3232,31 +3644,21 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -crypto@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037" - integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig== +css-blank-pseudo@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz#36523b01c12a25d812df343a32c322d2a2324561" + integrity sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ== + dependencies: + postcss-selector-parser "^6.0.9" -css-loader@^3.0.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" - integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ== +css-has-pseudo@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz#57f6be91ca242d5c9020ee3e51bbb5b89fc7af73" + integrity sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw== dependencies: - camelcase "^5.3.1" - cssesc "^3.0.0" - icss-utils "^4.1.1" - loader-utils "^1.2.3" - normalize-path "^3.0.0" - postcss "^7.0.32" - postcss-modules-extract-imports "^2.0.0" - postcss-modules-local-by-default "^3.0.2" - postcss-modules-scope "^2.2.0" - postcss-modules-values "^3.0.0" - postcss-value-parser "^4.1.0" - schema-utils "^2.7.0" - semver "^6.3.0" + postcss-selector-parser "^6.0.9" -css-loader@^5.0.1: +css-loader@^5.0.0: version "5.2.7" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.2.7.tgz#9b9f111edf6fb2be5dc62525644cbc9c232064ae" integrity sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg== @@ -3272,52 +3674,131 @@ css-loader@^5.0.1: schema-utils "^3.0.0" semver "^7.3.5" +css-loader@^6.7.1: + version "6.11.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.11.0.tgz#33bae3bf6363d0a7c2cf9031c96c744ff54d85ba" + integrity sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g== + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.33" + postcss-modules-extract-imports "^3.1.0" + postcss-modules-local-by-default "^4.0.5" + postcss-modules-scope "^3.2.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.2.0" + semver "^7.5.4" + +css-prefers-color-scheme@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz#ca8a22e5992c10a5b9d315155e7caee625903349" + integrity sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA== + +css-select@^4.1.3: + version "4.3.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" + integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== + dependencies: + boolbase "^1.0.0" + css-what "^6.0.1" + domhandler "^4.3.1" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-what@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + +cssdb@^7.1.0: + version "7.11.2" + resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-7.11.2.tgz#127a2f5b946ee653361a5af5333ea85a39df5ae5" + integrity sha512-lhQ32TFkc1X4eTefGfYPvgovRSzIMofHkigfH8nWtyRL4XJLsRhJFreRvEgKzept7x1rjBuy3J/MurXLaFxW/A== + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -cssom@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" - integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== - -cssom@~0.3.6: - version "0.3.8" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" - integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== - -cssstyle@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" - integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== - dependencies: - cssom "~0.3.6" - csstype@3.0.10: version "3.0.10" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5" integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA== csstype@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" - integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== +"d3-array@2 - 3", "d3-array@2.10.0 - 3", d3-array@^3.1.6: + version "3.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" + integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== dependencies: - es5-ext "^0.10.50" - type "^1.0.1" + internmap "1 - 2" -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== +"d3-color@1 - 3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" + integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== + +d3-ease@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" + integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== + +"d3-format@1 - 3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== + +"d3-interpolate@1.2.0 - 3", d3-interpolate@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + +d3-path@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526" + integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== + +d3-scale@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== + dependencies: + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" + +d3-shape@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5" + integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== + dependencies: + d3-path "^3.1.0" + +"d3-time-format@2 - 4": + version "4.1.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== + dependencies: + d3-time "1 - 3" + +"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" + integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== dependencies: - assert-plus "^1.0.0" + d3-array "2 - 3" + +d3-timer@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" + integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== data-urls@^2.0.0: version "2.0.0" @@ -3328,10 +3809,32 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -dayjs@1.11.5: - version "1.11.5" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.5.tgz#00e8cc627f231f9499c19b38af49f56dc0ac5e93" - integrity sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA== +data-view-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" + integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" + integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" + integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" debug@2.6.9, debug@^2.6.8: version "2.6.9" @@ -3340,117 +3843,103 @@ debug@2.6.9, debug@^2.6.8: dependencies: ms "2.0.0" -debug@4, debug@4.3.4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.3: +debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -decimal.js@^10.2.1: - version "10.4.2" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.2.tgz#0341651d1d997d86065a2ce3a441fbd0d8e8b98e" - integrity sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA== - -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== - dependencies: - mimic-response "^1.0.0" +decimal.js-light@^2.4.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" + integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== -deep-equal@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deep-is@^0.1.3, deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== +default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== + dependencies: + execa "^5.0.0" -define-properties@^1.1.3, define-properties@^1.1.4: +define-data-property@^1.0.1, define-data-property@^1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== dependencies: + define-data-property "^1.0.1" has-property-descriptors "^1.0.0" object-keys "^1.1.1" -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -depd@2.0.0, depd@~2.0.0: +depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -dependency-graph@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.9.0.tgz#11aed7e203bc8b00f48356d92db27b265c445318" - integrity sha512-9YLIBURXj4DJMFALxXw9K3Y3rwb5Fk0X5/8ipCzaN84+gKxoHK43tVKRNakCQbiEx07E8Uwhuq21BpUagFhZ8w== +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +dequal@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== -detect-indent@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" - integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== - -detect-newline@3.1.0, detect-newline@^3.0.0: +detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== -diff-sequences@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" - integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== +detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== diff-sequences@^28.1.1: version "28.1.1" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-28.1.1.tgz#9989dc731266dc2903457a70e996f3a041913ac6" integrity sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -3458,6 +3947,20 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +dns-packet@^5.2.2: + version "5.6.1" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f" + integrity sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw== + dependencies: + "@leichtgewicht/ip-codec" "^2.0.1" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -3465,6 +3968,13 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dom-converter@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" + integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== + dependencies: + utila "~0.4" + dom-helpers@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8" @@ -3472,6 +3982,14 @@ dom-helpers@^3.4.0: dependencies: "@babel/runtime" "^7.1.2" +dom-helpers@^5.0.1, dom-helpers@^5.2.0, dom-helpers@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + dom-serializer@^1.0.1: version "1.4.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" @@ -3481,36 +3999,19 @@ dom-serializer@^1.0.1: domhandler "^4.2.0" entities "^2.0.0" -dom4@^2.1.5: - version "2.1.6" - resolved "https://registry.yarnpkg.com/dom4/-/dom4-2.1.6.tgz#c90df07134aa0dbd81ed4d6ba1237b36fc164770" - integrity sha512-JkCVGnN4ofKGbjf5Uvc8mmxaATIErKQKSgACdBXpsQ3fY6DlIpAyWfiBSrGkttATssbDCp3psiAKWXk5gmjycA== - domelementtype@^2.0.1, domelementtype@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== -domexception@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" - integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== - dependencies: - webidl-conversions "^5.0.0" - -domhandler@^4.0.0, domhandler@^4.2.0: +domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== dependencies: domelementtype "^2.2.0" -dompurify@2.3.9: - version "2.3.9" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.9.tgz#a4be5e7278338d6db09922dffcf6182cd099d70a" - integrity sha512-3zOnuTwup4lPV/GfGS6UzG4ub9nhSYagR/5tB3AvDEwqyy5dtyCM2dVjwGDCnrPerXifBKTYh/UWCGKK7ydhhw== - -domutils@^2.5.2: +domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== @@ -3519,10 +4020,13 @@ domutils@^2.5.2: domelementtype "^2.2.0" domhandler "^4.2.0" -duplexer3@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" - integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" duplicate-package-checker-webpack-plugin@^3.0.0: version "3.0.0" @@ -3534,30 +4038,15 @@ duplicate-package-checker-webpack-plugin@^3.0.0: lodash "^4.17.4" semver "^5.4.1" -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -ecdsa-sig-formatter@1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" - integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== - dependencies: - safe-buffer "^5.0.1" - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.4.251: - version "1.4.284" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" - integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== +electron-to-chromium@^1.4.668: + version "1.4.736" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.736.tgz#ecb4348f4d5c70fb1e31c347e5bad6b751066416" + integrity sha512-Rer6wc3ynLelKNM4lOCg7/zPQj8tPOCB2hzD32PX9wd3hgRRi9MxEbmkFCokzcEhRVMiOVLjnL9ig9cefJ+6+Q== emittery@^0.10.2: version "0.10.2" @@ -3569,11 +4058,6 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha512-knHEZMgs8BB+MInokmNTg/OyPlAddghe1YBgNwJBc5zsJi/uyIcXoSDsL/W9ymOsBoBGdPIHXYJ9+qKFwRwDng== - emojis-list@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" @@ -3600,30 +4084,31 @@ enhanced-resolve@^4.0.0: memory-fs "^0.5.0" tapable "^1.0.0" -enhanced-resolve@^5.10.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" - integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== +enhanced-resolve@^5.16.0, enhanced-resolve@^5.7.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz#65ec88778083056cb32487faa9aef82ed0864787" + integrity sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" -enquirer@^2.3.5, enquirer@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== +enquirer@^2.3.6: + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== dependencies: ansi-colors "^4.1.1" + strip-ansi "^6.0.1" entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== -envinfo@7.8.1, envinfo@^7.7.3: - version "7.8.1" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" - integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== +envinfo@^7.7.3: + version "7.12.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.12.0.tgz#b56723b39c2053d67ea5714f026d05d4f5cc7acd" + integrity sha512-Iw9rQJBGpJRd3rwXm9ft/JiGoAZmLxxJZELYDQoPRZ4USVhkKtIcNBPw6U+/K2mBpaqM25JSV6Yl4Az9vO2wJg== errno@^0.1.3: version "0.1.8" @@ -3639,90 +4124,131 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.5: - version "1.20.4" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.4.tgz#1d103f9f8d78d4cf0713edcd6d0ed1a46eed5861" - integrity sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA== - dependencies: - call-bind "^1.0.2" +es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2: + version "1.23.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" + integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== + dependencies: + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.3" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + data-view-buffer "^1.0.1" + data-view-byte-length "^1.0.1" + data-view-byte-offset "^1.0.0" + es-define-property "^1.0.0" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-set-tostringtag "^2.0.3" es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.3" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-property-descriptors "^1.0.0" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.4" + get-symbol-description "^1.0.2" + globalthis "^1.0.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" has-symbols "^1.0.3" - internal-slot "^1.0.3" + hasown "^2.0.2" + internal-slot "^1.0.7" + is-array-buffer "^3.0.4" is-callable "^1.2.7" - is-negative-zero "^2.0.2" + is-data-view "^1.0.1" + is-negative-zero "^2.0.3" is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" + is-shared-array-buffer "^1.0.3" is-string "^1.0.7" + is-typed-array "^1.1.13" is-weakref "^1.0.2" - object-inspect "^1.12.2" + object-inspect "^1.13.1" object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - safe-regex-test "^1.0.0" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" - unbox-primitive "^1.0.2" - -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + object.assign "^4.1.5" + regexp.prototype.flags "^1.5.2" + safe-array-concat "^1.1.2" + safe-regex-test "^1.0.3" + string.prototype.trim "^1.2.9" + string.prototype.trimend "^1.0.8" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.2" + typed-array-byte-length "^1.0.1" + typed-array-byte-offset "^1.0.2" + typed-array-length "^1.0.6" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.15" + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" + get-intrinsic "^1.2.4" + +es-errors@^1.1.0, es-errors@^1.2.1, es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-iterator-helpers@^1.0.17: + version "1.0.18" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz#4d3424f46b24df38d064af6fbbc89274e29ea69d" + integrity sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.0" + es-errors "^1.3.0" + es-set-tostringtag "^2.0.3" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + globalthis "^1.0.3" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" + has-symbols "^1.0.3" + internal-slot "^1.0.7" + iterator.prototype "^1.1.2" + safe-array-concat "^1.1.2" + +es-module-lexer@^1.2.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.0.tgz#4878fee3789ad99e065f975fdd3c645529ff0236" + integrity sha512-pqrTKmwEIgafsYZAGw9kszYzmagcE/n4dbgwGWLEXg7J4QFJVQRBld8j3Q3GNez79jzxZshq0bcT962QHOghjw== -es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: - version "0.10.62" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" - integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== +es-object-atoms@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" + integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== dependencies: - es6-iterator "^2.0.3" - es6-symbol "^3.1.3" - next-tick "^1.1.0" + es-errors "^1.3.0" -es6-iterator@^2.0.3: +es-set-tostringtag@^2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" + integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" + get-intrinsic "^1.2.4" + has-tostringtag "^1.0.2" + hasown "^2.0.1" -es6-symbol@^3.1.1, es6-symbol@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== +es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== dependencies: - d "^1.0.1" - ext "^1.1.2" + hasown "^2.0.0" -es6-weak-map@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" - integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: - d "1" - es5-ext "^0.10.46" - es6-iterator "^2.0.3" - es6-symbol "^3.1.1" + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== escape-html@~1.0.3: version "1.0.3" @@ -3744,41 +4270,48 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escodegen@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" - integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== - dependencies: - esprima "^4.0.1" - estraverse "^5.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -eslint-config-prettier@^6.11.0: - version "6.15.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" - integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw== - dependencies: - get-stdin "^6.0.0" - -eslint-import-resolver-node@0.3.6: - version "0.3.6" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" - integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== - dependencies: - debug "^3.2.7" - resolve "^1.20.0" +eslint-config-prettier@^8.3.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11" + integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== -eslint-plugin-prettier@^3.1.4: - version "3.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5" - integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g== +eslint-plugin-prettier@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" + integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== dependencies: prettier-linter-helpers "^1.0.0" -eslint-scope@5.1.1, eslint-scope@^5.0.0, eslint-scope@^5.1.1: +eslint-plugin-react-hooks@^4.3.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" + integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== + +eslint-plugin-react@^7.28.0: + version "7.34.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz#6806b70c97796f5bbfb235a5d3379ece5f4da997" + integrity sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw== + dependencies: + array-includes "^3.1.7" + array.prototype.findlast "^1.2.4" + array.prototype.flatmap "^1.3.2" + array.prototype.toreversed "^1.1.2" + array.prototype.tosorted "^1.1.3" + doctrine "^2.1.0" + es-iterator-helpers "^1.0.17" + estraverse "^5.3.0" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.7" + object.fromentries "^2.0.7" + object.hasown "^1.1.3" + object.values "^1.1.7" + prop-types "^15.8.1" + resolve "^2.0.0-next.5" + semver "^6.3.1" + string.prototype.matchall "^4.0.10" + +eslint-scope@5.1.1, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -3786,87 +4319,81 @@ eslint-scope@5.1.1, eslint-scope@^5.0.0, eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^2.0.0, eslint-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + esrecurse "^4.3.0" + estraverse "^5.2.0" -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint@^7.3.1: - version "7.32.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" - integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== - dependencies: - "@babel/code-frame" "7.12.11" - "@eslint/eslintrc" "^0.4.3" - "@humanwhocodes/config-array" "^0.5.0" - ajv "^6.10.0" +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@^8.6.0: + version "8.57.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" + integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.57.0" + "@humanwhocodes/config-array" "^0.11.14" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.2" - debug "^4.0.1" + debug "^4.3.2" doctrine "^3.0.0" - enquirer "^2.3.5" escape-string-regexp "^4.0.0" - eslint-scope "^5.1.1" - eslint-utils "^2.1.0" - eslint-visitor-keys "^2.0.0" - espree "^7.3.1" - esquery "^1.4.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" file-entry-cache "^6.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.1.2" - globals "^13.6.0" - ignore "^4.0.6" - import-fresh "^3.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" imurmurhash "^0.1.4" is-glob "^4.0.0" - js-yaml "^3.13.1" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" lodash.merge "^4.6.2" - minimatch "^3.0.4" + minimatch "^3.1.2" natural-compare "^1.4.0" - optionator "^0.9.1" - progress "^2.0.0" - regexpp "^3.1.0" - semver "^7.2.1" - strip-ansi "^6.0.0" - strip-json-comments "^3.1.0" - table "^6.0.9" + optionator "^0.9.3" + strip-ansi "^6.0.1" text-table "^0.2.0" - v8-compile-cache "^2.0.3" -espree@^7.3.0, espree@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" - integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== dependencies: - acorn "^7.4.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^1.3.0" + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" -esprima@^4.0.0, esprima@^4.0.1: +esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== dependencies: estraverse "^5.1.0" @@ -3882,7 +4409,7 @@ estraverse@^4.1.1: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -estraverse@^5.1.0, estraverse@^5.2.0: +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== @@ -3897,13 +4424,10 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -event-emitter@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== - dependencies: - d "1" - es5-ext "~0.10.14" +eventemitter3@^4.0.0, eventemitter3@^4.0.1: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== events@^3.2.0: version "3.3.0" @@ -3940,12 +4464,17 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" +exenv-es6@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exenv-es6/-/exenv-es6-1.1.1.tgz#80b7a8c5af24d53331f755bac07e84abb1f6de67" + integrity sha512-vlVu3N8d6yEMpMsEm+7sUBAI81aqYYuEvfK0jNqmdb/OPXzzH7QWDDnVjMvDSY47JdHEqx/dfC/q8WkfoTmpGQ== + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== -expect@^28.1.3: +expect@^28.0.0, expect@^28.1.3: version "28.1.3" resolved "https://registry.yarnpkg.com/expect/-/expect-28.1.3.tgz#90a7c1a124f1824133dd4533cce2d2bdcb6603ec" integrity sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g== @@ -3956,22 +4485,17 @@ expect@^28.1.3: jest-message-util "^28.1.3" jest-util "^28.1.3" -express-rate-limit@5.5.1: - version "5.5.1" - resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-5.5.1.tgz#110c23f6a65dfa96ab468eda95e71697bc6987a2" - integrity sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg== - -express@4.18.1: - version "4.18.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf" - integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q== +express@^4.17.3: + version "4.19.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" + integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.0" + body-parser "1.20.2" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.5.0" + cookie "0.6.0" cookie-signature "1.0.6" debug "2.6.9" depd "2.0.0" @@ -3987,7 +4511,7 @@ express@4.18.1: parseurl "~1.3.3" path-to-regexp "0.1.7" proxy-addr "~2.0.7" - qs "6.10.3" + qs "6.11.0" range-parser "~1.2.1" safe-buffer "5.2.1" send "0.18.0" @@ -3998,51 +4522,25 @@ express@4.18.1: utils-merge "1.0.1" vary "~1.1.2" -ext@^1.1.2: - version "1.7.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" - integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== - dependencies: - type "^2.7.2" - -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== - -extsprintf@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" - integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-equals@^5.0.0, fast-equals@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-5.0.1.tgz#a4eefe3c5d1c0d021aeed0bc10ba5e0c12ee405d" + integrity sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ== -fast-glob@^3.0.3: - version "3.2.12" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== +fast-glob@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -4055,33 +4553,30 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== -fast-redact@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.2.tgz#d58e69e9084ce9fa4c1a6fa98a3e1ecf5d7839aa" - integrity sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw== - -fast-safe-stringify@2.1.1, fast-safe-stringify@^2.0.8: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - fastest-levenshtein@^1.0.12: version "1.0.16" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== dependencies: reusify "^1.0.4" +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + fb-watchman@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" @@ -4089,13 +4584,6 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -figures@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== - dependencies: - escape-string-regexp "^1.0.5" - file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -4103,21 +4591,13 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -file-loader@~4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-4.3.0.tgz#780f040f729b3d18019f20605f723e844b8a58af" - integrity sha512-aKrYPYjF1yG3oX0kWRrqrSMfgftm7oJW5M+m4owoldH5C51C0RkIwB++JbRvEW3IU6/ZG5n8UvEcdgwOt2UOWA== - dependencies: - loader-utils "^1.2.3" - schema-utils "^2.5.0" - -file-loader@~6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.0.0.tgz#97bbfaab7a2460c07bcbd72d3a6922407f67649f" - integrity sha512-/aMOAYEFXDdjG0wytpTL5YQLfZnnTmLNjn+AIrJ/6HVnTfDqLsVKUUwkDf4I4kgex36BvjuXEn/TX9B/1ESyqQ== +file-loader@~6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== dependencies: loader-utils "^2.0.0" - schema-utils "^2.6.5" + schema-utils "^3.0.0" fill-range@^7.0.1: version "7.0.1" @@ -4139,15 +4619,6 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" -find-cache-dir@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" - integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - find-root@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" @@ -4161,52 +4632,74 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== dependencies: - flatted "^3.1.0" + flatted "^3.2.9" + keyv "^4.5.3" rimraf "^3.0.2" -flatstr@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.12.tgz#c2ba6a08173edbb6c9640e3055b95e287ceb5931" - integrity sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw== +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^3.1.0: - version "3.2.7" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" - integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== +flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== +follow-redirects@^1.0.0: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== -form-data@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" + is-callable "^1.1.3" -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== +fork-ts-checker-webpack-plugin@^6.1.0: + version "6.5.3" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz#eda2eff6e22476a2688d10661688c47f611b37f3" + integrity sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ== dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" + "@babel/code-frame" "^7.8.3" + "@types/json-schema" "^7.0.5" + chalk "^4.1.0" + chokidar "^3.4.2" + cosmiconfig "^6.0.0" + deepmerge "^4.2.2" + fs-extra "^9.0.0" + glob "^7.1.6" + memfs "^3.1.2" + minimatch "^3.0.4" + schema-utils "2.7.0" + semver "^7.3.2" + tapable "^1.0.0" forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== +fraction.js@^4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" + integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== + free-style@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/free-style/-/free-style-3.1.0.tgz#4e2996029534e6b1731611d843437b9e2f473f08" @@ -4217,6 +4710,15 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== +fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" @@ -4226,7 +4728,7 @@ fs-extra@^7.0.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.1: +fs-extra@^9.0.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== @@ -4236,12 +4738,10 @@ fs-extra@^9.0.1: jsonfile "^6.0.1" universalify "^2.0.0" -fs-minipass@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" - integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== - dependencies: - minipass "^3.0.0" +fs-monkey@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.5.tgz#fe450175f0db0d7ea758102e1d84096acb925788" + integrity sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew== fs-readdir-recursive@^1.1.0: version "1.1.0" @@ -4254,31 +4754,26 @@ fs.realpath@^1.0.0: integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^2.3.2, fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== +function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" -functions-have-names@^1.2.2: +functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== @@ -4293,14 +4788,16 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" - integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== +get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== dependencies: - function-bind "^1.1.1" - has "^1.0.3" + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" has-symbols "^1.0.3" + hasown "^2.0.0" get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" @@ -4312,19 +4809,7 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== -get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== - -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.0.0, get-stream@^5.1.0: +get-stream@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== @@ -4336,25 +4821,14 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== +get-symbol-description@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" + integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== dependencies: - assert-plus "^1.0.0" - -git-hooks-list@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/git-hooks-list/-/git-hooks-list-1.0.3.tgz#be5baaf78203ce342f2f844a9d2b03dba1b45156" - integrity sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ== + call-bind "^1.0.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" @@ -4363,22 +4837,18 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + glob-to-regexp@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^6.0.1: - version "6.0.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - integrity sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A== - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -4408,10 +4878,10 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.6.0, globals@^13.9.0: - version "13.17.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4" - integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw== +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== dependencies: type-fest "^0.20.2" @@ -4420,71 +4890,46 @@ globals@^9.18.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== -globby@10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.0.tgz#abfcd0630037ae174a88590132c2f6804e291072" - integrity sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw== +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: - "@types/glob" "^7.1.1" array-union "^2.1.0" dir-glob "^3.0.1" - fast-glob "^3.0.3" - glob "^7.1.3" - ignore "^5.1.1" - merge2 "^1.2.3" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" slash "^3.0.0" -got@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== - -gud@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" - integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== - -handlebars@4.7.7: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== dependencies: - minimist "^1.2.5" - neo-async "^2.6.0" - source-map "^0.6.1" - wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" + get-intrinsic "^1.1.3" -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -har-validator@~5.1.0: - version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== - dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== has-ansi@^2.0.0: version "2.0.0" @@ -4508,50 +4953,132 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: - get-intrinsic "^1.1.1" + es-define-property "^1.0.0" + +has-proto@^1.0.1, has-proto@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== +has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== dependencies: - has-symbols "^1.0.2" + has-symbols "^1.0.3" -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== +hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +history@^4.9.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" + integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== + dependencies: + "@babel/runtime" "^7.1.2" + loose-envify "^1.2.0" + resolve-pathname "^3.0.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + value-equal "^1.0.1" + +hoist-non-react-statics@^3.1.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== dependencies: - function-bind "^1.1.1" + react-is "^16.7.0" hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== -html-encoding-sniffer@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" - integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== dependencies: - whatwg-encoding "^1.0.5" + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + +html-entities@^2.3.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" + integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -htmlparser2@^6.0.0: +html-loader@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-2.1.2.tgz#17eb111441e863a9308071ed876b4ba861f143df" + integrity sha512-XB4O1+6mpLp4qy/3qg5+1QPZ/uXvWtO64hNAX87sKHwcHkp1LJGU7V3sJ9iVmRACElAZXQ4YOO/Lbkx5kYfl9A== + dependencies: + html-minifier-terser "^5.1.1" + parse5 "^6.0.1" + +html-minifier-terser@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054" + integrity sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg== + dependencies: + camel-case "^4.1.1" + clean-css "^4.2.3" + commander "^4.1.1" + he "^1.2.0" + param-case "^3.0.3" + relateurl "^0.2.7" + terser "^4.6.3" + +html-minifier-terser@^6.0.2: + version "6.1.0" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" + integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== + dependencies: + camel-case "^4.1.2" + clean-css "^5.2.2" + commander "^8.3.0" + he "^1.2.0" + param-case "^3.0.4" + relateurl "^0.2.7" + terser "^5.10.0" + +html-webpack-plugin@^5.0.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz#50a8fa6709245608cb00e811eacecb8e0d7b7ea0" + integrity sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw== + dependencies: + "@types/html-minifier-terser" "^6.0.0" + html-minifier-terser "^6.0.2" + lodash "^4.17.21" + pretty-error "^4.0.0" + tapable "^2.0.0" + +htmlparser2@^6.0.0, htmlparser2@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== @@ -4561,10 +5088,10 @@ htmlparser2@^6.0.0: domutils "^2.5.2" entities "^2.0.0" -http-cache-semantics@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" - integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== http-errors@2.0.0: version "2.0.0" @@ -4577,36 +5104,51 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" -http-proxy-agent@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" - integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== dependencies: - "@tootallnate/once" "1" - agent-base "6" - debug "4" + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== +http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + +http-proxy-middleware@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz#43700d6d9eecb7419bf086a128d0f7205d9eb665" + integrity sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg== dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" + "@types/http-proxy" "^1.17.5" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" -http-status-codes@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-2.2.0.tgz#bb2efe63d941dfc2be18e15f703da525169622be" - integrity sha512-feERVo9iWxvnejp3SEfm/+oNG517npqL2/PIA8ORjyOZjGC7TwCRQsZylciLS64i6pJ0wRYz3rkXLRwbtFa8Ng== +http-proxy-middleware@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" + integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + dependencies: + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" -https-proxy-agent@5.0.1, https-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== dependencies: - agent-base "6" - debug "4" + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" human-signals@^1.1.1: version "1.1.1" @@ -4618,36 +5160,36 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -iconv-lite@0.4.24, iconv-lite@^0.4.24: +iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" -icss-utils@^4.0.0, icss-utils@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" - integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== dependencies: - postcss "^7.0.14" + safer-buffer ">= 2.1.2 < 3.0.0" icss-utils@^5.0.0, icss-utils@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +ignore@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== -ignore@^5.1.1: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== +immutable@^4.0.0: + version "4.3.5" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.5.tgz#f8b436e66d59f99760dc577f5c99a4fd2a5cc5a0" + integrity sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw== -import-fresh@^3.0.0, import-fresh@^3.2.1: +import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -4673,11 +5215,6 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -infer-owner@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" - integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -4686,50 +5223,41 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -inquirer@^7.1.0: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" - integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.19" - mute-stream "0.0.8" - run-async "^2.4.0" - rxjs "^6.6.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== +internal-slot@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" + integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" + es-errors "^1.3.0" + hasown "^2.0.0" side-channel "^1.0.4" +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + interpret@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== -invariant@^2.2.2: +interpret@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" + integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== + +invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -4741,19 +5269,31 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== +ipaddr.js@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" + integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== + +is-array-buffer@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" + integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== dependencies: call-bind "^1.0.2" - has-tostringtag "^1.0.0" + get-intrinsic "^1.2.1" is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== +is-async-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" + integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== + dependencies: + has-tostringtag "^1.0.0" + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -4776,30 +5316,49 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-callable@^1.1.4, is-callable@^1.2.7: +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.9.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" - integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-data-view@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" + integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== dependencies: - has "^1.0.3" + is-typed-array "^1.1.13" -is-date-object@^1.0.1: +is-date-object@^1.0.1, is-date-object@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== dependencies: has-tostringtag "^1.0.0" +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-finalizationregistry@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" + integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== + dependencies: + call-bind "^1.0.2" + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -4810,17 +5369,29 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: +is-generator-function@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== +is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== + +is-negative-zero@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== is-number-object@^1.0.4: version "1.0.7" @@ -4839,10 +5410,15 @@ is-obj@^1.0.1: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== -is-plain-obj@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== is-plain-object@^2.0.4: version "2.0.4" @@ -4856,17 +5432,7 @@ is-plain-object@^5.0.0: resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== -is-potential-custom-element-name@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" - integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== - -is-promise@^2.1.0, is-promise@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" - integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== - -is-regex@^1.0.4, is-regex@^1.1.4: +is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== @@ -4879,12 +5445,17 @@ is-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA== -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== +is-set@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== + +is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" + integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== dependencies: - call-bind "^1.0.2" + call-bind "^1.0.7" is-stream@^2.0.0: version "2.0.1" @@ -4905,16 +5476,23 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== +is-typed-array@^1.1.13: + version "1.1.13" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" + integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== + dependencies: + which-typed-array "^1.1.14" is-unicode-supported@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-weakmap@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== + is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -4922,6 +5500,31 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" +is-weakset@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" + integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ== + dependencies: + call-bind "^1.0.7" + get-intrinsic "^1.2.4" + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -4937,15 +5540,15 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== +isomorphic.js@^0.2.4: + version "0.2.5" + resolved "https://registry.yarnpkg.com/isomorphic.js/-/isomorphic.js-0.2.5.tgz#13eecf36f2dba53e85d355e11bf9d4208c6f7f88" + integrity sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw== istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" - integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: version "5.2.1" @@ -4959,12 +5562,12 @@ istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: semver "^6.3.0" istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== dependencies: istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" + make-dir "^4.0.0" supports-color "^7.1.0" istanbul-lib-source-maps@^4.0.0: @@ -4977,13 +5580,24 @@ istanbul-lib-source-maps@^4.0.0: source-map "^0.6.1" istanbul-reports@^3.1.3: - version "3.1.5" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" - integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + version "3.1.7" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +iterator.prototype@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" + integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== + dependencies: + define-properties "^1.2.1" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + reflect.getprototypeof "^1.0.4" + set-function-name "^2.0.1" + jest-changed-files@^28.1.3: version "28.1.3" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-28.1.3.tgz#d9aeee6792be3686c47cb988a8eaf82ff4238831" @@ -5063,16 +5677,6 @@ jest-config@^28.1.3: slash "^3.0.0" strip-json-comments "^3.1.1" -jest-diff@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" - integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== - dependencies: - chalk "^4.0.0" - diff-sequences "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" - jest-diff@^28.1.3: version "28.1.3" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.1.3.tgz#948a192d86f4e7a64c5264ad4da4877133d8792f" @@ -5113,11 +5717,6 @@ jest-environment-node@^28.1.3: jest-mock "^28.1.3" jest-util "^28.1.3" -jest-get-type@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" - integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== - jest-get-type@^28.0.2: version "28.0.2" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-28.0.2.tgz#34622e628e4fdcd793d46db8a242227901fcf203" @@ -5150,16 +5749,6 @@ jest-leak-detector@^28.1.3: jest-get-type "^28.0.2" pretty-format "^28.1.3" -jest-matcher-utils@^27.0.0: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" - integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== - dependencies: - chalk "^4.0.0" - jest-diff "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" - jest-matcher-utils@^28.1.3: version "28.1.3" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz#5a77f1c129dd5ba3b4d7fc20728806c78893146e" @@ -5194,9 +5783,9 @@ jest-mock@^28.1.3: "@types/node" "*" jest-pnp-resolver@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" - integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== jest-regex-util@^28.0.2: version "28.0.2" @@ -5348,15 +5937,6 @@ jest-watcher@^28.1.3: jest-util "^28.1.3" string-length "^4.0.1" -jest-worker@^26.5.0: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" - integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^7.0.0" - jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" @@ -5375,7 +5955,7 @@ jest-worker@^28.1.3: merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^28.1.3: +jest@^28: version "28.1.3" resolved "https://registry.yarnpkg.com/jest/-/jest-28.1.3.tgz#e9c6a7eecdebe3548ca2b18894a50f45b36dfc6b" integrity sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA== @@ -5385,10 +5965,15 @@ jest@^28.1.3: import-local "^3.0.2" jest-cli "^28.1.3" +jiti@^1.20.0: + version "1.21.0" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" + integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== + jquery@^3.1.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.1.tgz#fab0408f8b45fc19f956205773b62b292c147a16" - integrity sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw== + version "3.7.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" + integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" @@ -5400,13 +5985,6 @@ js-tokens@^3.0.2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== -js-yaml@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -5415,43 +5993,12 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== - -jsdom@16.7.0: - version "16.7.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" - integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== - dependencies: - abab "^2.0.5" - acorn "^8.2.4" - acorn-globals "^6.0.0" - cssom "^0.4.4" - cssstyle "^2.3.0" - data-urls "^2.0.0" - decimal.js "^10.2.1" - domexception "^2.0.1" - escodegen "^2.0.0" - form-data "^3.0.0" - html-encoding-sniffer "^2.0.1" - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" - is-potential-custom-element-name "^1.0.1" - nwsapi "^2.2.0" - parse5 "6.0.1" - saxes "^5.0.1" - symbol-tree "^3.2.4" - tough-cookie "^4.0.0" - w3c-hr-time "^1.0.2" - w3c-xmlserializer "^2.0.0" - webidl-conversions "^6.1.0" - whatwg-encoding "^1.0.5" - whatwg-mimetype "^2.3.0" - whatwg-url "^8.5.0" - ws "^7.4.6" - xml-name-validator "^3.0.0" +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" jsesc@^2.5.1: version "2.5.2" @@ -5463,10 +6010,10 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== json-parse-better-errors@^1.0.1: version "1.0.2" @@ -5485,14 +6032,14 @@ json-schema-compare@^0.2.2: dependencies: lodash "^4.17.4" -json-schema-merge-allof@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/json-schema-merge-allof/-/json-schema-merge-allof-0.6.0.tgz#64d48820fec26b228db837475ce3338936bf59a5" - integrity sha512-LEw4VMQVRceOPLuGRWcxW5orTTiR9ZAtqTAe4rQUjNADTeR81bezBVFa0MqIwp0YmHIM1KkhSjZM7o+IQhaPbQ== +json-schema-merge-allof@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/json-schema-merge-allof/-/json-schema-merge-allof-0.8.1.tgz#ed2828cdd958616ff74f932830a26291789eaaf2" + integrity sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w== dependencies: - compute-lcm "^1.1.0" + compute-lcm "^1.1.2" json-schema-compare "^0.2.2" - lodash "^4.17.4" + lodash "^4.17.20" json-schema-traverse@^0.4.1: version "0.4.1" @@ -5504,32 +6051,22 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json-schema@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" - integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== - json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== - -json5@^1.0.1: +json5@^1.0.1, json5@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" -json5@^2.1.1, json5@^2.1.2, json5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== +json5@^2.1.2, json5@^2.2.1, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonfile@^4.0.0: version "4.0.0" @@ -5547,88 +6084,46 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -jsonparse@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== - -jsonpointer@^5.0.0: +jsonpointer@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== -jsonwebtoken@8.5.1: - version "8.5.1" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" - integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== - dependencies: - jws "^3.2.2" - lodash.includes "^4.3.0" - lodash.isboolean "^3.0.3" - lodash.isinteger "^4.0.4" - lodash.isnumber "^3.0.3" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.once "^4.0.0" - ms "^2.1.1" - semver "^5.6.0" - -jsprim@^1.2.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" - integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" - -jwa@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" - integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== - dependencies: - buffer-equal-constant-time "1.0.1" - ecdsa-sig-formatter "1.0.11" - safe-buffer "^5.0.1" - -jws@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" - integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== - dependencies: - jwa "^1.4.1" - safe-buffer "^5.0.1" - -keygrip@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226" - integrity sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ== +"jsx-ast-utils@^2.4.1 || ^3.0.0": + version "3.3.5" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" + integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== dependencies: - tsscmp "1.0.6" + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + object.assign "^4.1.4" + object.values "^1.1.6" -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== dependencies: - json-buffer "3.0.0" + json-buffer "3.0.1" kind-of@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -kleur@4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" - integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== - kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +launch-editor@^2.6.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.1.tgz#f259c9ef95cbc9425620bbbd14b468fcdb4ffe3c" + integrity sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw== + dependencies: + picocolors "^1.0.0" + shell-quote "^1.8.1" + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -5642,13 +6137,12 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== +lib0@^0.2.85, lib0@^0.2.86: + version "0.2.93" + resolved "https://registry.yarnpkg.com/lib0/-/lib0-0.2.93.tgz#95487c2a97657313cb1d91fbcf9f6d64b7fcd062" + integrity sha512-M5IKsiFJYulS+8Eal8f+zAqf5ckm1vffW0fFDxfgxJ+uiVopvDdd3PxJmz0GsVi3YNO7QCFSq0nAsiDmNhLj9Q== dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" + isomorphic.js "^0.2.4" license-webpack-plugin@^2.3.14: version "2.3.21" @@ -5713,33 +6207,24 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== -loader-utils@^1.0.0, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== +loader-utils@^1.1.0, loader-utils@^1.2.3: + version "1.4.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3" + integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" json5 "^1.0.1" loader-utils@^2.0.0, loader-utils@~2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" - integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== + version "2.0.4" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" + integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" json5 "^2.1.2" -loader-utils@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" - integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== - dependencies: - big.js "^5.2.2" - emojis-list "^2.0.0" - json5 "^1.0.1" - locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -5747,48 +6232,23 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lockfile@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.4.tgz#07f819d25ae48f87e538e6578b6964a4981a5609" - integrity sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA== +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== dependencies: - signal-exit "^3.0.2" + p-locate "^5.0.0" + +lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== -lodash.includes@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" - integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== - -lodash.isboolean@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" - integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== - -lodash.isinteger@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" - integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== - -lodash.isnumber@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" - integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== - -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== - lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -5799,17 +6259,7 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.once@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== - -lodash.truncate@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" - integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== - -lodash@4, lodash@4.17.21, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0: +lodash@^4.17.14, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5832,38 +6282,26 @@ log-update@^4.0.0: slice-ansi "^4.0.0" wrap-ansi "^6.2.0" -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" -lowdb@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lowdb/-/lowdb-1.0.0.tgz#5243be6b22786ccce30e50c9a33eac36b20c8064" - integrity sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ== +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== dependencies: - graceful-fs "^4.1.3" - is-promise "^2.1.0" - lodash "4" - pify "^3.0.0" - steno "^0.4.1" - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + tslib "^2.0.3" -lru-cache@7.14.0: - version "7.14.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.14.0.tgz#21be64954a4680e303a09e9468f880b98a0b3c7f" - integrity sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ== +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" lru-cache@^6.0.0: version "6.0.0" @@ -5872,25 +6310,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -lru-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" - integrity sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ== - dependencies: - es5-ext "~0.10.2" - -lunr-mutable-indexes@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/lunr-mutable-indexes/-/lunr-mutable-indexes-2.3.2.tgz#864253489735d598c5140f3fb75c0a5c8be2e98c" - integrity sha512-Han6cdWAPPFM7C2AigS2Ofl3XjAT0yVMrUixodJEpyg71zCtZ2yzXc3s+suc/OaNt4ca6WJBEzVnEIjxCTwFMw== - dependencies: - lunr ">= 2.3.0 < 2.4.0" - -"lunr@>= 2.3.0 < 2.4.0": - version "2.3.9" - resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" - integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== - make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -5899,14 +6318,14 @@ make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" -make-dir@^3.0.0, make-dir@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== dependencies: - semver "^6.0.0" + semver "^7.5.3" -make-error@1.x: +make-error@1.x, make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -5918,34 +6337,35 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" -marked@4.0.18: - version "4.0.18" - resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.18.tgz#cd0ac54b2e5610cfb90e8fd46ccaa8292c9ed569" - integrity sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw== +markdown-loader@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/markdown-loader/-/markdown-loader-7.0.0.tgz#012cdd3a1f724585869c70168f4a5c4cb84bedbf" + integrity sha512-ZUZXYadxu177a+dBTunr+whAIz0PdVuOJnLde/dowczEoog6wwXKuzgKmFP/ZeJjQ/Nyf9NxOGXxnilEYHKxQQ== + dependencies: + loader-utils "^1.2.3" + marked "^4.0.12" -marked@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/marked/-/marked-4.1.0.tgz#3fc6e7485f21c1ca5d6ec4a39de820e146954796" - integrity sha512-+Z6KDjSPa6/723PQYyc1axYZpYYpDnECDaU6hkaf5gqBieBkMKYReL5hteF2QizhlMbgbo8umXl/clZ67+GlsA== +markdown-to-jsx@^7.4.1: + version "7.4.7" + resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.4.7.tgz#740ee7ec933865ef5cc683a0992797685a75e2ee" + integrity sha512-0+ls1IQZdU6cwM1yu0ZjjiVWYtkbExSyUIFU2ZeDIFuZM1W42Mh4OlJ4nb4apX4H8smxDHRdFaoIVJGwfv5hkg== + +marked@^4.0.12: + version "4.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -memoizee@0.4.15: - version "0.4.15" - resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72" - integrity sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ== +memfs@^3.1.2, memfs@^3.4.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" + integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== dependencies: - d "^1.0.1" - es5-ext "^0.10.53" - es6-weak-map "^2.0.3" - event-emitter "^0.3.5" - is-promise "^2.2.2" - lru-queue "^0.1.0" - next-tick "^1.1.0" - timers-ext "^0.1.7" + fs-monkey "^1.0.4" memory-fs@^0.5.0: version "0.5.0" @@ -5970,7 +6390,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.2.3, merge2@^1.3.0: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -5993,7 +6413,7 @@ mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -6005,109 +6425,48 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" - integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -mini-css-extract-plugin@~1.3.2: - version "1.3.9" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.3.9.tgz#47a32132b0fd97a119acd530e8421e8f6ab16d5e" - integrity sha512-Ac4s+xhVbqlyhXS5J/Vh/QXUz3ycXlCqoCPpg0vdfhsIBH9eg/It/9L1r1XhSCH737M1lqcWnMuWL13zcygn5A== +mini-css-extract-plugin@^2.7.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.1.tgz#75245f3f30ce3a56dbdd478084df6fe475f02dc7" + integrity sha512-/1HDlyFRxWIZPI1ZpgqlZ8jMw/1Dp/dl3P0L1jtZ+zVcHqwPhGwaJwKL00WVgfnBy6PWCde9W65or7IIETImuA== dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - webpack-sources "^1.1.0" + schema-utils "^4.0.0" + tapable "^2.2.1" + +mini-svg-data-uri@^1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz#8ab0aabcdf8c29ad5693ca595af19dd2ead09939" + integrity sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg== + +minimalistic-assert@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -"minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.1.1: +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimatch@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7" - integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg== - dependencies: - brace-expansion "^2.0.1" - -minimatch@~3.0.4: - version "3.0.8" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" - integrity sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@~1.2.0: - version "1.2.7" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" - integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== - -minipass-collect@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" - integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== - dependencies: - minipass "^3.0.0" - -minipass-flush@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" - integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== - dependencies: - minipass "^3.0.0" - -minipass-pipeline@^1.2.2: - version "1.2.4" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" - integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== - dependencies: - minipass "^3.0.0" - -minipass@^3.0.0, minipass@^3.1.1: - version "3.3.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.4.tgz#ca99f95dd77c43c7a76bf51e6d200025eee0ffae" - integrity sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw== - dependencies: - yallist "^4.0.0" - -minizlib@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" - integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== - dependencies: - minipass "^3.0.0" - yallist "^4.0.0" - -mkdirp@1.0.4, mkdirp@^1.0.3, mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.0: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -mkdirp@^0.5.1, mkdirp@~0.5.1: +mkdirp@^0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: minimist "^1.2.6" -moment@^2.24.0: - version "2.29.4" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" - integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -6118,76 +6477,71 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1: +ms@2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - -mv@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2" - integrity sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg== +multicast-dns@^7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" + integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== dependencies: - mkdirp "~0.5.1" - ncp "~2.0.0" - rimraf "~2.4.0" + dns-packet "^5.2.2" + thunky "^1.0.2" -nanoid@^3.1.23, nanoid@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" - integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -ncp@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" - integrity sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA== - negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -neo-async@^2.6.0, neo-async@^2.6.2: +neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -next-tick@1, next-tick@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" - integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== - nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-fetch@2.6.7, node-fetch@^2.6.0: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== dependencies: - whatwg-url "^5.0.0" + lower-case "^2.0.2" + tslib "^2.0.3" + +node-forge@^1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-releases@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" - integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== normalize-package-data@^2.3.2: version "2.5.0" @@ -6204,15 +6558,10 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - -normalize.css@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3" - integrity sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg== +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== npm-run-all@^4.1.3: version "4.1.5" @@ -6236,49 +6585,80 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -nwsapi@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0" - integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw== - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" -object-assign@^4, object-assign@^4.1.1: +object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.12.2, object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" +object-inspect@^1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" - integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== +object.assign@^4.1.4, object.assign@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" + integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" + call-bind "^1.0.5" + define-properties "^1.2.1" has-symbols "^1.0.3" object-keys "^1.1.1" +object.entries@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" + integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +object.fromentries@^2.0.7: + version "2.0.8" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" + integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + +object.hasown@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.4.tgz#e270ae377e4c120cdcb7656ce66884a6218283dc" + integrity sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg== + dependencies: + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + +object.values@^1.1.6, object.values@^1.1.7: + version "1.2.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" + integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + on-finished@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -6305,44 +6685,26 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== +open@^8.0.9: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" deep-is "^0.1.3" fast-levenshtein "^2.0.6" levn "^0.4.1" prelude-ls "^1.2.1" type-check "^0.4.0" - word-wrap "^1.2.3" - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - -os@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/os/-/os-0.1.2.tgz#f29a50c62908516ba42652de42f7038600cadbc2" - integrity sha512-ZoXJkvAnljwvc56MbvhtKVWmSkzV712k42Is2mA0+0KTSRakq5XXuXpjZjgAt9ctzl51ojhQWakQQpmOvXWfjQ== - -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== p-limit@^2.2.0: version "2.3.0" @@ -6365,6 +6727,13 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" @@ -6372,33 +6741,26 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" +p-retry@^4.5.0: + version "4.6.2" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" + integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== + dependencies: + "@types/retry" "0.12.0" + retry "^0.13.1" + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -package-json@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" - integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== - dependencies: - got "^9.6.0" - registry-auth-token "^4.0.0" - registry-url "^5.0.0" - semver "^6.2.0" - -paddy-react-edit-list@>=1.1.25: - version "1.1.25" - resolved "https://registry.yarnpkg.com/paddy-react-edit-list/-/paddy-react-edit-list-1.1.25.tgz#a1d925100dfa3df792b778369437b1343a242886" - integrity sha512-QqwWCPc09ue2ljy6ZuSfsWBm1NbFOxS6pDZNSygVZmoZUVMbiAKltwF8sPtDqIouJ+s6qbri3SpIWU0io2367Q== - dependencies: - "@ag-grid-community/client-side-row-model" "^29.2.0" - "@types/lodash" "^4.14.191" - ag-grid-community "^29.2.0" - ag-grid-react "^29.2.0" - lodash "^4.17.21" - react "^18.0.0" - react-dom "^18.0.0" +param-case@^3.0.3, param-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" + integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" parent-module@^1.0.0: version "1.0.1" @@ -6425,26 +6787,29 @@ parse-json@^5.0.0, parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parse-ms@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" - integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== - parse-srcset@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1" integrity sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q== -parse5@6.0.1: +parse5@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== -parseurl@~1.3.3: +parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + path-browserify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" @@ -6480,6 +6845,13 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +path-to-regexp@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" + integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== + dependencies: + isarray "0.0.1" + path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -6492,16 +6864,6 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== - -picocolors@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" - integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== - picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -6527,41 +6889,18 @@ pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -pino-std-serializers@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz#b56487c402d882eb96cd67c257868016b61ad671" - integrity sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg== - -pino@6.14.0: - version "6.14.0" - resolved "https://registry.yarnpkg.com/pino/-/pino-6.14.0.tgz#b745ea87a99a6c4c9b374e4f29ca7910d4c69f78" - integrity sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg== - dependencies: - fast-redact "^3.0.0" - fast-safe-stringify "^2.0.8" - flatstr "^1.0.12" - pino-std-serializers "^3.1.0" - process-warning "^1.0.0" - quick-format-unescaped "^4.0.3" - sonic-boom "^1.0.2" - pirates@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" - integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== -pkg-dir@^4.1.0, pkg-dir@^4.2.0: +pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" -pkginfo@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" - integrity sha512-8xCNE/aT/EXKenuMDZ+xTVwkT8gsoHN2z/Q29l80u0ppGEXVvsKRzNMbtKhg8LS8k1tJLAHHylf6p4VFmP6XUQ== - please-upgrade-node@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" @@ -6569,64 +6908,172 @@ please-upgrade-node@^3.2.0: dependencies: semver-compare "^1.0.0" -popper.js@^1.14.4, popper.js@^1.16.1: - version "1.16.1" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" - integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== +possible-typed-array-names@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" + integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== -postcss-modules-extract-imports@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" - integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== +postcss-attribute-case-insensitive@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz#03d761b24afc04c09e757e92ff53716ae8ea2741" + integrity sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ== dependencies: - postcss "^7.0.5" + postcss-selector-parser "^6.0.10" -postcss-modules-extract-imports@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" - integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== +postcss-clamp@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-clamp/-/postcss-clamp-4.1.0.tgz#7263e95abadd8c2ba1bd911b0b5a5c9c93e02363" + integrity sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow== + dependencies: + postcss-value-parser "^4.2.0" -postcss-modules-local-by-default@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" - integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== +postcss-color-functional-notation@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz#21a909e8d7454d3612d1659e471ce4696f28caec" + integrity sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg== dependencies: - icss-utils "^4.1.1" - postcss "^7.0.32" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-modules-local-by-default@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" - integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== +postcss-color-hex-alpha@^8.0.4: + version "8.0.4" + resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz#c66e2980f2fbc1a63f5b079663340ce8b55f25a5" + integrity sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ== dependencies: - icss-utils "^5.0.0" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-modules-scope@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" - integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== +postcss-color-rebeccapurple@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz#63fdab91d878ebc4dd4b7c02619a0c3d6a56ced0" + integrity sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg== dependencies: - postcss "^7.0.6" - postcss-selector-parser "^6.0.0" + postcss-value-parser "^4.2.0" -postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== +postcss-custom-media@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz#c8f9637edf45fef761b014c024cee013f80529ea" + integrity sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-custom-properties@^12.1.10: + version "12.1.11" + resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz#d14bb9b3989ac4d40aaa0e110b43be67ac7845cf" + integrity sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-custom-selectors@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz#1ab4684d65f30fed175520f82d223db0337239d9" + integrity sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg== dependencies: postcss-selector-parser "^6.0.4" -postcss-modules-values@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" - integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== +postcss-dir-pseudo-class@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz#2bf31de5de76added44e0a25ecf60ae9f7c7c26c" + integrity sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA== + dependencies: + postcss-selector-parser "^6.0.10" + +postcss-double-position-gradients@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz#b96318fdb477be95997e86edd29c6e3557a49b91" + integrity sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ== + dependencies: + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" + +postcss-env-function@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-4.0.6.tgz#7b2d24c812f540ed6eda4c81f6090416722a8e7a" + integrity sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-focus-visible@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz#50c9ea9afa0ee657fb75635fabad25e18d76bf9e" + integrity sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw== + dependencies: + postcss-selector-parser "^6.0.9" + +postcss-focus-within@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz#5b1d2ec603195f3344b716c0b75f61e44e8d2e20" + integrity sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ== + dependencies: + postcss-selector-parser "^6.0.9" + +postcss-font-variant@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz#efd59b4b7ea8bb06127f2d031bfbb7f24d32fa66" + integrity sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA== + +postcss-gap-properties@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz#f7e3cddcf73ee19e94ccf7cb77773f9560aa2fff" + integrity sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg== + +postcss-image-set-function@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz#08353bd756f1cbfb3b6e93182c7829879114481f" + integrity sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-initial@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-4.0.1.tgz#529f735f72c5724a0fb30527df6fb7ac54d7de42" + integrity sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ== + +postcss-lab-function@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz#6fe4c015102ff7cd27d1bd5385582f67ebdbdc98" + integrity sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w== + dependencies: + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" + +postcss-loader@^7.0.1: + version "7.3.4" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.3.4.tgz#aed9b79ce4ed7e9e89e56199d25ad1ec8f606209" + integrity sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A== dependencies: - icss-utils "^4.0.0" - postcss "^7.0.6" + cosmiconfig "^8.3.5" + jiti "^1.20.0" + semver "^7.5.4" + +postcss-logical@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-5.0.4.tgz#ec75b1ee54421acc04d5921576b7d8db6b0e6f73" + integrity sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g== + +postcss-media-minmax@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz#7140bddec173e2d6d657edbd8554a55794e2a5b5" + integrity sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ== + +postcss-modules-extract-imports@^3.0.0, postcss-modules-extract-imports@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" + integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== + +postcss-modules-local-by-default@^4.0.0, postcss-modules-local-by-default@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz#f1b9bd757a8edf4d8556e8d0f4f894260e3df78f" + integrity sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.0.0, postcss-modules-scope@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz#a43d28289a169ce2c15c00c4e64c0858e43457d5" + integrity sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ== + dependencies: + postcss-selector-parser "^6.0.4" postcss-modules-values@^4.0.0: version "4.0.0" @@ -6635,56 +7082,146 @@ postcss-modules-values@^4.0.0: dependencies: icss-utils "^5.0.0" -postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: - version "6.0.10" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" - integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== +postcss-nested@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c" + integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ== + dependencies: + postcss-selector-parser "^6.0.11" + +postcss-nesting@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-10.2.0.tgz#0b12ce0db8edfd2d8ae0aaf86427370b898890be" + integrity sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA== + dependencies: + "@csstools/selector-specificity" "^2.0.0" + postcss-selector-parser "^6.0.10" + +postcss-opacity-percentage@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz#5b89b35551a556e20c5d23eb5260fbfcf5245da6" + integrity sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A== + +postcss-overflow-shorthand@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz#7ed6486fec44b76f0eab15aa4866cda5d55d893e" + integrity sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-page-break@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-3.0.4.tgz#7fbf741c233621622b68d435babfb70dd8c1ee5f" + integrity sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ== + +postcss-place@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-7.0.5.tgz#95dbf85fd9656a3a6e60e832b5809914236986c4" + integrity sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-preset-env@^7.7.2: + version "7.8.3" + resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz#2a50f5e612c3149cc7af75634e202a5b2ad4f1e2" + integrity sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag== + dependencies: + "@csstools/postcss-cascade-layers" "^1.1.1" + "@csstools/postcss-color-function" "^1.1.1" + "@csstools/postcss-font-format-keywords" "^1.0.1" + "@csstools/postcss-hwb-function" "^1.0.2" + "@csstools/postcss-ic-unit" "^1.0.1" + "@csstools/postcss-is-pseudo-class" "^2.0.7" + "@csstools/postcss-nested-calc" "^1.0.0" + "@csstools/postcss-normalize-display-values" "^1.0.1" + "@csstools/postcss-oklab-function" "^1.1.1" + "@csstools/postcss-progressive-custom-properties" "^1.3.0" + "@csstools/postcss-stepped-value-functions" "^1.0.1" + "@csstools/postcss-text-decoration-shorthand" "^1.0.0" + "@csstools/postcss-trigonometric-functions" "^1.0.2" + "@csstools/postcss-unset-value" "^1.0.2" + autoprefixer "^10.4.13" + browserslist "^4.21.4" + css-blank-pseudo "^3.0.3" + css-has-pseudo "^3.0.4" + css-prefers-color-scheme "^6.0.3" + cssdb "^7.1.0" + postcss-attribute-case-insensitive "^5.0.2" + postcss-clamp "^4.1.0" + postcss-color-functional-notation "^4.2.4" + postcss-color-hex-alpha "^8.0.4" + postcss-color-rebeccapurple "^7.1.1" + postcss-custom-media "^8.0.2" + postcss-custom-properties "^12.1.10" + postcss-custom-selectors "^6.0.3" + postcss-dir-pseudo-class "^6.0.5" + postcss-double-position-gradients "^3.1.2" + postcss-env-function "^4.0.6" + postcss-focus-visible "^6.0.4" + postcss-focus-within "^5.0.4" + postcss-font-variant "^5.0.0" + postcss-gap-properties "^3.0.5" + postcss-image-set-function "^4.0.7" + postcss-initial "^4.0.1" + postcss-lab-function "^4.2.1" + postcss-logical "^5.0.4" + postcss-media-minmax "^5.0.0" + postcss-nesting "^10.2.0" + postcss-opacity-percentage "^1.1.2" + postcss-overflow-shorthand "^3.0.4" + postcss-page-break "^3.0.4" + postcss-place "^7.0.5" + postcss-pseudo-class-any-link "^7.1.6" + postcss-replace-overflow-wrap "^4.0.0" + postcss-selector-not "^6.0.1" + postcss-value-parser "^4.2.0" + +postcss-pseudo-class-any-link@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz#2693b221902da772c278def85a4d9a64b6e617ab" + integrity sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w== + dependencies: + postcss-selector-parser "^6.0.10" + +postcss-replace-overflow-wrap@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz#d2df6bed10b477bf9c52fab28c568b4b29ca4319" + integrity sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw== + +postcss-selector-not@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz#8f0a709bf7d4b45222793fc34409be407537556d" + integrity sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ== + dependencies: + postcss-selector-parser "^6.0.10" + +postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.9: + version "6.0.16" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz#3b88b9f5c5abd989ef4e2fc9ec8eedd34b20fb04" + integrity sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-value-parser@^4.1.0: +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.39" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" - integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== - dependencies: - picocolors "^0.2.1" - source-map "^0.6.1" - -postcss@^8.2.15, postcss@^8.3.11: - version "8.4.18" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.18.tgz#6d50046ea7d3d66a85e0e782074e7203bc7fbca2" - integrity sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA== +postcss@^8.2.15, postcss@^8.3.11, postcss@^8.4.14, postcss@^8.4.33: + version "8.4.38" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" + integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== dependencies: - nanoid "^3.3.4" + nanoid "^3.3.7" picocolors "^1.0.0" - source-map-js "^1.0.2" + source-map-js "^1.2.0" prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== - -prettier-bytes@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prettier-bytes/-/prettier-bytes-1.0.4.tgz#994b02aa46f699c50b6257b5faaa7fe2557e62d6" - integrity sha512-dLbWOa4xBn+qeWeIF60qRoB6Pk2jX5P3DIVgOQyMyvBpu931Q+8dXz8X0snJiFkQdohDDLnZQECjzsAj75hgZQ== - prettier-linter-helpers@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" @@ -6692,26 +7229,25 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.0.5: - version "2.7.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" - integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== +prettier-standalone@^1.3.1-0: + version "1.3.1-0" + resolved "https://registry.yarnpkg.com/prettier-standalone/-/prettier-standalone-1.3.1-0.tgz#8c302549316c723015642e66fd4192db68514d0c" + integrity sha512-wxJiwE5XS45BQD8QTXcTeqnWzsYrCliIYOYrURM8MiJaw8NA5q+BSd9UBhM5QPDFShn+pFWa8X2XH3y5A47q+Q== -prettier@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5" - integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg== +prettier@^2.6.2: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== -pretty-format@^27.0.0, pretty-format@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" - integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== +pretty-error@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" + integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== dependencies: - ansi-regex "^5.0.1" - ansi-styles "^5.0.0" - react-is "^17.0.1" + lodash "^4.17.20" + renderkid "^3.0.0" -pretty-format@^28.1.3: +pretty-format@^28.0.0, pretty-format@^28.1.3: version "28.1.3" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.3.tgz#c9fba8cedf99ce50963a11b27d982a9ae90970d5" integrity sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q== @@ -6721,38 +7257,26 @@ pretty-format@^28.1.3: ansi-styles "^5.0.0" react-is "^18.0.0" -pretty-ms@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-7.0.1.tgz#7d903eaab281f7d8e03c66f867e239dc32fb73e8" - integrity sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q== - dependencies: - parse-ms "^2.1.0" +prism-themes@^1.6.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/prism-themes/-/prism-themes-1.9.0.tgz#19c034f3205f1e28d75d89728e54ccd745f7e3dd" + integrity sha512-tX2AYsehKDw1EORwBps+WhBFKc2kxfoFpQAjxBndbZKr4fRmMkv47XN0BghC/K1qwodB1otbe4oF23vUTFDokw== + +prismjs@^1.28.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" + integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -process-warning@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" - integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== - process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -promise-inflight@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== - prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -6761,7 +7285,15 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types-extra@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b" + integrity sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew== + dependencies: + react-is "^16.3.2" + warning "^4.0.0" + +prop-types@^15.6.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -6783,11 +7315,6 @@ prr@~1.0.1: resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== -psl@^1.1.24, psl@^1.1.33: - version "1.9.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" - integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== - pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -6796,38 +7323,18 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== - punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -qs@6.10.3: - version "6.10.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" - integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== dependencies: side-channel "^1.0.4" -qs@~6.5.2: - version "6.5.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" - integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== - querystringify@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" @@ -6838,11 +7345,6 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -quick-format-unescaped@^4.0.3: - version "4.0.4" - resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" - integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== - randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -6850,22 +7352,22 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" -range-parser@~1.2.1: +range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" http-errors "2.0.0" iconv-lite "0.4.24" unpipe "1.0.0" -raw-loader@~4.0.0: +raw-loader@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.2.tgz#1aac6b7d1ad1501e66efdac1522c73e59a584eb6" integrity sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA== @@ -6873,26 +7375,25 @@ raw-loader@~4.0.0: loader-utils "^2.0.0" schema-utils "^3.0.0" -rc@1.2.8, rc@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -react-dom@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" - integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler "^0.20.2" +react-bootstrap@^2.0.0: + version "2.10.2" + resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-2.10.2.tgz#3b609eb0170e31b3d9ace297d3a016c202a42642" + integrity sha512-UvB7mRqQjivdZNxJNEA2yOQRB7L9N43nBnKc33K47+cH90/ujmnMwatTCwQLu83gLhrzAl8fsa6Lqig/KLghaA== + dependencies: + "@babel/runtime" "^7.22.5" + "@restart/hooks" "^0.4.9" + "@restart/ui" "^1.6.8" + "@types/react-transition-group" "^4.4.6" + classnames "^2.3.2" + dom-helpers "^5.2.1" + invariant "^2.2.4" + prop-types "^15.8.1" + prop-types-extra "^1.1.0" + react-transition-group "^4.4.5" + uncontrollable "^7.2.1" + warning "^4.0.3" -react-dom@^18.0.0: +react-dom@^18.0.0, react-dom@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== @@ -6900,17 +7401,12 @@ react-dom@^18.0.0: loose-envify "^1.1.0" scheduler "^0.23.0" -react-is@^16.13.1, react-is@^16.9.0: +react-is@^16.10.2, react-is@^16.13.1, react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-is@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== - -react-is@^18.0.0: +react-is@^18.0.0, react-is@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== @@ -6920,20 +7416,59 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== -react-popper@^1.3.7: - version "1.3.11" - resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.3.11.tgz#a2cc3f0a67b75b66cfa62d2c409f9dd1fcc71ffd" - integrity sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg== +react-router-dom@^5.2.0: + version "5.3.4" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.4.tgz#2ed62ffd88cae6db134445f4a0c0ae8b91d2e5e6" + integrity sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ== dependencies: - "@babel/runtime" "^7.1.2" - "@hypnosphi/create-react-context" "^0.3.1" - deep-equal "^1.1.1" - popper.js "^1.14.4" - prop-types "^15.6.1" - typed-styles "^0.0.7" - warning "^4.0.2" - -react-transition-group@^2.9.0: + "@babel/runtime" "^7.12.13" + history "^4.9.0" + loose-envify "^1.3.1" + prop-types "^15.6.2" + react-router "5.3.4" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react-router@5.3.4: + version "5.3.4" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.4.tgz#8ca252d70fcc37841e31473c7a151cf777887bb5" + integrity sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA== + dependencies: + "@babel/runtime" "^7.12.13" + history "^4.9.0" + hoist-non-react-statics "^3.1.0" + loose-envify "^1.3.1" + path-to-regexp "^1.7.0" + prop-types "^15.6.2" + react-is "^16.6.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react-router@^6.3.0: + version "6.22.3" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.22.3.tgz#9d9142f35e08be08c736a2082db5f0c9540a885e" + integrity sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ== + dependencies: + "@remix-run/router" "1.15.3" + +react-smooth@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/react-smooth/-/react-smooth-2.0.5.tgz#d153b7dffc7143d0c99e82db1532f8cf93f20ecd" + integrity sha512-BMP2Ad42tD60h0JW6BFaib+RJuV5dsXJK9Baxiv/HlNFjvRLqA9xrNKxVWnUIZPQfzUwGXIlU/dSYLU+54YGQA== + dependencies: + fast-equals "^5.0.0" + react-transition-group "2.9.0" + +react-smooth@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/react-smooth/-/react-smooth-4.0.1.tgz#6200d8699bfe051ae40ba187988323b1449eab1a" + integrity sha512-OE4hm7XqR0jNOq3Qmk9mFLyd6p2+j6bvbPJ7qlB7+oo0eNcL2l7WQzG6MBnT3EXY6xzkLMUBec3AfewJdA0J8w== + dependencies: + fast-equals "^5.0.1" + prop-types "^15.8.1" + react-transition-group "^4.4.5" + +react-transition-group@2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d" integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg== @@ -6943,15 +7478,17 @@ react-transition-group@^2.9.0: prop-types "^15.6.2" react-lifecycles-compat "^3.0.4" -react@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" - integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== +react-transition-group@^4.4.5: + version "4.4.5" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" + integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" -react@^18.0.0: +"react@>=17.0.0 <19.0.0", react@^18.0.0, react@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== @@ -6968,9 +7505,9 @@ read-pkg@^3.0.0: path-type "^3.0.0" readable-stream@^2.0.1: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -6980,6 +7517,15 @@ readable-stream@^2.0.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.0.6: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -6987,6 +7533,27 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +recharts-scale@^0.4.4: + version "0.4.5" + resolved "https://registry.yarnpkg.com/recharts-scale/-/recharts-scale-0.4.5.tgz#0969271f14e732e642fcc5bd4ab270d6e87dd1d9" + integrity sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w== + dependencies: + decimal.js-light "^2.4.1" + +recharts@^2.7.3: + version "2.12.5" + resolved "https://registry.yarnpkg.com/recharts/-/recharts-2.12.5.tgz#b335eb66173317dccb3e126fce1d7ac5b3cee1e9" + integrity sha512-Cy+BkqrFIYTHJCyKHJEPvbHE2kVQEP6PKbOHJ8ztRGTAhvHuUnCwDaKVb13OwRFZ0QNUk1QvGTDdgWSMbuMtKw== + dependencies: + clsx "^2.0.0" + eventemitter3 "^4.0.1" + lodash "^4.17.21" + react-is "^16.10.2" + react-smooth "^4.0.0" + recharts-scale "^0.4.4" + tiny-invariant "^1.3.1" + victory-vendor "^36.6.8" + rechoir@^0.7.0: version "0.7.1" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" @@ -6994,10 +7561,30 @@ rechoir@^0.7.0: dependencies: resolve "^1.9.0" +rechoir@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" + integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== + dependencies: + resolve "^1.20.0" + +reflect.getprototypeof@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" + integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.1" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + globalthis "^1.0.3" + which-builtin-type "^1.1.3" + regenerate-unicode-properties@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" - integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== + version "10.1.1" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" + integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== dependencies: regenerate "^1.4.2" @@ -7011,62 +7598,39 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.13.4: - version "0.13.10" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz#ed07b19616bcbec5da6274ebc75ae95634bfc2ee" - integrity sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw== +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== -regenerator-transform@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537" - integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg== +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== dependencies: "@babel/runtime" "^7.8.4" -regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== +regexp.prototype.flags@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" + integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - -regexpp@^3.0.0, regexpp@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + call-bind "^1.0.6" + define-properties "^1.2.1" + es-errors "^1.3.0" + set-function-name "^2.0.1" -regexpu-core@^5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.1.tgz#a69c26f324c1e962e9ffd0b88b055caba8089139" - integrity sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ== +regexpu-core@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== dependencies: + "@babel/regjsgen" "^0.8.0" regenerate "^1.4.2" regenerate-unicode-properties "^10.1.0" - regjsgen "^0.7.1" regjsparser "^0.9.1" unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.0.0" - -registry-auth-token@^4.0.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.2.tgz#f02d49c3668884612ca031419491a13539e21fac" - integrity sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg== - dependencies: - rc "1.2.8" - -registry-url@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" - integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== - dependencies: - rc "^1.2.8" - -regjsgen@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" - integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== + unicode-match-property-value-ecmascript "^2.1.0" regjsparser@^0.9.1: version "0.9.1" @@ -7075,31 +7639,21 @@ regjsparser@^0.9.1: dependencies: jsesc "~0.5.0" -request@2.88.0: - version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.0" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.4.3" - tunnel-agent "^0.6.0" - uuid "^3.3.2" +relateurl@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== + +renderkid@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" + integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== + dependencies: + css-select "^4.1.3" + dom-converter "^0.2.0" + htmlparser2 "^6.1.0" + lodash "^4.17.21" + strip-ansi "^6.0.1" require-directory@^2.1.1: version "2.1.1" @@ -7133,26 +7687,33 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-pathname@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" + integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== + resolve.exports@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" - integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== + version "1.1.1" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.1.tgz#05cfd5b3edf641571fd46fa608b610dda9ead999" + integrity sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ== resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.9.0: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== dependencies: - is-core-module "^2.9.0" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== +resolve@^2.0.0-next.5: + version "2.0.0-next.5" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== dependencies: - lowercase-keys "^1.0.0" + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" restore-cursor@^3.1.0: version "3.1.0" @@ -7162,22 +7723,20 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== rfdc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" - integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== - -rimraf@^2.6.2: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" + version "1.3.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f" + integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg== rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" @@ -7186,18 +7745,6 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" -rimraf@~2.4.0: - version "2.4.5" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da" - integrity sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ== - dependencies: - glob "^6.0.1" - -run-async@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -7205,48 +7752,51 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^6.6.0: - version "6.6.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" - integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== - dependencies: - tslib "^1.9.0" - rxjs@^7.5.1: - version "7.5.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39" - integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA== + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== dependencies: tslib "^2.1.0" +safe-array-concat@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" + integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== + dependencies: + call-bind "^1.0.7" + get-intrinsic "^1.2.4" + has-symbols "^1.0.3" + isarray "^2.0.5" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-regex-test@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" - integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== +safe-regex-test@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" + integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" + call-bind "^1.0.6" + es-errors "^1.3.0" is-regex "^1.1.4" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sanitize-html@~2.5.3: - version "2.5.3" - resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.5.3.tgz#91aa3dc760b072cdf92f9c6973747569b1ba1cd8" - integrity sha512-DGATXd1fs/Rm287/i5FBKVYSBBUL0iAaztOA1/RFhEs4yqo39/X52i/q/CwsfCUG5cilmXSBmnQmyWfnKhBlOg== +sanitize-html@~2.7.3: + version "2.7.3" + resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.7.3.tgz#166c868444ee4f9fd7352ac8c63fa86c343fc2bd" + integrity sha512-jMaHG29ak4miiJ8wgqA1849iInqORgNv7SLfSw9LtfOhEUQ1C0YHKH73R+hgyufBW9ZFeJrb057k9hjlfBCVlw== dependencies: deepmerge "^4.2.2" escape-string-regexp "^4.0.0" @@ -7255,20 +7805,21 @@ sanitize-html@~2.5.3: parse-srcset "^1.0.2" postcss "^8.3.11" -saxes@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" - integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== +sass-loader@^13.0.2: + version "13.3.3" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-13.3.3.tgz#60df5e858788cffb1a3215e5b92e9cba61e7e133" + integrity sha512-mt5YN2F1MOZr3d/wBRcZxeFgwgkH44wVc2zohO2YF6JiOMkiXe4BYRZpSu2sO1g71mo/j16txzUhsKZlqjVGzA== dependencies: - xmlchars "^2.2.0" + neo-async "^2.6.2" -scheduler@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" - integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== +sass@^1.53.0: + version "1.75.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.75.0.tgz#91bbe87fb02dfcc34e052ddd6ab80f60d392be6c" + integrity sha512-ShMYi3WkrDWxExyxSZPst4/okE9ts46xZmJDSawJQrnte7M1V9fScVB+uNXOVKRBt0PggHOwoZcn8mYX4trnBw== dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" scheduler@^0.23.0: version "0.23.0" @@ -7277,16 +7828,16 @@ scheduler@^0.23.0: dependencies: loose-envify "^1.1.0" -schema-utils@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== +schema-utils@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" + integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== dependencies: - ajv "^6.1.0" - ajv-errors "^1.0.0" - ajv-keywords "^3.1.0" + "@types/json-schema" "^7.0.4" + ajv "^6.12.2" + ajv-keywords "^3.4.1" -schema-utils@^2.5.0, schema-utils@^2.6.5, schema-utils@^2.7.0: +schema-utils@^2.7.0: version "2.7.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== @@ -7295,14 +7846,37 @@ schema-utils@^2.5.0, schema-utils@^2.6.5, schema-utils@^2.7.0: ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== +schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" + integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.9.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.1.0" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== + +selfsigned@^2.1.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" + integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" + "@types/node-forge" "^1.3.0" + node-forge "^1" semver-compare@^1.0.0: version "1.0.0" @@ -7310,28 +7884,21 @@ semver-compare@^1.0.0: integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow== "semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@7.3.7: - version "7.3.7" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" - integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== - dependencies: - lru-cache "^6.0.0" + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@7.x, semver@^7.2.1, semver@^7.3.2, semver@^7.3.5: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== +semver@7.x, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== send@0.18.0: version "0.18.0" @@ -7352,19 +7919,25 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" -serialize-javascript@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" - integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== +serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== dependencies: randombytes "^2.1.0" -serialize-javascript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== dependencies: - randombytes "^2.1.0" + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" serve-static@1.15.0: version "1.15.0" @@ -7376,6 +7949,33 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +set-function-name@^2.0.1, set-function-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.2" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + setprototypeof@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" @@ -7412,19 +8012,20 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote@^1.6.1: - version "1.7.4" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8" - integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw== +shell-quote@^1.6.1, shell-quote@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== +side-channel@^1.0.4, side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" @@ -7464,40 +8065,24 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" -sonic-boom@^1.0.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-1.4.1.tgz#d35d6a74076624f12e6f917ade7b9d75e918f53e" - integrity sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg== - dependencies: - atomic-sleep "^1.0.0" - flatstr "^1.0.12" - -sort-object-keys@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" - integrity sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg== - -sort-package-json@~1.44.0: - version "1.44.0" - resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-1.44.0.tgz#470330be868f8a524a4607b26f2a0233e93d8b6d" - integrity sha512-u9GUZvpavUCXV5SbEqXu9FRbsJrYU6WM10r3zA0gymGPufK5X82MblCLh9GW9l46pXKEZvK+FA3eVTqC4oMp4A== +sockjs@^0.3.24: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== dependencies: - detect-indent "^6.0.0" - detect-newline "3.1.0" - git-hooks-list "1.0.3" - globby "10.0.0" - is-plain-obj "2.1.0" - sort-object-keys "^1.1.3" + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" source-list-map@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== source-map-loader@^0.2.4: version "0.2.4" @@ -7507,6 +8092,17 @@ source-map-loader@^0.2.4: async "^2.5.0" loader-utils "^1.1.0" +source-map-loader@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-1.0.2.tgz#b0a6582b2eaa387ede1ecf8061ae0b93c23f9eb0" + integrity sha512-oX8d6ndRjN+tVyjj6PlXSyFPhDdVAPsZA30nD3/II8g4uOv8fCz0DMn5sy8KtVbDfKQxOpGwGJnK3xIW3tauDw== + dependencies: + data-urls "^2.0.0" + iconv-lite "^0.6.2" + loader-utils "^2.0.0" + schema-utils "^2.7.0" + source-map "^0.6.1" + source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -7515,7 +8111,7 @@ source-map-support@0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@~0.5.20: +source-map-support@^0.5.17, source-map-support@~0.5.12, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -7523,23 +8119,28 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +source-map@^0.7.3: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== spdx-expression-parse@^3.0.0: version "3.0.1" @@ -7550,41 +8151,42 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.12" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" - integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== + version "3.0.17" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz#887da8aa73218e51a1d917502d79863161a93f9c" + integrity sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg== + +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -sshpk@^1.7.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" - integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -ssri@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" - integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== - dependencies: - minipass "^3.1.1" - stack-utils@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" - integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== dependencies: escape-string-regexp "^2.0.0" @@ -7593,12 +8195,10 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -steno@^0.4.1: - version "0.4.4" - resolved "https://registry.yarnpkg.com/steno/-/steno-0.4.4.tgz#071105bdfc286e6615c0403c27e9d7b5dcb855cb" - integrity sha512-EEHMVYHNXFHfGtgjNITnka0aHhiAlo93F7z2/Pwd+g0teG9CnM3JIINM7hVVB5/rhw9voufD7Wukwgtw2uqh6w== - dependencies: - graceful-fs "^4.1.3" +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== string-argv@0.3.1: version "0.3.1" @@ -7622,32 +8222,68 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string.prototype.matchall@^4.0.10: + version "4.0.11" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" + integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.7" + regexp.prototype.flags "^1.5.2" + set-function-name "^2.0.2" + side-channel "^1.0.6" + string.prototype.padend@^3.0.0: - version "3.1.3" - resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz#997a6de12c92c7cb34dc8a201a6c53d9bd88a5f1" - integrity sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg== + version "3.1.6" + resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz#ba79cf8992609a91c872daa47c6bb144ee7f62a5" + integrity sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + +string.prototype.trim@^1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" + integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.0" + es-object-atoms "^1.0.0" + +string.prototype.trimend@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" + integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" -string.prototype.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== +string.prototype.trimstart@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" + integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" -string.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" + safe-buffer "~5.2.0" string_decoder@~1.1.1: version "1.1.1" @@ -7694,25 +8330,12 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - -style-loader@^0.23.1: - version "0.23.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.1.tgz#cb9154606f3e771ab6c4ab637026a1049174d925" - integrity sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg== - dependencies: - loader-utils "^1.1.0" - schema-utils "^1.0.0" - -style-loader@~2.0.0: +style-loader@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-2.0.0.tgz#9669602fd4690740eaaec137799a03addbbc393c" integrity sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ== @@ -7720,6 +8343,11 @@ style-loader@~2.0.0: loader-utils "^2.0.0" schema-utils "^3.0.0" +style-loader@~3.3.1: + version "3.3.4" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.4.tgz#f30f786c36db03a45cbd55b6a70d930c479090e7" + integrity sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w== + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -7759,60 +8387,29 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -svg-url-loader@~3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/svg-url-loader/-/svg-url-loader-3.0.3.tgz#95274eae80f4a46454a5b44e9582beb2f533465e" - integrity sha512-MKGiRNDs8fnHcZcPkhGcw9+130IXyFM9H8m6T7u3ScUuZYEeVzX0vNMru30D4MCF6vMYas5iw/Ru9lwFKBjaGw== - dependencies: - file-loader "~4.3.0" - loader-utils "~1.2.3" - -svg-url-loader@~6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/svg-url-loader/-/svg-url-loader-6.0.0.tgz#b94861d9f6badfb8ca3e7d3ec4655c1bf732ac5d" - integrity sha512-Qr5SCKxyxKcRnvnVrO3iQj9EX/v40UiGEMshgegzV7vpo3yc+HexELOdtWcA3MKjL8IyZZ1zOdcILmDEa/8JJQ== +svg-url-loader@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/svg-url-loader/-/svg-url-loader-7.1.1.tgz#0cbdb30beb8679cb060c12eaf30085747fa7591f" + integrity sha512-NlsMCePODm7FQhU9aEZyGLPx5Xe1QRI1cSEUE6vTq5LJc9l9pStagvXoEIyZ9O3r00w6G3+Wbkimb+SC3DI/Aw== dependencies: - file-loader "~6.0.0" + file-loader "~6.2.0" loader-utils "~2.0.0" -symbol-tree@^3.2.4: - version "3.2.4" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" - integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== - -table@^6.0.9: - version "6.8.0" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.0.tgz#87e28f14fa4321c3377ba286f07b79b281a3b3ca" - integrity sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA== - dependencies: - ajv "^8.0.1" - lodash.truncate "^4.4.2" - slice-ansi "^4.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" +tabbable@^5.2.0: + version "5.3.3" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-5.3.3.tgz#aac0ff88c73b22d6c3c5a50b1586310006b47fbf" + integrity sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA== tapable@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tapable@^2.1.1, tapable@^2.2.0: +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar@^6.0.2: - version "6.1.11" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" - integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^3.0.0" - minizlib "^2.1.1" - mkdirp "^1.0.3" - yallist "^4.0.0" - terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" @@ -7821,39 +8418,33 @@ terminal-link@^2.0.0: ansi-escapes "^4.2.1" supports-hyperlinks "^2.0.0" -terser-webpack-plugin@^4.1.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz#28daef4a83bd17c1db0297070adc07fc8cfc6a9a" - integrity sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ== - dependencies: - cacache "^15.0.5" - find-cache-dir "^3.3.1" - jest-worker "^26.5.0" - p-limit "^3.0.2" - schema-utils "^3.0.0" - serialize-javascript "^5.0.1" - source-map "^0.6.1" - terser "^5.3.4" - webpack-sources "^1.4.3" - -terser-webpack-plugin@^5.1.3: - version "5.3.6" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" - integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== +terser-webpack-plugin@^5.3.10, terser-webpack-plugin@^5.3.7: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== dependencies: - "@jridgewell/trace-mapping" "^0.3.14" + "@jridgewell/trace-mapping" "^0.3.20" jest-worker "^27.4.5" schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - terser "^5.14.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" + +terser@^4.6.3: + version "4.8.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.1.tgz#a00e5634562de2239fd404c649051bf6fc21144f" + integrity sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" -terser@^5.14.1, terser@^5.3.4: - version "5.15.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.1.tgz#8561af6e0fd6d839669c73b92bdd5777d870ed6c" - integrity sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw== +terser@^5.10.0, terser@^5.26.0: + version "5.30.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.30.3.tgz#f1bb68ded42408c316b548e3ec2526d7dd03f4d2" + integrity sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA== dependencies: - "@jridgewell/source-map" "^0.3.2" - acorn "^8.5.0" + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" commander "^2.20.0" source-map-support "~0.5.20" @@ -7871,25 +8462,25 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -"through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8: +through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== -timers-ext@^0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" - integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== - dependencies: - es5-ext "~0.10.46" - next-tick "1" +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" +tiny-invariant@^1.0.2, tiny-invariant@^1.3.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" + integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== + +tiny-warning@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== tmpl@1.0.5: version "1.0.5" @@ -7906,11 +8497,6 @@ to-fast-properties@^2.0.0: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -7918,36 +8504,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -to-string-loader@^1.1.6: - version "1.2.0" - resolved "https://registry.yarnpkg.com/to-string-loader/-/to-string-loader-1.2.0.tgz#4364aa044b9aa876473f4d7a36ef7d216a276e9c" - integrity sha512-KsWUL8FccgBW9FPFm4vYoQbOOcO5m6hKOGYoXjbseD9/4Ft+ravXN5jolQ9kTKYcK4zPt1j+khx97GPGnVoi6A== - dependencies: - loader-utils "^1.0.0" - toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== -tough-cookie@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" - integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== - dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.2.0" - url-parse "^1.5.3" - -tough-cookie@~2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== - dependencies: - psl "^1.1.24" - punycode "^1.4.1" - tr46@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" @@ -7955,11 +8516,6 @@ tr46@^2.1.0: dependencies: punycode "^2.1.1" -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - ts-jest@^28.0.8: version "28.0.8" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-28.0.8.tgz#cd204b8e7a2f78da32cf6c95c9a6165c5b99cc73" @@ -7974,61 +8530,65 @@ ts-jest@^28.0.8: semver "7.x" yargs-parser "^21.0.1" -ts-loader@^6.0.4: - version "6.2.2" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.2.tgz#dffa3879b01a1a1e0a4b85e2b8421dc0dfff1c58" - integrity sha512-HDo5kXZCBml3EUPcc7RlZOV/JGlLHwppTLEHb3SHnr5V7NXD4klMEkrhJe5wgRbaWsSXi+Y1SIBN/K9B6zWGWQ== +ts-loader@^8.0.14: + version "8.4.0" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.4.0.tgz#e845ea0f38d140bdc3d7d60293ca18d12ff2720f" + integrity sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw== dependencies: - chalk "^2.3.0" + chalk "^4.1.0" enhanced-resolve "^4.0.0" - loader-utils "^1.0.2" + loader-utils "^2.0.0" micromatch "^4.0.0" - semver "^6.0.0" + semver "^7.3.4" + +ts-node@^9.1.1: + version "9.1.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" + integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== + dependencies: + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.17" + yn "3.1.1" + +tsconfig-paths-webpack-plugin@^3.3.0: + version "3.5.2" + resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.2.tgz#01aafff59130c04a8c4ebc96a3045c43c376449a" + integrity sha512-EhnfjHbzm5IYI9YPNVIxx1moxMI4bpHD2e0zTXeDNQcwjjRaGepP7IhTHJkyDBG0CAOoxRfe7jCG630Ou+C6Pw== + dependencies: + chalk "^4.1.0" + enhanced-resolve "^5.7.0" + tsconfig-paths "^3.9.0" + +tsconfig-paths@^3.9.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.13.0, tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.1.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== - -tslib@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - -tsscmp@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" - integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA== +tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== -tsutils@^3.17.1: +tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== - -typanion@^3.3.1: - version "3.12.1" - resolved "https://registry.yarnpkg.com/typanion/-/typanion-3.12.1.tgz#d33deb130aba23ef6f2a3c69e7fb28148dd9089a" - integrity sha512-3SJF/czpzqq6G3lprGFLa6ps12yb1uQ1EmitNnep2fDMNh1aO/Zbq9sWY+3lem0zYb2oHJnQWyabTGUZ+L1ScQ== - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -8036,13 +8596,6 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== - dependencies: - prelude-ls "~1.1.2" - type-detect@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -8066,30 +8619,54 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== +typed-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" + integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + is-typed-array "^1.1.13" -type@^2.7.2: - version "2.7.2" - resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" - integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== +typed-array-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" + integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" -typed-styles@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" - integrity sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q== +typed-array-byte-offset@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" + integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" -typescript@~4.1.3: - version "4.1.6" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.6.tgz#1becd85d77567c3c741172339e93ce2e69932138" - integrity sha512-pxnwLxeb/Z5SP80JDRzVjh58KsM6jZHRAOtTpS7sXLS4ogXNKC9ANxHHZqLLeVHZN35jCtI4JdmLLbLiC1kBow== +typed-array-length@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" + integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" -typescript@~4.2.4: - version "4.2.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961" - integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg== +typescript@^4.4.3: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== typestyle@^2.0.4: version "2.4.0" @@ -8099,11 +8676,6 @@ typestyle@^2.0.4: csstype "3.0.10" free-style "3.1.0" -uglify-js@^3.1.4: - version "3.17.3" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.3.tgz#f0feedf019c4510f164099e8d7e72ff2d7304377" - integrity sha512-JmMFDME3iufZnBpyKL+uS78LRiC+mK55zWfM5f/pWBJfpOttXAqYfdDGRukYhJuyRinvPVAtUhvy7rlDybNtFg== - unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" @@ -8114,11 +8686,31 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +uncontrollable@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-7.2.1.tgz#1fa70ba0c57a14d5f78905d533cf63916dc75738" + integrity sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ== + dependencies: + "@babel/runtime" "^7.6.3" + "@types/react" ">=16.9.11" + invariant "^2.2.4" + react-lifecycles-compat "^3.0.4" + +uncontrollable@^8.0.1: + version "8.0.4" + resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-8.0.4.tgz#a0a8307f638795162fafd0550f4a1efa0f8c5eb6" + integrity sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ== + underscore@>=1.8.3: version "1.13.6" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" @@ -8132,59 +8724,35 @@ unicode-match-property-ecmascript@^2.0.0: unicode-canonical-property-names-ecmascript "^2.0.0" unicode-property-aliases-ecmascript "^2.0.0" -unicode-match-property-value-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" - integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== +unicode-match-property-value-ecmascript@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" + integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== unicode-property-aliases-ecmascript@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== -unique-filename@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" - integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== - dependencies: - imurmurhash "^0.1.4" - universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== -universalify@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" - integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== - universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -unix-crypt-td-js@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/unix-crypt-td-js/-/unix-crypt-td-js-1.1.4.tgz#4912dfad1c8aeb7d20fa0a39e4c31918c1d5d5dd" - integrity sha512-8rMeVYWSIyccIJscb9NdCfZKSRBKYTeVnwmiRYT2ulE3qd1RaDQ0xQDP+rI3ccIWbhu/zuo5cgN8z73belNZgw== + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -update-browserslist-db@^1.0.9: - version "1.0.10" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" - integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== dependencies: escalade "^3.1.1" picocolors "^1.0.0" @@ -8196,7 +8764,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url-loader@^4.1.0, url-loader@~4.1.0: +url-loader@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== @@ -8205,14 +8773,7 @@ url-loader@^4.1.0, url-loader@~4.1.0: mime-types "^2.1.27" schema-utils "^3.0.0" -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== - dependencies: - prepend-http "^2.0.0" - -url-parse@^1.5.3, url-parse@~1.5.1: +url-parse@~1.5.4: version "1.5.10" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== @@ -8220,42 +8781,34 @@ url-parse@^1.5.3, url-parse@~1.5.1: querystringify "^2.1.1" requires-port "^1.0.0" -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ== - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -util-deprecate@^1.0.2, util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +utila@~0.4: + version "0.4.0" + resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" + integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -v8-compile-cache@^2.0.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" - integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== v8-to-istanbul@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz#b6f994b0b5d4ef255e17a0d17dc444a9f5132fa4" - integrity sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w== + version "9.2.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" + integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== dependencies: "@jridgewell/trace-mapping" "^0.3.12" "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^1.6.0" + convert-source-map "^2.0.0" validate-npm-package-license@^3.0.1: version "3.0.4" @@ -8295,107 +8848,35 @@ validate.io-number@^1.0.3: resolved "https://registry.yarnpkg.com/validate.io-number/-/validate.io-number-1.0.3.tgz#f63ffeda248bf28a67a8d48e0e3b461a1665baf8" integrity sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg== -validator@13.7.0: - version "13.7.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857" - integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw== +value-equal@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" + integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== -vary@^1, vary@~1.1.2: +vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== -verdaccio-audit@10.2.2: - version "10.2.2" - resolved "https://registry.yarnpkg.com/verdaccio-audit/-/verdaccio-audit-10.2.2.tgz#254380e57932fda64b45cb739e9c42cc9fb2dfdf" - integrity sha512-f2uZlKD7vi0yEB0wN8WOf+eA/3SCyKD9cvK17Hh7Wm8f/bl7k1B3hHOTtUCn/yu85DGsj2pcNzrAfp2wMVgz9Q== - dependencies: - body-parser "1.20.0" - express "4.18.1" - https-proxy-agent "5.0.1" - node-fetch "2.6.7" - -verdaccio-htpasswd@10.5.0: - version "10.5.0" - resolved "https://registry.yarnpkg.com/verdaccio-htpasswd/-/verdaccio-htpasswd-10.5.0.tgz#de9ea2967856af765178b08485dc8e83f544a12c" - integrity sha512-olBsT3uy1TT2ZqmMCJUsMHrztJzoEpa8pxxvYrDZdWnEksl6mHV10lTeLbH9BUwbEheOeKkkdsERqUOs+if0jg== - dependencies: - "@verdaccio/file-locking" "10.3.0" - apache-md5 "1.1.7" - bcryptjs "2.4.3" - http-errors "2.0.0" - unix-crypt-td-js "1.1.4" - -verdaccio@^5.13.3: - version "5.15.4" - resolved "https://registry.yarnpkg.com/verdaccio/-/verdaccio-5.15.4.tgz#23b2b97b33b14ca30a6fc18b1226a1f082f7e476" - integrity sha512-yYMqpEQCv/BfYW5K/Nq57dbx68ICP1GfK7RJ0A3SlhKgl6idT8x4cJyLjH7C4k1Tln3LIQk1/X6ZtSl7xhzwOg== - dependencies: - "@verdaccio/commons-api" "10.2.0" - "@verdaccio/local-storage" "10.3.1" - "@verdaccio/readme" "10.4.1" - "@verdaccio/streams" "10.2.0" - "@verdaccio/ui-theme" "6.0.0-6-next.48" - JSONStream "1.3.5" - async "3.2.4" - body-parser "1.20.0" - clipanion "3.1.0" - compression "1.7.4" - cookies "0.8.0" - cors "2.8.5" - dayjs "1.11.5" - debug "^4.3.3" - envinfo "7.8.1" - eslint-import-resolver-node "0.3.6" - express "4.18.1" - express-rate-limit "5.5.1" - fast-safe-stringify "2.1.1" - handlebars "4.7.7" - http-errors "2.0.0" - js-yaml "4.1.0" - jsonwebtoken "8.5.1" - kleur "4.1.5" - lodash "4.17.21" - lru-cache "7.14.0" - lunr-mutable-indexes "2.3.2" - marked "4.1.0" - memoizee "0.4.15" - mime "3.0.0" - minimatch "5.1.0" - mkdirp "1.0.4" - mv "2.1.1" - pino "6.14.0" - pkginfo "0.4.1" - prettier-bytes "^1.0.4" - pretty-ms "^7.0.1" - request "2.88.0" - semver "7.3.7" - validator "13.7.0" - verdaccio-audit "10.2.2" - verdaccio-htpasswd "10.5.0" - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -w3c-hr-time@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" - integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== - dependencies: - browser-process-hrtime "^1.0.0" - -w3c-xmlserializer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" - integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== - dependencies: - xml-name-validator "^3.0.0" +victory-vendor@^36.6.8: + version "36.9.2" + resolved "https://registry.yarnpkg.com/victory-vendor/-/victory-vendor-36.9.2.tgz#668b02a448fa4ea0f788dbf4228b7e64669ff801" + integrity sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ== + dependencies: + "@types/d3-array" "^3.0.3" + "@types/d3-ease" "^3.0.0" + "@types/d3-interpolate" "^3.0.1" + "@types/d3-scale" "^4.0.2" + "@types/d3-shape" "^3.1.0" + "@types/d3-time" "^3.0.0" + "@types/d3-timer" "^3.0.0" + d3-array "^3.1.6" + d3-ease "^3.0.1" + d3-interpolate "^3.0.1" + d3-scale "^4.0.2" + d3-shape "^3.1.0" + d3-time "^3.0.0" + d3-timer "^3.0.1" walker@^1.0.8: version "1.0.8" @@ -8404,37 +8885,34 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" -warning@^4.0.2, warning@^4.0.3: +warning@^4.0.0, warning@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== dependencies: loose-envify "^1.0.0" -watchpack@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== +watchpack@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" + integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -webidl-conversions@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" - integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" webidl-conversions@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== -webpack-cli@^4.1.0, webpack-cli@^4.4.0: +webpack-cli@^4.5.0: version "4.10.0" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== @@ -8452,15 +8930,82 @@ webpack-cli@^4.1.0, webpack-cli@^4.4.0: rechoir "^0.7.0" webpack-merge "^5.7.3" -webpack-merge@^5.1.2, webpack-merge@^5.7.3: - version "5.8.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" - integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== +webpack-cli@^5.0.1: + version "5.1.4" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" + integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^2.1.1" + "@webpack-cli/info" "^2.0.2" + "@webpack-cli/serve" "^2.0.5" + colorette "^2.0.14" + commander "^10.0.1" + cross-spawn "^7.0.3" + envinfo "^7.7.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^3.1.1" + rechoir "^0.8.0" + webpack-merge "^5.7.3" + +webpack-dev-middleware@^5.3.4: + version "5.3.4" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz#eb7b39281cbce10e104eb2b8bf2b63fce49a3517" + integrity sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q== + dependencies: + colorette "^2.0.10" + memfs "^3.4.3" + mime-types "^2.1.31" + range-parser "^1.2.1" + schema-utils "^4.0.0" + +webpack-dev-server@^4.0.0: + version "4.15.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz#9e0c70a42a012560860adb186986da1248333173" + integrity sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g== + dependencies: + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/express" "^4.17.13" + "@types/serve-index" "^1.9.1" + "@types/serve-static" "^1.13.10" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.5.5" + ansi-html-community "^0.0.8" + bonjour-service "^1.0.11" + chokidar "^3.5.3" + colorette "^2.0.10" + compression "^1.7.4" + connect-history-api-fallback "^2.0.0" + default-gateway "^6.0.3" + express "^4.17.3" + graceful-fs "^4.2.6" + html-entities "^2.3.2" + http-proxy-middleware "^2.0.3" + ipaddr.js "^2.0.1" + launch-editor "^2.6.0" + open "^8.0.9" + p-retry "^4.5.0" + rimraf "^3.0.2" + schema-utils "^4.0.0" + selfsigned "^2.1.1" + serve-index "^1.9.1" + sockjs "^0.3.24" + spdy "^4.0.2" + webpack-dev-middleware "^5.3.4" + ws "^8.13.0" + +webpack-merge@^5.7.3, webpack-merge@^5.8.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" + integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== dependencies: clone-deep "^4.0.1" + flat "^5.0.2" wildcard "^2.0.0" -webpack-sources@^1.1.0, webpack-sources@^1.2.0, webpack-sources@^1.4.3: +webpack-sources@^1.2.0: version "1.4.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== @@ -8473,57 +9018,56 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5, webpack@^5.41.1: - version "5.74.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.74.0.tgz#02a5dac19a17e0bb47093f2be67c695102a55980" - integrity sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA== +webpack@^5, webpack@^5.76.1: + version "5.91.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.91.0.tgz#ffa92c1c618d18c878f06892bbdc3373c71a01d9" + integrity sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw== dependencies: "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" acorn "^8.7.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" + acorn-import-assertions "^1.9.0" + browserslist "^4.21.10" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" + enhanced-resolve "^5.16.0" + es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" + graceful-fs "^4.2.11" json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.1.0" + schema-utils "^3.2.0" tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.4.0" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" webpack-sources "^3.2.3" -whatwg-encoding@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" - integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== dependencies: - iconv-lite "0.4.24" + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== whatwg-mimetype@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -whatwg-url@^8.0.0, whatwg-url@^8.5.0: +whatwg-url@^8.0.0: version "8.7.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== @@ -8543,6 +9087,45 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-builtin-type@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" + integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== + dependencies: + function.prototype.name "^1.1.5" + has-tostringtag "^1.0.0" + is-async-function "^2.0.0" + is-date-object "^1.0.5" + is-finalizationregistry "^1.0.2" + is-generator-function "^1.0.10" + is-regex "^1.1.4" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.1" + which-typed-array "^1.1.9" + +which-collection@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== + dependencies: + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" + +which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.9: + version "1.1.15" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" + integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.2" + which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -8558,19 +9141,9 @@ which@^2.0.1: isexe "^2.0.0" wildcard@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" - integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== - -word-wrap@^1.2.3, word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== worker-loader@^3.0.2: version "3.0.8" @@ -8611,45 +9184,47 @@ write-file-atomic@^4.0.1: imurmurhash "^0.1.4" signal-exit "^3.0.7" -ws@^7.4.6: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== - -xml-name-validator@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" - integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== +ws@^8.11.0, ws@^8.13.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" + integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== -xmlchars@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" - integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +y-protocols@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/y-protocols/-/y-protocols-1.0.6.tgz#66dad8a95752623443e8e28c0e923682d2c0d495" + integrity sha512-vHRF2L6iT3rwj1jub/K5tYcTT/mEYDUppgNPXwp8fmLpui9f7Yeq3OEtTLVF012j39QnV+KEQpNqoN7CWU7Y9Q== + dependencies: + lib0 "^0.2.85" y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.0: +yaml@^1.10.0, yaml@^1.7.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yargs-parser@^21.0.0, yargs-parser@^21.0.1: +yargs-parser@^21.0.1, yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== yargs@^17.3.1: - version "17.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.0.tgz#e134900fc1f218bc230192bdec06a0a5f973e46c" - integrity sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g== + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" escalade "^3.1.1" @@ -8657,7 +9232,19 @@ yargs@^17.3.1: require-directory "^2.1.1" string-width "^4.2.3" y18n "^5.0.5" - yargs-parser "^21.0.0" + yargs-parser "^21.1.1" + +yjs@^13.5.40: + version "13.6.14" + resolved "https://registry.yarnpkg.com/yjs/-/yjs-13.6.14.tgz#9326dfa03d1be3fb9af9ef7e41de4bfc78849a9f" + integrity sha512-D+7KcUr0j+vBCUSKXXEWfA+bG4UQBviAwP3gYBhkstkgwy5+8diOPMx0iqLIOxNo/HxaREUimZRxqHGAHCL2BQ== + dependencies: + lib0 "^0.2.86" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== yocto-queue@^0.1.0: version "0.1.0"