diff --git a/.vscode/launch.json b/.vscode/launch.json index 6bd4d46..8c93e38 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -71,12 +71,21 @@ "type": "node", "request": "launch", "runtimeExecutable": "node", - "runtimeArgs": ["--nolazy", "-r", "ts-node/register"], - "args": ["${relativeFile}"], + "runtimeArgs": [ + "--nolazy", + "-r", + "ts-node/register" + ], + "args": [ + "${relativeFile}" + ], "sourceMaps": true, "cwd": "${workspaceRoot}", "protocol": "inspector", - "skipFiles": ["/**", "node_modules/**"], + "skipFiles": [ + "/**", + "node_modules/**" + ], "console": "integratedTerminal", "internalConsoleOptions": "neverOpen", "env": { @@ -87,20 +96,41 @@ }, // { - "name": "Python: Streamlit", - "type": "python", - "request": "launch", - "module": "streamlit", - "args": ["run", "${file}", "--server.headless=true", "--browser.gatherUsageStats=false"], - "env": { - "PYTHONPATH": "${workspaceFolder}" - }, - "console": "integratedTerminal" + "name": "Python: Debug Test", + "type": "debugpy", + "request": "launch", + "module": "pytest", + "args": [ + "${file}" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}" + }, + "console": "integratedTerminal" + }, + { + "name": "Python: Debug Streamlit", + "type": "debugpy", + "request": "launch", + "module": "streamlit", + "args": [ + "run", + "${file}", + "--server.headless=true", + "--browser.gatherUsageStats=false" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}" + }, + "console": "integratedTerminal" } ], "inputs": [ { - "options": ["rxdb", "kinto"], + "options": [ + "rxdb", + "kinto" + ], "id": "libName", "type": "pickString", "default": "rxdb", diff --git a/README.md b/README.md index 8c03f87..36981a9 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,12 @@ import { getRxDatabaseCreator } from '@ngx-odm/rxdb/config'; multiInstance: true, // <- multiInstance (optional, default: true) ignoreDuplicate: false, options: { + plugins: [ + // will be loaded by together with core plugins + RxDBDevModePlugin, // <- add only for development + RxDBAttachmentsPlugin, + RxDBLeaderElectionPlugin, + ], storageType: 'dexie|memory', // <- storageType (optional, use if you want defaults provided automatically) dumpPath: 'assets/dump.json', // path to datbase dump file (optional) }, @@ -106,7 +112,7 @@ const todoCollectionConfig: RxCollectionCreatorExtended = { }) export class TodosModule { constructor( - @Inject(NgxRxdbCollectionService) private collectionService: NgxRxdbCollection + @Inject(RXDB_COLLECTION) private collectionService: RxDBCollectionService ) { this.collectionService.sync(); // INFO: collection is ready } @@ -116,11 +122,13 @@ export class TodosModule { ### In your `FeatureService` ```typescript +import { RXDB_COLLECTION } from '@ngx-odm/rxdb'; +import { RxDBCollectionService } from '@ngx-odm/rxdb/collection'; + @Injectable() export class TodosService { - private collectionService: NgxRxdbCollection = inject>( - NgxRxdbCollectionService - ); + private collectionService: RxDBCollectionService = + inject>(RXDB_COLLECTION); // store & get filter as property of a `local` document filter$ = this.collectionService .getLocal('local', 'filterValue') @@ -177,6 +185,12 @@ export const appConfig: ApplicationConfig = { multiInstance: true, ignoreDuplicate: false, storage: getRxStorageDexie(), + plugins: [ + // will be loaded by together with core plugins + RxDBDevModePlugin, // <- add only for development + RxDBAttachmentsPlugin, + RxDBLeaderElectionPlugin, + ], }) ), ], diff --git a/packages/rxdb/README.md b/packages/rxdb/README.md index 2317583..36981a9 100644 --- a/packages/rxdb/README.md +++ b/packages/rxdb/README.md @@ -4,7 +4,7 @@ ## Demo -![Example Screencast](https://github.com/voznik/ngx-odm/blob/master/examples/screencast.gif?raw=true) +![Example Screencast](examples/screencast.gif) [demo](https://voznik.github.io/ngx-odm/) - based on TodoMVC @@ -63,6 +63,12 @@ import { getRxDatabaseCreator } from '@ngx-odm/rxdb/config'; multiInstance: true, // <- multiInstance (optional, default: true) ignoreDuplicate: false, options: { + plugins: [ + // will be loaded by together with core plugins + RxDBDevModePlugin, // <- add only for development + RxDBAttachmentsPlugin, + RxDBLeaderElectionPlugin, + ], storageType: 'dexie|memory', // <- storageType (optional, use if you want defaults provided automatically) dumpPath: 'assets/dump.json', // path to datbase dump file (optional) }, @@ -106,7 +112,7 @@ const todoCollectionConfig: RxCollectionCreatorExtended = { }) export class TodosModule { constructor( - @Inject(NgxRxdbCollectionService) private collectionService: NgxRxdbCollection + @Inject(RXDB_COLLECTION) private collectionService: RxDBCollectionService ) { this.collectionService.sync(); // INFO: collection is ready } @@ -116,11 +122,13 @@ export class TodosModule { ### In your `FeatureService` ```typescript +import { RXDB_COLLECTION } from '@ngx-odm/rxdb'; +import { RxDBCollectionService } from '@ngx-odm/rxdb/collection'; + @Injectable() export class TodosService { - private collectionService: NgxRxdbCollection = inject>( - NgxRxdbCollectionService - ); + private collectionService: RxDBCollectionService = + inject>(RXDB_COLLECTION); // store & get filter as property of a `local` document filter$ = this.collectionService .getLocal('local', 'filterValue') @@ -177,6 +185,12 @@ export const appConfig: ApplicationConfig = { multiInstance: true, ignoreDuplicate: false, storage: getRxStorageDexie(), + plugins: [ + // will be loaded by together with core plugins + RxDBDevModePlugin, // <- add only for development + RxDBAttachmentsPlugin, + RxDBLeaderElectionPlugin, + ], }) ), ], @@ -247,7 +261,14 @@ By using this module you can simplify your work with RxDB in Angular application - optionally provide syncronization with remote db (CouchDB, Kinto etc.) as DB options - Automatically initialize RxCollection for each _lazy-loaded Feature module / standalone component_ with config - Work with documents via _NgxRxdbCollectionService_ with unified methods instead of using _RxCollection_ directly (though you still have access to _RxCollection_ and _RxDatabase_ instance) + - simple methods to work database & documents (with queries) + - simple methods to work with local documents + - simple methods to work with attachments + - simple replication sync initialization - Work with signals and entities with `@ngrx/signals` and `@ngrx/entity` (optionally _zoneless_) (see [example](examples/standalone/src/app/todos/todos.store.ts)) +- Persist collection query ([mango-query-syntax](https://github.com/cloudant/mango)) in URL with new plugin `query-params-plugin` (in demo, set localStorage `_ngx_rxdb_queryparams` ) + - provide Observable of current URL (automatically for Angular) + - simple methods to set or patch filter, sort, limit, skip diff --git a/packages/streamlit-rxdb-dataframe/example.py b/packages/streamlit-rxdb-dataframe/example.py index c39a703..1082a84 100644 --- a/packages/streamlit-rxdb-dataframe/example.py +++ b/packages/streamlit-rxdb-dataframe/example.py @@ -31,13 +31,13 @@ state = RxDBSessionState() -# operators = ["$eq", "$gt", "$gte", "$lt", "$lte", "$ne"] +column_config = state.column_config +query = state.query def on_change_dataframe(rxdb_state: RxDBSessionState): print("RxDBDataframe component on_change call") print("collection.info()", rxdb_state.info) - print("dataframe.head()", rxdb_state.dataframe.head()) @cache_data @@ -47,7 +47,6 @@ def apply_row_style(row): ) # noqa: E501 -query = state.query display = st.radio( "Display RxDB collection as:", options=["dataframe", "data_editor", "table"], @@ -76,27 +75,36 @@ def apply_row_style(row): ) if display == "data_editor": - st.data_editor( - df.style.apply(apply_row_style, axis=1), - use_container_width=True, - hide_index=True, - column_config=state.column_config, - column_order=["title", "completed", "createdAt"], - num_rows="dynamic", - key=RXDB_COLLECTION_EDITOR_KEY, - ) + try: + st.data_editor( + df.copy().style.apply(apply_row_style, axis=1), + use_container_width=True, + hide_index=True, + column_config=column_config, + column_order=["title", "completed", "createdAt"], + num_rows="dynamic", + key=RXDB_COLLECTION_EDITOR_KEY, + ) + except Exception as e: + st.error(f"An error occurred: {str(e)}") elif display == "dataframe": - st.dataframe( - df.style.apply(apply_row_style, axis=1), - use_container_width=True, - hide_index=True, - column_config=state.column_config, - column_order=["title", "completed", "createdAt"], - ) + try: + st.dataframe( + df.style.apply(apply_row_style, axis=1), + use_container_width=True, + hide_index=True, + column_config=column_config, + column_order=["title", "completed", "createdAt"], + ) + except Exception as e: + st.error(f"An error occurred: {str(e)}") else: - st.table( - df.style.apply(apply_row_style, axis=1), - ) + try: + st.table( + df.style.apply(apply_row_style, axis=1), + ) + except Exception as e: + st.error(f"An error occurred: {str(e)}") with st.sidebar: @@ -105,60 +113,3 @@ def apply_row_style(row): st.write("RsDB Session State:") st.json(st.session_state, expanded=False) - # TODO: Add form to construct RxQuery - # query_container = st.container() - # with query_container: - # to_filter_columns = st.multiselect( - # "Filter dataframe on", - # df.columns, - # key=f"{prefix}_multiselect", - # ) - # filters: Dict[str, Any] = dict() - # for column in to_filter_columns: - # left, right = st.columns((1, 20)) - # # Treat columns with < 10 unique values as categorical - # if is_categorical_dtype(df[column]) or df[column].nunique() < 10: - # left.write("↳") - # filters[column] = right.multiselect( - # f"Values for {column}", - # df[column].unique(), - # default=list(df[column].unique()), - # key=f"{prefix}_{column}", - # ) - # df = df[df[column].isin(filters[column])] - # elif is_numeric_dtype(df[column]): - # left.write("↳") - # _min = float(df[column].min()) - # _max = float(df[column].max()) - # step = (_max - _min) / 100 - # filters[column] = right.slider( - # f"Values for {column}", - # _min, - # _max, - # (_min, _max), - # step=step, - # key=f"{prefix}_{column}", - # ) - # df = df[df[column].between(*filters[column])] - # elif is_datetime64_any_dtype(df[column]): - # left.write("↳") - # filters[column] = right.date_input( - # f"Values for {column}", - # value=( - # df[column].min(), - # df[column].max(), - # ), - # key=f"{prefix}_{column}", - # ) - # if len(filters[column]) == 2: - # filters[column] = tuple(map(pd.to_datetime, filters[column])) # noqa: E501 - # start_date, end_date = filters[column] - # df = df.loc[df[column].between(start_date, end_date)] - # else: - # left.write("↳") - # filters[column] = right.text_input( - # f"Pattern in {column}", - # key=f"{prefix}_{column}", - # ) - # if filters[column]: - # print(filters[column]) diff --git a/packages/streamlit-rxdb-dataframe/poetry.lock b/packages/streamlit-rxdb-dataframe/poetry.lock index 6b26233..1db27f6 100644 --- a/packages/streamlit-rxdb-dataframe/poetry.lock +++ b/packages/streamlit-rxdb-dataframe/poetry.lock @@ -45,35 +45,47 @@ tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "p [[package]] name = "black" -version = "22.12.0" +version = "23.12.1" description = "The uncompromising code formatter." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, - {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, - {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, - {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, - {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, - {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, - {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, - {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, - {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, - {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, - {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, - {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, + {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, + {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, + {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, + {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, + {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, + {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, + {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, + {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, + {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, + {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, + {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, + {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, + {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, + {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, + {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, + {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, + {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, + {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, + {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, + {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, + {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, + {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, ] [package.dependencies] click = ">=8.0.0" mypy-extensions = ">=0.4.3" +packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] +d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] @@ -585,44 +597,49 @@ files = [ [[package]] name = "mypy" -version = "0.971" +version = "1.9.0" description = "Optional static typing for Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "mypy-0.971-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2899a3cbd394da157194f913a931edfd4be5f274a88041c9dc2d9cdcb1c315c"}, - {file = "mypy-0.971-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98e02d56ebe93981c41211c05adb630d1d26c14195d04d95e49cd97dbc046dc5"}, - {file = "mypy-0.971-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:19830b7dba7d5356d3e26e2427a2ec91c994cd92d983142cbd025ebe81d69cf3"}, - {file = "mypy-0.971-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:02ef476f6dcb86e6f502ae39a16b93285fef97e7f1ff22932b657d1ef1f28655"}, - {file = "mypy-0.971-cp310-cp310-win_amd64.whl", hash = "sha256:25c5750ba5609a0c7550b73a33deb314ecfb559c350bb050b655505e8aed4103"}, - {file = "mypy-0.971-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d3348e7eb2eea2472db611486846742d5d52d1290576de99d59edeb7cd4a42ca"}, - {file = "mypy-0.971-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3fa7a477b9900be9b7dd4bab30a12759e5abe9586574ceb944bc29cddf8f0417"}, - {file = "mypy-0.971-cp36-cp36m-win_amd64.whl", hash = "sha256:2ad53cf9c3adc43cf3bea0a7d01a2f2e86db9fe7596dfecb4496a5dda63cbb09"}, - {file = "mypy-0.971-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:855048b6feb6dfe09d3353466004490b1872887150c5bb5caad7838b57328cc8"}, - {file = "mypy-0.971-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:23488a14a83bca6e54402c2e6435467a4138785df93ec85aeff64c6170077fb0"}, - {file = "mypy-0.971-cp37-cp37m-win_amd64.whl", hash = "sha256:4b21e5b1a70dfb972490035128f305c39bc4bc253f34e96a4adf9127cf943eb2"}, - {file = "mypy-0.971-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9796a2ba7b4b538649caa5cecd398d873f4022ed2333ffde58eaf604c4d2cb27"}, - {file = "mypy-0.971-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a361d92635ad4ada1b1b2d3630fc2f53f2127d51cf2def9db83cba32e47c856"}, - {file = "mypy-0.971-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b793b899f7cf563b1e7044a5c97361196b938e92f0a4343a5d27966a53d2ec71"}, - {file = "mypy-0.971-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d1ea5d12c8e2d266b5fb8c7a5d2e9c0219fedfeb493b7ed60cd350322384ac27"}, - {file = "mypy-0.971-cp38-cp38-win_amd64.whl", hash = "sha256:23c7ff43fff4b0df93a186581885c8512bc50fc4d4910e0f838e35d6bb6b5e58"}, - {file = "mypy-0.971-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1f7656b69974a6933e987ee8ffb951d836272d6c0f81d727f1d0e2696074d9e6"}, - {file = "mypy-0.971-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d2022bfadb7a5c2ef410d6a7c9763188afdb7f3533f22a0a32be10d571ee4bbe"}, - {file = "mypy-0.971-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef943c72a786b0f8d90fd76e9b39ce81fb7171172daf84bf43eaf937e9f220a9"}, - {file = "mypy-0.971-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d744f72eb39f69312bc6c2abf8ff6656973120e2eb3f3ec4f758ed47e414a4bf"}, - {file = "mypy-0.971-cp39-cp39-win_amd64.whl", hash = "sha256:77a514ea15d3007d33a9e2157b0ba9c267496acf12a7f2b9b9f8446337aac5b0"}, - {file = "mypy-0.971-py3-none-any.whl", hash = "sha256:0d054ef16b071149917085f51f89555a576e2618d5d9dd70bd6eea6410af3ac9"}, - {file = "mypy-0.971.tar.gz", hash = "sha256:40b0f21484238269ae6a57200c807d80debc6459d444c0489a102d7c6a75fa56"}, + {file = "mypy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"}, + {file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"}, + {file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"}, + {file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"}, + {file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"}, + {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"}, + {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"}, + {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"}, + {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"}, + {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"}, + {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"}, + {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"}, + {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"}, + {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"}, + {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"}, + {file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"}, + {file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"}, + {file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"}, + {file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"}, + {file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"}, + {file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"}, + {file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"}, + {file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"}, + {file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"}, + {file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"}, + {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"}, + {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"}, ] [package.dependencies] -mypy-extensions = ">=0.4.3" +mypy-extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=3.10" +typing-extensions = ">=4.1.0" [package.extras] dmypy = ["psutil (>=4.0)"] -python2 = ["typed-ast (>=1.4.0,<2)"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] reports = ["lxml"] [[package]] @@ -933,47 +950,47 @@ files = [ [[package]] name = "pyarrow" -version = "15.0.1" +version = "15.0.2" description = "Python library for Apache Arrow" optional = false python-versions = ">=3.8" files = [ - {file = "pyarrow-15.0.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:c2ddb3be5ea938c329a84171694fc230b241ce1b6b0ff1a0280509af51c375fa"}, - {file = "pyarrow-15.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7543ea88a0ff72f8e6baaf9bfdbec2c62aeabdbede9e4a571c71cc3bc43b6302"}, - {file = "pyarrow-15.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1519e218a6941fc074e4501088d891afcb2adf77c236e03c34babcf3d6a0d1c7"}, - {file = "pyarrow-15.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28cafa86e1944761970d3b3fc0411b14ff9b5c2b73cd22aaf470d7a3976335f5"}, - {file = "pyarrow-15.0.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:be5c3d463e33d03eab496e1af7916b1d44001c08f0f458ad27dc16093a020638"}, - {file = "pyarrow-15.0.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:47b1eda15d3aa3f49a07b1808648e1397e5dc6a80a30bf87faa8e2d02dad7ac3"}, - {file = "pyarrow-15.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e524a31be7db22deebbbcf242b189063ab9a7652c62471d296b31bc6e3cae77b"}, - {file = "pyarrow-15.0.1-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:a476fefe8bdd56122fb0d4881b785413e025858803cc1302d0d788d3522b374d"}, - {file = "pyarrow-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:309e6191be385f2e220586bfdb643f9bb21d7e1bc6dd0a6963dc538e347b2431"}, - {file = "pyarrow-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83bc586903dbeb4365cbc72b602f99f70b96c5882e5dfac5278813c7d624ca3c"}, - {file = "pyarrow-15.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07e652daac6d8b05280cd2af31c0fb61a4490ec6a53dc01588014d9fa3fdbee9"}, - {file = "pyarrow-15.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:abad2e08652df153a72177ce20c897d083b0c4ebeec051239e2654ddf4d3c996"}, - {file = "pyarrow-15.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cde663352bc83ad75ba7b3206e049ca1a69809223942362a8649e37bd22f9e3b"}, - {file = "pyarrow-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:1b6e237dd7a08482a8b8f3f6512d258d2460f182931832a8c6ef3953203d31e1"}, - {file = "pyarrow-15.0.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:7bd167536ee23192760b8c731d39b7cfd37914c27fd4582335ffd08450ff799d"}, - {file = "pyarrow-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7c08bb31eb2984ba5c3747d375bb522e7e536b8b25b149c9cb5e1c49b0ccb736"}, - {file = "pyarrow-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0f9c1d630ed2524bd1ddf28ec92780a7b599fd54704cd653519f7ff5aec177a"}, - {file = "pyarrow-15.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5186048493395220550bca7b524420471aac2d77af831f584ce132680f55c3df"}, - {file = "pyarrow-15.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:31dc30c7ec8958da3a3d9f31d6c3630429b2091ede0ecd0d989fd6bec129f0e4"}, - {file = "pyarrow-15.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:3f111a014fb8ac2297b43a74bf4495cc479a332908f7ee49cb7cbd50714cb0c1"}, - {file = "pyarrow-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:a6d1f7c15d7f68f08490d0cb34611497c74285b8a6bbeab4ef3fc20117310983"}, - {file = "pyarrow-15.0.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:9ad931b996f51c2f978ed517b55cb3c6078272fb4ec579e3da5a8c14873b698d"}, - {file = "pyarrow-15.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:738f6b53ab1c2f66b2bde8a1d77e186aeaab702d849e0dfa1158c9e2c030add3"}, - {file = "pyarrow-15.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c1c3fc16bc74e33bf8f1e5a212938ed8d88e902f372c4dac6b5bad328567d2f"}, - {file = "pyarrow-15.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1fa92512128f6c1b8dde0468c1454dd70f3bff623970e370d52efd4d24fd0be"}, - {file = "pyarrow-15.0.1-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:b4157f307c202cbbdac147d9b07447a281fa8e63494f7fc85081da351ec6ace9"}, - {file = "pyarrow-15.0.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:b75e7da26f383787f80ad76143b44844ffa28648fcc7099a83df1538c078d2f2"}, - {file = "pyarrow-15.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:3a99eac76ae14096c209850935057b9e8ce97a78397c5cde8724674774f34e5d"}, - {file = "pyarrow-15.0.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:dd532d3177e031e9b2d2df19fd003d0cc0520d1747659fcabbd4d9bb87de508c"}, - {file = "pyarrow-15.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ce8c89848fd37e5313fc2ce601483038ee5566db96ba0808d5883b2e2e55dc53"}, - {file = "pyarrow-15.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:862eac5e5f3b6477f7a92b2f27e560e1f4e5e9edfca9ea9da8a7478bb4abd5ce"}, - {file = "pyarrow-15.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f0ea3a29cd5cb99bf14c1c4533eceaa00ea8fb580950fb5a89a5c771a994a4e"}, - {file = "pyarrow-15.0.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:bb902f780cfd624b2e8fd8501fadab17618fdb548532620ef3d91312aaf0888a"}, - {file = "pyarrow-15.0.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:4f87757f02735a6bb4ad2e1b98279ac45d53b748d5baf52401516413007c6999"}, - {file = "pyarrow-15.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:efd3816c7fbfcbd406ac0f69873cebb052effd7cdc153ae5836d1b00845845d7"}, - {file = "pyarrow-15.0.1.tar.gz", hash = "sha256:21d812548d39d490e0c6928a7c663f37b96bf764034123d4b4ab4530ecc757a9"}, + {file = "pyarrow-15.0.2-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:88b340f0a1d05b5ccc3d2d986279045655b1fe8e41aba6ca44ea28da0d1455d8"}, + {file = "pyarrow-15.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eaa8f96cecf32da508e6c7f69bb8401f03745c050c1dd42ec2596f2e98deecac"}, + {file = "pyarrow-15.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23c6753ed4f6adb8461e7c383e418391b8d8453c5d67e17f416c3a5d5709afbd"}, + {file = "pyarrow-15.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f639c059035011db8c0497e541a8a45d98a58dbe34dc8fadd0ef128f2cee46e5"}, + {file = "pyarrow-15.0.2-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:290e36a59a0993e9a5224ed2fb3e53375770f07379a0ea03ee2fce2e6d30b423"}, + {file = "pyarrow-15.0.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:06c2bb2a98bc792f040bef31ad3e9be6a63d0cb39189227c08a7d955db96816e"}, + {file = "pyarrow-15.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:f7a197f3670606a960ddc12adbe8075cea5f707ad7bf0dffa09637fdbb89f76c"}, + {file = "pyarrow-15.0.2-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:5f8bc839ea36b1f99984c78e06e7a06054693dc2af8920f6fb416b5bca9944e4"}, + {file = "pyarrow-15.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5e81dfb4e519baa6b4c80410421528c214427e77ca0ea9461eb4097c328fa33"}, + {file = "pyarrow-15.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a4f240852b302a7af4646c8bfe9950c4691a419847001178662a98915fd7ee7"}, + {file = "pyarrow-15.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e7d9cfb5a1e648e172428c7a42b744610956f3b70f524aa3a6c02a448ba853e"}, + {file = "pyarrow-15.0.2-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2d4f905209de70c0eb5b2de6763104d5a9a37430f137678edfb9a675bac9cd98"}, + {file = "pyarrow-15.0.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:90adb99e8ce5f36fbecbbc422e7dcbcbed07d985eed6062e459e23f9e71fd197"}, + {file = "pyarrow-15.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:b116e7fd7889294cbd24eb90cd9bdd3850be3738d61297855a71ac3b8124ee38"}, + {file = "pyarrow-15.0.2-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:25335e6f1f07fdaa026a61c758ee7d19ce824a866b27bba744348fa73bb5a440"}, + {file = "pyarrow-15.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:90f19e976d9c3d8e73c80be84ddbe2f830b6304e4c576349d9360e335cd627fc"}, + {file = "pyarrow-15.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a22366249bf5fd40ddacc4f03cd3160f2d7c247692945afb1899bab8a140ddfb"}, + {file = "pyarrow-15.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2a335198f886b07e4b5ea16d08ee06557e07db54a8400cc0d03c7f6a22f785f"}, + {file = "pyarrow-15.0.2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e6d459c0c22f0b9c810a3917a1de3ee704b021a5fb8b3bacf968eece6df098f"}, + {file = "pyarrow-15.0.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:033b7cad32198754d93465dcfb71d0ba7cb7cd5c9afd7052cab7214676eec38b"}, + {file = "pyarrow-15.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:29850d050379d6e8b5a693098f4de7fd6a2bea4365bfd073d7c57c57b95041ee"}, + {file = "pyarrow-15.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:7167107d7fb6dcadb375b4b691b7e316f4368f39f6f45405a05535d7ad5e5058"}, + {file = "pyarrow-15.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e85241b44cc3d365ef950432a1b3bd44ac54626f37b2e3a0cc89c20e45dfd8bf"}, + {file = "pyarrow-15.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:248723e4ed3255fcd73edcecc209744d58a9ca852e4cf3d2577811b6d4b59818"}, + {file = "pyarrow-15.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ff3bdfe6f1b81ca5b73b70a8d482d37a766433823e0c21e22d1d7dde76ca33f"}, + {file = "pyarrow-15.0.2-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:f3d77463dee7e9f284ef42d341689b459a63ff2e75cee2b9302058d0d98fe142"}, + {file = "pyarrow-15.0.2-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:8c1faf2482fb89766e79745670cbca04e7018497d85be9242d5350cba21357e1"}, + {file = "pyarrow-15.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:28f3016958a8e45a1069303a4a4f6a7d4910643fc08adb1e2e4a7ff056272ad3"}, + {file = "pyarrow-15.0.2-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:89722cb64286ab3d4daf168386f6968c126057b8c7ec3ef96302e81d8cdb8ae4"}, + {file = "pyarrow-15.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cd0ba387705044b3ac77b1b317165c0498299b08261d8122c96051024f953cd5"}, + {file = "pyarrow-15.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad2459bf1f22b6a5cdcc27ebfd99307d5526b62d217b984b9f5c974651398832"}, + {file = "pyarrow-15.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58922e4bfece8b02abf7159f1f53a8f4d9f8e08f2d988109126c17c3bb261f22"}, + {file = "pyarrow-15.0.2-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:adccc81d3dc0478ea0b498807b39a8d41628fa9210729b2f718b78cb997c7c91"}, + {file = "pyarrow-15.0.2-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:8bd2baa5fe531571847983f36a30ddbf65261ef23e496862ece83bdceb70420d"}, + {file = "pyarrow-15.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6669799a1d4ca9da9c7e06ef48368320f5856f36f9a4dd31a11839dda3f6cc8c"}, + {file = "pyarrow-15.0.2.tar.gz", hash = "sha256:9c9bc803cb3b7bfacc1e96ffbfd923601065d9d3f911179d81e72d99fd74a3d9"}, ] [package.dependencies] @@ -1052,16 +1069,6 @@ files = [ plugins = ["importlib-metadata"] windows-terminal = ["colorama (>=0.4.6)"] -[[package]] -name = "pyperclip" -version = "1.8.2" -description = "A cross-platform clipboard module for Python. (Only handles plain text for now.)" -optional = false -python-versions = "*" -files = [ - {file = "pyperclip-1.8.2.tar.gz", hash = "sha256:105254a8b04934f0bc84e9c24eb360a591aaf6535c9def5f29d92af107a9bf57"}, -] - [[package]] name = "pytest" version = "7.4.4" @@ -1133,20 +1140,6 @@ files = [ [package.dependencies] six = ">=1.5" -[[package]] -name = "python-dotenv" -version = "1.0.1" -description = "Read key-value pairs from a .env file and set them as environment variables" -optional = false -python-versions = ">=3.8" -files = [ - {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, - {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, -] - -[package.extras] -cli = ["click (>=5.0)"] - [[package]] name = "python-slugify" version = "8.0.4" @@ -1177,13 +1170,13 @@ files = [ [[package]] name = "referencing" -version = "0.33.0" +version = "0.34.0" description = "JSON Referencing + Python" optional = false python-versions = ">=3.8" files = [ - {file = "referencing-0.33.0-py3-none-any.whl", hash = "sha256:39240f2ecc770258f28b642dd47fd74bc8b02484de54e1882b74b35ebd779bd5"}, - {file = "referencing-0.33.0.tar.gz", hash = "sha256:c775fedf74bc0f9189c2a3be1c12fd03e8c23f4d371dce795df44e06c5b412f7"}, + {file = "referencing-0.34.0-py3-none-any.whl", hash = "sha256:d53ae300ceddd3169f1ffa9caf2cb7b769e92657e4fafb23d34b93679116dfd4"}, + {file = "referencing-0.34.0.tar.gz", hash = "sha256:5773bd84ef41799a5a8ca72dc34590c041eb01bf9aa02632b4a973fb0181a844"}, ] [package.dependencies] @@ -1394,23 +1387,6 @@ watchdog = {version = ">=2.1.5", markers = "platform_system != \"Darwin\""} [package.extras] snowflake = ["snowflake-connector-python (>=2.8.0)", "snowflake-snowpark-python (>=0.9.0)"] -[[package]] -name = "streamlit-parameters" -version = "0.1.5" -description = "Streamlit parameter management for page configuration" -optional = false -python-versions = "*" -files = [ - {file = "streamlit_parameters-0.1.5-py3-none-any.whl", hash = "sha256:de69024ba84d5df6cc48bd5f86d429371b00590697c1caafcf9a9c6071660af6"}, - {file = "streamlit_parameters-0.1.5.tar.gz", hash = "sha256:d800981d58aa29e25d238de1bcee203bd9f7602bb78a858900bec422f4573a98"}, -] - -[package.dependencies] -streamlit = ">=1.12,<2" - -[package.extras] -test = ["pytest", "pytest-mock", "tox"] - [[package]] name = "tenacity" version = "8.2.3" @@ -1572,4 +1548,4 @@ watchmedo = ["PyYAML (>=3.10)"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "55329c5e879e252159baecdb32a131f467baadf199ea3d66a0865dec0d0d7821" +content-hash = "84aea7fa420c79670167c9bac937fad70e889a60ac30418e05406f4ea396bda0" diff --git a/packages/streamlit-rxdb-dataframe/pyproject.toml b/packages/streamlit-rxdb-dataframe/pyproject.toml index acf02f1..b812a12 100644 --- a/packages/streamlit-rxdb-dataframe/pyproject.toml +++ b/packages/streamlit-rxdb-dataframe/pyproject.toml @@ -1,20 +1,21 @@ [tool.poetry] name = "streamlit-rxdb-dataframe" version = "0.1.0" -description = "" -authors = ["voznik "] +description = "Custom streamlit component connecting local browser indexedDB database as RxDB collection as dataframe" +authors = ["voznik "] readme = "README.md" -packages = [{include = "rxdb_dataframe"}] +license = "MIT" +homepage = "https://github.com/voznik/ngx-odm" +repository = "https://github.com/voznik/ngx-odm" +keywords = ["streamlit", "indexedDB", "RxDB", "browser", "connection", "dataframe"] +packages = [{ include = "rxdb_dataframe" }] [tool.poetry.dependencies] python = "^3.10" pytest-playwright = "^0.4.4" streamlit = "^1.31.0" -pyperclip = "^1.8.2" -python-dotenv = "^1.0.1" playwright = "^1.41.2" pandas = "^2.2.1" -streamlit-parameters = "^0.1.5" jsonschema = "^4.21.1" @@ -24,10 +25,10 @@ build-backend = "poetry.core.masonry.api" [tool.poetry.group.dev.dependencies] pytest = "^7.1.3" -black = "^22.8.0" -isort = "^5.10.1" -mypy = "^0.971" -streamlit = ">=1.31.0" +black = "^23.1.0" +isort = "^5.12.0" +mypy = "^1.0.0" +flake8 = "^7.0.0" flake8-annotations-complexity = "^0.0.8" [tool.isort] diff --git a/packages/streamlit-rxdb-dataframe/rxdb_dataframe/__init__.py b/packages/streamlit-rxdb-dataframe/rxdb_dataframe/__init__.py index d1e4eca..b98c236 100644 --- a/packages/streamlit-rxdb-dataframe/rxdb_dataframe/__init__.py +++ b/packages/streamlit-rxdb-dataframe/rxdb_dataframe/__init__.py @@ -82,7 +82,6 @@ def __init__(self): "info": {}, # collection info "with_rev": False, # include revision in the result "query": {"selector": {}, "sort": []}, # collection query - "dataframe": None, # "column_config": None, # ColumnConfig "docs": [], # collection documents } @@ -139,6 +138,8 @@ def __setitem__(self, key, value): "ignoreDuplicate": True, } +# blueprint_df: pd.DataFrame = None + @cache_data def get_dataframe_by_schema(schema: dict) -> pd: @@ -146,7 +147,7 @@ def get_dataframe_by_schema(schema: dict) -> pd: Create a `pandas.DataFrame` based on the given JSONSchema. """ df = pd.DataFrame() - properties = schema["properties"] + properties = schema.get("properties", {}) for column, prop in properties.items(): if prop["type"] == "string" and prop.get("format") == "date-time": df[column] = pd.Series(dtype="datetime64[ns]") @@ -170,17 +171,18 @@ def get_dataframe_by_schema(schema: dict) -> pd: @cache_data def get_column_config(schema: dict) -> ColumnConfigMap: """ - Generates a column configuration dictionary based on the given schema. + Generates a (default) column configuration dictionary based on the given schema, + which can be used to configure streamlit dataframe or data_editor widgets. + Use own column config if default one is not suitable for your use case. INFO: https://docs.streamlit.io/library/api-reference/data/st.column_config """ - properties = schema["properties"] + properties = schema.get("properties", {}) column_config: ColumnConfigMap = {} for key, prop in properties.items(): - if ( - prop["type"] == ColumnDataKind.STRING - and prop.get("format") == "date-time" # marks column as datetime - ): + if prop.get("enum") and len(prop["enum"]) > 0: + column_config[key] = st.column_config.SelectboxColumn(options=prop["enum"]) + elif prop["type"] == ColumnDataKind.STRING and prop.get("format") == "date-time": column_config[key] = st.column_config.DatetimeColumn( format="YYYY-MM-DD HH:mm", ) @@ -190,8 +192,6 @@ def get_column_config(schema: dict) -> ColumnConfigMap: column_config[key] = st.column_config.CheckboxColumn() elif prop["type"] == "object": column_config[key] = st.column_config.Column() - elif prop.get("enum") and len(prop["enum"]) > 0: - column_config[key] = st.column_config.SelectboxColumn(options=prop["enum"]) elif prop["type"] == ColumnDataKind.INTEGER and prop.get("format", None) == "time": column_config[key] = st.column_config.NumberColumn() elif prop["type"] == ColumnDataKind.INTEGER: @@ -204,13 +204,12 @@ def get_column_config(schema: dict) -> ColumnConfigMap: st.column_config.NumberColumn( max_value=prop.get("max", None), min_value=prop.get("min", None) ) - # assign common properties for every column try: column: ColumnConfig = column_config[key] column["label"] = prop.get("title", "") column["help"] = "format: " + prop.get("format", column["type_config"]["type"]) - column["disabled"] = prop.get("readOnly", False) - column["required"] = key in schema.get("required", []) # noqa: E501 + # column["disabled"] = prop.get("readOnly", False) + column["required"] = key in schema.get("required", []) except Exception as e: print(f"An error occurred: {str(e)}") @@ -225,8 +224,9 @@ def rxdb_dataframe( on_change: Optional[Callable] = None, ) -> pd.DataFrame: state = RxDBSessionState() - if state.dataframe is None: - state.dataframe = get_dataframe_by_schema(collection_config["schema"]) + blueprint_df = get_dataframe_by_schema(collection_config["schema"]) + result_df = blueprint_df.copy() + if state.column_config is None: state.column_config = get_column_config(collection_config["schema"]) @@ -240,17 +240,19 @@ def rxdb_dataframe( ) try: - if result and result["docs"]: - result_df = pd.DataFrame(result["docs"], columns=state.dataframe.columns) + if result: + result_df = pd.DataFrame(result["docs"], columns=blueprint_df.columns) + for col in blueprint_df.columns: + if blueprint_df[col].dtype == "datetime64[ns]": + result_df[col] = pd.to_datetime(result_df[col]) state.docs = result["docs"] state.info = result["info"] state.query = result["query"] # store query here from response, to prevent re-rendering - state.dataframe = result_df on_change(state) except Exception as e: print(f"An error occurred: {str(e)}") - return state.dataframe + return result_df __title__ = "RxDB Dataframe" diff --git a/packages/streamlit-rxdb-dataframe/rxdb_dataframe/frontend/public/assets/data/col.dump.json b/packages/streamlit-rxdb-dataframe/rxdb_dataframe/frontend/public/assets/data/col.dump.json index 16de3ee..78219b8 100644 --- a/packages/streamlit-rxdb-dataframe/rxdb_dataframe/frontend/public/assets/data/col.dump.json +++ b/packages/streamlit-rxdb-dataframe/rxdb_dataframe/frontend/public/assets/data/col.dump.json @@ -6,21 +6,21 @@ "id": "a4c6a479-7cca-4d3b-ab90-45d3eaa957f3", "title": "Check other examples", "completed": false, - "createdAt": 1548979200000, + "createdAt": "2019-02-01T00:00:00.000Z", "last_modified": 1548979200000 }, { "id": "a4c6a479-7cca-4d3b-bc10-45d3eaa957r5", "title": "Use \"@ngx-odm/rxdb\" in your project", "completed": false, - "createdAt": 1698404710931, + "createdAt": "2023-10-27T11:05:10.931Z", "last_modified": 1698404710931 }, { "id": "ac3ef2c6-c98b-43e1-9047-71d68b1f92f4", "title": "Open Todo list example", "completed": true, - "createdAt": 1546300800000, + "createdAt": "2019-02-01T00:01:00.000Z", "last_modified": 1546300800000 } ] diff --git a/packages/streamlit-rxdb-dataframe/rxdb_dataframe/test___init__.py b/packages/streamlit-rxdb-dataframe/rxdb_dataframe/test___init__.py new file mode 100644 index 0000000..2806314 --- /dev/null +++ b/packages/streamlit-rxdb-dataframe/rxdb_dataframe/test___init__.py @@ -0,0 +1,74 @@ +import pandas as pd +import pytest + +from rxdb_dataframe import get_dataframe_by_schema + + +def test_get_dataframe_by_schema(): + # Test case 1: Empty schema + schema = {} + expected_df = pd.DataFrame() + assert get_dataframe_by_schema(schema).equals(expected_df) + + # Test case 2: Schema with string properties + schema = { + "properties": { + "name": {"type": "string"}, + "age": {"type": "string"}, + "city": {"type": "string"}, + } + } + expected_df = pd.DataFrame( + { + "name": pd.Series(dtype="object"), + "age": pd.Series(dtype="object"), + "city": pd.Series(dtype="object"), + } + ) + assert get_dataframe_by_schema(schema).equals(expected_df) + + # Test case 3: Schema with boolean properties + schema = { + "properties": {"is_active": {"type": "boolean"}, "has_permission": {"type": "boolean"}} + } + expected_df = pd.DataFrame( + {"is_active": pd.Series(dtype="bool"), "has_permission": pd.Series(dtype="bool")} + ) + assert get_dataframe_by_schema(schema).equals(expected_df) + + +def test_get_dataframe_by_schema(): + # Test case 1: Empty schema + schema = {} + expected_df = pd.DataFrame() + assert get_dataframe_by_schema(schema).equals(expected_df) + + # Test case 2: Schema with string properties + schema = { + "properties": { + "name": {"type": "string"}, + "age": {"type": "string"}, + "city": {"type": "string"}, + } + } + expected_df = pd.DataFrame( + { + "name": pd.Series(dtype="object"), + "age": pd.Series(dtype="object"), + "city": pd.Series(dtype="object"), + } + ) + assert get_dataframe_by_schema(schema).equals(expected_df) + + # Test case 3: Schema with boolean properties + schema = { + "properties": {"is_active": {"type": "boolean"}, "has_permission": {"type": "boolean"}} + } + expected_df = pd.DataFrame( + {"is_active": pd.Series(dtype="bool"), "has_permission": pd.Series(dtype="bool")} + ) + assert get_dataframe_by_schema(schema).equals(expected_df) + + +if __name__ == "__main__": + pytest.main([__file__]) diff --git a/packages/streamlit-rxdb-dataframe/screencast.gif b/packages/streamlit-rxdb-dataframe/screencast.gif new file mode 100644 index 0000000..2b2647f Binary files /dev/null and b/packages/streamlit-rxdb-dataframe/screencast.gif differ diff --git a/packages/streamlit-rxdb-dataframe/screenshot.png b/packages/streamlit-rxdb-dataframe/screenshot.png new file mode 100644 index 0000000..cc9fc64 Binary files /dev/null and b/packages/streamlit-rxdb-dataframe/screenshot.png differ diff --git a/packages/streamlit-rxdb-dataframe/tests/test_rxdb_dataframe.py b/packages/streamlit-rxdb-dataframe/tests/test_rxdb_dataframe.py new file mode 100644 index 0000000..404ca39 --- /dev/null +++ b/packages/streamlit-rxdb-dataframe/tests/test_rxdb_dataframe.py @@ -0,0 +1,70 @@ +import pandas as pd +from rxdb_dataframe import get_column_config, get_dataframe_by_schema + + +def test_get_column_config(): + schema = { + "properties": { + "name": {"type": "string", "maxLength": 50}, + "age": {"type": "integer", "min": 0, "max": 100}, + "is_active": {"type": "boolean"}, + "gender": {"type": "string", "enum": ["Male", "Female", "Other"]}, + "birth_date": {"type": "string", "format": "date-time"}, + }, + "required": ["name", "age"], + } + + column_config = get_column_config(schema) + + assert "name" in column_config + assert column_config["name"]["type_config"]["type"] == "text" + assert column_config["name"]["type_config"]["max_chars"] == 50 + + assert "age" in column_config + assert column_config["age"]["type_config"]["type"] == "number" + assert column_config["age"]["type_config"]["min_value"] == 0 + assert column_config["age"]["type_config"]["max_value"] == 100 + + assert "is_active" in column_config + assert column_config["is_active"]["type_config"]["type"] == "checkbox" + + assert "gender" in column_config + assert column_config["gender"]["type_config"]["type"] == "selectbox" + assert column_config["gender"]["type_config"]["options"] == ["Male", "Female", "Other"] + + assert "birth_date" in column_config + assert column_config["birth_date"]["type_config"]["type"] == "datetime" + assert column_config["birth_date"]["type_config"]["format"] == "YYYY-MM-DD HH:mm" + + +def test_get_dataframe_by_schema(): + # Test case 1: Empty schema + schema = {} + expected_df = pd.DataFrame() + assert get_dataframe_by_schema(schema).equals(expected_df) + + # Test case 2: Schema with string properties + schema = { + "properties": { + "name": {"type": "string"}, + "age": {"type": "string"}, + "city": {"type": "string"}, + } + } + expected_df = pd.DataFrame( + { + "name": pd.Series(dtype="object"), + "age": pd.Series(dtype="object"), + "city": pd.Series(dtype="object"), + } + ) + assert get_dataframe_by_schema(schema).equals(expected_df) + + # Test case 3: Schema with boolean properties + schema = { + "properties": {"is_active": {"type": "boolean"}, "has_permission": {"type": "boolean"}} + } + expected_df = pd.DataFrame( + {"is_active": pd.Series(dtype="bool"), "has_permission": pd.Series(dtype="bool")} + ) + assert get_dataframe_by_schema(schema).equals(expected_df)