├── .gitignore ├── .streamlit └── config.toml ├── Home.py ├── LICENSE ├── Pipfile ├── Pipfile.lock ├── README.md ├── pages ├── 01_🔹_Compute_insights.py ├── 02_🔹_Storage_insights.py ├── 03_🔹_Data_Transfer_insights.py └── 04_🤔_About_this_app.py └── utils ├── charts.py ├── gui.py ├── processing.py ├── snowflake_connector.py └── sql.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Streamlit secrets 2 | .streamlit/secrets.toml 3 | 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /.streamlit/config.toml: -------------------------------------------------------------------------------- 1 | [runner] 2 | fastReruns = true 3 | 4 | [theme] 5 | primaryColor = "#1c83e1" 6 | -------------------------------------------------------------------------------- /Home.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | st.set_page_config(page_title="Usage Insights app", page_icon="🌀", layout="centered") 4 | 5 | from utils import gui 6 | 7 | gui.icon("🌀") 8 | 9 | # Make sure session state is preserved 10 | for key in st.session_state: 11 | st.session_state[key] = st.session_state[key] 12 | 13 | st.title("Welcome to the Usage Insights app!") 14 | st.sidebar.text(f"Account: {st.secrets.sf_usage_app.account}") 15 | st.sidebar.info("Choose a page!") 16 | st.markdown( 17 | """ 18 | This app provides insights on a demo Snowflake account usage. 19 | 20 | ### Get started! 21 | 22 | 👈 Select a page in the sidebar! 23 | """ 24 | ) 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [requires] 7 | python_version = "3.9" 8 | 9 | [packages] 10 | streamlit = ">=1.10.0" # Requires multipage app 11 | requests = "*" 12 | matplotlib = "*" 13 | millify = "*" 14 | plost = {editable = true, ref = "streamlit-style", git = "https://github.com/jrieke/plost"} # Docs https://share.streamlit.io/jrieke/plost/streamlit-style/ 15 | numpy = "*" 16 | snowflake-connector-python = ">=2.7.8" 17 | sqlparse = "*" 18 | 19 | [dev-packages] 20 | black = "*" # Pretty formatting of Python code 21 | pynvim = "*" # Allows nvim users to use black formatting 22 | pre-commit = "*" 23 | flake8 = "*" 24 | flake8-bugbear = "*" 25 | typed-ast = ">=1.5.0" 26 | mypy = "*" 27 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "2f652e94201d84d4069906fa9b57fbaead9e3d9942989e45aa473bdd471bfc90" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.9" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "altair": { 20 | "hashes": [ 21 | "sha256:0c724848ae53410c13fa28be2b3b9a9dcb7b5caa1a70f7f217bd663bb419935a", 22 | "sha256:d87d9372e63b48cd96b2a6415f0cf9457f50162ab79dc7a31cd7e024dd840026" 23 | ], 24 | "markers": "python_version >= '3.7'", 25 | "version": "==4.2.0" 26 | }, 27 | "appnope": { 28 | "hashes": [ 29 | "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24", 30 | "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e" 31 | ], 32 | "markers": "platform_system == 'Darwin'", 33 | "version": "==0.1.3" 34 | }, 35 | "argon2-cffi": { 36 | "hashes": [ 37 | "sha256:8c976986f2c5c0e5000919e6de187906cfd81fb1c72bf9d88c01177e77da7f80", 38 | "sha256:d384164d944190a7dd7ef22c6aa3ff197da12962bd04b17f64d4e93d934dba5b" 39 | ], 40 | "markers": "python_version >= '3.6'", 41 | "version": "==21.3.0" 42 | }, 43 | "argon2-cffi-bindings": { 44 | "hashes": [ 45 | "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670", 46 | "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f", 47 | "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583", 48 | "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194", 49 | "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c", 50 | "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a", 51 | "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082", 52 | "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5", 53 | "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f", 54 | "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7", 55 | "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d", 56 | "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f", 57 | "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae", 58 | "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3", 59 | "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86", 60 | "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367", 61 | "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d", 62 | "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93", 63 | "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb", 64 | "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e", 65 | "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351" 66 | ], 67 | "markers": "python_version >= '3.6'", 68 | "version": "==21.2.0" 69 | }, 70 | "asn1crypto": { 71 | "hashes": [ 72 | "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c", 73 | "sha256:db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67" 74 | ], 75 | "version": "==1.5.1" 76 | }, 77 | "asttokens": { 78 | "hashes": [ 79 | "sha256:0844691e88552595a6f4a4281a9f7f79b8dd45ca4ccea82e5e05b4bbdb76705c", 80 | "sha256:9a54c114f02c7a9480d56550932546a3f1fe71d8a02f1bc7ccd0ee3ee35cf4d5" 81 | ], 82 | "version": "==2.0.5" 83 | }, 84 | "attrs": { 85 | "hashes": [ 86 | "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4", 87 | "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd" 88 | ], 89 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", 90 | "version": "==21.4.0" 91 | }, 92 | "backcall": { 93 | "hashes": [ 94 | "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e", 95 | "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255" 96 | ], 97 | "version": "==0.2.0" 98 | }, 99 | "beautifulsoup4": { 100 | "hashes": [ 101 | "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30", 102 | "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693" 103 | ], 104 | "markers": "python_version >= '3.6'", 105 | "version": "==4.11.1" 106 | }, 107 | "bleach": { 108 | "hashes": [ 109 | "sha256:08a1fe86d253b5c88c92cc3d810fd8048a16d15762e1e5b74d502256e5926aa1", 110 | "sha256:c6d6cc054bdc9c83b48b8083e236e5f00f238428666d2ce2e083eaa5fd568565" 111 | ], 112 | "markers": "python_version >= '3.7'", 113 | "version": "==5.0.0" 114 | }, 115 | "blinker": { 116 | "hashes": [ 117 | "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6" 118 | ], 119 | "version": "==1.4" 120 | }, 121 | "cachetools": { 122 | "hashes": [ 123 | "sha256:6a94c6402995a99c3970cc7e4884bb60b4a8639938157eeed436098bf9831757", 124 | "sha256:f9f17d2aec496a9aa6b76f53e3b614c965223c061982d434d160f930c698a9db" 125 | ], 126 | "markers": "python_version ~= '3.7'", 127 | "version": "==5.2.0" 128 | }, 129 | "certifi": { 130 | "hashes": [ 131 | "sha256:9c5705e395cd70084351dd8ad5c41e65655e08ce46f2ec9cf6c2c08390f71eb7", 132 | "sha256:f1d53542ee8cbedbe2118b5686372fb33c297fcd6379b050cca0ef13a597382a" 133 | ], 134 | "markers": "python_version >= '3.6'", 135 | "version": "==2022.5.18.1" 136 | }, 137 | "cffi": { 138 | "hashes": [ 139 | "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3", 140 | "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2", 141 | "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636", 142 | "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20", 143 | "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728", 144 | "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27", 145 | "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66", 146 | "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443", 147 | "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0", 148 | "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7", 149 | "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39", 150 | "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605", 151 | "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a", 152 | "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37", 153 | "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029", 154 | "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139", 155 | "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc", 156 | "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df", 157 | "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14", 158 | "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880", 159 | "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2", 160 | "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a", 161 | "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e", 162 | "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474", 163 | "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024", 164 | "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8", 165 | "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0", 166 | "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e", 167 | "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a", 168 | "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e", 169 | "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032", 170 | "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6", 171 | "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e", 172 | "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b", 173 | "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e", 174 | "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954", 175 | "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962", 176 | "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c", 177 | "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4", 178 | "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55", 179 | "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962", 180 | "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023", 181 | "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c", 182 | "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6", 183 | "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8", 184 | "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382", 185 | "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7", 186 | "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc", 187 | "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997", 188 | "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796" 189 | ], 190 | "version": "==1.15.0" 191 | }, 192 | "charset-normalizer": { 193 | "hashes": [ 194 | "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597", 195 | "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df" 196 | ], 197 | "markers": "python_version >= '3.5'", 198 | "version": "==2.0.12" 199 | }, 200 | "click": { 201 | "hashes": [ 202 | "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", 203 | "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" 204 | ], 205 | "markers": "python_version >= '3.7'", 206 | "version": "==8.1.3" 207 | }, 208 | "colour": { 209 | "hashes": [ 210 | "sha256:33f6db9d564fadc16e59921a56999b79571160ce09916303d35346dddc17978c", 211 | "sha256:af20120fefd2afede8b001fbef2ea9da70ad7d49fafdb6489025dae8745c3aee" 212 | ], 213 | "version": "==0.1.5" 214 | }, 215 | "commonmark": { 216 | "hashes": [ 217 | "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60", 218 | "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9" 219 | ], 220 | "version": "==0.9.1" 221 | }, 222 | "cryptography": { 223 | "hashes": [ 224 | "sha256:0a3bf09bb0b7a2c93ce7b98cb107e9170a90c51a0162a20af1c61c765b90e60b", 225 | "sha256:1f64a62b3b75e4005df19d3b5235abd43fa6358d5516cfc43d87aeba8d08dd51", 226 | "sha256:32db5cc49c73f39aac27574522cecd0a4bb7384e71198bc65a0d23f901e89bb7", 227 | "sha256:4881d09298cd0b669bb15b9cfe6166f16fc1277b4ed0d04a22f3d6430cb30f1d", 228 | "sha256:4e2dddd38a5ba733be6a025a1475a9f45e4e41139d1321f412c6b360b19070b6", 229 | "sha256:53e0285b49fd0ab6e604f4c5d9c5ddd98de77018542e88366923f152dbeb3c29", 230 | "sha256:70f8f4f7bb2ac9f340655cbac89d68c527af5bb4387522a8413e841e3e6628c9", 231 | "sha256:7b2d54e787a884ffc6e187262823b6feb06c338084bbe80d45166a1cb1c6c5bf", 232 | "sha256:7be666cc4599b415f320839e36367b273db8501127b38316f3b9f22f17a0b815", 233 | "sha256:8241cac0aae90b82d6b5c443b853723bcc66963970c67e56e71a2609dc4b5eaf", 234 | "sha256:82740818f2f240a5da8dfb8943b360e4f24022b093207160c77cadade47d7c85", 235 | "sha256:8897b7b7ec077c819187a123174b645eb680c13df68354ed99f9b40a50898f77", 236 | "sha256:c2c5250ff0d36fd58550252f54915776940e4e866f38f3a7866d92b32a654b86", 237 | "sha256:ca9f686517ec2c4a4ce930207f75c00bf03d94e5063cbc00a1dc42531511b7eb", 238 | "sha256:d2b3d199647468d410994dbeb8cec5816fb74feb9368aedf300af709ef507e3e", 239 | "sha256:da73d095f8590ad437cd5e9faf6628a218aa7c387e1fdf67b888b47ba56a17f0", 240 | "sha256:e167b6b710c7f7bc54e67ef593f8731e1f45aa35f8a8a7b72d6e42ec76afd4b3", 241 | "sha256:ea634401ca02367c1567f012317502ef3437522e2fc44a3ea1844de028fa4b84", 242 | "sha256:ec6597aa85ce03f3e507566b8bcdf9da2227ec86c4266bd5e6ab4d9e0cc8dab2", 243 | "sha256:f64b232348ee82f13aac22856515ce0195837f6968aeaa94a3d0353ea2ec06a6" 244 | ], 245 | "markers": "python_version >= '3.6'", 246 | "version": "==36.0.2" 247 | }, 248 | "cycler": { 249 | "hashes": [ 250 | "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3", 251 | "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f" 252 | ], 253 | "markers": "python_version >= '3.6'", 254 | "version": "==0.11.0" 255 | }, 256 | "debugpy": { 257 | "hashes": [ 258 | "sha256:0d383b91efee57dbb923ba20801130cf60450a0eda60bce25bccd937de8e323a", 259 | "sha256:0e3aa2368883e83e7b689ddff3cafb595f7b711f6a065886b46a96a7fef874e7", 260 | "sha256:132defb585b518955358321d0f42f6aa815aa15b432be27db654807707c70b2f", 261 | "sha256:1ff853e60e77e1c16f85a31adb8360bb2d98ca588d7ed645b7f0985b240bdb5e", 262 | "sha256:245c7789a012f86210847ec7ee9f38c30a30d4c2223c3e111829a76c9006a5d0", 263 | "sha256:30abefefd2ff5a5481162d613cb70e60e2fa80a5eb4c994717c0f008ed25d2e1", 264 | "sha256:40de9ba137d355538432209d05e0f5fe5d0498dce761c39119ad4b950b51db31", 265 | "sha256:4de7777842da7e08652f2776c552070bbdd758557fdec73a15d7be0e4aab95ce", 266 | "sha256:5c492235d6b68f879df3bdbdb01f25c15be15682665517c2c7d0420e5658d71f", 267 | "sha256:72bcfa97f3afa0064afc77ab811f48ad4a06ac330f290b675082c24437730366", 268 | "sha256:7b79c40852991f7b6c3ea65845ed0f5f6b731c37f4f9ad9c61e2ab4bd48a9275", 269 | "sha256:8e972c717d95f56b6a3a7a29a5ede1ee8f2c3802f6f0e678203b0778eb322bf1", 270 | "sha256:8ee75844242b4537beb5899f3e60a578454d1f136b99e8d57ac424573797b94a", 271 | "sha256:a65a2499761d47df3e9ea9567109be6e73d412e00ac3ffcf74839f3ddfcdf028", 272 | "sha256:a8aaeb53e87225141fda7b9081bd87155c1debc13e2f5a532d341112d1983b65", 273 | "sha256:bd980d533d0ddfc451e03a3bb32acb2900049fec39afc3425b944ebf0889be62", 274 | "sha256:e3513399177dd37af4c1332df52da5da1d0c387e5927dc4c0709e26ee7302e8f", 275 | "sha256:eb1946efac0c0c3d411cea0b5ac772fbde744109fd9520fb0c5a51979faf05ad" 276 | ], 277 | "markers": "python_version >= '3.7'", 278 | "version": "==1.6.0" 279 | }, 280 | "decorator": { 281 | "hashes": [ 282 | "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", 283 | "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186" 284 | ], 285 | "markers": "python_version >= '3.5'", 286 | "version": "==5.1.1" 287 | }, 288 | "defusedxml": { 289 | "hashes": [ 290 | "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", 291 | "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61" 292 | ], 293 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", 294 | "version": "==0.7.1" 295 | }, 296 | "entrypoints": { 297 | "hashes": [ 298 | "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4", 299 | "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f" 300 | ], 301 | "markers": "python_version >= '3.6'", 302 | "version": "==0.4" 303 | }, 304 | "executing": { 305 | "hashes": [ 306 | "sha256:c6554e21c6b060590a6d3be4b82fb78f8f0194d809de5ea7df1c093763311501", 307 | "sha256:d1eef132db1b83649a3905ca6dd8897f71ac6f8cac79a7e58a1a09cf137546c9" 308 | ], 309 | "version": "==0.8.3" 310 | }, 311 | "fastjsonschema": { 312 | "hashes": [ 313 | "sha256:0a572f0836962d844c1fc435e200b2e4f4677e4e6611a2e3bdd01ba697c275ec", 314 | "sha256:ddb0b1d8243e6e3abb822bd14e447a89f4ab7439342912d590444831fa00b6a0" 315 | ], 316 | "version": "==2.15.3" 317 | }, 318 | "fonttools": { 319 | "hashes": [ 320 | "sha256:c0fdcfa8ceebd7c1b2021240bd46ef77aa8e7408cf10434be55df52384865f8e", 321 | "sha256:f829c579a8678fa939a1d9e9894d01941db869de44390adb49ce67055a06cc2a" 322 | ], 323 | "markers": "python_version >= '3.7'", 324 | "version": "==4.33.3" 325 | }, 326 | "gitdb": { 327 | "hashes": [ 328 | "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd", 329 | "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa" 330 | ], 331 | "markers": "python_version >= '3.6'", 332 | "version": "==4.0.9" 333 | }, 334 | "gitpython": { 335 | "hashes": [ 336 | "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704", 337 | "sha256:5b68b000463593e05ff2b261acff0ff0972df8ab1b70d3cdbd41b546c8b8fc3d" 338 | ], 339 | "markers": "python_version >= '3.7'", 340 | "version": "==3.1.27" 341 | }, 342 | "idna": { 343 | "hashes": [ 344 | "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", 345 | "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" 346 | ], 347 | "markers": "python_version >= '3.5'", 348 | "version": "==3.3" 349 | }, 350 | "importlib-metadata": { 351 | "hashes": [ 352 | "sha256:5d26852efe48c0a32b0509ffbc583fda1a2266545a78d104a6f4aff3db17d700", 353 | "sha256:c58c8eb8a762858f49e18436ff552e83914778e50e9d2f1660535ffb364552ec" 354 | ], 355 | "markers": "python_version >= '3.7'", 356 | "version": "==4.11.4" 357 | }, 358 | "ipykernel": { 359 | "hashes": [ 360 | "sha256:6f42070a5d87ecbf4a2fc27a7faae8d690fd3794825a090ddf6b00b9678a5b69", 361 | "sha256:fedc79bebd8a438162d056e0c7662d5ac8a47d1f6ef33a702e8460248dc4517f" 362 | ], 363 | "markers": "python_version >= '3.4'", 364 | "version": "==6.13.1" 365 | }, 366 | "ipython": { 367 | "hashes": [ 368 | "sha256:7ca74052a38fa25fe9bedf52da0be7d3fdd2fb027c3b778ea78dfe8c212937d1", 369 | "sha256:f2db3a10254241d9b447232cec8b424847f338d9d36f9a577a6192c332a46abd" 370 | ], 371 | "markers": "python_version >= '3.8'", 372 | "version": "==8.4.0" 373 | }, 374 | "ipython-genutils": { 375 | "hashes": [ 376 | "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8", 377 | "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8" 378 | ], 379 | "version": "==0.2.0" 380 | }, 381 | "ipywidgets": { 382 | "hashes": [ 383 | "sha256:ab4a5596855a88b83761921c768707d65e5847068139bc1729ddfe834703542a", 384 | "sha256:e58ff58bc94d481e91ecb6e13a5cb96a87b6b8ade135e055603d0ca24593df38" 385 | ], 386 | "markers": "python_version >= '3.7'", 387 | "version": "==7.7.0" 388 | }, 389 | "jedi": { 390 | "hashes": [ 391 | "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d", 392 | "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab" 393 | ], 394 | "markers": "python_version >= '3.6'", 395 | "version": "==0.18.1" 396 | }, 397 | "jinja2": { 398 | "hashes": [ 399 | "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", 400 | "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" 401 | ], 402 | "markers": "python_version >= '3.7'", 403 | "version": "==3.1.2" 404 | }, 405 | "jsonschema": { 406 | "hashes": [ 407 | "sha256:1c92d2db1900b668201f1797887d66453ab1fbfea51df8e4b46236689c427baf", 408 | "sha256:9d6397ba4a6c0bf0300736057f649e3e12ecbc07d3e81a0dacb72de4e9801957" 409 | ], 410 | "markers": "python_version >= '3.7'", 411 | "version": "==4.6.0" 412 | }, 413 | "jupyter-client": { 414 | "hashes": [ 415 | "sha256:17d74b0d0a7b24f1c8c527b24fcf4607c56bee542ffe8e3418e50b21e514b621", 416 | "sha256:aa9a6c32054b290374f95f73bb0cae91455c58dfb84f65c8591912b8f65e6d56" 417 | ], 418 | "markers": "python_version >= '3.7'", 419 | "version": "==7.3.4" 420 | }, 421 | "jupyter-core": { 422 | "hashes": [ 423 | "sha256:a6de44b16b7b31d7271130c71a6792c4040f077011961138afed5e5e73181aec", 424 | "sha256:e7f5212177af7ab34179690140f188aa9bf3d322d8155ed972cbded19f55b6f3" 425 | ], 426 | "markers": "python_version >= '3.7'", 427 | "version": "==4.10.0" 428 | }, 429 | "jupyterlab-pygments": { 430 | "hashes": [ 431 | "sha256:2405800db07c9f770863bcf8049a529c3dd4d3e28536638bd7c1c01d2748309f", 432 | "sha256:7405d7fde60819d905a9fa8ce89e4cd830e318cdad22a0030f7a901da705585d" 433 | ], 434 | "markers": "python_version >= '3.7'", 435 | "version": "==0.2.2" 436 | }, 437 | "jupyterlab-widgets": { 438 | "hashes": [ 439 | "sha256:c2a9bd3789f120f64d73268c066ed3b000c56bc1dda217be5cdc43e7b4ebad3f", 440 | "sha256:d5f41bc1713795385f718d44dcba47e1e1473c6289f28a95aa6b2c0782ee372a" 441 | ], 442 | "markers": "python_version >= '3.6'", 443 | "version": "==1.1.0" 444 | }, 445 | "kiwisolver": { 446 | "hashes": [ 447 | "sha256:0b7f50a1a25361da3440f07c58cd1d79957c2244209e4f166990e770256b6b0b", 448 | "sha256:0c380bb5ae20d829c1a5473cfcae64267b73aaa4060adc091f6df1743784aae0", 449 | "sha256:0d98dca86f77b851350c250f0149aa5852b36572514d20feeadd3c6b1efe38d0", 450 | "sha256:0e45e780a74416ef2f173189ef4387e44b5494f45e290bcb1f03735faa6779bf", 451 | "sha256:0e8afdf533b613122e4bbaf3c1e42c2a5e9e2d1dd3a0a017749a7658757cb377", 452 | "sha256:1008346a7741620ab9cc6c96e8ad9b46f7a74ce839dbb8805ddf6b119d5fc6c2", 453 | "sha256:1d1078ba770d6165abed3d9a1be1f9e79b61515de1dd00d942fa53bba79f01ae", 454 | "sha256:1dcade8f6fe12a2bb4efe2cbe22116556e3b6899728d3b2a0d3b367db323eacc", 455 | "sha256:240009fdf4fa87844f805e23f48995537a8cb8f8c361e35fda6b5ac97fcb906f", 456 | "sha256:240c2d51d098395c012ddbcb9bd7b3ba5de412a1d11840698859f51d0e643c4f", 457 | "sha256:262c248c60f22c2b547683ad521e8a3db5909c71f679b93876921549107a0c24", 458 | "sha256:2e6cda72db409eefad6b021e8a4f964965a629f577812afc7860c69df7bdb84a", 459 | "sha256:3c032c41ae4c3a321b43a3650e6ecc7406b99ff3e5279f24c9b310f41bc98479", 460 | "sha256:42f6ef9b640deb6f7d438e0a371aedd8bef6ddfde30683491b2e6f568b4e884e", 461 | "sha256:484f2a5f0307bc944bc79db235f41048bae4106ffa764168a068d88b644b305d", 462 | "sha256:69b2d6c12f2ad5f55104a36a356192cfb680c049fe5e7c1f6620fc37f119cdc2", 463 | "sha256:6e395ece147f0692ca7cdb05a028d31b83b72c369f7b4a2c1798f4b96af1e3d8", 464 | "sha256:6ece2e12e4b57bc5646b354f436416cd2a6f090c1dadcd92b0ca4542190d7190", 465 | "sha256:71469b5845b9876b8d3d252e201bef6f47bf7456804d2fbe9a1d6e19e78a1e65", 466 | "sha256:7f606d91b8a8816be476513a77fd30abe66227039bd6f8b406c348cb0247dcc9", 467 | "sha256:7f88c4b8e449908eeddb3bbd4242bd4dc2c7a15a7aa44bb33df893203f02dc2d", 468 | "sha256:81237957b15469ea9151ec8ca08ce05656090ffabc476a752ef5ad7e2644c526", 469 | "sha256:89b57c2984f4464840e4b768affeff6b6809c6150d1166938ade3e22fbe22db8", 470 | "sha256:8a830a03970c462d1a2311c90e05679da56d3bd8e78a4ba9985cb78ef7836c9f", 471 | "sha256:8ae5a071185f1a93777c79a9a1e67ac46544d4607f18d07131eece08d415083a", 472 | "sha256:8b6086aa6936865962b2cee0e7aaecf01ab6778ce099288354a7229b4d9f1408", 473 | "sha256:8ec2e55bf31b43aabe32089125dca3b46fdfe9f50afbf0756ae11e14c97b80ca", 474 | "sha256:8ff3033e43e7ca1389ee59fb7ecb8303abb8713c008a1da49b00869e92e3dd7c", 475 | "sha256:91eb4916271655dfe3a952249cb37a5c00b6ba68b4417ee15af9ba549b5ba61d", 476 | "sha256:9d2bb56309fb75a811d81ed55fbe2208aa77a3a09ff5f546ca95e7bb5fac6eff", 477 | "sha256:a4e8f072db1d6fb7a7cc05a6dbef8442c93001f4bb604f1081d8c2db3ca97159", 478 | "sha256:b1605c7c38cc6a85212dfd6a641f3905a33412e49f7c003f35f9ac6d71f67720", 479 | "sha256:b3e251e5c38ac623c5d786adb21477f018712f8c6fa54781bd38aa1c60b60fc2", 480 | "sha256:b978afdb913ca953cf128d57181da2e8798e8b6153be866ae2a9c446c6162f40", 481 | "sha256:be9a650890fb60393e60aacb65878c4a38bb334720aa5ecb1c13d0dac54dd73b", 482 | "sha256:c222f91a45da9e01a9bc4f760727ae49050f8e8345c4ff6525495f7a164c8973", 483 | "sha256:c839bf28e45d7ddad4ae8f986928dbf5a6d42ff79760d54ec8ada8fb263e097c", 484 | "sha256:cbb5eb4a2ea1ffec26268d49766cafa8f957fe5c1b41ad00733763fae77f9436", 485 | "sha256:e348f1904a4fab4153407f7ccc27e43b2a139752e8acf12e6640ba683093dd96", 486 | "sha256:e677cc3626287f343de751e11b1e8a5b915a6ac897e8aecdbc996cd34de753a0", 487 | "sha256:f74f2a13af201559e3d32b9ddfc303c94ae63d63d7f4326d06ce6fe67e7a8255", 488 | "sha256:fa4d97d7d2b2c082e67907c0b8d9f31b85aa5d3ba0d33096b7116f03f8061261", 489 | "sha256:ffbdb9a96c536f0405895b5e21ee39ec579cb0ed97bdbd169ae2b55f41d73219" 490 | ], 491 | "markers": "python_version >= '3.7'", 492 | "version": "==1.4.2" 493 | }, 494 | "markupsafe": { 495 | "hashes": [ 496 | "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003", 497 | "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88", 498 | "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5", 499 | "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7", 500 | "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a", 501 | "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603", 502 | "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1", 503 | "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135", 504 | "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247", 505 | "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6", 506 | "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601", 507 | "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77", 508 | "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02", 509 | "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e", 510 | "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63", 511 | "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f", 512 | "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980", 513 | "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b", 514 | "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812", 515 | "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff", 516 | "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96", 517 | "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1", 518 | "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925", 519 | "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a", 520 | "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6", 521 | "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e", 522 | "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f", 523 | "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4", 524 | "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f", 525 | "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3", 526 | "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c", 527 | "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a", 528 | "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417", 529 | "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a", 530 | "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a", 531 | "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37", 532 | "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452", 533 | "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933", 534 | "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a", 535 | "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7" 536 | ], 537 | "markers": "python_version >= '3.7'", 538 | "version": "==2.1.1" 539 | }, 540 | "matplotlib": { 541 | "hashes": [ 542 | "sha256:03bbb3f5f78836855e127b5dab228d99551ad0642918ccbf3067fcd52ac7ac5e", 543 | "sha256:24173c23d1bcbaed5bf47b8785d27933a1ac26a5d772200a0f3e0e38f471b001", 544 | "sha256:2a0967d4156adbd0d46db06bc1a877f0370bce28d10206a5071f9ecd6dc60b79", 545 | "sha256:2e8bda1088b941ead50caabd682601bece983cadb2283cafff56e8fcddbf7d7f", 546 | "sha256:31fbc2af27ebb820763f077ec7adc79b5a031c2f3f7af446bd7909674cd59460", 547 | "sha256:364e6bca34edc10a96aa3b1d7cd76eb2eea19a4097198c1b19e89bee47ed5781", 548 | "sha256:3d8e129af95b156b41cb3be0d9a7512cc6d73e2b2109f82108f566dbabdbf377", 549 | "sha256:44c6436868186564450df8fd2fc20ed9daaef5caad699aa04069e87099f9b5a8", 550 | "sha256:48cf850ce14fa18067f2d9e0d646763681948487a8080ec0af2686468b4607a2", 551 | "sha256:49a5938ed6ef9dda560f26ea930a2baae11ea99e1c2080c8714341ecfda72a89", 552 | "sha256:4a05f2b37222319753a5d43c0a4fd97ed4ff15ab502113e3f2625c26728040cf", 553 | "sha256:4a44cdfdb9d1b2f18b1e7d315eb3843abb097869cd1ef89cfce6a488cd1b5182", 554 | "sha256:4fa28ca76ac5c2b2d54bc058b3dad8e22ee85d26d1ee1b116a6fd4d2277b6a04", 555 | "sha256:5844cea45d804174bf0fac219b4ab50774e504bef477fc10f8f730ce2d623441", 556 | "sha256:5a32ea6e12e80dedaca2d4795d9ed40f97bfa56e6011e14f31502fdd528b9c89", 557 | "sha256:6c623b355d605a81c661546af7f24414165a8a2022cddbe7380a31a4170fa2e9", 558 | "sha256:751d3815b555dcd6187ad35b21736dc12ce6925fc3fa363bbc6dc0f86f16484f", 559 | "sha256:75c406c527a3aa07638689586343f4b344fcc7ab1f79c396699eb550cd2b91f7", 560 | "sha256:77157be0fc4469cbfb901270c205e7d8adb3607af23cef8bd11419600647ceed", 561 | "sha256:7d7705022df2c42bb02937a2a824f4ec3cca915700dd80dc23916af47ff05f1a", 562 | "sha256:7f409716119fa39b03da3d9602bd9b41142fab7a0568758cd136cd80b1bf36c8", 563 | "sha256:9480842d5aadb6e754f0b8f4ebeb73065ac8be1855baa93cd082e46e770591e9", 564 | "sha256:9776e1a10636ee5f06ca8efe0122c6de57ffe7e8c843e0fb6e001e9d9256ec95", 565 | "sha256:a91426ae910819383d337ba0dc7971c7cefdaa38599868476d94389a329e599b", 566 | "sha256:b4fedaa5a9aa9ce14001541812849ed1713112651295fdddd640ea6620e6cf98", 567 | "sha256:b6c63cd01cad0ea8704f1fd586e9dc5777ccedcd42f63cbbaa3eae8dd41172a1", 568 | "sha256:b8d3f4e71e26307e8c120b72c16671d70c5cd08ae412355c11254aa8254fb87f", 569 | "sha256:c4b82c2ae6d305fcbeb0eb9c93df2602ebd2f174f6e8c8a5d92f9445baa0c1d3", 570 | "sha256:c772264631e5ae61f0bd41313bbe48e1b9bcc95b974033e1118c9caa1a84d5c6", 571 | "sha256:c87973ddec10812bddc6c286b88fdd654a666080fbe846a1f7a3b4ba7b11ab78", 572 | "sha256:e2b696699386766ef171a259d72b203a3c75d99d03ec383b97fc2054f52e15cf", 573 | "sha256:ea75df8e567743207e2b479ba3d8843537be1c146d4b1e3e395319a4e1a77fe9", 574 | "sha256:ebc27ad11df3c1661f4677a7762e57a8a91dd41b466c3605e90717c9a5f90c82", 575 | "sha256:ee0b8e586ac07f83bb2950717e66cb305e2859baf6f00a9c39cc576e0ce9629c", 576 | "sha256:ee175a571e692fc8ae8e41ac353c0e07259113f4cb063b0ec769eff9717e84bb" 577 | ], 578 | "index": "pypi", 579 | "version": "==3.5.2" 580 | }, 581 | "matplotlib-inline": { 582 | "hashes": [ 583 | "sha256:a04bfba22e0d1395479f866853ec1ee28eea1485c1d69a6faf00dc3e24ff34ee", 584 | "sha256:aed605ba3b72462d64d475a21a9296f400a19c4f74a31b59103d2a99ffd5aa5c" 585 | ], 586 | "markers": "python_version >= '3.5'", 587 | "version": "==0.1.3" 588 | }, 589 | "millify": { 590 | "hashes": [ 591 | "sha256:619defdc98b6d23f941b5ce4aaf4bf87a0e0f64cd0446ffa299be94486597f1a" 592 | ], 593 | "index": "pypi", 594 | "version": "==0.1.1" 595 | }, 596 | "mistune": { 597 | "hashes": [ 598 | "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e", 599 | "sha256:88a1051873018da288eee8538d476dffe1262495144b33ecb586c4ab266bb8d4" 600 | ], 601 | "version": "==0.8.4" 602 | }, 603 | "nbclient": { 604 | "hashes": [ 605 | "sha256:cdef7757cead1735d2c70cc66095b072dced8a1e6d1c7639ef90cd3e04a11f2e", 606 | "sha256:f251bba200a2b401a061dfd700a7a70b5772f664fb49d4a2d3e5536ec0e98c76" 607 | ], 608 | "markers": "python_version >= '3.7'", 609 | "version": "==0.6.4" 610 | }, 611 | "nbconvert": { 612 | "hashes": [ 613 | "sha256:223e46e27abe8596b8aed54301fadbba433b7ffea8196a68fd7b1ff509eee99d", 614 | "sha256:c56dd0b8978a1811a5654f74c727ff16ca87dd5a43abd435a1c49b840fcd8360" 615 | ], 616 | "markers": "python_version >= '3.7'", 617 | "version": "==6.5.0" 618 | }, 619 | "nbformat": { 620 | "hashes": [ 621 | "sha256:0d6072aaec95dddc39735c144ee8bbc6589c383fb462e4058abc855348152dad", 622 | "sha256:44ba5ca6acb80c5d5a500f1e5b83ede8cbe364d5a495c4c8cf60aaf1ba656501" 623 | ], 624 | "markers": "python_version >= '3.7'", 625 | "version": "==5.4.0" 626 | }, 627 | "nest-asyncio": { 628 | "hashes": [ 629 | "sha256:b98e3ec1b246135e4642eceffa5a6c23a3ab12c82ff816a92c612d68205813b2", 630 | "sha256:e442291cd942698be619823a17a86a5759eabe1f8613084790de189fe9e16d65" 631 | ], 632 | "markers": "python_version >= '3.5'", 633 | "version": "==1.5.5" 634 | }, 635 | "notebook": { 636 | "hashes": [ 637 | "sha256:6268c9ec9048cff7a45405c990c29ac9ca40b0bc3ec29263d218c5e01f2b4e86", 638 | "sha256:8c07a3bb7640e371f8a609bdbb2366a1976c6a2589da8ef917f761a61e3ad8b1" 639 | ], 640 | "markers": "python_version >= '3.7'", 641 | "version": "==6.4.12" 642 | }, 643 | "numpy": { 644 | "hashes": [ 645 | "sha256:0791fbd1e43bf74b3502133207e378901272f3c156c4df4954cad833b1380207", 646 | "sha256:1ce7ab2053e36c0a71e7a13a7475bd3b1f54750b4b433adc96313e127b870887", 647 | "sha256:2d487e06ecbf1dc2f18e7efce82ded4f705f4bd0cd02677ffccfb39e5c284c7e", 648 | "sha256:37431a77ceb9307c28382c9773da9f306435135fae6b80b62a11c53cfedd8802", 649 | "sha256:3e1ffa4748168e1cc8d3cde93f006fe92b5421396221a02f2274aab6ac83b077", 650 | "sha256:425b390e4619f58d8526b3dcf656dde069133ae5c240229821f01b5f44ea07af", 651 | "sha256:43a8ca7391b626b4c4fe20aefe79fec683279e31e7c79716863b4b25021e0e74", 652 | "sha256:4c6036521f11a731ce0648f10c18ae66d7143865f19f7299943c985cdc95afb5", 653 | "sha256:59d55e634968b8f77d3fd674a3cf0b96e85147cd6556ec64ade018f27e9479e1", 654 | "sha256:64f56fc53a2d18b1924abd15745e30d82a5782b2cab3429aceecc6875bd5add0", 655 | "sha256:7228ad13744f63575b3a972d7ee4fd61815b2879998e70930d4ccf9ec721dce0", 656 | "sha256:9ce7df0abeabe7fbd8ccbf343dc0db72f68549856b863ae3dd580255d009648e", 657 | "sha256:a911e317e8c826ea632205e63ed8507e0dc877dcdc49744584dfc363df9ca08c", 658 | "sha256:b89bf9b94b3d624e7bb480344e91f68c1c6c75f026ed6755955117de00917a7c", 659 | "sha256:ba9ead61dfb5d971d77b6c131a9dbee62294a932bf6a356e48c75ae684e635b3", 660 | "sha256:c1d937820db6e43bec43e8d016b9b3165dcb42892ea9f106c70fb13d430ffe72", 661 | "sha256:cc7f00008eb7d3f2489fca6f334ec19ca63e31371be28fd5dad955b16ec285bd", 662 | "sha256:d4c5d5eb2ec8da0b4f50c9a843393971f31f1d60be87e0fb0917a49133d257d6", 663 | "sha256:e96d7f3096a36c8754207ab89d4b3282ba7b49ea140e4973591852c77d09eb76", 664 | "sha256:f0725df166cf4785c0bc4cbfb320203182b1ecd30fee6e541c8752a92df6aa32", 665 | "sha256:f3eb268dbd5cfaffd9448113539e44e2dd1c5ca9ce25576f7c04a5453edc26fa", 666 | "sha256:fb7a980c81dd932381f8228a426df8aeb70d59bbcda2af075b627bbc50207cba" 667 | ], 668 | "index": "pypi", 669 | "version": "==1.22.4" 670 | }, 671 | "oscrypto": { 672 | "hashes": [ 673 | "sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085", 674 | "sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4" 675 | ], 676 | "version": "==1.3.0" 677 | }, 678 | "packaging": { 679 | "hashes": [ 680 | "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", 681 | "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" 682 | ], 683 | "markers": "python_version >= '3.6'", 684 | "version": "==21.3" 685 | }, 686 | "pandas": { 687 | "hashes": [ 688 | "sha256:0010771bd9223f7afe5f051eb47c4a49534345dfa144f2f5470b27189a4dd3b5", 689 | "sha256:061609334a8182ab500a90fe66d46f6f387de62d3a9cb9aa7e62e3146c712167", 690 | "sha256:09d8be7dd9e1c4c98224c4dfe8abd60d145d934e9fc1f5f411266308ae683e6a", 691 | "sha256:295872bf1a09758aba199992c3ecde455f01caf32266d50abc1a073e828a7b9d", 692 | "sha256:3228198333dd13c90b6434ddf61aa6d57deaca98cf7b654f4ad68a2db84f8cfe", 693 | "sha256:385c52e85aaa8ea6a4c600a9b2821181a51f8be0aee3af6f2dcb41dafc4fc1d0", 694 | "sha256:51649ef604a945f781105a6d2ecf88db7da0f4868ac5d45c51cb66081c4d9c73", 695 | "sha256:5586cc95692564b441f4747c47c8a9746792e87b40a4680a2feb7794defb1ce3", 696 | "sha256:5a206afa84ed20e07603f50d22b5f0db3fb556486d8c2462d8bc364831a4b417", 697 | "sha256:5b79af3a69e5175c6fa7b4e046b21a646c8b74e92c6581a9d825687d92071b51", 698 | "sha256:5c54ea4ef3823108cd4ec7fb27ccba4c3a775e0f83e39c5e17f5094cb17748bc", 699 | "sha256:8c5bf555b6b0075294b73965adaafb39cf71c312e38c5935c93d78f41c19828a", 700 | "sha256:92bc1fc585f1463ca827b45535957815b7deb218c549b7c18402c322c7549a12", 701 | "sha256:95c1e422ced0199cf4a34385ff124b69412c4bc912011ce895582bee620dfcaa", 702 | "sha256:b8134651258bce418cb79c71adeff0a44090c98d955f6953168ba16cc285d9f7", 703 | "sha256:be67c782c4f1b1f24c2f16a157e12c2693fd510f8df18e3287c77f33d124ed07", 704 | "sha256:c072c7f06b9242c855ed8021ff970c0e8f8b10b35e2640c657d2a541c5950f59", 705 | "sha256:d0d4f13e4be7ce89d7057a786023c461dd9370040bdb5efa0a7fe76b556867a0", 706 | "sha256:df82739e00bb6daf4bba4479a40f38c718b598a84654cbd8bb498fd6b0aa8c16", 707 | "sha256:f549097993744ff8c41b5e8f2f0d3cbfaabe89b4ae32c8c08ead6cc535b80139", 708 | "sha256:ff08a14ef21d94cdf18eef7c569d66f2e24e0bc89350bcd7d243dd804e3b5eb2" 709 | ], 710 | "markers": "python_version >= '3.8'", 711 | "version": "==1.4.2" 712 | }, 713 | "pandocfilters": { 714 | "hashes": [ 715 | "sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38", 716 | "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f" 717 | ], 718 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", 719 | "version": "==1.5.0" 720 | }, 721 | "parso": { 722 | "hashes": [ 723 | "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0", 724 | "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75" 725 | ], 726 | "markers": "python_version >= '3.6'", 727 | "version": "==0.8.3" 728 | }, 729 | "pexpect": { 730 | "hashes": [ 731 | "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937", 732 | "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c" 733 | ], 734 | "markers": "sys_platform != 'win32'", 735 | "version": "==4.8.0" 736 | }, 737 | "pickleshare": { 738 | "hashes": [ 739 | "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca", 740 | "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56" 741 | ], 742 | "version": "==0.7.5" 743 | }, 744 | "pillow": { 745 | "hashes": [ 746 | "sha256:088df396b047477dd1bbc7de6e22f58400dae2f21310d9e2ec2933b2ef7dfa4f", 747 | "sha256:09e67ef6e430f90caa093528bd758b0616f8165e57ed8d8ce014ae32df6a831d", 748 | "sha256:0b4d5ad2cd3a1f0d1df882d926b37dbb2ab6c823ae21d041b46910c8f8cd844b", 749 | "sha256:0b525a356680022b0af53385944026d3486fc8c013638cf9900eb87c866afb4c", 750 | "sha256:1d4331aeb12f6b3791911a6da82de72257a99ad99726ed6b63f481c0184b6fb9", 751 | "sha256:20d514c989fa28e73a5adbddd7a171afa5824710d0ab06d4e1234195d2a2e546", 752 | "sha256:2b291cab8a888658d72b575a03e340509b6b050b62db1f5539dd5cd18fd50578", 753 | "sha256:3f6c1716c473ebd1649663bf3b42702d0d53e27af8b64642be0dd3598c761fb1", 754 | "sha256:42dfefbef90eb67c10c45a73a9bc1599d4dac920f7dfcbf4ec6b80cb620757fe", 755 | "sha256:488f3383cf5159907d48d32957ac6f9ea85ccdcc296c14eca1a4e396ecc32098", 756 | "sha256:4d45dbe4b21a9679c3e8b3f7f4f42a45a7d3ddff8a4a16109dff0e1da30a35b2", 757 | "sha256:53c27bd452e0f1bc4bfed07ceb235663a1df7c74df08e37fd6b03eb89454946a", 758 | "sha256:55e74faf8359ddda43fee01bffbc5bd99d96ea508d8a08c527099e84eb708f45", 759 | "sha256:59789a7d06c742e9d13b883d5e3569188c16acb02eeed2510fd3bfdbc1bd1530", 760 | "sha256:5b650dbbc0969a4e226d98a0b440c2f07a850896aed9266b6fedc0f7e7834108", 761 | "sha256:66daa16952d5bf0c9d5389c5e9df562922a59bd16d77e2a276e575d32e38afd1", 762 | "sha256:6e760cf01259a1c0a50f3c845f9cad1af30577fd8b670339b1659c6d0e7a41dd", 763 | "sha256:7502539939b53d7565f3d11d87c78e7ec900d3c72945d4ee0e2f250d598309a0", 764 | "sha256:769a7f131a2f43752455cc72f9f7a093c3ff3856bf976c5fb53a59d0ccc704f6", 765 | "sha256:7c150dbbb4a94ea4825d1e5f2c5501af7141ea95825fadd7829f9b11c97aaf6c", 766 | "sha256:8844217cdf66eabe39567118f229e275f0727e9195635a15e0e4b9227458daaf", 767 | "sha256:8a66fe50386162df2da701b3722781cbe90ce043e7d53c1fd6bd801bca6b48d4", 768 | "sha256:9370d6744d379f2de5d7fa95cdbd3a4d92f0b0ef29609b4b1687f16bc197063d", 769 | "sha256:937a54e5694684f74dcbf6e24cc453bfc5b33940216ddd8f4cd8f0f79167f765", 770 | "sha256:9c857532c719fb30fafabd2371ce9b7031812ff3889d75273827633bca0c4602", 771 | "sha256:a4165205a13b16a29e1ac57efeee6be2dfd5b5408122d59ef2145bc3239fa340", 772 | "sha256:b3fe2ff1e1715d4475d7e2c3e8dabd7c025f4410f79513b4ff2de3d51ce0fa9c", 773 | "sha256:b6617221ff08fbd3b7a811950b5c3f9367f6e941b86259843eab77c8e3d2b56b", 774 | "sha256:b761727ed7d593e49671d1827044b942dd2f4caae6e51bab144d4accf8244a84", 775 | "sha256:baf3be0b9446a4083cc0c5bb9f9c964034be5374b5bc09757be89f5d2fa247b8", 776 | "sha256:c17770a62a71718a74b7548098a74cd6880be16bcfff5f937f900ead90ca8e92", 777 | "sha256:c67db410508b9de9c4694c57ed754b65a460e4812126e87f5052ecf23a011a54", 778 | "sha256:d78ca526a559fb84faaaf84da2dd4addef5edb109db8b81677c0bb1aad342601", 779 | "sha256:e9ed59d1b6ee837f4515b9584f3d26cf0388b742a11ecdae0d9237a94505d03a", 780 | "sha256:f054b020c4d7e9786ae0404278ea318768eb123403b18453e28e47cdb7a0a4bf", 781 | "sha256:f372d0f08eff1475ef426344efe42493f71f377ec52237bf153c5713de987251", 782 | "sha256:f3f6a6034140e9e17e9abc175fc7a266a6e63652028e157750bd98e804a8ed9a", 783 | "sha256:ffde4c6fabb52891d81606411cbfaf77756e3b561b566efd270b3ed3791fde4e" 784 | ], 785 | "markers": "python_version >= '3.7'", 786 | "version": "==9.1.1" 787 | }, 788 | "plost": { 789 | "editable": true, 790 | "git": "https://github.com/jrieke/plost", 791 | "ref": "7cdd932077c9b56f2e6b3c87e8095f76679bf30d" 792 | }, 793 | "prometheus-client": { 794 | "hashes": [ 795 | "sha256:522fded625282822a89e2773452f42df14b5a8e84a86433e3f8a189c1d54dc01", 796 | "sha256:5459c427624961076277fdc6dc50540e2bacb98eebde99886e59ec55ed92093a" 797 | ], 798 | "markers": "python_version >= '3.6'", 799 | "version": "==0.14.1" 800 | }, 801 | "prompt-toolkit": { 802 | "hashes": [ 803 | "sha256:62291dad495e665fca0bda814e342c69952086afb0f4094d0893d357e5c78752", 804 | "sha256:bd640f60e8cecd74f0dc249713d433ace2ddc62b65ee07f96d358e0b152b6ea7" 805 | ], 806 | "markers": "python_full_version >= '3.6.2'", 807 | "version": "==3.0.29" 808 | }, 809 | "protobuf": { 810 | "hashes": [ 811 | "sha256:06059eb6953ff01e56a25cd02cca1a9649a75a7e65397b5b9b4e929ed71d10cf", 812 | "sha256:097c5d8a9808302fb0da7e20edf0b8d4703274d140fd25c5edabddcde43e081f", 813 | "sha256:284f86a6207c897542d7e956eb243a36bb8f9564c1742b253462386e96c6b78f", 814 | "sha256:32ca378605b41fd180dfe4e14d3226386d8d1b002ab31c969c366549e66a2bb7", 815 | "sha256:3cc797c9d15d7689ed507b165cd05913acb992d78b379f6014e013f9ecb20996", 816 | "sha256:62f1b5c4cd6c5402b4e2d63804ba49a327e0c386c99b1675c8a0fefda23b2067", 817 | "sha256:69ccfdf3657ba59569c64295b7d51325f91af586f8d5793b734260dfe2e94e2c", 818 | "sha256:6f50601512a3d23625d8a85b1638d914a0970f17920ff39cec63aaef80a93fb7", 819 | "sha256:7403941f6d0992d40161aa8bb23e12575637008a5a02283a930addc0508982f9", 820 | "sha256:755f3aee41354ae395e104d62119cb223339a8f3276a0cd009ffabfcdd46bb0c", 821 | "sha256:77053d28427a29987ca9caf7b72ccafee011257561259faba8dd308fda9a8739", 822 | "sha256:7e371f10abe57cee5021797126c93479f59fccc9693dafd6bd5633ab67808a91", 823 | "sha256:9016d01c91e8e625141d24ec1b20fed584703e527d28512aa8c8707f105a683c", 824 | "sha256:9be73ad47579abc26c12024239d3540e6b765182a91dbc88e23658ab71767153", 825 | "sha256:adc31566d027f45efe3f44eeb5b1f329da43891634d61c75a5944e9be6dd42c9", 826 | "sha256:adfc6cf69c7f8c50fd24c793964eef18f0ac321315439d94945820612849c388", 827 | "sha256:af0ebadc74e281a517141daad9d0f2c5d93ab78e9d455113719a45a49da9db4e", 828 | "sha256:cb29edb9eab15742d791e1025dd7b6a8f6fcb53802ad2f6e3adcb102051063ab", 829 | "sha256:cd68be2559e2a3b84f517fb029ee611546f7812b1fdd0aa2ecc9bc6ec0e4fdde", 830 | "sha256:cdee09140e1cd184ba9324ec1df410e7147242b94b5f8b0c64fc89e38a8ba531", 831 | "sha256:db977c4ca738dd9ce508557d4fce0f5aebd105e158c725beec86feb1f6bc20d8", 832 | "sha256:dd5789b2948ca702c17027c84c2accb552fc30f4622a98ab5c51fcfe8c50d3e7", 833 | "sha256:e250a42f15bf9d5b09fe1b293bdba2801cd520a9f5ea2d7fb7536d4441811d20", 834 | "sha256:ff8d8fa42675249bb456f5db06c00de6c2f4c27a065955917b28c4f15978b9c3" 835 | ], 836 | "markers": "python_version >= '3.7'", 837 | "version": "==3.20.1" 838 | }, 839 | "psutil": { 840 | "hashes": [ 841 | "sha256:068935df39055bf27a29824b95c801c7a5130f118b806eee663cad28dca97685", 842 | "sha256:0904727e0b0a038830b019551cf3204dd48ef5c6868adc776e06e93d615fc5fc", 843 | "sha256:0f15a19a05f39a09327345bc279c1ba4a8cfb0172cc0d3c7f7d16c813b2e7d36", 844 | "sha256:19f36c16012ba9cfc742604df189f2f28d2720e23ff7d1e81602dbe066be9fd1", 845 | "sha256:20b27771b077dcaa0de1de3ad52d22538fe101f9946d6dc7869e6f694f079329", 846 | "sha256:28976df6c64ddd6320d281128817f32c29b539a52bdae5e192537bc338a9ec81", 847 | "sha256:29a442e25fab1f4d05e2655bb1b8ab6887981838d22effa2396d584b740194de", 848 | "sha256:3054e923204b8e9c23a55b23b6df73a8089ae1d075cb0bf711d3e9da1724ded4", 849 | "sha256:32c52611756096ae91f5d1499fe6c53b86f4a9ada147ee42db4991ba1520e574", 850 | "sha256:3a76ad658641172d9c6e593de6fe248ddde825b5866464c3b2ee26c35da9d237", 851 | "sha256:44d1826150d49ffd62035785a9e2c56afcea66e55b43b8b630d7706276e87f22", 852 | "sha256:4b6750a73a9c4a4e689490ccb862d53c7b976a2a35c4e1846d049dcc3f17d83b", 853 | "sha256:56960b9e8edcca1456f8c86a196f0c3d8e3e361320071c93378d41445ffd28b0", 854 | "sha256:57f1819b5d9e95cdfb0c881a8a5b7d542ed0b7c522d575706a80bedc848c8954", 855 | "sha256:58678bbadae12e0db55186dc58f2888839228ac9f41cc7848853539b70490021", 856 | "sha256:645bd4f7bb5b8633803e0b6746ff1628724668681a434482546887d22c7a9537", 857 | "sha256:799759d809c31aab5fe4579e50addf84565e71c1dc9f1c31258f159ff70d3f87", 858 | "sha256:79c9108d9aa7fa6fba6e668b61b82facc067a6b81517cab34d07a84aa89f3df0", 859 | "sha256:91c7ff2a40c373d0cc9121d54bc5f31c4fa09c346528e6a08d1845bce5771ffc", 860 | "sha256:9272167b5f5fbfe16945be3db475b3ce8d792386907e673a209da686176552af", 861 | "sha256:944c4b4b82dc4a1b805329c980f270f170fdc9945464223f2ec8e57563139cf4", 862 | "sha256:a6a11e48cb93a5fa606306493f439b4aa7c56cb03fc9ace7f6bfa21aaf07c453", 863 | "sha256:a8746bfe4e8f659528c5c7e9af5090c5a7d252f32b2e859c584ef7d8efb1e689", 864 | "sha256:abd9246e4cdd5b554a2ddd97c157e292ac11ef3e7af25ac56b08b455c829dca8", 865 | "sha256:b14ee12da9338f5e5b3a3ef7ca58b3cba30f5b66f7662159762932e6d0b8f680", 866 | "sha256:b88f75005586131276634027f4219d06e0561292be8bd6bc7f2f00bdabd63c4e", 867 | "sha256:c7be9d7f5b0d206f0bbc3794b8e16fb7dbc53ec9e40bbe8787c6f2d38efcf6c9", 868 | "sha256:d2d006286fbcb60f0b391741f520862e9b69f4019b4d738a2a45728c7e952f1b", 869 | "sha256:db417f0865f90bdc07fa30e1aadc69b6f4cad7f86324b02aa842034efe8d8c4d", 870 | "sha256:e7e10454cb1ab62cc6ce776e1c135a64045a11ec4c6d254d3f7689c16eb3efd2", 871 | "sha256:f65f9a46d984b8cd9b3750c2bdb419b2996895b005aefa6cbaba9a143b1ce2c5", 872 | "sha256:fea896b54f3a4ae6f790ac1d017101252c93f6fe075d0e7571543510f11d2676" 873 | ], 874 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", 875 | "version": "==5.9.1" 876 | }, 877 | "ptyprocess": { 878 | "hashes": [ 879 | "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", 880 | "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" 881 | ], 882 | "version": "==0.7.0" 883 | }, 884 | "pure-eval": { 885 | "hashes": [ 886 | "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350", 887 | "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3" 888 | ], 889 | "version": "==0.2.2" 890 | }, 891 | "pyarrow": { 892 | "hashes": [ 893 | "sha256:03a10daad957970e914920b793f6a49416699e791f4c827927fd4e4d892a5d16", 894 | "sha256:15511ce2f50343f3fd5e9f7c30e4d004da9134e9597e93e9c96c3985928cbe82", 895 | "sha256:1dd482ccb07c96188947ad94d7536ab696afde23ad172df8e18944ec79f55055", 896 | "sha256:25a5f7c7f36df520b0b7363ba9f51c3070799d4b05d587c60c0adaba57763479", 897 | "sha256:3bd201af6e01f475f02be88cf1f6ee9856ab98c11d8bbb6f58347c58cd07be00", 898 | "sha256:3fee786259d986f8c046100ced54d63b0c8c9f7cdb7d1bbe07dc69e0f928141c", 899 | "sha256:42b7982301a9ccd06e1dd4fabd2e8e5df74b93ce4c6b87b81eb9e2d86dc79871", 900 | "sha256:4a18a211ed888f1ac0b0ebcb99e2d9a3e913a481120ee9b1fe33d3fedb945d4e", 901 | "sha256:51e58778fcb8829fca37fbfaea7f208d5ce7ea89ea133dd13d8ce745278ee6f0", 902 | "sha256:541e7845ce5f27a861eb5b88ee165d931943347eec17b9ff1e308663531c9647", 903 | "sha256:65c7f4cc2be195e3db09296d31a654bb6d8786deebcab00f0e2455fd109d7456", 904 | "sha256:69b043a3fce064ebd9fbae6abc30e885680296e5bd5e6f7353e6a87966cf2ad7", 905 | "sha256:6ea2c54e6b5ecd64e8299d2abb40770fe83a718f5ddc3825ddd5cd28e352cce1", 906 | "sha256:78a6ac39cd793582998dac88ab5c1c1dd1e6503df6672f064f33a21937ec1d8d", 907 | "sha256:81b87b782a1366279411f7b235deab07c8c016e13f9af9f7c7b0ee564fedcc8f", 908 | "sha256:8392b9a1e837230090fe916415ed4c3433b2ddb1a798e3f6438303c70fbabcfc", 909 | "sha256:863be6bad6c53797129610930794a3e797cb7d41c0a30e6794a2ac0e42ce41b8", 910 | "sha256:8cd86e04a899bef43e25184f4b934584861d787cf7519851a8c031803d45c6d8", 911 | "sha256:95c7822eb37663e073da9892f3499fe28e84f3464711a3e555e0c5463fd53a19", 912 | "sha256:98c13b2e28a91b0fbf24b483df54a8d7814c074c2623ecef40dce1fa52f6539b", 913 | "sha256:ba2b7aa7efb59156b87987a06f5241932914e4d5bbb74a465306b00a6c808849", 914 | "sha256:c9c97c8e288847e091dfbcdf8ce51160e638346f51919a9e74fe038b2e8aee62", 915 | "sha256:cb06cacc19f3b426681f2f6803cc06ff481e7fe5b3a533b406bc5b2138843d4f", 916 | "sha256:ce64bc1da3109ef5ab9e4c60316945a7239c798098a631358e9ab39f6e5529e9", 917 | "sha256:d5ef4372559b191cafe7db8932801eee252bfc35e983304e7d60b6954576a071", 918 | "sha256:d6f1e1040413651819074ef5b500835c6c42e6c446532a1ddef8bc5054e8dba5", 919 | "sha256:deb400df8f19a90b662babceb6dd12daddda6bb357c216e558b207c0770c7654", 920 | "sha256:ea132067ec712d1b1116a841db1c95861508862b21eddbcafefbce8e4b96b867", 921 | "sha256:ece333706a94c1221ced8b299042f85fd88b5db802d71be70024433ddf3aecab", 922 | "sha256:edad25522ad509e534400d6ab98cf1872d30c31bc5e947712bfd57def7af15bb" 923 | ], 924 | "markers": "python_version >= '3.7'", 925 | "version": "==8.0.0" 926 | }, 927 | "pycparser": { 928 | "hashes": [ 929 | "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", 930 | "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" 931 | ], 932 | "version": "==2.21" 933 | }, 934 | "pycryptodomex": { 935 | "hashes": [ 936 | "sha256:1ca8e1b4c62038bb2da55451385246f51f412c5f5eabd64812c01766a5989b4a", 937 | "sha256:298c00ea41a81a491d5b244d295d18369e5aac4b61b77b2de5b249ca61cd6659", 938 | "sha256:2aa887683eee493e015545bd69d3d21ac8d5ad582674ec98f4af84511e353e45", 939 | "sha256:2ce76ed0081fd6ac8c74edc75b9d14eca2064173af79843c24fa62573263c1f2", 940 | "sha256:3da13c2535b7aea94cc2a6d1b1b37746814c74b6e80790daddd55ca5c120a489", 941 | "sha256:406ec8cfe0c098fadb18d597dc2ee6de4428d640c0ccafa453f3d9b2e58d29e2", 942 | "sha256:4d0db8df9ffae36f416897ad184608d9d7a8c2b46c4612c6bc759b26c073f750", 943 | "sha256:530756d2faa40af4c1f74123e1d889bd07feae45bac2fd32f259a35f7aa74151", 944 | "sha256:77931df40bb5ce5e13f4de2bfc982b2ddc0198971fbd947776c8bb5050896eb2", 945 | "sha256:797a36bd1f69df9e2798e33edb4bd04e5a30478efc08f9428c087f17f65a7045", 946 | "sha256:8085bd0ad2034352eee4d4f3e2da985c2749cb7344b939f4d95ead38c2520859", 947 | "sha256:8536bc08d130cae6dcba1ea689f2913dfd332d06113904d171f2f56da6228e89", 948 | "sha256:a4d412eba5679ede84b41dbe48b1bed8f33131ab9db06c238a235334733acc5e", 949 | "sha256:aebecde2adc4a6847094d3bd6a8a9538ef3438a5ea84ac1983fcb167db614461", 950 | "sha256:b276cc4deb4a80f9dfd47a41ebb464b1fe91efd8b1b8620cf5ccf8b824b850d6", 951 | "sha256:b5a185ae79f899b01ca49f365bdf15a45d78d9856f09b0de1a41b92afce1a07f", 952 | "sha256:c4d8977ccda886d88dc3ca789de2f1adc714df912ff3934b3d0a3f3d777deafb", 953 | "sha256:c5dd3ffa663c982d7f1be9eb494a8924f6d40e2e2f7d1d27384cfab1b2ac0662", 954 | "sha256:ca88f2f7020002638276439a01ffbb0355634907d1aa5ca91f3dc0c2e44e8f3b", 955 | "sha256:d2cce1c82a7845d7e2e8a0956c6b7ed3f1661c9acf18eb120fc71e098ab5c6fe", 956 | "sha256:d709572d64825d8d59ea112e11cc7faf6007f294e9951324b7574af4251e4de8", 957 | "sha256:da8db8374295fb532b4b0c467e66800ef17d100e4d5faa2bbbd6df35502da125", 958 | "sha256:e36c7e3b5382cd5669cf199c4a04a0279a43b2a3bdd77627e9b89778ac9ec08c", 959 | "sha256:e95a4a6c54d27a84a4624d2af8bb9ee178111604653194ca6880c98dcad92f48", 960 | "sha256:ee835def05622e0c8b1435a906491760a43d0c462f065ec9143ec4b8d79f8bff", 961 | "sha256:f75009715dcf4a3d680c2338ab19dac5498f8121173a929872950f4fb3a48fbf", 962 | "sha256:f8524b8bc89470cec7ac51734907818d3620fb1637f8f8b542d650ebec42a126" 963 | ], 964 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", 965 | "version": "==3.14.1" 966 | }, 967 | "pydeck": { 968 | "hashes": [ 969 | "sha256:7fc49b00840608068b930f9269169c7c9f3198b8b4635c934ba6d887c4e54503", 970 | "sha256:907601c99f7510e16d27d7cb62bfa145216d166a2b5c9c50cfe2b65b032ebd2e" 971 | ], 972 | "markers": "python_version >= '3.7'", 973 | "version": "==0.7.1" 974 | }, 975 | "pygments": { 976 | "hashes": [ 977 | "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb", 978 | "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519" 979 | ], 980 | "markers": "python_version >= '3.6'", 981 | "version": "==2.12.0" 982 | }, 983 | "pyjwt": { 984 | "hashes": [ 985 | "sha256:72d1d253f32dbd4f5c88eaf1fdc62f3a19f676ccbadb9dbc5d07e951b2b26daf", 986 | "sha256:d42908208c699b3b973cbeb01a969ba6a96c821eefb1c5bfe4c390c01d67abba" 987 | ], 988 | "markers": "python_version >= '3.6'", 989 | "version": "==2.4.0" 990 | }, 991 | "pympler": { 992 | "hashes": [ 993 | "sha256:993f1a3599ca3f4fcd7160c7545ad06310c9e12f70174ae7ae8d4e25f6c5d3fa", 994 | "sha256:d260dda9ae781e1eab6ea15bacb84015849833ba5555f141d2d9b7b7473b307d" 995 | ], 996 | "markers": "python_version >= '3.6'", 997 | "version": "==1.0.1" 998 | }, 999 | "pyopenssl": { 1000 | "hashes": [ 1001 | "sha256:660b1b1425aac4a1bea1d94168a85d99f0b3144c869dd4390d27629d0087f1bf", 1002 | "sha256:ea252b38c87425b64116f808355e8da644ef9b07e429398bfece610f893ee2e0" 1003 | ], 1004 | "markers": "python_version >= '3.6'", 1005 | "version": "==22.0.0" 1006 | }, 1007 | "pyparsing": { 1008 | "hashes": [ 1009 | "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", 1010 | "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc" 1011 | ], 1012 | "markers": "python_full_version >= '3.6.8'", 1013 | "version": "==3.0.9" 1014 | }, 1015 | "pyrsistent": { 1016 | "hashes": [ 1017 | "sha256:0e3e1fcc45199df76053026a51cc59ab2ea3fc7c094c6627e93b7b44cdae2c8c", 1018 | "sha256:1b34eedd6812bf4d33814fca1b66005805d3640ce53140ab8bbb1e2651b0d9bc", 1019 | "sha256:4ed6784ceac462a7d6fcb7e9b663e93b9a6fb373b7f43594f9ff68875788e01e", 1020 | "sha256:5d45866ececf4a5fff8742c25722da6d4c9e180daa7b405dc0a2a2790d668c26", 1021 | "sha256:636ce2dc235046ccd3d8c56a7ad54e99d5c1cd0ef07d9ae847306c91d11b5fec", 1022 | "sha256:6455fc599df93d1f60e1c5c4fe471499f08d190d57eca040c0ea182301321286", 1023 | "sha256:6bc66318fb7ee012071b2792024564973ecc80e9522842eb4e17743604b5e045", 1024 | "sha256:7bfe2388663fd18bd8ce7db2c91c7400bf3e1a9e8bd7d63bf7e77d39051b85ec", 1025 | "sha256:7ec335fc998faa4febe75cc5268a9eac0478b3f681602c1f27befaf2a1abe1d8", 1026 | "sha256:914474c9f1d93080338ace89cb2acee74f4f666fb0424896fcfb8d86058bf17c", 1027 | "sha256:b568f35ad53a7b07ed9b1b2bae09eb15cdd671a5ba5d2c66caee40dbf91c68ca", 1028 | "sha256:cdfd2c361b8a8e5d9499b9082b501c452ade8bbf42aef97ea04854f4a3f43b22", 1029 | "sha256:d1b96547410f76078eaf66d282ddca2e4baae8964364abb4f4dcdde855cd123a", 1030 | "sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96", 1031 | "sha256:d7a096646eab884bf8bed965bad63ea327e0d0c38989fc83c5ea7b8a87037bfc", 1032 | "sha256:df46c854f490f81210870e509818b729db4488e1f30f2a1ce1698b2295a878d1", 1033 | "sha256:e24a828f57e0c337c8d8bb9f6b12f09dfdf0273da25fda9e314f0b684b415a07", 1034 | "sha256:e4f3149fd5eb9b285d6bfb54d2e5173f6a116fe19172686797c056672689daf6", 1035 | "sha256:e92a52c166426efbe0d1ec1332ee9119b6d32fc1f0bbfd55d5c1088070e7fc1b", 1036 | "sha256:f87cc2863ef33c709e237d4b5f4502a62a00fab450c9e020892e8e2ede5847f5", 1037 | "sha256:fd8da6d0124efa2f67d86fa70c851022f87c98e205f0594e1fae044e7119a5a6" 1038 | ], 1039 | "markers": "python_version >= '3.7'", 1040 | "version": "==0.18.1" 1041 | }, 1042 | "python-dateutil": { 1043 | "hashes": [ 1044 | "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", 1045 | "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" 1046 | ], 1047 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", 1048 | "version": "==2.8.2" 1049 | }, 1050 | "pytz": { 1051 | "hashes": [ 1052 | "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7", 1053 | "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c" 1054 | ], 1055 | "version": "==2022.1" 1056 | }, 1057 | "pytz-deprecation-shim": { 1058 | "hashes": [ 1059 | "sha256:8314c9692a636c8eb3bda879b9f119e350e93223ae83e70e80c31675a0fdc1a6", 1060 | "sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d" 1061 | ], 1062 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", 1063 | "version": "==0.1.0.post0" 1064 | }, 1065 | "pyzmq": { 1066 | "hashes": [ 1067 | "sha256:057176dd3f5ccf5aad4abd662d76b6a39bbf799baaf2f39cd4fdaf2eab326e43", 1068 | "sha256:05ec90a8da618f2398f9d1aa20b18a9ef332992c6ac23e8c866099faad6ef0d6", 1069 | "sha256:154de02b15422af28b53d29a02de72121ba503634955017255573fc1f995143d", 1070 | "sha256:16b832adb5d8716f46051da5533c480250bf126984ce86804db6137a3a7f931b", 1071 | "sha256:1df26aa854bdd3a8341bf199064dd6aa6e240f2eaa3c9fa8d217e5d8b868c73e", 1072 | "sha256:28f9164fb2658b7b414fa0894c75b1a9c61375774cdc1bdb7298beb042a2cd87", 1073 | "sha256:2951c29b8649f3672af9dca8ff61d86310d3664d9629788b1c66422fb13b1239", 1074 | "sha256:2b08774057ae7ce8a2eb4e7d54db05358234440706ce43a85814500c5d7bd22e", 1075 | "sha256:2e2ac40f7a91c740ec68d6db07ae19ea9259c959333c68bee56ab2c799a67d66", 1076 | "sha256:312e56799410c34797417a4060a8bd37d4db1f06d1ec0c54f7c8fd81e0d90376", 1077 | "sha256:38f778a74e3889392e949326cfd0e9b2eb37dcbb2980d98fad2c51703d523db2", 1078 | "sha256:3955dd5bbbe02f454655296ee36a66c334c7102a29b8458223d168c0380edfd5", 1079 | "sha256:425ba851a6f9892bde1da2024d82e2fe6796bd77e3391fb96665c50fe9d4c6a5", 1080 | "sha256:48bbc2db041ab28eeee4a3e8ada0ed336640946dd5a8e53dbd3805f9dbdcf0dc", 1081 | "sha256:4fbcd657cda75574fd1315a4c44bd322bc2e219039fb09f146bbe6f8aef039e9", 1082 | "sha256:523ba7fd4d8fe75ad09c1e574a648892b75a97d0cfc8005727681053ac19555b", 1083 | "sha256:53b2c1326c2e484d450932d2be739f064b7cb572faabec38386098a28516a529", 1084 | "sha256:540d7146c3cdc9bbffab039ea067f494eba24d1abe5bd33eb9f963c01e3305d4", 1085 | "sha256:563d4281c4dbdf647d93114420151d33f895afc4c46b7115a67a0aa5347e6624", 1086 | "sha256:67a049bcf967a39993858beed873ed3405536019820922d4efacfe35ab3da51a", 1087 | "sha256:67ec63ae3c9c1fa2e077fcb42e77035e2121a04f987464bdf9945a28535d30ad", 1088 | "sha256:68e22c5d3be451e87d47f956b397a7823bfbde2176341bc902fba30f96831d7e", 1089 | "sha256:6ab4b6108e69f63c917cd7ef7217c5727955b1ac90600e44a13ed5312019a014", 1090 | "sha256:6bd7f18bd4cf51ea8d7e54825902cf36f9d2f35cc51ef618373988d5398b8dd0", 1091 | "sha256:6cd53e861bccc0bdc4620f68fb4a91d5bcfe9f4213cf8e200fa498044d33a6dc", 1092 | "sha256:6d346e551fa64b89d57a4ac74b9bc66703413f02f50093e089e861999ec5cccc", 1093 | "sha256:6ff8708fabc9f9bc2949f457d39b4088c9656c4c9ac15fbbbbaafce8f6d07833", 1094 | "sha256:7626e8384275a7dea6f3d1f749fb5e00299042e9c895fc3dbe24cb154909c242", 1095 | "sha256:7e7346b2b33dcd4a2171dd8a9870ae283eec8f6231dcbcf237a0f41e74751a50", 1096 | "sha256:81623c67cb71b93b5f7e06c9107f3781738ae86866db830c950223d87af2a235", 1097 | "sha256:83f1c76068faf62c32a36dd62dc4db642c2027bbbd960f8f6345b59e9d4dc472", 1098 | "sha256:8679bb1dd723ecbea03b1f96c98972815775fd8ec756c440a14f289c436c472e", 1099 | "sha256:86fb683cb9a9c0bb7476988b7957393ecdd22777d87d804442c66e62c99197f9", 1100 | "sha256:8757c62f7960cd26122f7aaaf86eda1e016fa85734c3777b8054dd334d7dea4d", 1101 | "sha256:894be7d17228e7328cc188096c0162697211ec91761f6812fff12790cbe11c66", 1102 | "sha256:8a0f240bf43c29be1bd82d77e602a61c798e9de02e5f8bb7bb414cb814f43236", 1103 | "sha256:8c3abf7eab5b76ae162c4fbb16d514a947fc57fd995b64e5ea8ef8ba3b888a69", 1104 | "sha256:93332c6972e4c91522c4810e907f3aea067424338071161b39cacded022559df", 1105 | "sha256:97d6c676dc97d593625d9fc48154f2ffeabb619a1e6fe8d2a5b53f97e3e9bdee", 1106 | "sha256:99dd85f0ca1db8d17a01a25c2bbb7784d25a2d39497c6beddbe96bff74194e04", 1107 | "sha256:9c7fb691fb07ec7ab99fd173bb0e7e0248d31bf83d484a87b917a342f63812c9", 1108 | "sha256:b3bc3cf200aab74f3d758586ac50295214eda496ac6a6636e0c881c5958d9123", 1109 | "sha256:bba54f97578943f48f621b4a7afb8eb022370da26a88b88ccc9fee9f3ef7ce45", 1110 | "sha256:bd2a13a0f8367e50347cbac87ae230ae1953935443240238f956bf10668bead6", 1111 | "sha256:cbc1184349ca6e5112898aa7fc3efa1b1bbae24ab1edc774cfd09cbfd3b091d7", 1112 | "sha256:cd82cca9c489e441574804dbda2dd8e114cf3be7935b03de11dade2c9478aea6", 1113 | "sha256:ce8ba5ed8b0a7a203922d61cff45ee6001a41a9359f04f00d055a4e988755569", 1114 | "sha256:cfee22e072a382b92ee0709dbb8203dabd52d54258051e770d9d2a81b162530b", 1115 | "sha256:d977df6f7c4109ed1d96ffb6795f6af77114be606ae4556efbfc9cac725db65d", 1116 | "sha256:da72a384a1d7e87490ca71182f3ab469ed21d847adc16b70c34faac5a3b12801", 1117 | "sha256:ddf4ad1d651e6c9234945061e1a31fe27a4be0dea21c498b87b186fadf8f5919", 1118 | "sha256:eb0ae5dfda83bbce660179d7b41c1c38fd833a54d2e6d9b258c644f3b75ef94d", 1119 | "sha256:f4c7d370badc60ac94a554bc571a46d03e39d8aacfba8006b334512e184aed59", 1120 | "sha256:f6c378b435a26fda8996579c0e324b108d2ca0d01b4661503a75634e5155559f", 1121 | "sha256:f6c9d30888503f2f5f87d6d41f016301352dd98da4a861bd10663c3a2d99d3b5", 1122 | "sha256:fab8a7877275060f7b303e1f91c218069a2814a616b6a5ee2d8a3737deb15915", 1123 | "sha256:fc32e7d7f98cac3d8d5153ed2cb583158ae3d446a6efb8e28ccb1c54a09f4169" 1124 | ], 1125 | "markers": "python_version >= '3.6'", 1126 | "version": "==23.1.0" 1127 | }, 1128 | "requests": { 1129 | "hashes": [ 1130 | "sha256:bc7861137fbce630f17b03d3ad02ad0bf978c844f3536d0edda6499dafce2b6f", 1131 | "sha256:d568723a7ebd25875d8d1eaf5dfa068cd2fc8194b2e483d7b1f7c81918dbec6b" 1132 | ], 1133 | "index": "pypi", 1134 | "version": "==2.28.0" 1135 | }, 1136 | "rich": { 1137 | "hashes": [ 1138 | "sha256:4c586de507202505346f3e32d1363eb9ed6932f0c2f63184dea88983ff4971e2", 1139 | "sha256:d2bbd99c320a2532ac71ff6a3164867884357da3e3301f0240090c5d2fdac7ec" 1140 | ], 1141 | "markers": "python_version < '4' and python_full_version >= '3.6.3'", 1142 | "version": "==12.4.4" 1143 | }, 1144 | "semver": { 1145 | "hashes": [ 1146 | "sha256:ced8b23dceb22134307c1b8abfa523da14198793d9787ac838e70e29e77458d4", 1147 | "sha256:fa0fe2722ee1c3f57eac478820c3a5ae2f624af8264cbdf9000c980ff7f75e3f" 1148 | ], 1149 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", 1150 | "version": "==2.13.0" 1151 | }, 1152 | "send2trash": { 1153 | "hashes": [ 1154 | "sha256:d2c24762fd3759860a0aff155e45871447ea58d2be6bdd39b5c8f966a0c99c2d", 1155 | "sha256:f20eaadfdb517eaca5ce077640cb261c7d2698385a6a0f072a4a5447fd49fa08" 1156 | ], 1157 | "version": "==1.8.0" 1158 | }, 1159 | "setuptools": { 1160 | "hashes": [ 1161 | "sha256:d1746e7fd520e83bbe210d02fff1aa1a425ad671c7a9da7d246ec2401a087198", 1162 | "sha256:e7d11f3db616cda0751372244c2ba798e8e56a28e096ec4529010b803485f3fe" 1163 | ], 1164 | "markers": "python_version >= '3.7'", 1165 | "version": "==62.3.3" 1166 | }, 1167 | "six": { 1168 | "hashes": [ 1169 | "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", 1170 | "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" 1171 | ], 1172 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", 1173 | "version": "==1.16.0" 1174 | }, 1175 | "smmap": { 1176 | "hashes": [ 1177 | "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94", 1178 | "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936" 1179 | ], 1180 | "markers": "python_version >= '3.6'", 1181 | "version": "==5.0.0" 1182 | }, 1183 | "snowflake-connector-python": { 1184 | "hashes": [ 1185 | "sha256:05ca68da880a73d366c16605e7debf04b257ed08a19d0f32fe383394d8dbb923", 1186 | "sha256:5b1752d45c897fbb3b4a582702a28519ec7c1b4025c4f1d6845b8d0431077697", 1187 | "sha256:606aa9ef66c540f1474d0e2c03720750487bfa1998ad4089c454c14f1b5373d6", 1188 | "sha256:62ba074b03e359edd409866c6e9c330c6d009bfeab5533d04dfe328e13e99ae8", 1189 | "sha256:714a27d322ff9f1f078cbf2a3209633743475fc05e4f6caee39f7859f2e68d69", 1190 | "sha256:98e3ed26ea976af6b09e3b015c4fa0d626bf36ffdb550bee81d9b88a50ea76b4", 1191 | "sha256:9cfb07b048bcb1fe646d03f7480ccb6a877e9c45067302e90bcff7fd72f6bc2f", 1192 | "sha256:9f49fe81994bf38f4c44cd5df6b2f1a5df4735625d0a516ba689dcbc6eb8fa7e", 1193 | "sha256:ac18f39e1dfc703fb4668e1a133887fab999a314acec7ad7c55dfeab50b5a247", 1194 | "sha256:b4cd78bf75f98afbbf02f5eb2cd2f735b0c212f7f679384aee358bb84930e1aa", 1195 | "sha256:bbd4d74837f25aa673f02ff450233bc81858af872192b45b11e11e0c2531d669", 1196 | "sha256:ca7a26c4d628a552811d2235a88d5ba9bce2b1931d46c6f3aaa7db4edc20a616", 1197 | "sha256:db828f6091160db51447eb713438576d0f62f2d963b260e1d3b753f37033284c", 1198 | "sha256:e597c51133e1ab7c63bdc3031a40b58d833d6e56b96fcc61e23bdfaad58aff3c", 1199 | "sha256:f7b08aba0ed5b33ff869d3e28848919cfc593753f24fd1b68fd7f3f8424691c8", 1200 | "sha256:ff414bf9649cc72b6f5254491b233c8b64f29f82a1c4578ff7a6b14fc2576436" 1201 | ], 1202 | "index": "pypi", 1203 | "version": "==2.7.8" 1204 | }, 1205 | "soupsieve": { 1206 | "hashes": [ 1207 | "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759", 1208 | "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d" 1209 | ], 1210 | "markers": "python_version >= '3.6'", 1211 | "version": "==2.3.2.post1" 1212 | }, 1213 | "sqlparse": { 1214 | "hashes": [ 1215 | "sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae", 1216 | "sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d" 1217 | ], 1218 | "index": "pypi", 1219 | "version": "==0.4.2" 1220 | }, 1221 | "stack-data": { 1222 | "hashes": [ 1223 | "sha256:45692d41bd633a9503a5195552df22b583caf16f0b27c4e58c98d88c8b648e12", 1224 | "sha256:999762f9c3132308789affa03e9271bbbe947bf78311851f4d485d8402ed858e" 1225 | ], 1226 | "version": "==0.2.0" 1227 | }, 1228 | "streamlit": { 1229 | "hashes": [ 1230 | "sha256:4febd37144a62177e583d6970ab50f351a2bfd4eb112cf19e38c25b12246a4db", 1231 | "sha256:9479d623dd4bec1fc7bd27e85d5012672351210e640889022ee7b4631c4efb2c" 1232 | ], 1233 | "index": "pypi", 1234 | "version": "==1.10.0" 1235 | }, 1236 | "terminado": { 1237 | "hashes": [ 1238 | "sha256:0d5f126fbfdb5887b25ae7d9d07b0d716b1cc0ccaacc71c1f3c14d228e065197", 1239 | "sha256:ab4eeedccfcc1e6134bfee86106af90852c69d602884ea3a1e8ca6d4486e9bfe" 1240 | ], 1241 | "markers": "python_version >= '3.7'", 1242 | "version": "==0.15.0" 1243 | }, 1244 | "tinycss2": { 1245 | "hashes": [ 1246 | "sha256:b2e44dd8883c360c35dd0d1b5aad0b610e5156c2cb3b33434634e539ead9d8bf", 1247 | "sha256:fe794ceaadfe3cf3e686b22155d0da5780dd0e273471a51846d0a02bc204fec8" 1248 | ], 1249 | "markers": "python_version >= '3.6'", 1250 | "version": "==1.1.1" 1251 | }, 1252 | "toml": { 1253 | "hashes": [ 1254 | "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", 1255 | "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" 1256 | ], 1257 | "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", 1258 | "version": "==0.10.2" 1259 | }, 1260 | "toolz": { 1261 | "hashes": [ 1262 | "sha256:6b312d5e15138552f1bda8a4e66c30e236c831b612b2bf0005f8a1df10a4bc33", 1263 | "sha256:a5700ce83414c64514d82d60bcda8aabfde092d1c1a8663f9200c07fdcc6da8f" 1264 | ], 1265 | "markers": "python_version >= '3.5'", 1266 | "version": "==0.11.2" 1267 | }, 1268 | "tornado": { 1269 | "hashes": [ 1270 | "sha256:0a00ff4561e2929a2c37ce706cb8233b7907e0cdc22eab98888aca5dd3775feb", 1271 | "sha256:0d321a39c36e5f2c4ff12b4ed58d41390460f798422c4504e09eb5678e09998c", 1272 | "sha256:1e8225a1070cd8eec59a996c43229fe8f95689cb16e552d130b9793cb570a288", 1273 | "sha256:20241b3cb4f425e971cb0a8e4ffc9b0a861530ae3c52f2b0434e6c1b57e9fd95", 1274 | "sha256:25ad220258349a12ae87ede08a7b04aca51237721f63b1808d39bdb4b2164558", 1275 | "sha256:33892118b165401f291070100d6d09359ca74addda679b60390b09f8ef325ffe", 1276 | "sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791", 1277 | "sha256:3447475585bae2e77ecb832fc0300c3695516a47d46cefa0528181a34c5b9d3d", 1278 | "sha256:34ca2dac9e4d7afb0bed4677512e36a52f09caa6fded70b4e3e1c89dbd92c326", 1279 | "sha256:3e63498f680547ed24d2c71e6497f24bca791aca2fe116dbc2bd0ac7f191691b", 1280 | "sha256:548430be2740e327b3fe0201abe471f314741efcb0067ec4f2d7dcfb4825f3e4", 1281 | "sha256:6196a5c39286cc37c024cd78834fb9345e464525d8991c21e908cc046d1cc02c", 1282 | "sha256:61b32d06ae8a036a6607805e6720ef00a3c98207038444ba7fd3d169cd998910", 1283 | "sha256:6286efab1ed6e74b7028327365cf7346b1d777d63ab30e21a0f4d5b275fc17d5", 1284 | "sha256:65d98939f1a2e74b58839f8c4dab3b6b3c1ce84972ae712be02845e65391ac7c", 1285 | "sha256:66324e4e1beede9ac79e60f88de548da58b1f8ab4b2f1354d8375774f997e6c0", 1286 | "sha256:6c77c9937962577a6a76917845d06af6ab9197702a42e1346d8ae2e76b5e3675", 1287 | "sha256:70dec29e8ac485dbf57481baee40781c63e381bebea080991893cd297742b8fd", 1288 | "sha256:7250a3fa399f08ec9cb3f7b1b987955d17e044f1ade821b32e5f435130250d7f", 1289 | "sha256:748290bf9112b581c525e6e6d3820621ff020ed95af6f17fedef416b27ed564c", 1290 | "sha256:7da13da6f985aab7f6f28debab00c67ff9cbacd588e8477034c0652ac141feea", 1291 | "sha256:8f959b26f2634a091bb42241c3ed8d3cedb506e7c27b8dd5c7b9f745318ddbb6", 1292 | "sha256:9de9e5188a782be6b1ce866e8a51bc76a0fbaa0e16613823fc38e4fc2556ad05", 1293 | "sha256:a48900ecea1cbb71b8c71c620dee15b62f85f7c14189bdeee54966fbd9a0c5bd", 1294 | "sha256:b87936fd2c317b6ee08a5741ea06b9d11a6074ef4cc42e031bc6403f82a32575", 1295 | "sha256:c77da1263aa361938476f04c4b6c8916001b90b2c2fdd92d8d535e1af48fba5a", 1296 | "sha256:cb5ec8eead331e3bb4ce8066cf06d2dfef1bfb1b2a73082dfe8a161301b76e37", 1297 | "sha256:cc0ee35043162abbf717b7df924597ade8e5395e7b66d18270116f8745ceb795", 1298 | "sha256:d14d30e7f46a0476efb0deb5b61343b1526f73ebb5ed84f23dc794bdb88f9d9f", 1299 | "sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32", 1300 | "sha256:d3d20ea5782ba63ed13bc2b8c291a053c8d807a8fa927d941bd718468f7b950c", 1301 | "sha256:d3f7594930c423fd9f5d1a76bee85a2c36fd8b4b16921cae7e965f22575e9c01", 1302 | "sha256:dcef026f608f678c118779cd6591c8af6e9b4155c44e0d1bc0c87c036fb8c8c4", 1303 | "sha256:e0791ac58d91ac58f694d8d2957884df8e4e2f6687cdf367ef7eb7497f79eaa2", 1304 | "sha256:e385b637ac3acaae8022e7e47dfa7b83d3620e432e3ecb9a3f7f58f150e50921", 1305 | "sha256:e519d64089b0876c7b467274468709dadf11e41d65f63bba207e04217f47c085", 1306 | "sha256:e7229e60ac41a1202444497ddde70a48d33909e484f96eb0da9baf8dc68541df", 1307 | "sha256:ed3ad863b1b40cd1d4bd21e7498329ccaece75db5a5bf58cd3c9f130843e7102", 1308 | "sha256:f0ba29bafd8e7e22920567ce0d232c26d4d47c8b5cf4ed7b562b5db39fa199c5", 1309 | "sha256:fa2ba70284fa42c2a5ecb35e322e68823288a4251f9ba9cc77be04ae15eada68", 1310 | "sha256:fba85b6cd9c39be262fcd23865652920832b61583de2a2ca907dbd8e8a8c81e5" 1311 | ], 1312 | "markers": "python_version >= '3.5'", 1313 | "version": "==6.1" 1314 | }, 1315 | "traitlets": { 1316 | "hashes": [ 1317 | "sha256:1530d04badddc6a73d50b7ee34667d4b96914da352109117b4280cb56523a51b", 1318 | "sha256:74803a1baa59af70f023671d86d5c7a834c931186df26d50d362ee6a1ff021fd" 1319 | ], 1320 | "markers": "python_version >= '3.7'", 1321 | "version": "==5.2.2.post1" 1322 | }, 1323 | "typing-extensions": { 1324 | "hashes": [ 1325 | "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708", 1326 | "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376" 1327 | ], 1328 | "markers": "python_version >= '3.7'", 1329 | "version": "==4.2.0" 1330 | }, 1331 | "tzdata": { 1332 | "hashes": [ 1333 | "sha256:238e70234214138ed7b4e8a0fab0e5e13872edab3be586ab8198c407620e2ab9", 1334 | "sha256:8b536a8ec63dc0751342b3984193a3118f8fca2afe25752bb9b7fffd398552d3" 1335 | ], 1336 | "markers": "python_version >= '3.6'", 1337 | "version": "==2022.1" 1338 | }, 1339 | "tzlocal": { 1340 | "hashes": [ 1341 | "sha256:89885494684c929d9191c57aa27502afc87a579be5cdd3225c77c463ea043745", 1342 | "sha256:ee5842fa3a795f023514ac2d801c4a81d1743bbe642e3940143326b3a00addd7" 1343 | ], 1344 | "markers": "python_version >= '3.6'", 1345 | "version": "==4.2" 1346 | }, 1347 | "urllib3": { 1348 | "hashes": [ 1349 | "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14", 1350 | "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e" 1351 | ], 1352 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", 1353 | "version": "==1.26.9" 1354 | }, 1355 | "validators": { 1356 | "hashes": [ 1357 | "sha256:24148ce4e64100a2d5e267233e23e7afeb55316b47d30faae7eb6e7292bc226a" 1358 | ], 1359 | "markers": "python_version >= '3.4'", 1360 | "version": "==0.20.0" 1361 | }, 1362 | "wcwidth": { 1363 | "hashes": [ 1364 | "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784", 1365 | "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83" 1366 | ], 1367 | "version": "==0.2.5" 1368 | }, 1369 | "webencodings": { 1370 | "hashes": [ 1371 | "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", 1372 | "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" 1373 | ], 1374 | "version": "==0.5.1" 1375 | }, 1376 | "widgetsnbextension": { 1377 | "hashes": [ 1378 | "sha256:4fd321cad39fdcf8a8e248a657202d42917ada8e8ed5dd3f60f073e0d54ceabd", 1379 | "sha256:e84a7a9fcb9baf3d57106e184a7389a8f8eb935bf741a5eb9d60aa18cc029a80" 1380 | ], 1381 | "markers": "python_version >= '3.7'", 1382 | "version": "==3.6.0" 1383 | }, 1384 | "zipp": { 1385 | "hashes": [ 1386 | "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad", 1387 | "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099" 1388 | ], 1389 | "markers": "python_version >= '3.7'", 1390 | "version": "==3.8.0" 1391 | } 1392 | }, 1393 | "develop": { 1394 | "attrs": { 1395 | "hashes": [ 1396 | "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4", 1397 | "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd" 1398 | ], 1399 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", 1400 | "version": "==21.4.0" 1401 | }, 1402 | "black": { 1403 | "hashes": [ 1404 | "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b", 1405 | "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176", 1406 | "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09", 1407 | "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a", 1408 | "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015", 1409 | "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79", 1410 | "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb", 1411 | "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20", 1412 | "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464", 1413 | "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968", 1414 | "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82", 1415 | "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21", 1416 | "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0", 1417 | "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265", 1418 | "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b", 1419 | "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a", 1420 | "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72", 1421 | "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce", 1422 | "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0", 1423 | "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a", 1424 | "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163", 1425 | "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad", 1426 | "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d" 1427 | ], 1428 | "index": "pypi", 1429 | "version": "==22.3.0" 1430 | }, 1431 | "cfgv": { 1432 | "hashes": [ 1433 | "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426", 1434 | "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736" 1435 | ], 1436 | "markers": "python_full_version >= '3.6.1'", 1437 | "version": "==3.3.1" 1438 | }, 1439 | "click": { 1440 | "hashes": [ 1441 | "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", 1442 | "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" 1443 | ], 1444 | "markers": "python_version >= '3.7'", 1445 | "version": "==8.1.3" 1446 | }, 1447 | "distlib": { 1448 | "hashes": [ 1449 | "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b", 1450 | "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579" 1451 | ], 1452 | "version": "==0.3.4" 1453 | }, 1454 | "filelock": { 1455 | "hashes": [ 1456 | "sha256:37def7b658813cda163b56fc564cdc75e86d338246458c4c28ae84cabefa2404", 1457 | "sha256:3a0fd85166ad9dbab54c9aec96737b744106dc5f15c0b09a6744a445299fcf04" 1458 | ], 1459 | "markers": "python_version >= '3.7'", 1460 | "version": "==3.7.1" 1461 | }, 1462 | "flake8": { 1463 | "hashes": [ 1464 | "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d", 1465 | "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d" 1466 | ], 1467 | "index": "pypi", 1468 | "version": "==4.0.1" 1469 | }, 1470 | "flake8-bugbear": { 1471 | "hashes": [ 1472 | "sha256:ec374101cddf65bd7a96d393847d74e58d3b98669dbf9768344c39b6290e8bd6", 1473 | "sha256:f7c080563fca75ee6b205d06b181ecba22b802babb96b0b084cc7743d6908a55" 1474 | ], 1475 | "index": "pypi", 1476 | "version": "==22.4.25" 1477 | }, 1478 | "greenlet": { 1479 | "hashes": [ 1480 | "sha256:0051c6f1f27cb756ffc0ffbac7d2cd48cb0362ac1736871399a739b2885134d3", 1481 | "sha256:00e44c8afdbe5467e4f7b5851be223be68adb4272f44696ee71fe46b7036a711", 1482 | "sha256:013d61294b6cd8fe3242932c1c5e36e5d1db2c8afb58606c5a67efce62c1f5fd", 1483 | "sha256:049fe7579230e44daef03a259faa24511d10ebfa44f69411d99e6a184fe68073", 1484 | "sha256:14d4f3cd4e8b524ae9b8aa567858beed70c392fdec26dbdb0a8a418392e71708", 1485 | "sha256:166eac03e48784a6a6e0e5f041cfebb1ab400b394db188c48b3a84737f505b67", 1486 | "sha256:17ff94e7a83aa8671a25bf5b59326ec26da379ace2ebc4411d690d80a7fbcf23", 1487 | "sha256:1e12bdc622676ce47ae9abbf455c189e442afdde8818d9da983085df6312e7a1", 1488 | "sha256:21915eb821a6b3d9d8eefdaf57d6c345b970ad722f856cd71739493ce003ad08", 1489 | "sha256:288c6a76705dc54fba69fbcb59904ae4ad768b4c768839b8ca5fdadec6dd8cfd", 1490 | "sha256:2bde6792f313f4e918caabc46532aa64aa27a0db05d75b20edfc5c6f46479de2", 1491 | "sha256:32ca72bbc673adbcfecb935bb3fb1b74e663d10a4b241aaa2f5a75fe1d1f90aa", 1492 | "sha256:356b3576ad078c89a6107caa9c50cc14e98e3a6c4874a37c3e0273e4baf33de8", 1493 | "sha256:40b951f601af999a8bf2ce8c71e8aaa4e8c6f78ff8afae7b808aae2dc50d4c40", 1494 | "sha256:572e1787d1460da79590bf44304abbc0a2da944ea64ec549188fa84d89bba7ab", 1495 | "sha256:58df5c2a0e293bf665a51f8a100d3e9956febfbf1d9aaf8c0677cf70218910c6", 1496 | "sha256:64e6175c2e53195278d7388c454e0b30997573f3f4bd63697f88d855f7a6a1fc", 1497 | "sha256:7227b47e73dedaa513cdebb98469705ef0d66eb5a1250144468e9c3097d6b59b", 1498 | "sha256:7418b6bfc7fe3331541b84bb2141c9baf1ec7132a7ecd9f375912eca810e714e", 1499 | "sha256:7cbd7574ce8e138bda9df4efc6bf2ab8572c9aff640d8ecfece1b006b68da963", 1500 | "sha256:7ff61ff178250f9bb3cd89752df0f1dd0e27316a8bd1465351652b1b4a4cdfd3", 1501 | "sha256:833e1551925ed51e6b44c800e71e77dacd7e49181fdc9ac9a0bf3714d515785d", 1502 | "sha256:8639cadfda96737427330a094476d4c7a56ac03de7265622fcf4cfe57c8ae18d", 1503 | "sha256:8c5d5b35f789a030ebb95bff352f1d27a93d81069f2adb3182d99882e095cefe", 1504 | "sha256:8c790abda465726cfb8bb08bd4ca9a5d0a7bd77c7ac1ca1b839ad823b948ea28", 1505 | "sha256:8d2f1fb53a421b410751887eb4ff21386d119ef9cde3797bf5e7ed49fb51a3b3", 1506 | "sha256:903bbd302a2378f984aef528f76d4c9b1748f318fe1294961c072bdc7f2ffa3e", 1507 | "sha256:93f81b134a165cc17123626ab8da2e30c0455441d4ab5576eed73a64c025b25c", 1508 | "sha256:95e69877983ea39b7303570fa6760f81a3eec23d0e3ab2021b7144b94d06202d", 1509 | "sha256:9633b3034d3d901f0a46b7939f8c4d64427dfba6bbc5a36b1a67364cf148a1b0", 1510 | "sha256:97e5306482182170ade15c4b0d8386ded995a07d7cc2ca8f27958d34d6736497", 1511 | "sha256:9f3cba480d3deb69f6ee2c1825060177a22c7826431458c697df88e6aeb3caee", 1512 | "sha256:aa5b467f15e78b82257319aebc78dd2915e4c1436c3c0d1ad6f53e47ba6e2713", 1513 | "sha256:abb7a75ed8b968f3061327c433a0fbd17b729947b400747c334a9c29a9af6c58", 1514 | "sha256:aec52725173bd3a7b56fe91bc56eccb26fbdff1386ef123abb63c84c5b43b63a", 1515 | "sha256:b11548073a2213d950c3f671aa88e6f83cda6e2fb97a8b6317b1b5b33d850e06", 1516 | "sha256:b1692f7d6bc45e3200844be0dba153612103db241691088626a33ff1f24a0d88", 1517 | "sha256:b336501a05e13b616ef81ce329c0e09ac5ed8c732d9ba7e3e983fcc1a9e86965", 1518 | "sha256:b8c008de9d0daba7b6666aa5bbfdc23dcd78cafc33997c9b7741ff6353bafb7f", 1519 | "sha256:b92e29e58bef6d9cfd340c72b04d74c4b4e9f70c9fa7c78b674d1fec18896dc4", 1520 | "sha256:be5f425ff1f5f4b3c1e33ad64ab994eed12fc284a6ea71c5243fd564502ecbe5", 1521 | "sha256:dd0b1e9e891f69e7675ba5c92e28b90eaa045f6ab134ffe70b52e948aa175b3c", 1522 | "sha256:e30f5ea4ae2346e62cedde8794a56858a67b878dd79f7df76a0767e356b1744a", 1523 | "sha256:e6a36bb9474218c7a5b27ae476035497a6990e21d04c279884eb10d9b290f1b1", 1524 | "sha256:e859fcb4cbe93504ea18008d1df98dee4f7766db66c435e4882ab35cf70cac43", 1525 | "sha256:eb6ea6da4c787111adf40f697b4e58732ee0942b5d3bd8f435277643329ba627", 1526 | "sha256:ec8c433b3ab0419100bd45b47c9c8551248a5aee30ca5e9d399a0b57ac04651b", 1527 | "sha256:eff9d20417ff9dcb0d25e2defc2574d10b491bf2e693b4e491914738b7908168", 1528 | "sha256:f0214eb2a23b85528310dad848ad2ac58e735612929c8072f6093f3585fd342d", 1529 | "sha256:f276df9830dba7a333544bd41070e8175762a7ac20350786b322b714b0e654f5", 1530 | "sha256:f3acda1924472472ddd60c29e5b9db0cec629fbe3c5c5accb74d6d6d14773478", 1531 | "sha256:f70a9e237bb792c7cc7e44c531fd48f5897961701cdaa06cf22fc14965c496cf", 1532 | "sha256:f9d29ca8a77117315101425ec7ec2a47a22ccf59f5593378fc4077ac5b754fce", 1533 | "sha256:fa877ca7f6b48054f847b61d6fa7bed5cebb663ebc55e018fda12db09dcc664c", 1534 | "sha256:fdcec0b8399108577ec290f55551d926d9a1fa6cad45882093a7a07ac5ec147b" 1535 | ], 1536 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", 1537 | "version": "==1.1.2" 1538 | }, 1539 | "identify": { 1540 | "hashes": [ 1541 | "sha256:0dca2ea3e4381c435ef9c33ba100a78a9b40c0bab11189c7cf121f75815efeaa", 1542 | "sha256:3d11b16f3fe19f52039fb7e39c9c884b21cb1b586988114fbe42671f03de3e82" 1543 | ], 1544 | "markers": "python_version >= '3.7'", 1545 | "version": "==2.5.1" 1546 | }, 1547 | "mccabe": { 1548 | "hashes": [ 1549 | "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", 1550 | "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" 1551 | ], 1552 | "version": "==0.6.1" 1553 | }, 1554 | "msgpack": { 1555 | "hashes": [ 1556 | "sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467", 1557 | "sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae", 1558 | "sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92", 1559 | "sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef", 1560 | "sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624", 1561 | "sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227", 1562 | "sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88", 1563 | "sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9", 1564 | "sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8", 1565 | "sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd", 1566 | "sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6", 1567 | "sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55", 1568 | "sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e", 1569 | "sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2", 1570 | "sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44", 1571 | "sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6", 1572 | "sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9", 1573 | "sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab", 1574 | "sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae", 1575 | "sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa", 1576 | "sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9", 1577 | "sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e", 1578 | "sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250", 1579 | "sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce", 1580 | "sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075", 1581 | "sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236", 1582 | "sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae", 1583 | "sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e", 1584 | "sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f", 1585 | "sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08", 1586 | "sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6", 1587 | "sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d", 1588 | "sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43", 1589 | "sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1", 1590 | "sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6", 1591 | "sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0", 1592 | "sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c", 1593 | "sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff", 1594 | "sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db", 1595 | "sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243", 1596 | "sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661", 1597 | "sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba", 1598 | "sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e", 1599 | "sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb", 1600 | "sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52", 1601 | "sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6", 1602 | "sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1", 1603 | "sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f", 1604 | "sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da", 1605 | "sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f", 1606 | "sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c", 1607 | "sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8" 1608 | ], 1609 | "version": "==1.0.4" 1610 | }, 1611 | "mypy": { 1612 | "hashes": [ 1613 | "sha256:006be38474216b833eca29ff6b73e143386f352e10e9c2fbe76aa8549e5554f5", 1614 | "sha256:03c6cc893e7563e7b2949b969e63f02c000b32502a1b4d1314cabe391aa87d66", 1615 | "sha256:0e9f70df36405c25cc530a86eeda1e0867863d9471fe76d1273c783df3d35c2e", 1616 | "sha256:1ece702f29270ec6af25db8cf6185c04c02311c6bb21a69f423d40e527b75c56", 1617 | "sha256:3e09f1f983a71d0672bbc97ae33ee3709d10c779beb613febc36805a6e28bb4e", 1618 | "sha256:439c726a3b3da7ca84a0199a8ab444cd8896d95012c4a6c4a0d808e3147abf5d", 1619 | "sha256:5a0b53747f713f490affdceef835d8f0cb7285187a6a44c33821b6d1f46ed813", 1620 | "sha256:5f1332964963d4832a94bebc10f13d3279be3ce8f6c64da563d6ee6e2eeda932", 1621 | "sha256:63e85a03770ebf403291ec50097954cc5caf2a9205c888ce3a61bd3f82e17569", 1622 | "sha256:64759a273d590040a592e0f4186539858c948302c653c2eac840c7a3cd29e51b", 1623 | "sha256:697540876638ce349b01b6786bc6094ccdaba88af446a9abb967293ce6eaa2b0", 1624 | "sha256:9940e6916ed9371809b35b2154baf1f684acba935cd09928952310fbddaba648", 1625 | "sha256:9f5f5a74085d9a81a1f9c78081d60a0040c3efb3f28e5c9912b900adf59a16e6", 1626 | "sha256:a5ea0875a049de1b63b972456542f04643daf320d27dc592d7c3d9cd5d9bf950", 1627 | "sha256:b117650592e1782819829605a193360a08aa99f1fc23d1d71e1a75a142dc7e15", 1628 | "sha256:b24be97351084b11582fef18d79004b3e4db572219deee0212078f7cf6352723", 1629 | "sha256:b88f784e9e35dcaa075519096dc947a388319cb86811b6af621e3523980f1c8a", 1630 | "sha256:bdd5ca340beffb8c44cb9dc26697628d1b88c6bddf5c2f6eb308c46f269bb6f3", 1631 | "sha256:d5aaf1edaa7692490f72bdb9fbd941fbf2e201713523bdb3f4038be0af8846c6", 1632 | "sha256:e999229b9f3198c0c880d5e269f9f8129c8862451ce53a011326cad38b9ccd24", 1633 | "sha256:f4a21d01fc0ba4e31d82f0fff195682e29f9401a8bdb7173891070eb260aeb3b", 1634 | "sha256:f4b794db44168a4fc886e3450201365c9526a522c46ba089b55e1f11c163750d", 1635 | "sha256:f730d56cb924d371c26b8eaddeea3cc07d78ff51c521c6d04899ac6904b75492" 1636 | ], 1637 | "index": "pypi", 1638 | "version": "==0.961" 1639 | }, 1640 | "mypy-extensions": { 1641 | "hashes": [ 1642 | "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", 1643 | "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" 1644 | ], 1645 | "version": "==0.4.3" 1646 | }, 1647 | "nodeenv": { 1648 | "hashes": [ 1649 | "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b", 1650 | "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7" 1651 | ], 1652 | "version": "==1.6.0" 1653 | }, 1654 | "pathspec": { 1655 | "hashes": [ 1656 | "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a", 1657 | "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1" 1658 | ], 1659 | "version": "==0.9.0" 1660 | }, 1661 | "platformdirs": { 1662 | "hashes": [ 1663 | "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788", 1664 | "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19" 1665 | ], 1666 | "markers": "python_version >= '3.7'", 1667 | "version": "==2.5.2" 1668 | }, 1669 | "pre-commit": { 1670 | "hashes": [ 1671 | "sha256:10c62741aa5704faea2ad69cb550ca78082efe5697d6f04e5710c3c229afdd10", 1672 | "sha256:4233a1e38621c87d9dda9808c6606d7e7ba0e087cd56d3fe03202a01d2919615" 1673 | ], 1674 | "index": "pypi", 1675 | "version": "==2.19.0" 1676 | }, 1677 | "pycodestyle": { 1678 | "hashes": [ 1679 | "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20", 1680 | "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f" 1681 | ], 1682 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", 1683 | "version": "==2.8.0" 1684 | }, 1685 | "pyflakes": { 1686 | "hashes": [ 1687 | "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c", 1688 | "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e" 1689 | ], 1690 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", 1691 | "version": "==2.4.0" 1692 | }, 1693 | "pynvim": { 1694 | "hashes": [ 1695 | "sha256:3a795378bde5e8092fbeb3a1a99be9c613d2685542f1db0e5c6fd467eed56dff" 1696 | ], 1697 | "index": "pypi", 1698 | "version": "==0.4.3" 1699 | }, 1700 | "pyyaml": { 1701 | "hashes": [ 1702 | "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", 1703 | "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", 1704 | "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", 1705 | "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", 1706 | "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", 1707 | "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", 1708 | "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", 1709 | "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", 1710 | "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", 1711 | "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", 1712 | "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", 1713 | "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", 1714 | "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", 1715 | "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", 1716 | "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", 1717 | "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", 1718 | "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", 1719 | "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", 1720 | "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", 1721 | "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", 1722 | "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", 1723 | "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", 1724 | "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", 1725 | "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", 1726 | "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", 1727 | "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", 1728 | "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", 1729 | "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", 1730 | "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", 1731 | "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", 1732 | "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", 1733 | "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", 1734 | "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" 1735 | ], 1736 | "markers": "python_version >= '3.6'", 1737 | "version": "==6.0" 1738 | }, 1739 | "six": { 1740 | "hashes": [ 1741 | "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", 1742 | "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" 1743 | ], 1744 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", 1745 | "version": "==1.16.0" 1746 | }, 1747 | "toml": { 1748 | "hashes": [ 1749 | "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", 1750 | "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" 1751 | ], 1752 | "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", 1753 | "version": "==0.10.2" 1754 | }, 1755 | "tomli": { 1756 | "hashes": [ 1757 | "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", 1758 | "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" 1759 | ], 1760 | "markers": "python_version < '3.11'", 1761 | "version": "==2.0.1" 1762 | }, 1763 | "typed-ast": { 1764 | "hashes": [ 1765 | "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2", 1766 | "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1", 1767 | "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6", 1768 | "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62", 1769 | "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac", 1770 | "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d", 1771 | "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc", 1772 | "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2", 1773 | "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97", 1774 | "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35", 1775 | "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6", 1776 | "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1", 1777 | "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4", 1778 | "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c", 1779 | "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e", 1780 | "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec", 1781 | "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f", 1782 | "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72", 1783 | "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47", 1784 | "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72", 1785 | "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe", 1786 | "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6", 1787 | "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3", 1788 | "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66" 1789 | ], 1790 | "index": "pypi", 1791 | "version": "==1.5.4" 1792 | }, 1793 | "typing-extensions": { 1794 | "hashes": [ 1795 | "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708", 1796 | "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376" 1797 | ], 1798 | "markers": "python_version >= '3.7'", 1799 | "version": "==4.2.0" 1800 | }, 1801 | "virtualenv": { 1802 | "hashes": [ 1803 | "sha256:e617f16e25b42eb4f6e74096b9c9e37713cf10bf30168fb4a739f3fa8f898a3a", 1804 | "sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5" 1805 | ], 1806 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", 1807 | "version": "==20.14.1" 1808 | } 1809 | } 1810 | } 1811 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!NOTE] 2 | > Discover many more Streamlit & Snowflake apps in the [snowflake-demo-streamlit](https://github.com/Snowflake-Labs/snowflake-demo-streamlit) repository 3 | 4 | --- 5 | 6 | # Streamlit demo: 🌀 The Snowflake Usage Insights app 7 | 8 | This app provides insights on a demo Snowflake account usage. 9 | 10 | It was made using :balloon: [Streamlit](https://www.streamlit.io) and the :snowflake: [Snowflake Python connector](https://github.com/snowflakedb/snowflake-connector-python)! 11 | 12 | CleanShot 2022-06-13 at 23 03 10@2x 13 | 14 | ### Can I use this app with my own Snowflake account? 15 | 16 | This demo app currently only supports basic username / password authentication 17 | to connect to your Snowflake account. For security purposes, we recommend cloning this app and running it **locally** instead of on Streamlit Cloud. If you're interested, head over to the next section! 18 | 19 | ### Run this app locally 20 | Follow these steps: 21 | 22 | 1. **Set up dependencies.** Get [Pipenv](https://pipenv-fork.readthedocs.io/en/latest/install.html#pragmatic-installation-of-pipenv), 23 | clone/fork this repository and within the directory, run: 24 | ``` 25 | pipenv clean && pipenv install --python 3.9 26 | ``` 27 | 28 | 2. **Set up credentials.** Create a file `.streamlit/secrets.toml` and fill in your Snowflake account 29 | credentials. The file should look like this: 30 | ``` 31 | [sf_usage_app] 32 | user = "..." 33 | account = "..." 34 | password = "..." 35 | warehouse = "..." 36 | ``` 37 | 38 | 3. **Run the app locally.** Simply run: 39 | ``` 40 | pipenv run streamlit run Home.py 41 | ``` 42 | 43 | 🎊 Your browser should now be opened with the Streamlit app running locally! 44 | 45 | ### Contribute 46 | 47 | Feel free to contribute! Simply make sure to: 48 | 1. Install development dependencies `pipenv install --python 3.9 --dev` 49 | 2. Set up pre-commit hooks `pipenv run pre-commit install` 50 | 51 | ### Questions? Comments? 52 | 53 | Please ask in the [Streamlit community](https://discuss.streamlit.io). 54 | -------------------------------------------------------------------------------- /pages/01_🔹_Compute_insights.py: -------------------------------------------------------------------------------- 1 | import plost 2 | import streamlit as st 3 | 4 | st.set_page_config( 5 | page_title="Usage Insights app - Compute", page_icon="🔹", layout="centered" 6 | ) 7 | 8 | from utils import charts, gui, processing 9 | from utils import snowflake_connector as sf 10 | from utils import sql as sql 11 | 12 | 13 | def main(): 14 | 15 | # Date selector widget 16 | with st.sidebar: 17 | date_from, date_to = gui.date_selector() 18 | 19 | # Header 20 | gui.icon("🔹") 21 | st.title("Compute insights") 22 | 23 | # ---------------------- 24 | # ---- Service type ---- 25 | # ---------------------- 26 | 27 | gui.space(1) 28 | st.subheader("Service type") 29 | 30 | # Get data 31 | query = sql.CONSUMPTION_PER_SERVICE_TYPE_QUERY 32 | df = sf.sql_to_dataframe( 33 | query.format(date_from=date_from, date_to=date_to) 34 | ) 35 | 36 | # Add filtering widget per Service type 37 | all_values = df["SERVICE_TYPE"].unique().tolist() 38 | selected_value = st.selectbox( 39 | "Choose service type", 40 | ["All"] + all_values, 41 | 0, 42 | ) 43 | 44 | if selected_value == "All": 45 | selected_value = all_values 46 | else: 47 | selected_value = [selected_value] 48 | 49 | # Filter df accordingly 50 | df = df[df["SERVICE_TYPE"].isin(selected_value)] 51 | 52 | # Get consumption 53 | consumption = int(df["CREDITS_USED"].sum()) 54 | 55 | if df.empty: 56 | st.caption("No data found.") 57 | elif consumption == 0: 58 | st.caption("No consumption found.") 59 | else: 60 | # Sum of credits used 61 | credits_used_html = gui.underline( 62 | text=gui.pretty_print_credits(consumption), 63 | ) 64 | credits_used_html += " were used" 65 | 66 | gui.space(1) 67 | st.write(credits_used_html, unsafe_allow_html=True) 68 | 69 | gui.space(1) 70 | gui.subsubheader( 71 | "**Compute** spend over time", 72 | "Aggregated by day", 73 | ) 74 | 75 | # Resample by day 76 | df_resampled = processing.resample_by_day( 77 | df, 78 | date_column="START_TIME", 79 | ) 80 | 81 | # Bar chart 82 | bar_chart = charts.get_bar_chart( 83 | df=df_resampled, 84 | date_column="START_TIME", 85 | value_column="CREDITS_USED", 86 | ) 87 | 88 | st.altair_chart(bar_chart, use_container_width=True) 89 | 90 | # Group by 91 | agg_config = {"CREDITS_USED": "sum"} 92 | df_grouped = ( 93 | df.groupby(["NAME", "SERVICE_TYPE"]).agg(agg_config).reset_index() 94 | ) 95 | 96 | # Sort and pretty print credits 97 | df_grouped_top_10 = df_grouped.sort_values( 98 | by="CREDITS_USED", ascending=False 99 | ).head(10) 100 | 101 | df_grouped_top_10["CREDITS_USED"] = df_grouped_top_10[ 102 | "CREDITS_USED" 103 | ].apply(gui.pretty_print_credits) 104 | 105 | gui.subsubheader( 106 | "**Compute** spend", 107 | " Grouped by NAME", 108 | "Top 10", 109 | ) 110 | 111 | st.dataframe( 112 | gui.dataframe_with_podium( 113 | df_grouped_top_10, 114 | )[["NAME", "SERVICE_TYPE", "CREDITS_USED"]], 115 | width=600, 116 | ) 117 | 118 | gui.space(1) 119 | gui.hbar() 120 | 121 | # ------------------- 122 | # ---- Warehouse ---- 123 | # ------------------- 124 | 125 | st.subheader("Warehouse") 126 | 127 | # Get data 128 | warehouse_usage_hourly = sf.sql_to_dataframe( 129 | sql.WAREHOUSE_USAGE_HOURLY.format( 130 | date_from=date_from, 131 | date_to=date_to, 132 | ) 133 | ) 134 | 135 | # Add filtering widget per Warehouse name 136 | warehouses = warehouse_usage_hourly.WAREHOUSE_NAME.unique() 137 | selected_warehouse = st.selectbox( 138 | "Choose warehouse", 139 | warehouses.tolist(), 140 | ) 141 | 142 | # Filter accordingly 143 | warehouse_usage_hourly_filtered = warehouse_usage_hourly[ 144 | warehouse_usage_hourly.WAREHOUSE_NAME.eq(selected_warehouse) 145 | ] 146 | 147 | # Resample so that all the period has data (fill with 0 if needed) 148 | warehouse_usage_hourly_filtered = processing.resample_date_period( 149 | warehouse_usage_hourly_filtered, 150 | date_from, 151 | date_to, 152 | value_column="CREDITS_USED_COMPUTE", 153 | ) 154 | 155 | gui.subsubheader("Time-histogram of **warehouse usage**") 156 | 157 | plost.time_hist( 158 | data=warehouse_usage_hourly_filtered, 159 | date="START_TIME", 160 | x_unit="day", 161 | y_unit="hours", 162 | color={ 163 | "field": "CREDITS_USED_COMPUTE", 164 | "scale": { 165 | "scheme": charts.ALTAIR_SCHEME, 166 | }, 167 | }, 168 | aggregate=None, 169 | legend=None, 170 | ) 171 | 172 | gui.space(1) 173 | gui.hbar() 174 | 175 | # ----------------- 176 | # ---- Queries ---- 177 | # ----------------- 178 | 179 | st.subheader("Queries") 180 | 181 | # Get data 182 | queries_data = sf.get_queries_data( 183 | date_from, 184 | date_to, 185 | ) 186 | 187 | # Add filtering widget per Warehouse name 188 | warehouses = queries_data.WAREHOUSE_NAME.dropna().unique().tolist() 189 | selected_warehouse = st.selectbox( 190 | "Choose warehouse", 191 | warehouses, 192 | ) 193 | 194 | # Filter accordingly 195 | queries_data = queries_data[ 196 | queries_data.WAREHOUSE_NAME.eq(selected_warehouse) 197 | ] 198 | 199 | gui.subsubheader( 200 | "Histogram of **queries duration** (in secs)", "Log scale" 201 | ) 202 | 203 | # Histogram 204 | histogram = charts.get_histogram_chart( 205 | df=queries_data, 206 | date_column="DURATION_SECS", 207 | ) 208 | 209 | st.altair_chart(histogram, use_container_width=True) 210 | 211 | # Top-3 longest queries 212 | queries_podium_df = gui.dataframe_with_podium( 213 | queries_data, "DURATION_SECS" 214 | ).head(3) 215 | 216 | # Only show if at least three queries! 217 | if len(queries_podium_df) >= 3: 218 | with st.expander("🔎 Zoom into top-3 longest queries in detail"): 219 | for query in queries_podium_df.itertuples(): 220 | st.caption(f"{query.Index} {query.DURATION_SECS_PP}") 221 | st.code(query.QUERY_TEXT_PP, "sql") 222 | 223 | gui.space(1) 224 | st.write("Time-histograms of **aggregate queries duration** (in secs)") 225 | 226 | # Resample so that all the period has data (fill with 0 if needed) 227 | queries_data = processing.resample_date_period( 228 | queries_data, date_from, date_to, "DURATION_SECS" 229 | ) 230 | 231 | num_days_selected = (date_to - date_from).days 232 | if num_days_selected > 14: 233 | st.caption("Week-day histogram") 234 | plost.time_hist( 235 | data=queries_data, 236 | date="START_TIME", 237 | x_unit="week", 238 | y_unit="day", 239 | color={ 240 | "field": "DURATION_SECS", 241 | "scale": {"scheme": charts.ALTAIR_SCHEME}, 242 | }, 243 | aggregate="sum", 244 | legend=None, 245 | ) 246 | 247 | st.caption("Day-hour histogram") 248 | plost.time_hist( 249 | data=queries_data, 250 | date="START_TIME", 251 | x_unit="day", 252 | y_unit="hours", 253 | color={ 254 | "field": "DURATION_SECS", 255 | "scale": {"scheme": charts.ALTAIR_SCHEME}, 256 | }, 257 | aggregate="sum", 258 | legend=None, 259 | ) 260 | 261 | gui.space(1) 262 | gui.subsubheader( 263 | "**Query optimization**: longest and most frequent queries", 264 | "Log scales (🖱️ hover for real values!)", 265 | ) 266 | 267 | queries_agg = sf.sql_to_dataframe( 268 | sql.QUERIES_COUNT_QUERY.format( 269 | date_from=date_from, 270 | date_to=date_to, 271 | num_min=1, 272 | limit=10_000, 273 | warehouse_name=selected_warehouse, 274 | ) 275 | ) 276 | 277 | queries_agg = processing.apply_log1p( 278 | df=queries_agg, columns=["EXECUTION_MINUTES", "NUMBER_OF_QUERIES"] 279 | ) 280 | 281 | scatter_chart = charts.get_scatter_chart(df=queries_agg) 282 | 283 | st.altair_chart( 284 | scatter_chart, 285 | use_container_width=True, 286 | ) 287 | 288 | gui.space(1) 289 | gui.hbar() 290 | 291 | # ------------- 292 | # --- Users --- 293 | # ------------- 294 | 295 | st.subheader("Users") 296 | 297 | # Get data 298 | users_data = sf.sql_to_dataframe( 299 | sql.USERS_QUERY.format( 300 | date_from=date_from, 301 | date_to=date_to, 302 | ) 303 | ) 304 | 305 | gui.subsubheader("**Users** with the **largest** number of credits spent") 306 | 307 | # Bar chart 308 | plost.bar_chart( 309 | data=users_data, 310 | bar="USER_NAME", 311 | value="APPROXIMATE_CREDITS_USED", 312 | color=gui.BLUE_COLOR, 313 | direction="horizontal", 314 | height=200, 315 | use_container_width=True, 316 | ) 317 | 318 | 319 | if __name__ == "__main__": 320 | main() 321 | -------------------------------------------------------------------------------- /pages/02_🔹_Storage_insights.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | st.set_page_config( 4 | page_title="Usage Insights app - Storage", page_icon="🔹", layout="centered" 5 | ) 6 | 7 | from utils import charts, gui, processing 8 | from utils import snowflake_connector as sf 9 | from utils import sql 10 | 11 | 12 | def main(): 13 | 14 | # Date selector widget 15 | with st.sidebar: 16 | date_from, date_to = gui.date_selector() 17 | 18 | # Header 19 | gui.icon("🔹") 20 | st.title("Storage insights") 21 | 22 | # Get data 23 | query = sql.STORAGE_QUERY 24 | df = sf.sql_to_dataframe( 25 | query.format(date_from=date_from, date_to=date_to) 26 | ) 27 | 28 | # Get consumption 29 | consumption = df["DATABASE_BYTES"].sum() 30 | 31 | if df.empty: 32 | st.caption("No data found.") 33 | st.stop() 34 | if consumption == 0: 35 | st.caption("No consumption!") 36 | st.stop() 37 | 38 | # Resample by day 39 | df_resampled = processing.resample_by_day( 40 | df, 41 | date_column="USAGE_DATE", 42 | ) 43 | 44 | # Average bytes used per day 45 | credits_used_html = "Average " 46 | credits_used_html += gui.underline( 47 | text=gui.pretty_print_bytes(int(df_resampled.DATABASE_BYTES.mean())), 48 | color=gui.BLUE_COLOR, 49 | ) 50 | credits_used_html += " were used per day" 51 | 52 | gui.space(1) 53 | st.write(credits_used_html, unsafe_allow_html=True) 54 | 55 | gui.space(1) 56 | gui.subsubheader( 57 | "**Storage** spend over time", 58 | "Aggregated by day", 59 | ) 60 | 61 | # Bar chart 62 | chart = charts.get_bar_chart( 63 | df=df_resampled, 64 | date_column="USAGE_DATE", 65 | value_column="DATABASE_BYTES", 66 | ) 67 | 68 | st.altair_chart(chart, use_container_width=True) 69 | 70 | # st.write( 71 | # df_resampled.groupby( 72 | # ["OBJECT_NAME", "USAGE_DATE"] 73 | # ).DATABASE_BYTES.mean() 74 | # ) 75 | 76 | # Group by 77 | df_grouped = ( 78 | df.groupby(["OBJECT_NAME", "USAGE_DATE"]) 79 | .DATABASE_BYTES.mean() 80 | .reset_index() 81 | .groupby("OBJECT_NAME") 82 | .mean() 83 | .reset_index() 84 | ) 85 | # agg_config = {"DATABASE_BYTES": "sum"} 86 | # df_grouped = df.groupby("OBJECT_NAME").agg(agg_config).reset_index() 87 | 88 | # Sort and pretty print credits 89 | df_grouped_top_10 = df_grouped.sort_values( 90 | by="DATABASE_BYTES", ascending=False 91 | ).head(10) 92 | 93 | df_grouped_top_10["AVG_DAILY_STORAGE_SIZE"] = df_grouped_top_10[ 94 | "DATABASE_BYTES" 95 | ].apply(gui.pretty_print_bytes) 96 | 97 | # Pretty print BYTES 98 | # value_pretty_print_column = "DATABASE_BYTES_PP" 99 | # df_grouped[value_pretty_print_column] = df_grouped["DATABASE_BYTES"].apply( 100 | # gui.pretty_print_bytes 101 | # ) 102 | # df_grouped["AVG_DAILY_STORAGE_SIZE"] = df_grouped[ 103 | # "DATABASE_BYTES_PP" 104 | # ].apply(lambda x: x + " " * 10) 105 | 106 | # df_grouped = df_grouped.sort_values( 107 | # by="DATABASE_BYTES", 108 | # ascending=False, 109 | # ) 110 | 111 | gui.subsubheader( 112 | "**Storage** spend per day", 113 | "Average", 114 | "Grouped by OBJECT_NAME", 115 | "Top 10", 116 | ) 117 | 118 | st.dataframe( 119 | gui.dataframe_with_podium( 120 | df_grouped_top_10[["OBJECT_NAME", "AVG_DAILY_STORAGE_SIZE"]], 121 | ), 122 | ) 123 | 124 | 125 | if __name__ == "__main__": 126 | main() 127 | -------------------------------------------------------------------------------- /pages/03_🔹_Data_Transfer_insights.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | st.set_page_config( 4 | page_title="Usage Insights app - Data Transfer", 5 | page_icon="🔹", 6 | layout="centered", 7 | ) 8 | 9 | from utils import charts, gui, processing 10 | from utils import snowflake_connector as sf 11 | from utils import sql 12 | 13 | 14 | def main(): 15 | 16 | # Date selector widget 17 | with st.sidebar: 18 | date_from, date_to = gui.date_selector() 19 | 20 | # Header 21 | gui.icon("🔹") 22 | st.title("Data Transfer insights") 23 | 24 | # Get data 25 | query = sql.DATA_TRANSFER_QUERY 26 | df = sf.sql_to_dataframe( 27 | query.format( 28 | date_from=date_from, 29 | date_to=date_to, 30 | ) 31 | ) 32 | 33 | gui.space(1) 34 | st.subheader("Target region") 35 | 36 | # Add filtering widget 37 | all_values = df["TARGET_REGION"].unique().tolist() 38 | selected_value = st.selectbox( 39 | "Choose target region", 40 | ["All"] + all_values, 41 | 0, 42 | ) 43 | 44 | if selected_value == "All": 45 | selected_value = all_values 46 | else: 47 | selected_value = [selected_value] 48 | 49 | # Filter df accordingly 50 | df = df[df["TARGET_REGION"].isin(selected_value)] 51 | 52 | # Get consumption 53 | consumption = int(df["BYTES_TRANSFERRED"].sum()) 54 | 55 | if df.empty: 56 | st.caption("No data found.") 57 | st.stop() 58 | if consumption == 0: 59 | st.caption("No consumption!") 60 | st.stop() 61 | 62 | # Sum of credits used 63 | credits_used_html = gui.underline( 64 | text=gui.pretty_print_bytes(consumption), 65 | color=gui.BLUE_COLOR, 66 | ) 67 | credits_used_html += " were used" 68 | 69 | gui.space(1) 70 | st.write(credits_used_html, unsafe_allow_html=True) 71 | 72 | gui.space(1) 73 | gui.subsubheader( 74 | "**Data Transfer** spend over time", 75 | "Aggregated by day", 76 | ) 77 | 78 | # Resample by day 79 | df_resampled = processing.resample_by_day( 80 | df, 81 | date_column="START_TIME", 82 | ) 83 | 84 | # Bar chart 85 | chart = charts.get_bar_chart( 86 | df=df_resampled, 87 | date_column="START_TIME", 88 | value_column="BYTES_TRANSFERRED", 89 | ) 90 | 91 | st.altair_chart(chart, use_container_width=True) 92 | 93 | # Group by 94 | agg_config = {"BYTES_TRANSFERRED": "sum"} 95 | df_grouped = ( 96 | df.groupby(["TRANSFER_TYPE", "TARGET_CLOUD", "TARGET_REGION"]) 97 | .agg(agg_config) 98 | .reset_index() 99 | ) 100 | 101 | # Sort and pretty print credits 102 | df_grouped_top_10 = df_grouped.sort_values( 103 | by="BYTES_TRANSFERRED", ascending=False 104 | ).head(10) 105 | 106 | df_grouped_top_10["BYTES_TRANSFERRED"] = df_grouped_top_10[ 107 | "BYTES_TRANSFERRED" 108 | ].apply(gui.pretty_print_bytes) 109 | 110 | gui.subsubheader( 111 | "**Storage** spend", 112 | " Grouped by TRANSFER_TYPE", 113 | "Top 10", 114 | ) 115 | 116 | st.dataframe( 117 | gui.dataframe_with_podium( 118 | df_grouped_top_10[ 119 | [ 120 | "TRANSFER_TYPE", 121 | "TARGET_CLOUD", 122 | "TARGET_REGION", 123 | "BYTES_TRANSFERRED", 124 | ] 125 | ] 126 | ), 127 | width=600, 128 | ) 129 | 130 | 131 | if __name__ == "__main__": 132 | main() 133 | -------------------------------------------------------------------------------- /pages/04_🤔_About_this_app.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | st.set_page_config( 4 | page_title="Usage Insights app - About", page_icon="🤔", layout="centered" 5 | ) 6 | 7 | from utils import gui 8 | 9 | gui.icon("🤔") 10 | st.title("About this app") 11 | 12 | st.write( 13 | """ 14 | ### How does this app work? 15 | 16 | - Using [Streamlit](https://www.streamlit.io) and the [Snowflake Python 17 | connector](https://github.com/snowflakedb/snowflake-connector-python). 18 | - Check out our public repository 🐙 19 | [snowflake-usage-app](https://github.com/streamlit/snowflake-usage-app) to 20 | learn more about it! 21 | 22 | ### Questions? Comments? 23 | 24 | Please ask in the [Streamlit community](https://discuss.streamlit.io). 25 | """ 26 | ) 27 | -------------------------------------------------------------------------------- /utils/charts.py: -------------------------------------------------------------------------------- 1 | import altair as alt 2 | import pandas as pd 3 | import streamlit as st 4 | 5 | from utils import gui 6 | 7 | ALTAIR_AXIS_CONFIG = dict( 8 | gridColor="#e6eaf1", 9 | tickColor="#e6eaf1", 10 | domainColor="#e6eaf1", 11 | labelColor="#828797", 12 | titleFontWeight="bold", 13 | ) 14 | 15 | ALTAIR_SCHEME = "blues" 16 | 17 | 18 | @st.cache_data(ttl=60 * 60 * 12) 19 | def get_bar_chart( 20 | df: pd.DataFrame, 21 | date_column: str, 22 | value_column: str, 23 | color: str = gui.BLUE_COLOR, 24 | ) -> alt.Chart: 25 | 26 | config = { 27 | "x": alt.X(f"yearmonthdate({date_column})", title="Day"), 28 | "y": alt.Y(f"sum({value_column})", title="Consumption"), 29 | "tooltip": (date_column, value_column), 30 | } 31 | 32 | chart = ( 33 | alt.Chart(df) 34 | .mark_bar() 35 | .encode(**config) 36 | .configure_mark(opacity=1, color=color) 37 | .configure_axis(**ALTAIR_AXIS_CONFIG) 38 | .interactive() 39 | ) 40 | 41 | return chart 42 | 43 | 44 | @st.cache_data(ttl=60 * 60 * 12) 45 | def get_histogram_chart( 46 | df: pd.DataFrame, 47 | date_column: str, 48 | ) -> alt.Chart: 49 | 50 | chart = ( 51 | alt.Chart(df) 52 | .mark_bar() 53 | .encode( 54 | x=alt.X( 55 | date_column, 56 | bin=alt.BinParams( 57 | maxbins=100, 58 | ), 59 | ), 60 | y=alt.Y( 61 | "count()", 62 | title="Count of Records", 63 | scale=alt.Scale(type="symlog"), 64 | ), 65 | tooltip=[date_column, "count()"], 66 | ) 67 | .configure_mark( 68 | color=gui.BLUE_COLOR, 69 | ) 70 | .configure_axis(**ALTAIR_AXIS_CONFIG) 71 | .interactive() 72 | ) 73 | 74 | return chart 75 | 76 | 77 | @st.cache_data(ttl=60 * 60 * 12) 78 | def get_scatter_chart( 79 | df: pd.DataFrame, 80 | ) -> alt.Chart: 81 | chart = ( 82 | alt.Chart(df) 83 | .mark_circle( 84 | size=200, 85 | ) 86 | .encode( 87 | x=alt.X( 88 | "NUMBER_OF_QUERIES_LOG:Q", 89 | title="Number of queries (log scale)", 90 | scale=alt.Scale( 91 | domain=[ 92 | df.NUMBER_OF_QUERIES_LOG.min() - 0.5, 93 | df.NUMBER_OF_QUERIES_LOG.max() + 0.5, 94 | ] 95 | ), 96 | ), 97 | y=alt.Y( 98 | "EXECUTION_MINUTES_LOG:Q", 99 | title="Execution minutes (log scale)", 100 | scale=alt.Scale( 101 | domain=[ 102 | df.EXECUTION_MINUTES_LOG.min() - 0.5, 103 | df.EXECUTION_MINUTES_LOG.max() + 0.5, 104 | ] 105 | ), 106 | ), 107 | tooltip=[ 108 | "QUERY_TEXT", 109 | "NUMBER_OF_QUERIES", 110 | "EXECUTION_MINUTES", 111 | ], 112 | ) 113 | .configure_mark(opacity=0.7, color=gui.BLUE_COLOR) 114 | .configure_axis(**ALTAIR_AXIS_CONFIG) 115 | .interactive() 116 | ) 117 | 118 | return chart 119 | 120 | 121 | if __name__ == "__main__": 122 | pass 123 | -------------------------------------------------------------------------------- /utils/gui.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import math 3 | 4 | import pandas as pd 5 | import sqlparse 6 | import streamlit as st 7 | from millify import millify 8 | 9 | BLUE_COLOR = "#1c83e1" 10 | 11 | 12 | def icon(emoji: str): 13 | """Shows an emoji as a Notion-style page icon.""" 14 | st.write( 15 | f'{emoji}', 16 | unsafe_allow_html=True, 17 | ) 18 | 19 | 20 | def space(num_lines: int = 1): 21 | """Adds empty lines to the Streamlit app.""" 22 | for _ in range(num_lines): 23 | st.write("") 24 | 25 | 26 | def hbar(): 27 | """Adds a horizontal bar""" 28 | st.write("---") 29 | 30 | 31 | def subsubheader(*args): 32 | text = " · ".join(tuple(args)) 33 | st.write(text) 34 | 35 | 36 | def underline(text: str, color: str = BLUE_COLOR) -> str: 37 | """Underlines input text using HTML""" 38 | style = "font-size:18px; text-decoration-style: dotted; " 39 | style += "text-underline-offset: 5px; " 40 | style += f"text-decoration-color:{color};" 41 | return f""" {text} """ 42 | 43 | 44 | def dataframe_with_podium( 45 | df: pd.DataFrame, sort_by: str = None 46 | ) -> pd.DataFrame: 47 | """Replaces dataframe indices 1, 2, 3 with medals 🥇, 🥈, 🥉""" 48 | 49 | if sort_by: 50 | # Sort dataframe and take top-10 51 | sorted_df = ( 52 | df.sort_values(by=sort_by, ascending=False) 53 | .reset_index(drop=True) 54 | .head(10) 55 | ) 56 | else: 57 | sorted_df = df.head(10).copy() 58 | 59 | # Replace index to highlight the podium (gold, metal, bronze) 60 | new_index = ["🥇", "🥈", "🥉"] + list(map(str, range(4, 11))) 61 | sorted_df.index = new_index[: len(sorted_df)] 62 | return sorted_df 63 | 64 | 65 | def date_selector() -> tuple[datetime.date, datetime.date]: 66 | """Adds a date selector with a few different options.""" 67 | 68 | DATE_RANGE_OPTIONS = [ 69 | "Last 7 days", 70 | "Last 28 days", 71 | "Last 3 months", 72 | "Last 6 months", 73 | "Last 12 months", 74 | "All time", 75 | "Custom", 76 | ] 77 | 78 | if "date_range" in st.session_state: 79 | index = DATE_RANGE_OPTIONS.index(st.session_state.date_range) 80 | else: 81 | index = 0 82 | 83 | date_range = st.selectbox( 84 | "Date range", 85 | options=[ 86 | "Last 7 days", 87 | "Last 28 days", 88 | "Last 3 months", 89 | "Last 6 months", 90 | "Last 12 months", 91 | "All time", 92 | "Custom", 93 | ], 94 | index=index, 95 | key="date_range", 96 | ) 97 | 98 | if date_range != "Custom": 99 | date_to = datetime.date.today() 100 | if date_range == "Last 7 days": 101 | date_from = date_to - datetime.timedelta(days=7) 102 | elif date_range == "Last 28 days": 103 | date_from = date_to - datetime.timedelta(days=28) 104 | elif date_range == "Last 3 months": 105 | date_from = date_to - datetime.timedelta(weeks=12) 106 | elif date_range == "Last 6 months": 107 | date_from = date_to - datetime.timedelta(weeks=24) 108 | elif date_range == "Last 12 months": 109 | date_from = date_to - datetime.timedelta(days=365) 110 | else: 111 | date_from = datetime.date(year=2016, month=1, day=1) 112 | 113 | if "custom" in st.session_state: 114 | value = st.session_state.custom 115 | else: 116 | value = ( 117 | date_to - datetime.timedelta(days=7), 118 | date_to, 119 | ) 120 | 121 | if date_range == "Custom": 122 | date_from, date_to = st.date_input( 123 | "Choose start and end date", 124 | value=value, 125 | key="custom", 126 | ) 127 | 128 | st.caption(f"Your selection is from **{date_from}** to **{date_to}**") 129 | 130 | return date_from, date_to 131 | 132 | 133 | def pretty_print_credits(credits: float) -> str: 134 | return f"{millify(credits, 1)} Credits" 135 | 136 | 137 | def pretty_print_bytes(size_bytes: int, binary: bool = False) -> str: 138 | basis = 1024 if binary else 1000 139 | if size_bytes == 0: 140 | return "0B" 141 | size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") 142 | i = int(math.floor(math.log(size_bytes, basis))) 143 | p = math.pow(basis, i) 144 | s = round(size_bytes / p, 2) 145 | return "%s %s" % (s, size_name[i]) + " " * 8 146 | 147 | 148 | def pretty_print_seconds(seconds: int) -> str: 149 | minutes, seconds = divmod(seconds, 60) 150 | hours, minutes = divmod(minutes, 60) 151 | 152 | pretty_print = "" 153 | if hours: 154 | pretty_print += f"{hours} hr{'s' if hours > 1 else ''} " 155 | if minutes: 156 | pretty_print += f"{minutes} min{'s' if minutes > 1 else ''} " 157 | if seconds: 158 | pretty_print += f"{seconds} sec{'s' if seconds > 1 else ''}" 159 | return pretty_print 160 | 161 | 162 | def pretty_print_sql_query(query: str) -> str: 163 | return sqlparse.format( 164 | query, 165 | reindent=True, 166 | keyword_case="upper", 167 | ) 168 | 169 | 170 | if __name__ == "__main__": 171 | pass 172 | -------------------------------------------------------------------------------- /utils/processing.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | import streamlit as st 4 | 5 | 6 | @st.cache_data 7 | def resample_by_day(df: pd.DataFrame, date_column: str) -> pd.DataFrame: 8 | """Resample a dataframe's date_column by day, summing values.""" 9 | return ( 10 | df.set_index(date_column).resample("1D").sum().reset_index(date_column) 11 | ) 12 | 13 | 14 | @st.cache_data 15 | def resample_date_period( 16 | df: pd.DataFrame, date_from: str, date_to: str, value_column: str 17 | ) -> pd.DataFrame: 18 | """Resample a dataframe to make sure there are values in value_column 19 | for the full date period from date_from to date_to.""" 20 | 21 | empty_df = pd.DataFrame() 22 | empty_df["START_TIME"] = pd.date_range(date_from, date_to, freq="H") 23 | empty_df[value_column] = 0 24 | return empty_df.append( 25 | df, 26 | ignore_index=True, 27 | ) 28 | 29 | 30 | @st.cache_data 31 | def apply_log1p(df: pd.DataFrame, columns: list) -> pd.DataFrame: 32 | """Apply log1p on input columns and store into new columns in input df 33 | with suffix _LOG.""" 34 | log_columns = [f"{column}_LOG" for column in columns] 35 | df[log_columns] = df[columns].apply(np.log1p) 36 | return df 37 | 38 | 39 | if __name__ == "__main__": 40 | pass 41 | -------------------------------------------------------------------------------- /utils/snowflake_connector.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from typing import Any, Dict 3 | 4 | import pandas as pd 5 | import streamlit as st 6 | from snowflake.connector import connect 7 | from snowflake.connector.connection import SnowflakeConnection 8 | 9 | from utils import gui, sql 10 | 11 | TIME_TO_LIVE = 60 * 60 * 6 # 6 hours caching 12 | 13 | 14 | # Share the connector across all users connected to the app 15 | @st.cache_resource 16 | def get_connector( 17 | secrets_key: str = "snowflake", 18 | input_params: Dict[str, Any] = None, 19 | use_browser=True, 20 | ) -> SnowflakeConnection: 21 | """Get a connector to Snowflake. By default, the connector will look 22 | for credentials found under st.secrets["snowflake"]. 23 | 24 | Args: 25 | secrets_key (str, optional): Streamlit secrets key for the credentials. 26 | Defaults to 'snowflake' 27 | 28 | params (dict, optional): Connector parameters. 29 | Overrides Streamlit secrets. Defaults to None. 30 | 31 | local_development (bool, optional): If True, this will open a 32 | tab in your browser to collect requirements. Defaults to True. 33 | 34 | Returns: 35 | SnowflakeConnection: Snowflake connector object. 36 | """ 37 | 38 | # Default params 39 | params: Dict[str, Any] = { 40 | **st.secrets[secrets_key], 41 | "client_session_keep_alive": True, 42 | "client_store_temporary_credential": True, 43 | } 44 | 45 | # Override default params with input params 46 | if input_params: 47 | for key in input_params.keys(): 48 | params[key] = input_params[key] 49 | 50 | # This will open a tab in your browser and sign you in 51 | if use_browser: 52 | params["authenticator"] = "externalbrowser" 53 | 54 | connector = connect(**params) 55 | return connector 56 | 57 | 58 | snowflake_connector = get_connector( 59 | secrets_key="sf_usage_app", 60 | use_browser=False, 61 | ) 62 | 63 | cur = snowflake_connector.cursor() 64 | cur.execute(f"use warehouse {st.secrets.sf_usage_app.warehouse};") 65 | 66 | 67 | @st.cache_data(ttl=TIME_TO_LIVE) 68 | def sql_to_dataframe(sql_query: str) -> pd.DataFrame: 69 | data = pd.read_sql( 70 | sql_query, 71 | snowflake_connector, 72 | ) 73 | return data 74 | 75 | 76 | @st.cache_data(ttl=TIME_TO_LIVE) 77 | def get_queries_data( 78 | date_from: datetime.date, 79 | date_to: datetime.date, 80 | ): 81 | queries_data = sql_to_dataframe( 82 | sql.QUERIES_QUERY.format( 83 | date_from=date_from, 84 | date_to=date_to, 85 | ) 86 | ) 87 | queries_data["DURATION_SECS"] = round( 88 | (queries_data.TOTAL_ELAPSED_TIME) / 1000 89 | ) 90 | queries_data["DURATION_SECS_PP"] = queries_data.DURATION_SECS.apply( 91 | gui.pretty_print_seconds 92 | ) 93 | queries_data["QUERY_TEXT_PP"] = queries_data.QUERY_TEXT.apply( 94 | gui.pretty_print_sql_query 95 | ) 96 | return queries_data 97 | 98 | 99 | if __name__ == "__main__": 100 | pass 101 | -------------------------------------------------------------------------------- /utils/sql.py: -------------------------------------------------------------------------------- 1 | QUERIES_QUERY = """ 2 | select * 3 | from snowflake.account_usage.query_history 4 | where START_TIME >= convert_timezone('UTC', 'UTC', ('{date_from}T00:00:00Z')::timestamp_ltz) 5 | and START_TIME < convert_timezone('UTC', 'UTC', ('{date_to}T00:00:00Z')::timestamp_ltz); 6 | """ 7 | 8 | QUERIES_COUNT_QUERY = """ 9 | select QUERY_TEXT, 10 | count(*) as number_of_queries, 11 | sum(TOTAL_ELAPSED_TIME)/1000 as execution_seconds, 12 | sum(TOTAL_ELAPSED_TIME)/(1000*60) as execution_minutes, 13 | sum(TOTAL_ELAPSED_TIME)/(1000*60*60) as execution_hours 14 | from SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY Q 15 | where 1=1 16 | and Q.START_TIME >= convert_timezone('UTC', 'UTC', ('{date_from}T00:00:00Z')::timestamp_ltz) 17 | and Q.START_TIME <= convert_timezone('UTC', 'UTC', ('{date_to}T00:00:00Z')::timestamp_ltz) 18 | and TOTAL_ELAPSED_TIME > 0 --only get queries that actually used compute 19 | and WAREHOUSE_NAME = '{warehouse_name}' 20 | 21 | group by 1 22 | having count(*) >= {num_min} --configurable/minimal threshold 23 | 24 | order by 2 desc 25 | limit {limit}; --configurable upper bound threshold 26 | """ 27 | 28 | CONSUMPTION_PER_SERVICE_TYPE_QUERY = """ 29 | select date_trunc('hour', convert_timezone('UTC', start_time)) as start_time, 30 | name, 31 | service_type, 32 | round(sum(credits_used), 1) as credits_used, 33 | round(sum(credits_used_compute), 1) as credits_compute, 34 | round(sum(credits_used_cloud_services), 1) as credits_cloud 35 | from snowflake.account_usage.metering_history 36 | where start_time >= convert_timezone('UTC', 'UTC', ('{date_from}T00:00:00Z')::timestamp_ltz) 37 | and start_time < convert_timezone('UTC', 'UTC', ('{date_to}T00:00:00Z')::timestamp_ltz) 38 | group by 1, 2, 3; 39 | """ 40 | 41 | WAREHOUSE_USAGE_HOURLY = """ 42 | // Credits used by [hour, warehouse] (past 7 days) 43 | select START_TIME , 44 | WAREHOUSE_NAME , 45 | CREDITS_USED_COMPUTE 46 | from SNOWFLAKE.ACCOUNT_USAGE.WAREHOUSE_METERING_HISTORY 47 | where START_TIME >= convert_timezone('UTC', 'UTC', ('{date_from}T00:00:00Z')::timestamp_ltz) 48 | and start_time < convert_timezone('UTC', 'UTC', ('{date_to}T00:00:00Z')::timestamp_ltz) 49 | and WAREHOUSE_ID > 0 // Skip pseudo-VWs such as "CLOUD_SERVICES_ONLY" 50 | order by 1 desc, 51 | 2 52 | """ 53 | 54 | STORAGE_QUERY = """ 55 | select convert_timezone('UTC', usage_date) as usage_date, 56 | database_name as object_name, 57 | 'database' as object_type, 58 | max(AVERAGE_DATABASE_BYTES) as database_bytes, 59 | max(AVERAGE_FAILSAFE_BYTES) as failsafe_bytes, 60 | 0 as stage_bytes 61 | from snowflake.account_usage.database_storage_usage_history 62 | where usage_date >= date_trunc('day', ('{date_from}T00:00:00Z')::timestamp_ntz) 63 | and usage_date < date_trunc('day', ('{date_to}T00:00:00Z')::timestamp_ntz) 64 | group by 1, 2, 3 65 | union all 66 | select convert_timezone('UTC', usage_date) as usage_date, 67 | 'Stages' as object_name, 68 | 'stage' as object_type, 69 | 0 as database_bytes, 70 | 0 as failsafe_bytes, 71 | max(AVERAGE_STAGE_BYTES) as stage_bytes 72 | from snowflake.account_usage.stage_storage_usage_history 73 | where usage_date >= date_trunc('day', ('{date_from}T00:00:00Z')::timestamp_ntz) 74 | and usage_date < date_trunc('day', ('{date_to}T00:00:00Z')::timestamp_ntz) 75 | group by 1, 2, 3; 76 | """ 77 | 78 | DATA_TRANSFER_QUERY = """ 79 | select date_trunc('hour', convert_timezone('UTC', start_time)) as start_time, 80 | target_cloud, 81 | target_region, 82 | transfer_type, 83 | sum(bytes_transferred) as bytes_transferred 84 | from snowflake.account_usage.data_transfer_history 85 | where start_time >= convert_timezone('UTC', 'UTC', ('{date_from}T00:00:00Z')::timestamp_ltz) 86 | and start_time < convert_timezone('UTC', 'UTC', ('{date_to}T00:00:00Z')::timestamp_ltz) 87 | group by 1, 2, 3, 4; 88 | """ 89 | 90 | USERS_QUERY = """ 91 | with USER_HOUR_EXECUTION_CTE as 92 | (select USER_NAME , 93 | WAREHOUSE_NAME , 94 | DATE_TRUNC('hour', START_TIME) as START_TIME_HOUR , 95 | SUM(EXECUTION_TIME) as USER_HOUR_EXECUTION_TIME 96 | from "SNOWFLAKE"."ACCOUNT_USAGE"."QUERY_HISTORY" 97 | where WAREHOUSE_NAME is not null 98 | and EXECUTION_TIME > 0 99 | and START_TIME > convert_timezone('UTC', 'UTC', ('{date_from}T00:00:00Z')::timestamp_ltz) 100 | and START_TIME <= convert_timezone('UTC', 'UTC', ('{date_to}T00:00:00Z')::timestamp_ltz) 101 | group by 1, 102 | 2, 103 | 3), 104 | HOUR_EXECUTION_CTE as 105 | (select START_TIME_HOUR , 106 | WAREHOUSE_NAME , 107 | SUM(USER_HOUR_EXECUTION_TIME) as HOUR_EXECUTION_TIME 108 | from USER_HOUR_EXECUTION_CTE 109 | group by 1, 110 | 2), 111 | APPROXIMATE_CREDITS as 112 | (select A.USER_NAME , 113 | C.WAREHOUSE_NAME , 114 | (A.USER_HOUR_EXECUTION_TIME/B.HOUR_EXECUTION_TIME)*C.CREDITS_USED as APPROXIMATE_CREDITS_USED 115 | from USER_HOUR_EXECUTION_CTE A 116 | join HOUR_EXECUTION_CTE B on A.START_TIME_HOUR = B.START_TIME_HOUR 117 | and B.WAREHOUSE_NAME = A.WAREHOUSE_NAME 118 | join "SNOWFLAKE"."ACCOUNT_USAGE"."WAREHOUSE_METERING_HISTORY" C on C.WAREHOUSE_NAME = A.WAREHOUSE_NAME 119 | and C.START_TIME = A.START_TIME_HOUR) 120 | select USER_NAME, 121 | WAREHOUSE_NAME, 122 | SUM(APPROXIMATE_CREDITS_USED) as APPROXIMATE_CREDITS_USED 123 | from APPROXIMATE_CREDITS 124 | group by 1, 125 | 2 126 | order by 3 desc; 127 | """ 128 | 129 | if __name__ == "__main__": 130 | pass 131 | --------------------------------------------------------------------------------