done
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2018-2025 Faculty Science Limited
|
||||
Copyright 2025 the dash-bootstrap-components maintainers
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1 @@
|
||||
uv
|
||||
@@ -0,0 +1,28 @@
|
||||
Copyright 2010 Pallets
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,92 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: MarkupSafe
|
||||
Version: 3.0.2
|
||||
Summary: Safely add untrusted strings to HTML/XML markup.
|
||||
Maintainer-email: Pallets <contact@palletsprojects.com>
|
||||
License: Copyright 2010 Pallets
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Project-URL: Donate, https://palletsprojects.com/donate
|
||||
Project-URL: Documentation, https://markupsafe.palletsprojects.com/
|
||||
Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/
|
||||
Project-URL: Source, https://github.com/pallets/markupsafe/
|
||||
Project-URL: Chat, https://discord.gg/pallets
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||
Classifier: Topic :: Text Processing :: Markup :: HTML
|
||||
Classifier: Typing :: Typed
|
||||
Requires-Python: >=3.9
|
||||
Description-Content-Type: text/markdown
|
||||
License-File: LICENSE.txt
|
||||
|
||||
# MarkupSafe
|
||||
|
||||
MarkupSafe implements a text object that escapes characters so it is
|
||||
safe to use in HTML and XML. Characters that have special meanings are
|
||||
replaced so that they display as the actual characters. This mitigates
|
||||
injection attacks, meaning untrusted user input can safely be displayed
|
||||
on a page.
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
```pycon
|
||||
>>> from markupsafe import Markup, escape
|
||||
|
||||
>>> # escape replaces special characters and wraps in Markup
|
||||
>>> escape("<script>alert(document.cookie);</script>")
|
||||
Markup('<script>alert(document.cookie);</script>')
|
||||
|
||||
>>> # wrap in Markup to mark text "safe" and prevent escaping
|
||||
>>> Markup("<strong>Hello</strong>")
|
||||
Markup('<strong>hello</strong>')
|
||||
|
||||
>>> escape(Markup("<strong>Hello</strong>"))
|
||||
Markup('<strong>hello</strong>')
|
||||
|
||||
>>> # Markup is a str subclass
|
||||
>>> # methods and operators escape their arguments
|
||||
>>> template = Markup("Hello <em>{name}</em>")
|
||||
>>> template.format(name='"World"')
|
||||
Markup('Hello <em>"World"</em>')
|
||||
```
|
||||
|
||||
## Donate
|
||||
|
||||
The Pallets organization develops and supports MarkupSafe and other
|
||||
popular packages. In order to grow the community of contributors and
|
||||
users, and allow the maintainers to devote more time to the projects,
|
||||
[please donate today][].
|
||||
|
||||
[please donate today]: https://palletsprojects.com/donate
|
||||
@@ -0,0 +1,13 @@
|
||||
MarkupSafe-3.0.2.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2
|
||||
MarkupSafe-3.0.2.dist-info/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475
|
||||
MarkupSafe-3.0.2.dist-info/METADATA,sha256=aAwbZhSmXdfFuMM-rEHpeiHRkBOGESyVLJIuwzHP-nw,3975
|
||||
MarkupSafe-3.0.2.dist-info/RECORD,,
|
||||
MarkupSafe-3.0.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
MarkupSafe-3.0.2.dist-info/WHEEL,sha256=wZi4olA0NR6c8yfzURN7DX9ImcSoHfH-g7UT7-9uFnE,109
|
||||
MarkupSafe-3.0.2.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11
|
||||
markupsafe/__init__.py,sha256=sr-U6_27DfaSrj5jnHYxWN-pvhM27sjlDplMDPZKm7k,13214
|
||||
markupsafe/_native.py,sha256=hSLs8Jmz5aqayuengJJ3kdT5PwNpBWpKrmQSdipndC8,210
|
||||
markupsafe/_speedups.c,sha256=O7XulmTo-epI6n2FtMVOrJXl8EAaIwD2iNYmBI5SEoQ,4149
|
||||
markupsafe/_speedups.cpython-311-darwin.so,sha256=NHnXuz84IzAulUxl_VDkSUlQVKrzHXMIAWxCi0e01dM,50688
|
||||
markupsafe/_speedups.pyi,sha256=ENd1bYe7gbBUf2ywyYWOGUpnXOHNJ-cgTNqetlW8h5k,41
|
||||
markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
@@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: setuptools (75.2.0)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp311-cp311-macosx_11_0_arm64
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
markupsafe
|
||||
@@ -0,0 +1,7 @@
|
||||
dash-bootstrap-components
|
||||
Copyright 2018-2025 Faculty Science Limited
|
||||
Copyright 2025 the dash-bootstrap-components maintainers
|
||||
|
||||
This product includes software originally developed at Faculty Science Limited (https://faculty.ai/).
|
||||
|
||||
The dash-bootstrap-components logo was originally designed by Bureau Bureau (https://bureaubureau.uk/).
|
||||
@@ -0,0 +1 @@
|
||||
uv
|
||||
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2017-2021 Ingy döt Net
|
||||
Copyright (c) 2006-2016 Kirill Simonov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,46 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: PyYAML
|
||||
Version: 6.0.2
|
||||
Summary: YAML parser and emitter for Python
|
||||
Home-page: https://pyyaml.org/
|
||||
Download-URL: https://pypi.org/project/PyYAML/
|
||||
Author: Kirill Simonov
|
||||
Author-email: xi@resolvent.net
|
||||
License: MIT
|
||||
Project-URL: Bug Tracker, https://github.com/yaml/pyyaml/issues
|
||||
Project-URL: CI, https://github.com/yaml/pyyaml/actions
|
||||
Project-URL: Documentation, https://pyyaml.org/wiki/PyYAMLDocumentation
|
||||
Project-URL: Mailing lists, http://lists.sourceforge.net/lists/listinfo/yaml-core
|
||||
Project-URL: Source Code, https://github.com/yaml/pyyaml
|
||||
Platform: Any
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Cython
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Programming Language :: Python :: 3.13
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Classifier: Topic :: Text Processing :: Markup
|
||||
Requires-Python: >=3.8
|
||||
License-File: LICENSE
|
||||
|
||||
YAML is a data serialization format designed for human readability
|
||||
and interaction with scripting languages. PyYAML is a YAML parser
|
||||
and emitter for Python.
|
||||
|
||||
PyYAML features a complete YAML 1.1 parser, Unicode support, pickle
|
||||
support, capable extension API, and sensible error messages. PyYAML
|
||||
supports standard YAML tags and provides Python-specific tags that
|
||||
allow to represent an arbitrary Python object.
|
||||
|
||||
PyYAML is applicable for a broad range of tasks from complex
|
||||
configuration files to object serialization and persistence.
|
||||
@@ -0,0 +1,26 @@
|
||||
PyYAML-6.0.2.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2
|
||||
PyYAML-6.0.2.dist-info/LICENSE,sha256=jTko-dxEkP1jVwfLiOsmvXZBAqcoKVQwfT5RZ6V36KQ,1101
|
||||
PyYAML-6.0.2.dist-info/METADATA,sha256=9-odFB5seu4pGPcEv7E8iyxNF51_uKnaNGjLAhz2lto,2060
|
||||
PyYAML-6.0.2.dist-info/RECORD,,
|
||||
PyYAML-6.0.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
PyYAML-6.0.2.dist-info/WHEEL,sha256=LFVzND6nAdWMS-norKkn42oL86bk-j1PiLvh1xzptX0,110
|
||||
PyYAML-6.0.2.dist-info/top_level.txt,sha256=rpj0IVMTisAjh_1vG3Ccf9v5jpCQwAz6cD1IVU5ZdhQ,11
|
||||
_yaml/__init__.py,sha256=04Ae_5osxahpJHa3XBZUAf4wi6XX32gR8D6X6p64GEA,1402
|
||||
yaml/__init__.py,sha256=N35S01HMesFTe0aRRMWkPj0Pa8IEbHpE9FK7cr5Bdtw,12311
|
||||
yaml/_yaml.cpython-311-darwin.so,sha256=YdahBTjS8KitV8Lm6bzs2ON1yRZtfHTI-UguNFhwElI,359272
|
||||
yaml/composer.py,sha256=_Ko30Wr6eDWUeUpauUGT3Lcg9QPBnOPVlTnIMRGJ9FM,4883
|
||||
yaml/constructor.py,sha256=kNgkfaeLUkwQYY_Q6Ff1Tz2XVw_pG1xVE9Ak7z-viLA,28639
|
||||
yaml/cyaml.py,sha256=6ZrAG9fAYvdVe2FK_w0hmXoG7ZYsoYUwapG8CiC72H0,3851
|
||||
yaml/dumper.py,sha256=PLctZlYwZLp7XmeUdwRuv4nYOZ2UBnDIUy8-lKfLF-o,2837
|
||||
yaml/emitter.py,sha256=jghtaU7eFwg31bG0B7RZea_29Adi9CKmXq_QjgQpCkQ,43006
|
||||
yaml/error.py,sha256=Ah9z-toHJUbE9j-M8YpxgSRM5CgLCcwVzJgLLRF2Fxo,2533
|
||||
yaml/events.py,sha256=50_TksgQiE4up-lKo_V-nBy-tAIxkIPQxY5qDhKCeHw,2445
|
||||
yaml/loader.py,sha256=UVa-zIqmkFSCIYq_PgSGm4NSJttHY2Rf_zQ4_b1fHN0,2061
|
||||
yaml/nodes.py,sha256=gPKNj8pKCdh2d4gr3gIYINnPOaOxGhJAUiYhGRnPE84,1440
|
||||
yaml/parser.py,sha256=ilWp5vvgoHFGzvOZDItFoGjD6D42nhlZrZyjAwa0oJo,25495
|
||||
yaml/reader.py,sha256=0dmzirOiDG4Xo41RnuQS7K9rkY3xjHiVasfDMNTqCNw,6794
|
||||
yaml/representer.py,sha256=IuWP-cAW9sHKEnS0gCqSa894k1Bg4cgTxaDwIcbRQ-Y,14190
|
||||
yaml/resolver.py,sha256=9L-VYfm4mWHxUD1Vg4X7rjDRK_7VZd6b92wzq7Y2IKY,9004
|
||||
yaml/scanner.py,sha256=YEM3iLZSaQwXcQRg2l2R4MdT0zGP2F9eHkKGKnHyWQY,51279
|
||||
yaml/serializer.py,sha256=ChuFgmhU01hj4xgI8GaKv6vfM2Bujwa9i7d2FAHj7cA,4165
|
||||
yaml/tokens.py,sha256=lTQIzSVw8Mg9wv459-TjiOQe6wVziqaRlqX2_89rp54,2573
|
||||
@@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.44.0)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp311-cp311-macosx_11_0_arm64
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
_yaml
|
||||
yaml
|
||||
@@ -0,0 +1,124 @@
|
||||
<p align="center">
|
||||
<a href="https://www.dash-bootstrap-components.com/">
|
||||
<img src="https://cdn.jsdelivr.net/gh/dbc-team/dash-bootstrap-components@main/readme-images/logo.png" alt="dash-bootstrap-components logo" width="200" height="200">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h3 align="center">Dash Bootstrap Components</h3>
|
||||
|
||||
<p align="center">
|
||||
Bootstrap components for Plotly Dash
|
||||
<br>
|
||||
<a href="https://www.dash-bootstrap-components.com/">Explore the documentation</a>
|
||||
·
|
||||
<a href="https://github.com/dbc-team/dash-bootstrap-components/issues/new?template=bug.md">Report a bug</a>
|
||||
·
|
||||
<a href="https://github.com/dbc-team/dash-bootstrap-components/issues/new?template=feature.md">Request a feature</a>
|
||||
<br>
|
||||
<br>
|
||||
<img alt="GitHub Actions" src="https://github.com/dbc-team/dash-bootstrap-components/actions/workflows/tests.yml/badge.svg">
|
||||
<img alt="GitHub" src="https://img.shields.io/github/license/dbc-team/dash-bootstrap-components">
|
||||
<img alt="PyPI" src="https://img.shields.io/pypi/v/dash-bootstrap-components">
|
||||
<img alt="Conda (channel only)" src="https://img.shields.io/conda/vn/conda-forge/dash-bootstrap-components">
|
||||
<img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/dash-bootstrap-components">
|
||||
</p>
|
||||
|
||||
_dash-bootstrap-components_ is a library of [Bootstrap][bootstrap-homepage]
|
||||
components for use with [Plotly Dash][dash-homepage], that makes it easier to
|
||||
build consistently styled Dash apps with complex, responsive layouts.
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Quick start](#quick-start)
|
||||
- [Contributing](#contributing)
|
||||
- [Copyright and license](#copyright-and-license)
|
||||
|
||||
## Installation
|
||||
|
||||
### PyPI
|
||||
|
||||
You can install _dash-bootstrap-components_ with `pip`:
|
||||
|
||||
```sh
|
||||
pip install dash-bootstrap-components
|
||||
```
|
||||
|
||||
### Anaconda
|
||||
|
||||
You can also install _dash-bootstrap-components_ with `conda` through the
|
||||
conda-forge channel:
|
||||
|
||||
```sh
|
||||
conda install -c conda-forge dash-bootstrap-components
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
To use _dash-bootstrap-components_ you must do two things:
|
||||
|
||||
- Link a Bootstrap v5 compatible stylesheet
|
||||
- Incorporate _dash-bootstrap-components_ into your layout
|
||||
|
||||
### Linking a stylesheet
|
||||
|
||||
_dash-bootstrap-components_ doesn't come with CSS included. This is to give you
|
||||
the freedom to use any Bootstrap v5 stylesheet of your choice. This means
|
||||
however that in order for the components to be styled properly, you must link
|
||||
to a stylesheet yourself.
|
||||
|
||||
For convenience, links to [BootstrapCDN][bootstrapcdn] for each theme are
|
||||
available through the `themes` module, which can be used as follows:
|
||||
|
||||
```python
|
||||
import dash
|
||||
import dash_bootstrap_components as dbc
|
||||
|
||||
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
|
||||
```
|
||||
|
||||
For more information on how to link local or external CSS, check out the
|
||||
[Dash documentation][dash-docs-external].
|
||||
|
||||
### Build the layout
|
||||
|
||||
With CSS linked, you can start building your app's layout with our Bootstrap
|
||||
components. These include layout components for organising the content of your app on the page, as well as UI components like navbars, cards, alerts and many more.
|
||||
|
||||

|
||||
|
||||
See our [_documentation_][docs-components] for a full list of available
|
||||
components.
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions to _dash-bootstrap-components_. If you find a bug or
|
||||
something is unclear please [submit a bug report][bug-report], if you have ideas
|
||||
for new features please feel free to make a [feature request][feature-request].
|
||||
|
||||
If you would like to submit a pull request, please read our
|
||||
[contributing guide][contribution-guide], which contains instructions on how to
|
||||
build and install _dash-bootstrap-components_ locally, how to check your code
|
||||
will pass our linting checks, and how to submit the pull request itself.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
The _dash-bootstrap-components_ maintainers would like to thank [Faculty][faculty] for their early support in helping this project get off the ground. Since 2025, it has been maintained by the Dash community.
|
||||
|
||||
## Copyright and license
|
||||
|
||||
Copyright © 2018–2025 [Faculty Science Ltd.][faculty]
|
||||
Copyright © 2025 the _dash-bootstrap-components_ maintainers
|
||||
|
||||
Released under the [Apache 2.0 license](https://github.com/dbc-team/dash-bootstrap-components/blob/main/LICENSE).
|
||||
|
||||
|
||||
[dash-homepage]: https://dash.plotly.com/
|
||||
[dash-docs-external]: https://dash.plotly.com/external-resources
|
||||
[bootstrap-homepage]: https://getbootstrap.com/
|
||||
[docs-components]: https://www.dash-bootstrap-components.com/docs/components
|
||||
[bootstrapcdn]: https://www.bootstrapcdn.com/
|
||||
[faculty]: https://faculty.ai
|
||||
[bug-report]: https://github.com/dbc-team/dash-bootstrap-components/issues/new?template=bug.md
|
||||
[feature-request]: https://github.com/dbc-team/dash-bootstrap-components/issues/new?template=feature.md
|
||||
[contribution-guide]: https://github.com/dbc-team/dash-bootstrap-components/blob/main/.github/CONTRIBUTING.md
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,883 @@
|
||||
"""
|
||||
colors
|
||||
=====
|
||||
|
||||
Functions that manipulate colors and arrays of colors.
|
||||
|
||||
-----
|
||||
There are three basic types of color types: rgb, hex and tuple:
|
||||
|
||||
rgb - An rgb color is a string of the form 'rgb(a,b,c)' where a, b and c are
|
||||
integers between 0 and 255 inclusive.
|
||||
|
||||
hex - A hex color is a string of the form '#xxxxxx' where each x is a
|
||||
character that belongs to the set [0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f]. This is
|
||||
just the set of characters used in the hexadecimal numeric system.
|
||||
|
||||
tuple - A tuple color is a 3-tuple of the form (a,b,c) where a, b and c are
|
||||
floats between 0 and 1 inclusive.
|
||||
|
||||
-----
|
||||
Colormaps and Colorscales:
|
||||
A colormap or a colorscale is a correspondence between values - Pythonic
|
||||
objects such as strings and floats - to colors.
|
||||
|
||||
There are typically two main types of colormaps that exist: numerical and
|
||||
categorical colormaps.
|
||||
|
||||
Numerical:
|
||||
----------
|
||||
Numerical colormaps are used when the coloring column being used takes a
|
||||
spectrum of values or numbers.
|
||||
|
||||
A classic example from the Plotly library:
|
||||
```
|
||||
rainbow_colorscale = [
|
||||
[0, 'rgb(150,0,90)'], [0.125, 'rgb(0,0,200)'],
|
||||
[0.25, 'rgb(0,25,255)'], [0.375, 'rgb(0,152,255)'],
|
||||
[0.5, 'rgb(44,255,150)'], [0.625, 'rgb(151,255,0)'],
|
||||
[0.75, 'rgb(255,234,0)'], [0.875, 'rgb(255,111,0)'],
|
||||
[1, 'rgb(255,0,0)']
|
||||
]
|
||||
```
|
||||
|
||||
Notice that this colorscale is a list of lists with each inner list containing
|
||||
a number and a color. These left hand numbers in the nested lists go from 0 to
|
||||
1, and they are like pointers tell you when a number is mapped to a specific
|
||||
color.
|
||||
|
||||
If you have a column of numbers `col_num` that you want to plot, and you know
|
||||
|
||||
```
|
||||
min(col_num) = 0
|
||||
max(col_num) = 100
|
||||
```
|
||||
|
||||
then if you pull out the number `12.5` in the list and want to figure out what
|
||||
color the corresponding chart element (bar, scatter plot, etc) is going to be,
|
||||
you'll figure out that proportionally 12.5 to 100 is the same as 0.125 to 1.
|
||||
So, the point will be mapped to 'rgb(0,0,200)'.
|
||||
|
||||
All other colors between the pinned values in a colorscale are linearly
|
||||
interpolated.
|
||||
|
||||
Categorical:
|
||||
------------
|
||||
Alternatively, a categorical colormap is used to assign a specific value in a
|
||||
color column to a specific color everytime it appears in the dataset.
|
||||
|
||||
A column of strings in a panadas.dataframe that is chosen to serve as the
|
||||
color index would naturally use a categorical colormap. However, you can
|
||||
choose to use a categorical colormap with a column of numbers.
|
||||
|
||||
Be careful! If you have a lot of unique numbers in your color column you will
|
||||
end up with a colormap that is massive and may slow down graphing performance.
|
||||
"""
|
||||
|
||||
import decimal
|
||||
from numbers import Number
|
||||
|
||||
from _plotly_utils import exceptions
|
||||
|
||||
|
||||
# Built-in qualitative color sequences and sequential,
|
||||
# diverging and cyclical color scales.
|
||||
#
|
||||
# Initially ported over from plotly_express
|
||||
from . import ( # noqa: F401
|
||||
qualitative,
|
||||
sequential,
|
||||
diverging,
|
||||
cyclical,
|
||||
cmocean,
|
||||
colorbrewer,
|
||||
carto,
|
||||
plotlyjs,
|
||||
)
|
||||
|
||||
DEFAULT_PLOTLY_COLORS = [
|
||||
"rgb(31, 119, 180)",
|
||||
"rgb(255, 127, 14)",
|
||||
"rgb(44, 160, 44)",
|
||||
"rgb(214, 39, 40)",
|
||||
"rgb(148, 103, 189)",
|
||||
"rgb(140, 86, 75)",
|
||||
"rgb(227, 119, 194)",
|
||||
"rgb(127, 127, 127)",
|
||||
"rgb(188, 189, 34)",
|
||||
"rgb(23, 190, 207)",
|
||||
]
|
||||
|
||||
PLOTLY_SCALES = {
|
||||
"Greys": [[0, "rgb(0,0,0)"], [1, "rgb(255,255,255)"]],
|
||||
"YlGnBu": [
|
||||
[0, "rgb(8,29,88)"],
|
||||
[0.125, "rgb(37,52,148)"],
|
||||
[0.25, "rgb(34,94,168)"],
|
||||
[0.375, "rgb(29,145,192)"],
|
||||
[0.5, "rgb(65,182,196)"],
|
||||
[0.625, "rgb(127,205,187)"],
|
||||
[0.75, "rgb(199,233,180)"],
|
||||
[0.875, "rgb(237,248,217)"],
|
||||
[1, "rgb(255,255,217)"],
|
||||
],
|
||||
"Greens": [
|
||||
[0, "rgb(0,68,27)"],
|
||||
[0.125, "rgb(0,109,44)"],
|
||||
[0.25, "rgb(35,139,69)"],
|
||||
[0.375, "rgb(65,171,93)"],
|
||||
[0.5, "rgb(116,196,118)"],
|
||||
[0.625, "rgb(161,217,155)"],
|
||||
[0.75, "rgb(199,233,192)"],
|
||||
[0.875, "rgb(229,245,224)"],
|
||||
[1, "rgb(247,252,245)"],
|
||||
],
|
||||
"YlOrRd": [
|
||||
[0, "rgb(128,0,38)"],
|
||||
[0.125, "rgb(189,0,38)"],
|
||||
[0.25, "rgb(227,26,28)"],
|
||||
[0.375, "rgb(252,78,42)"],
|
||||
[0.5, "rgb(253,141,60)"],
|
||||
[0.625, "rgb(254,178,76)"],
|
||||
[0.75, "rgb(254,217,118)"],
|
||||
[0.875, "rgb(255,237,160)"],
|
||||
[1, "rgb(255,255,204)"],
|
||||
],
|
||||
"Bluered": [[0, "rgb(0,0,255)"], [1, "rgb(255,0,0)"]],
|
||||
# modified RdBu based on
|
||||
# www.sandia.gov/~kmorel/documents/ColorMaps/ColorMapsExpanded.pdf
|
||||
"RdBu": [
|
||||
[0, "rgb(5,10,172)"],
|
||||
[0.35, "rgb(106,137,247)"],
|
||||
[0.5, "rgb(190,190,190)"],
|
||||
[0.6, "rgb(220,170,132)"],
|
||||
[0.7, "rgb(230,145,90)"],
|
||||
[1, "rgb(178,10,28)"],
|
||||
],
|
||||
# Scale for non-negative numeric values
|
||||
"Reds": [
|
||||
[0, "rgb(220,220,220)"],
|
||||
[0.2, "rgb(245,195,157)"],
|
||||
[0.4, "rgb(245,160,105)"],
|
||||
[1, "rgb(178,10,28)"],
|
||||
],
|
||||
# Scale for non-positive numeric values
|
||||
"Blues": [
|
||||
[0, "rgb(5,10,172)"],
|
||||
[0.35, "rgb(40,60,190)"],
|
||||
[0.5, "rgb(70,100,245)"],
|
||||
[0.6, "rgb(90,120,245)"],
|
||||
[0.7, "rgb(106,137,247)"],
|
||||
[1, "rgb(220,220,220)"],
|
||||
],
|
||||
"Picnic": [
|
||||
[0, "rgb(0,0,255)"],
|
||||
[0.1, "rgb(51,153,255)"],
|
||||
[0.2, "rgb(102,204,255)"],
|
||||
[0.3, "rgb(153,204,255)"],
|
||||
[0.4, "rgb(204,204,255)"],
|
||||
[0.5, "rgb(255,255,255)"],
|
||||
[0.6, "rgb(255,204,255)"],
|
||||
[0.7, "rgb(255,153,255)"],
|
||||
[0.8, "rgb(255,102,204)"],
|
||||
[0.9, "rgb(255,102,102)"],
|
||||
[1, "rgb(255,0,0)"],
|
||||
],
|
||||
"Rainbow": [
|
||||
[0, "rgb(150,0,90)"],
|
||||
[0.125, "rgb(0,0,200)"],
|
||||
[0.25, "rgb(0,25,255)"],
|
||||
[0.375, "rgb(0,152,255)"],
|
||||
[0.5, "rgb(44,255,150)"],
|
||||
[0.625, "rgb(151,255,0)"],
|
||||
[0.75, "rgb(255,234,0)"],
|
||||
[0.875, "rgb(255,111,0)"],
|
||||
[1, "rgb(255,0,0)"],
|
||||
],
|
||||
"Portland": [
|
||||
[0, "rgb(12,51,131)"],
|
||||
[0.25, "rgb(10,136,186)"],
|
||||
[0.5, "rgb(242,211,56)"],
|
||||
[0.75, "rgb(242,143,56)"],
|
||||
[1, "rgb(217,30,30)"],
|
||||
],
|
||||
"Jet": [
|
||||
[0, "rgb(0,0,131)"],
|
||||
[0.125, "rgb(0,60,170)"],
|
||||
[0.375, "rgb(5,255,255)"],
|
||||
[0.625, "rgb(255,255,0)"],
|
||||
[0.875, "rgb(250,0,0)"],
|
||||
[1, "rgb(128,0,0)"],
|
||||
],
|
||||
"Hot": [
|
||||
[0, "rgb(0,0,0)"],
|
||||
[0.3, "rgb(230,0,0)"],
|
||||
[0.6, "rgb(255,210,0)"],
|
||||
[1, "rgb(255,255,255)"],
|
||||
],
|
||||
"Blackbody": [
|
||||
[0, "rgb(0,0,0)"],
|
||||
[0.2, "rgb(230,0,0)"],
|
||||
[0.4, "rgb(230,210,0)"],
|
||||
[0.7, "rgb(255,255,255)"],
|
||||
[1, "rgb(160,200,255)"],
|
||||
],
|
||||
"Earth": [
|
||||
[0, "rgb(0,0,130)"],
|
||||
[0.1, "rgb(0,180,180)"],
|
||||
[0.2, "rgb(40,210,40)"],
|
||||
[0.4, "rgb(230,230,50)"],
|
||||
[0.6, "rgb(120,70,20)"],
|
||||
[1, "rgb(255,255,255)"],
|
||||
],
|
||||
"Electric": [
|
||||
[0, "rgb(0,0,0)"],
|
||||
[0.15, "rgb(30,0,100)"],
|
||||
[0.4, "rgb(120,0,100)"],
|
||||
[0.6, "rgb(160,90,0)"],
|
||||
[0.8, "rgb(230,200,0)"],
|
||||
[1, "rgb(255,250,220)"],
|
||||
],
|
||||
"Viridis": [
|
||||
[0, "#440154"],
|
||||
[0.06274509803921569, "#48186a"],
|
||||
[0.12549019607843137, "#472d7b"],
|
||||
[0.18823529411764706, "#424086"],
|
||||
[0.25098039215686274, "#3b528b"],
|
||||
[0.3137254901960784, "#33638d"],
|
||||
[0.3764705882352941, "#2c728e"],
|
||||
[0.4392156862745098, "#26828e"],
|
||||
[0.5019607843137255, "#21918c"],
|
||||
[0.5647058823529412, "#1fa088"],
|
||||
[0.6274509803921569, "#28ae80"],
|
||||
[0.6901960784313725, "#3fbc73"],
|
||||
[0.7529411764705882, "#5ec962"],
|
||||
[0.8156862745098039, "#84d44b"],
|
||||
[0.8784313725490196, "#addc30"],
|
||||
[0.9411764705882353, "#d8e219"],
|
||||
[1, "#fde725"],
|
||||
],
|
||||
"Cividis": [
|
||||
[0.000000, "rgb(0,32,76)"],
|
||||
[0.058824, "rgb(0,42,102)"],
|
||||
[0.117647, "rgb(0,52,110)"],
|
||||
[0.176471, "rgb(39,63,108)"],
|
||||
[0.235294, "rgb(60,74,107)"],
|
||||
[0.294118, "rgb(76,85,107)"],
|
||||
[0.352941, "rgb(91,95,109)"],
|
||||
[0.411765, "rgb(104,106,112)"],
|
||||
[0.470588, "rgb(117,117,117)"],
|
||||
[0.529412, "rgb(131,129,120)"],
|
||||
[0.588235, "rgb(146,140,120)"],
|
||||
[0.647059, "rgb(161,152,118)"],
|
||||
[0.705882, "rgb(176,165,114)"],
|
||||
[0.764706, "rgb(192,177,109)"],
|
||||
[0.823529, "rgb(209,191,102)"],
|
||||
[0.882353, "rgb(225,204,92)"],
|
||||
[0.941176, "rgb(243,219,79)"],
|
||||
[1.000000, "rgb(255,233,69)"],
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def color_parser(colors, function):
|
||||
"""
|
||||
Takes color(s) and a function and applies the function on the color(s)
|
||||
|
||||
In particular, this function identifies whether the given color object
|
||||
is an iterable or not and applies the given color-parsing function to
|
||||
the color or iterable of colors. If given an iterable, it will only be
|
||||
able to work with it if all items in the iterable are of the same type
|
||||
- rgb string, hex string or tuple
|
||||
"""
|
||||
if isinstance(colors, str):
|
||||
return function(colors)
|
||||
|
||||
if isinstance(colors, tuple) and isinstance(colors[0], Number):
|
||||
return function(colors)
|
||||
|
||||
if hasattr(colors, "__iter__"):
|
||||
if isinstance(colors, tuple):
|
||||
new_color_tuple = tuple(function(item) for item in colors)
|
||||
return new_color_tuple
|
||||
|
||||
else:
|
||||
new_color_list = [function(item) for item in colors]
|
||||
return new_color_list
|
||||
|
||||
|
||||
def validate_colors(colors, colortype="tuple"):
|
||||
"""
|
||||
Validates color(s) and returns a list of color(s) of a specified type
|
||||
"""
|
||||
from numbers import Number
|
||||
|
||||
if colors is None:
|
||||
colors = DEFAULT_PLOTLY_COLORS
|
||||
|
||||
if isinstance(colors, str):
|
||||
if colors in PLOTLY_SCALES:
|
||||
colors_list = colorscale_to_colors(PLOTLY_SCALES[colors])
|
||||
# TODO: fix _gantt.py/_scatter.py so that they can accept the
|
||||
# actual colorscale and not just a list of the first and last
|
||||
# color in the plotly colorscale. In resolving this issue we
|
||||
# will be removing the immediate line below
|
||||
colors = [colors_list[0]] + [colors_list[-1]]
|
||||
elif "rgb" in colors or "#" in colors:
|
||||
colors = [colors]
|
||||
else:
|
||||
raise exceptions.PlotlyError(
|
||||
"If your colors variable is a string, it must be a "
|
||||
"Plotly scale, an rgb color or a hex color."
|
||||
)
|
||||
|
||||
elif isinstance(colors, tuple):
|
||||
if isinstance(colors[0], Number):
|
||||
colors = [colors]
|
||||
else:
|
||||
colors = list(colors)
|
||||
|
||||
# convert color elements in list to tuple color
|
||||
for j, each_color in enumerate(colors):
|
||||
if "rgb" in each_color:
|
||||
each_color = color_parser(each_color, unlabel_rgb)
|
||||
for value in each_color:
|
||||
if value > 255.0:
|
||||
raise exceptions.PlotlyError(
|
||||
"Whoops! The elements in your rgb colors "
|
||||
"tuples cannot exceed 255.0."
|
||||
)
|
||||
each_color = color_parser(each_color, unconvert_from_RGB_255)
|
||||
colors[j] = each_color
|
||||
|
||||
if "#" in each_color:
|
||||
each_color = color_parser(each_color, hex_to_rgb)
|
||||
each_color = color_parser(each_color, unconvert_from_RGB_255)
|
||||
|
||||
colors[j] = each_color
|
||||
|
||||
if isinstance(each_color, tuple):
|
||||
for value in each_color:
|
||||
if value > 1.0:
|
||||
raise exceptions.PlotlyError(
|
||||
"Whoops! The elements in your colors tuples cannot exceed 1.0."
|
||||
)
|
||||
colors[j] = each_color
|
||||
|
||||
if colortype == "rgb" and not isinstance(colors, str):
|
||||
for j, each_color in enumerate(colors):
|
||||
rgb_color = color_parser(each_color, convert_to_RGB_255)
|
||||
colors[j] = color_parser(rgb_color, label_rgb)
|
||||
|
||||
return colors
|
||||
|
||||
|
||||
def validate_colors_dict(colors, colortype="tuple"):
|
||||
"""
|
||||
Validates dictionary of color(s)
|
||||
"""
|
||||
# validate each color element in the dictionary
|
||||
for key in colors:
|
||||
if "rgb" in colors[key]:
|
||||
colors[key] = color_parser(colors[key], unlabel_rgb)
|
||||
for value in colors[key]:
|
||||
if value > 255.0:
|
||||
raise exceptions.PlotlyError(
|
||||
"Whoops! The elements in your rgb colors "
|
||||
"tuples cannot exceed 255.0."
|
||||
)
|
||||
colors[key] = color_parser(colors[key], unconvert_from_RGB_255)
|
||||
|
||||
if "#" in colors[key]:
|
||||
colors[key] = color_parser(colors[key], hex_to_rgb)
|
||||
colors[key] = color_parser(colors[key], unconvert_from_RGB_255)
|
||||
|
||||
if isinstance(colors[key], tuple):
|
||||
for value in colors[key]:
|
||||
if value > 1.0:
|
||||
raise exceptions.PlotlyError(
|
||||
"Whoops! The elements in your colors tuples cannot exceed 1.0."
|
||||
)
|
||||
|
||||
if colortype == "rgb":
|
||||
for key in colors:
|
||||
colors[key] = color_parser(colors[key], convert_to_RGB_255)
|
||||
colors[key] = color_parser(colors[key], label_rgb)
|
||||
|
||||
return colors
|
||||
|
||||
|
||||
def convert_colors_to_same_type(
|
||||
colors,
|
||||
colortype="rgb",
|
||||
scale=None,
|
||||
return_default_colors=False,
|
||||
num_of_defualt_colors=2,
|
||||
):
|
||||
"""
|
||||
Converts color(s) to the specified color type
|
||||
|
||||
Takes a single color or an iterable of colors, as well as a list of scale
|
||||
values, and outputs a 2-pair of the list of color(s) converted all to an
|
||||
rgb or tuple color type, aswell as the scale as the second element. If
|
||||
colors is a Plotly Scale name, then 'scale' will be forced to the scale
|
||||
from the respective colorscale and the colors in that colorscale will also
|
||||
be coverted to the selected colortype. If colors is None, then there is an
|
||||
option to return portion of the DEFAULT_PLOTLY_COLORS
|
||||
|
||||
:param (str|tuple|list) colors: either a plotly scale name, an rgb or hex
|
||||
color, a color tuple or a list/tuple of colors
|
||||
:param (list) scale: see docs for validate_scale_values()
|
||||
|
||||
:rtype (tuple) (colors_list, scale) if scale is None in the function call,
|
||||
then scale will remain None in the returned tuple
|
||||
"""
|
||||
colors_list = []
|
||||
|
||||
if colors is None and return_default_colors is True:
|
||||
colors_list = DEFAULT_PLOTLY_COLORS[0:num_of_defualt_colors]
|
||||
|
||||
if isinstance(colors, str):
|
||||
if colors in PLOTLY_SCALES:
|
||||
colors_list = colorscale_to_colors(PLOTLY_SCALES[colors])
|
||||
if scale is None:
|
||||
scale = colorscale_to_scale(PLOTLY_SCALES[colors])
|
||||
|
||||
elif "rgb" in colors or "#" in colors:
|
||||
colors_list = [colors]
|
||||
|
||||
elif isinstance(colors, tuple):
|
||||
if isinstance(colors[0], Number):
|
||||
colors_list = [colors]
|
||||
else:
|
||||
colors_list = list(colors)
|
||||
|
||||
elif isinstance(colors, list):
|
||||
colors_list = colors
|
||||
|
||||
# validate scale
|
||||
if scale is not None:
|
||||
validate_scale_values(scale)
|
||||
|
||||
if len(colors_list) != len(scale):
|
||||
raise exceptions.PlotlyError(
|
||||
"Make sure that the length of your scale matches the length "
|
||||
"of your list of colors which is {}.".format(len(colors_list))
|
||||
)
|
||||
|
||||
# convert all colors to rgb
|
||||
for j, each_color in enumerate(colors_list):
|
||||
if "#" in each_color:
|
||||
each_color = color_parser(each_color, hex_to_rgb)
|
||||
each_color = color_parser(each_color, label_rgb)
|
||||
colors_list[j] = each_color
|
||||
|
||||
elif isinstance(each_color, tuple):
|
||||
each_color = color_parser(each_color, convert_to_RGB_255)
|
||||
each_color = color_parser(each_color, label_rgb)
|
||||
colors_list[j] = each_color
|
||||
|
||||
if colortype == "rgb":
|
||||
return (colors_list, scale)
|
||||
elif colortype == "tuple":
|
||||
for j, each_color in enumerate(colors_list):
|
||||
each_color = color_parser(each_color, unlabel_rgb)
|
||||
each_color = color_parser(each_color, unconvert_from_RGB_255)
|
||||
colors_list[j] = each_color
|
||||
return (colors_list, scale)
|
||||
else:
|
||||
raise exceptions.PlotlyError(
|
||||
"You must select either rgb or tuple for your colortype variable."
|
||||
)
|
||||
|
||||
|
||||
def convert_dict_colors_to_same_type(colors_dict, colortype="rgb"):
|
||||
"""
|
||||
Converts a colors in a dictionary of colors to the specified color type
|
||||
|
||||
:param (dict) colors_dict: a dictionary whose values are single colors
|
||||
"""
|
||||
for key in colors_dict:
|
||||
if "#" in colors_dict[key]:
|
||||
colors_dict[key] = color_parser(colors_dict[key], hex_to_rgb)
|
||||
colors_dict[key] = color_parser(colors_dict[key], label_rgb)
|
||||
|
||||
elif isinstance(colors_dict[key], tuple):
|
||||
colors_dict[key] = color_parser(colors_dict[key], convert_to_RGB_255)
|
||||
colors_dict[key] = color_parser(colors_dict[key], label_rgb)
|
||||
|
||||
if colortype == "rgb":
|
||||
return colors_dict
|
||||
elif colortype == "tuple":
|
||||
for key in colors_dict:
|
||||
colors_dict[key] = color_parser(colors_dict[key], unlabel_rgb)
|
||||
colors_dict[key] = color_parser(colors_dict[key], unconvert_from_RGB_255)
|
||||
return colors_dict
|
||||
else:
|
||||
raise exceptions.PlotlyError(
|
||||
"You must select either rgb or tuple for your colortype variable."
|
||||
)
|
||||
|
||||
|
||||
def validate_scale_values(scale):
|
||||
"""
|
||||
Validates scale values from a colorscale
|
||||
|
||||
:param (list) scale: a strictly increasing list of floats that begins
|
||||
with 0 and ends with 1. Its usage derives from a colorscale which is
|
||||
a list of two-lists (a list with two elements) of the form
|
||||
[value, color] which are used to determine how interpolation weighting
|
||||
works between the colors in the colorscale. Therefore scale is just
|
||||
the extraction of these values from the two-lists in order
|
||||
"""
|
||||
if len(scale) < 2:
|
||||
raise exceptions.PlotlyError(
|
||||
"You must input a list of scale values that has at least two values."
|
||||
)
|
||||
|
||||
if (scale[0] != 0) or (scale[-1] != 1):
|
||||
raise exceptions.PlotlyError(
|
||||
"The first and last number in your scale must be 0.0 and 1.0 respectively."
|
||||
)
|
||||
|
||||
if not all(x < y for x, y in zip(scale, scale[1:])):
|
||||
raise exceptions.PlotlyError(
|
||||
"'scale' must be a list that contains a strictly increasing "
|
||||
"sequence of numbers."
|
||||
)
|
||||
|
||||
|
||||
def validate_colorscale(colorscale):
|
||||
"""Validate the structure, scale values and colors of colorscale."""
|
||||
if not isinstance(colorscale, list):
|
||||
# TODO Write tests for these exceptions
|
||||
raise exceptions.PlotlyError("A valid colorscale must be a list.")
|
||||
if not all(isinstance(innerlist, list) for innerlist in colorscale):
|
||||
raise exceptions.PlotlyError("A valid colorscale must be a list of lists.")
|
||||
colorscale_colors = colorscale_to_colors(colorscale)
|
||||
scale_values = colorscale_to_scale(colorscale)
|
||||
|
||||
validate_scale_values(scale_values)
|
||||
validate_colors(colorscale_colors)
|
||||
|
||||
|
||||
def make_colorscale(colors, scale=None):
|
||||
"""
|
||||
Makes a colorscale from a list of colors and a scale
|
||||
|
||||
Takes a list of colors and scales and constructs a colorscale based
|
||||
on the colors in sequential order. If 'scale' is left empty, a linear-
|
||||
interpolated colorscale will be generated. If 'scale' is a specificed
|
||||
list, it must be the same legnth as colors and must contain all floats
|
||||
For documentation regarding to the form of the output, see
|
||||
https://plot.ly/python/reference/#mesh3d-colorscale
|
||||
|
||||
:param (list) colors: a list of single colors
|
||||
"""
|
||||
colorscale = []
|
||||
|
||||
# validate minimum colors length of 2
|
||||
if len(colors) < 2:
|
||||
raise exceptions.PlotlyError(
|
||||
"You must input a list of colors that has at least two colors."
|
||||
)
|
||||
|
||||
if scale is None:
|
||||
scale_incr = 1.0 / (len(colors) - 1)
|
||||
return [[i * scale_incr, color] for i, color in enumerate(colors)]
|
||||
|
||||
else:
|
||||
if len(colors) != len(scale):
|
||||
raise exceptions.PlotlyError(
|
||||
"The length of colors and scale must be the same."
|
||||
)
|
||||
|
||||
validate_scale_values(scale)
|
||||
|
||||
colorscale = [list(tup) for tup in zip(scale, colors)]
|
||||
return colorscale
|
||||
|
||||
|
||||
def find_intermediate_color(lowcolor, highcolor, intermed, colortype="tuple"):
|
||||
"""
|
||||
Returns the color at a given distance between two colors
|
||||
|
||||
This function takes two color tuples, where each element is between 0
|
||||
and 1, along with a value 0 < intermed < 1 and returns a color that is
|
||||
intermed-percent from lowcolor to highcolor. If colortype is set to 'rgb',
|
||||
the function will automatically convert the rgb type to a tuple, find the
|
||||
intermediate color and return it as an rgb color.
|
||||
"""
|
||||
if colortype == "rgb":
|
||||
# convert to tuple color, eg. (1, 0.45, 0.7)
|
||||
lowcolor = unlabel_rgb(lowcolor)
|
||||
highcolor = unlabel_rgb(highcolor)
|
||||
|
||||
diff_0 = float(highcolor[0] - lowcolor[0])
|
||||
diff_1 = float(highcolor[1] - lowcolor[1])
|
||||
diff_2 = float(highcolor[2] - lowcolor[2])
|
||||
|
||||
inter_med_tuple = (
|
||||
lowcolor[0] + intermed * diff_0,
|
||||
lowcolor[1] + intermed * diff_1,
|
||||
lowcolor[2] + intermed * diff_2,
|
||||
)
|
||||
|
||||
if colortype == "rgb":
|
||||
# back to an rgb string, e.g. rgb(30, 20, 10)
|
||||
inter_med_rgb = label_rgb(inter_med_tuple)
|
||||
return inter_med_rgb
|
||||
|
||||
return inter_med_tuple
|
||||
|
||||
|
||||
def unconvert_from_RGB_255(colors):
|
||||
"""
|
||||
Return a tuple where each element gets divided by 255
|
||||
|
||||
Takes a (list of) color tuple(s) where each element is between 0 and
|
||||
255. Returns the same tuples where each tuple element is normalized to
|
||||
a value between 0 and 1
|
||||
"""
|
||||
return (colors[0] / (255.0), colors[1] / (255.0), colors[2] / (255.0))
|
||||
|
||||
|
||||
def convert_to_RGB_255(colors):
|
||||
"""
|
||||
Multiplies each element of a triplet by 255
|
||||
|
||||
Each coordinate of the color tuple is rounded to the nearest float and
|
||||
then is turned into an integer. If a number is of the form x.5, then
|
||||
if x is odd, the number rounds up to (x+1). Otherwise, it rounds down
|
||||
to just x. This is the way rounding works in Python 3 and in current
|
||||
statistical analysis to avoid rounding bias
|
||||
|
||||
:param (list) rgb_components: grabs the three R, G and B values to be
|
||||
returned as computed in the function
|
||||
"""
|
||||
rgb_components = []
|
||||
|
||||
for component in colors:
|
||||
rounded_num = decimal.Decimal(str(component * 255.0)).quantize(
|
||||
decimal.Decimal("1"), rounding=decimal.ROUND_HALF_EVEN
|
||||
)
|
||||
# convert rounded number to an integer from 'Decimal' form
|
||||
rounded_num = int(rounded_num)
|
||||
rgb_components.append(rounded_num)
|
||||
|
||||
return (rgb_components[0], rgb_components[1], rgb_components[2])
|
||||
|
||||
|
||||
def n_colors(lowcolor, highcolor, n_colors, colortype="tuple"):
|
||||
"""
|
||||
Splits a low and high color into a list of n_colors colors in it
|
||||
|
||||
Accepts two color tuples and returns a list of n_colors colors
|
||||
which form the intermediate colors between lowcolor and highcolor
|
||||
from linearly interpolating through RGB space. If colortype is 'rgb'
|
||||
the function will return a list of colors in the same form.
|
||||
"""
|
||||
if colortype == "rgb":
|
||||
# convert to tuple
|
||||
lowcolor = unlabel_rgb(lowcolor)
|
||||
highcolor = unlabel_rgb(highcolor)
|
||||
|
||||
diff_0 = float(highcolor[0] - lowcolor[0])
|
||||
incr_0 = diff_0 / (n_colors - 1)
|
||||
diff_1 = float(highcolor[1] - lowcolor[1])
|
||||
incr_1 = diff_1 / (n_colors - 1)
|
||||
diff_2 = float(highcolor[2] - lowcolor[2])
|
||||
incr_2 = diff_2 / (n_colors - 1)
|
||||
list_of_colors = []
|
||||
|
||||
def _constrain_color(c):
|
||||
if c > 255.0:
|
||||
return 255.0
|
||||
elif c < 0.0:
|
||||
return 0.0
|
||||
else:
|
||||
return c
|
||||
|
||||
for index in range(n_colors):
|
||||
new_tuple = (
|
||||
_constrain_color(lowcolor[0] + (index * incr_0)),
|
||||
_constrain_color(lowcolor[1] + (index * incr_1)),
|
||||
_constrain_color(lowcolor[2] + (index * incr_2)),
|
||||
)
|
||||
list_of_colors.append(new_tuple)
|
||||
|
||||
if colortype == "rgb":
|
||||
# back to an rgb string
|
||||
list_of_colors = color_parser(list_of_colors, label_rgb)
|
||||
|
||||
return list_of_colors
|
||||
|
||||
|
||||
def label_rgb(colors):
|
||||
"""
|
||||
Takes tuple (a, b, c) and returns an rgb color 'rgb(a, b, c)'
|
||||
"""
|
||||
return "rgb(%s, %s, %s)" % (colors[0], colors[1], colors[2])
|
||||
|
||||
|
||||
def unlabel_rgb(colors):
|
||||
"""
|
||||
Takes rgb color(s) 'rgb(a, b, c)' and returns tuple(s) (a, b, c)
|
||||
|
||||
This function takes either an 'rgb(a, b, c)' color or a list of
|
||||
such colors and returns the color tuples in tuple(s) (a, b, c)
|
||||
"""
|
||||
str_vals = ""
|
||||
for index in range(len(colors)):
|
||||
try:
|
||||
float(colors[index])
|
||||
str_vals = str_vals + colors[index]
|
||||
except ValueError:
|
||||
if colors[index] == "," or colors[index] == ".":
|
||||
str_vals = str_vals + colors[index]
|
||||
|
||||
str_vals = str_vals + ","
|
||||
numbers = []
|
||||
str_num = ""
|
||||
for char in str_vals:
|
||||
if char != ",":
|
||||
str_num = str_num + char
|
||||
else:
|
||||
numbers.append(float(str_num))
|
||||
str_num = ""
|
||||
return (numbers[0], numbers[1], numbers[2])
|
||||
|
||||
|
||||
def hex_to_rgb(value):
|
||||
"""
|
||||
Calculates rgb values from a hex color code.
|
||||
|
||||
:param (string) value: Hex color string
|
||||
|
||||
:rtype (tuple) (r_value, g_value, b_value): tuple of rgb values
|
||||
"""
|
||||
value = value.lstrip("#")
|
||||
hex_total_length = len(value)
|
||||
rgb_section_length = hex_total_length // 3
|
||||
return tuple(
|
||||
int(value[i : i + rgb_section_length], 16)
|
||||
for i in range(0, hex_total_length, rgb_section_length)
|
||||
)
|
||||
|
||||
|
||||
def colorscale_to_colors(colorscale):
|
||||
"""
|
||||
Extracts the colors from colorscale as a list
|
||||
"""
|
||||
color_list = []
|
||||
for item in colorscale:
|
||||
color_list.append(item[1])
|
||||
return color_list
|
||||
|
||||
|
||||
def colorscale_to_scale(colorscale):
|
||||
"""
|
||||
Extracts the interpolation scale values from colorscale as a list
|
||||
"""
|
||||
scale_list = []
|
||||
for item in colorscale:
|
||||
scale_list.append(item[0])
|
||||
return scale_list
|
||||
|
||||
|
||||
def convert_colorscale_to_rgb(colorscale):
|
||||
"""
|
||||
Converts the colors in a colorscale to rgb colors
|
||||
|
||||
A colorscale is an array of arrays, each with a numeric value as the
|
||||
first item and a color as the second. This function specifically is
|
||||
converting a colorscale with tuple colors (each coordinate between 0
|
||||
and 1) into a colorscale with the colors transformed into rgb colors
|
||||
"""
|
||||
for color in colorscale:
|
||||
color[1] = convert_to_RGB_255(color[1])
|
||||
|
||||
for color in colorscale:
|
||||
color[1] = label_rgb(color[1])
|
||||
return colorscale
|
||||
|
||||
|
||||
def named_colorscales():
|
||||
"""
|
||||
Returns lowercased names of built-in continuous colorscales.
|
||||
"""
|
||||
from _plotly_utils.basevalidators import ColorscaleValidator
|
||||
|
||||
return [c for c in ColorscaleValidator("", "").named_colorscales]
|
||||
|
||||
|
||||
def get_colorscale(name):
|
||||
"""
|
||||
Returns the colorscale for a given name. See `named_colorscales` for the
|
||||
built-in colorscales.
|
||||
"""
|
||||
from _plotly_utils.basevalidators import ColorscaleValidator
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise exceptions.PlotlyError("Name argument have to be a string.")
|
||||
|
||||
name = name.lower()
|
||||
if name[-2:] == "_r":
|
||||
should_reverse = True
|
||||
name = name[:-2]
|
||||
else:
|
||||
should_reverse = False
|
||||
|
||||
if name in ColorscaleValidator("", "").named_colorscales:
|
||||
colorscale = ColorscaleValidator("", "").named_colorscales[name]
|
||||
else:
|
||||
raise exceptions.PlotlyError(f"Colorscale {name} is not a built-in scale.")
|
||||
|
||||
if should_reverse:
|
||||
colorscale = colorscale[::-1]
|
||||
return make_colorscale(colorscale)
|
||||
|
||||
|
||||
def sample_colorscale(colorscale, samplepoints, low=0.0, high=1.0, colortype="rgb"):
|
||||
"""
|
||||
Samples a colorscale at specific points.
|
||||
|
||||
Interpolates between colors in a colorscale to find the specific colors
|
||||
corresponding to the specified sample values. The colorscale can be specified
|
||||
as a list of `[scale, color]` pairs, as a list of colors, or as a named
|
||||
plotly colorscale. The samplepoints can be specefied as an iterable of specific
|
||||
points in the range [0.0, 1.0], or as an integer number of points which will
|
||||
be spaced equally between the low value (default 0.0) and the high value
|
||||
(default 1.0). The output is a list of colors, formatted according to the
|
||||
specified colortype.
|
||||
"""
|
||||
from bisect import bisect_left
|
||||
|
||||
try:
|
||||
validate_colorscale(colorscale)
|
||||
except exceptions.PlotlyError:
|
||||
if isinstance(colorscale, str):
|
||||
colorscale = get_colorscale(colorscale)
|
||||
else:
|
||||
colorscale = make_colorscale(colorscale)
|
||||
|
||||
scale = colorscale_to_scale(colorscale)
|
||||
validate_scale_values(scale)
|
||||
colors = colorscale_to_colors(colorscale)
|
||||
colors = validate_colors(colors, colortype="tuple")
|
||||
|
||||
if isinstance(samplepoints, int):
|
||||
samplepoints = [
|
||||
low + idx / (samplepoints - 1) * (high - low) for idx in range(samplepoints)
|
||||
]
|
||||
elif isinstance(samplepoints, float):
|
||||
samplepoints = [samplepoints]
|
||||
|
||||
sampled_colors = []
|
||||
for point in samplepoints:
|
||||
high = bisect_left(scale, point)
|
||||
low = high - 1
|
||||
interpolant = (point - scale[low]) / (scale[high] - scale[low])
|
||||
sampled_color = find_intermediate_color(colors[low], colors[high], interpolant)
|
||||
sampled_colors.append(sampled_color)
|
||||
return validate_colors(sampled_colors, colortype=colortype)
|
||||
@@ -0,0 +1,161 @@
|
||||
def _swatches(module_names, module_contents, template=None):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
template : str or dict or plotly.graph_objects.layout.Template instance
|
||||
The figure template name or definition.
|
||||
|
||||
Returns
|
||||
-------
|
||||
fig : graph_objects.Figure containing the displayed image
|
||||
A `Figure` object. This figure demonstrates the color scales and
|
||||
sequences in this module, as stacked bar charts.
|
||||
"""
|
||||
import plotly.graph_objs as go
|
||||
from plotly.express._core import apply_default_cascade
|
||||
|
||||
args = dict(template=template)
|
||||
apply_default_cascade(args)
|
||||
|
||||
sequences = [
|
||||
(k, v)
|
||||
for k, v in module_contents.items()
|
||||
if not (k.startswith("_") or k.startswith("swatches") or k.endswith("_r"))
|
||||
]
|
||||
|
||||
return go.Figure(
|
||||
data=[
|
||||
go.Bar(
|
||||
orientation="h",
|
||||
y=[name] * len(colors),
|
||||
x=[1] * len(colors),
|
||||
customdata=list(range(len(colors))),
|
||||
marker=dict(color=colors),
|
||||
hovertemplate="%{y}[%{customdata}] = %{marker.color}<extra></extra>",
|
||||
)
|
||||
for name, colors in reversed(sequences)
|
||||
],
|
||||
layout=dict(
|
||||
title="plotly.colors." + module_names.split(".")[-1],
|
||||
barmode="stack",
|
||||
barnorm="fraction",
|
||||
bargap=0.5,
|
||||
showlegend=False,
|
||||
xaxis=dict(range=[-0.02, 1.02], showticklabels=False, showgrid=False),
|
||||
height=max(600, 40 * len(sequences)),
|
||||
template=args["template"],
|
||||
margin=dict(b=10),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def _swatches_continuous(module_names, module_contents, template=None):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
template : str or dict or plotly.graph_objects.layout.Template instance
|
||||
The figure template name or definition.
|
||||
|
||||
Returns
|
||||
-------
|
||||
fig : graph_objects.Figure containing the displayed image
|
||||
A `Figure` object. This figure demonstrates the color scales and
|
||||
sequences in this module, as stacked bar charts.
|
||||
"""
|
||||
import plotly.graph_objs as go
|
||||
from plotly.express._core import apply_default_cascade
|
||||
|
||||
args = dict(template=template)
|
||||
apply_default_cascade(args)
|
||||
|
||||
sequences = [
|
||||
(k, v)
|
||||
for k, v in module_contents.items()
|
||||
if not (k.startswith("_") or k.startswith("swatches") or k.endswith("_r"))
|
||||
]
|
||||
|
||||
n = 100
|
||||
|
||||
return go.Figure(
|
||||
data=[
|
||||
go.Bar(
|
||||
orientation="h",
|
||||
y=[name] * n,
|
||||
x=[1] * n,
|
||||
customdata=[(x + 1) / n for x in range(n)],
|
||||
marker=dict(color=list(range(n)), colorscale=name, line_width=0),
|
||||
hovertemplate="%{customdata}",
|
||||
name=name,
|
||||
)
|
||||
for name, colors in reversed(sequences)
|
||||
],
|
||||
layout=dict(
|
||||
title="plotly.colors." + module_names.split(".")[-1],
|
||||
barmode="stack",
|
||||
barnorm="fraction",
|
||||
bargap=0.3,
|
||||
showlegend=False,
|
||||
xaxis=dict(range=[-0.02, 1.02], showticklabels=False, showgrid=False),
|
||||
height=max(600, 40 * len(sequences)),
|
||||
width=500,
|
||||
template=args["template"],
|
||||
margin=dict(b=10),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def _swatches_cyclical(module_names, module_contents, template=None):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
template : str or dict or plotly.graph_objects.layout.Template instance
|
||||
The figure template name or definition.
|
||||
|
||||
Returns
|
||||
-------
|
||||
fig : graph_objects.Figure containing the displayed image
|
||||
A `Figure` object. This figure demonstrates the color scales and
|
||||
sequences in this module, as polar bar charts.
|
||||
"""
|
||||
import plotly.graph_objects as go
|
||||
from plotly.subplots import make_subplots
|
||||
from plotly.express._core import apply_default_cascade
|
||||
|
||||
args = dict(template=template)
|
||||
apply_default_cascade(args)
|
||||
|
||||
rows = 2
|
||||
cols = 4
|
||||
scales = [
|
||||
(k, v)
|
||||
for k, v in module_contents.items()
|
||||
if not (k.startswith("_") or k.startswith("swatches") or k.endswith("_r"))
|
||||
]
|
||||
names = [name for name, colors in scales]
|
||||
fig = make_subplots(
|
||||
rows=rows,
|
||||
cols=cols,
|
||||
subplot_titles=names,
|
||||
specs=[[{"type": "polar"}] * cols] * rows,
|
||||
)
|
||||
|
||||
for i, (name, scale) in enumerate(scales):
|
||||
fig.add_trace(
|
||||
go.Barpolar(
|
||||
r=[1] * int(360 / 5),
|
||||
theta=list(range(0, 360, 5)),
|
||||
marker_color=list(range(0, 360, 5)),
|
||||
marker_cmin=0,
|
||||
marker_cmax=360,
|
||||
marker_colorscale=name,
|
||||
name=name,
|
||||
),
|
||||
row=int(i / cols) + 1,
|
||||
col=i % cols + 1,
|
||||
)
|
||||
fig.update_traces(width=5.2, marker_line_width=0, base=0.5, showlegend=False)
|
||||
fig.update_polars(angularaxis_visible=False, radialaxis_visible=False)
|
||||
fig.update_layout(
|
||||
title="plotly.colors." + module_names.split(".")[-1], template=args["template"]
|
||||
)
|
||||
return fig
|
||||
@@ -0,0 +1,419 @@
|
||||
"""
|
||||
Color sequences and scales from CARTO's CartoColors
|
||||
|
||||
Learn more at https://github.com/CartoDB/CartoColor
|
||||
|
||||
CARTOColors are made available under a Creative Commons Attribution license: https://creativecommons.org/licenses/by/3.0/us/
|
||||
"""
|
||||
|
||||
from ._swatches import _swatches
|
||||
|
||||
|
||||
def swatches(template=None):
|
||||
return _swatches(__name__, globals(), template)
|
||||
|
||||
|
||||
swatches.__doc__ = _swatches.__doc__
|
||||
|
||||
Burg = [
|
||||
"rgb(255, 198, 196)",
|
||||
"rgb(244, 163, 168)",
|
||||
"rgb(227, 129, 145)",
|
||||
"rgb(204, 96, 125)",
|
||||
"rgb(173, 70, 108)",
|
||||
"rgb(139, 48, 88)",
|
||||
"rgb(103, 32, 68)",
|
||||
]
|
||||
|
||||
Burgyl = [
|
||||
"rgb(251, 230, 197)",
|
||||
"rgb(245, 186, 152)",
|
||||
"rgb(238, 138, 130)",
|
||||
"rgb(220, 113, 118)",
|
||||
"rgb(200, 88, 108)",
|
||||
"rgb(156, 63, 93)",
|
||||
"rgb(112, 40, 74)",
|
||||
]
|
||||
|
||||
Redor = [
|
||||
"rgb(246, 210, 169)",
|
||||
"rgb(245, 183, 142)",
|
||||
"rgb(241, 156, 124)",
|
||||
"rgb(234, 129, 113)",
|
||||
"rgb(221, 104, 108)",
|
||||
"rgb(202, 82, 104)",
|
||||
"rgb(177, 63, 100)",
|
||||
]
|
||||
|
||||
Oryel = [
|
||||
"rgb(236, 218, 154)",
|
||||
"rgb(239, 196, 126)",
|
||||
"rgb(243, 173, 106)",
|
||||
"rgb(247, 148, 93)",
|
||||
"rgb(249, 123, 87)",
|
||||
"rgb(246, 99, 86)",
|
||||
"rgb(238, 77, 90)",
|
||||
]
|
||||
|
||||
Peach = [
|
||||
"rgb(253, 224, 197)",
|
||||
"rgb(250, 203, 166)",
|
||||
"rgb(248, 181, 139)",
|
||||
"rgb(245, 158, 114)",
|
||||
"rgb(242, 133, 93)",
|
||||
"rgb(239, 106, 76)",
|
||||
"rgb(235, 74, 64)",
|
||||
]
|
||||
|
||||
Pinkyl = [
|
||||
"rgb(254, 246, 181)",
|
||||
"rgb(255, 221, 154)",
|
||||
"rgb(255, 194, 133)",
|
||||
"rgb(255, 166, 121)",
|
||||
"rgb(250, 138, 118)",
|
||||
"rgb(241, 109, 122)",
|
||||
"rgb(225, 83, 131)",
|
||||
]
|
||||
|
||||
Mint = [
|
||||
"rgb(228, 241, 225)",
|
||||
"rgb(180, 217, 204)",
|
||||
"rgb(137, 192, 182)",
|
||||
"rgb(99, 166, 160)",
|
||||
"rgb(68, 140, 138)",
|
||||
"rgb(40, 114, 116)",
|
||||
"rgb(13, 88, 95)",
|
||||
]
|
||||
|
||||
Blugrn = [
|
||||
"rgb(196, 230, 195)",
|
||||
"rgb(150, 210, 164)",
|
||||
"rgb(109, 188, 144)",
|
||||
"rgb(77, 162, 132)",
|
||||
"rgb(54, 135, 122)",
|
||||
"rgb(38, 107, 110)",
|
||||
"rgb(29, 79, 96)",
|
||||
]
|
||||
|
||||
Darkmint = [
|
||||
"rgb(210, 251, 212)",
|
||||
"rgb(165, 219, 194)",
|
||||
"rgb(123, 188, 176)",
|
||||
"rgb(85, 156, 158)",
|
||||
"rgb(58, 124, 137)",
|
||||
"rgb(35, 93, 114)",
|
||||
"rgb(18, 63, 90)",
|
||||
]
|
||||
|
||||
Emrld = [
|
||||
"rgb(211, 242, 163)",
|
||||
"rgb(151, 225, 150)",
|
||||
"rgb(108, 192, 139)",
|
||||
"rgb(76, 155, 130)",
|
||||
"rgb(33, 122, 121)",
|
||||
"rgb(16, 89, 101)",
|
||||
"rgb(7, 64, 80)",
|
||||
]
|
||||
|
||||
Aggrnyl = [
|
||||
"rgb(36, 86, 104)",
|
||||
"rgb(15, 114, 121)",
|
||||
"rgb(13, 143, 129)",
|
||||
"rgb(57, 171, 126)",
|
||||
"rgb(110, 197, 116)",
|
||||
"rgb(169, 220, 103)",
|
||||
"rgb(237, 239, 93)",
|
||||
]
|
||||
|
||||
Bluyl = [
|
||||
"rgb(247, 254, 174)",
|
||||
"rgb(183, 230, 165)",
|
||||
"rgb(124, 203, 162)",
|
||||
"rgb(70, 174, 160)",
|
||||
"rgb(8, 144, 153)",
|
||||
"rgb(0, 113, 139)",
|
||||
"rgb(4, 82, 117)",
|
||||
]
|
||||
|
||||
Teal = [
|
||||
"rgb(209, 238, 234)",
|
||||
"rgb(168, 219, 217)",
|
||||
"rgb(133, 196, 201)",
|
||||
"rgb(104, 171, 184)",
|
||||
"rgb(79, 144, 166)",
|
||||
"rgb(59, 115, 143)",
|
||||
"rgb(42, 86, 116)",
|
||||
]
|
||||
|
||||
Tealgrn = [
|
||||
"rgb(176, 242, 188)",
|
||||
"rgb(137, 232, 172)",
|
||||
"rgb(103, 219, 165)",
|
||||
"rgb(76, 200, 163)",
|
||||
"rgb(56, 178, 163)",
|
||||
"rgb(44, 152, 160)",
|
||||
"rgb(37, 125, 152)",
|
||||
]
|
||||
|
||||
Purp = [
|
||||
"rgb(243, 224, 247)",
|
||||
"rgb(228, 199, 241)",
|
||||
"rgb(209, 175, 232)",
|
||||
"rgb(185, 152, 221)",
|
||||
"rgb(159, 130, 206)",
|
||||
"rgb(130, 109, 186)",
|
||||
"rgb(99, 88, 159)",
|
||||
]
|
||||
|
||||
Purpor = [
|
||||
"rgb(249, 221, 218)",
|
||||
"rgb(242, 185, 196)",
|
||||
"rgb(229, 151, 185)",
|
||||
"rgb(206, 120, 179)",
|
||||
"rgb(173, 95, 173)",
|
||||
"rgb(131, 75, 160)",
|
||||
"rgb(87, 59, 136)",
|
||||
]
|
||||
|
||||
Sunset = [
|
||||
"rgb(243, 231, 155)",
|
||||
"rgb(250, 196, 132)",
|
||||
"rgb(248, 160, 126)",
|
||||
"rgb(235, 127, 134)",
|
||||
"rgb(206, 102, 147)",
|
||||
"rgb(160, 89, 160)",
|
||||
"rgb(92, 83, 165)",
|
||||
]
|
||||
|
||||
Magenta = [
|
||||
"rgb(243, 203, 211)",
|
||||
"rgb(234, 169, 189)",
|
||||
"rgb(221, 136, 172)",
|
||||
"rgb(202, 105, 157)",
|
||||
"rgb(177, 77, 142)",
|
||||
"rgb(145, 53, 125)",
|
||||
"rgb(108, 33, 103)",
|
||||
]
|
||||
|
||||
Sunsetdark = [
|
||||
"rgb(252, 222, 156)",
|
||||
"rgb(250, 164, 118)",
|
||||
"rgb(240, 116, 110)",
|
||||
"rgb(227, 79, 111)",
|
||||
"rgb(220, 57, 119)",
|
||||
"rgb(185, 37, 122)",
|
||||
"rgb(124, 29, 111)",
|
||||
]
|
||||
|
||||
Agsunset = [
|
||||
"rgb(75, 41, 145)",
|
||||
"rgb(135, 44, 162)",
|
||||
"rgb(192, 54, 157)",
|
||||
"rgb(234, 79, 136)",
|
||||
"rgb(250, 120, 118)",
|
||||
"rgb(246, 169, 122)",
|
||||
"rgb(237, 217, 163)",
|
||||
]
|
||||
|
||||
Brwnyl = [
|
||||
"rgb(237, 229, 207)",
|
||||
"rgb(224, 194, 162)",
|
||||
"rgb(211, 156, 131)",
|
||||
"rgb(193, 118, 111)",
|
||||
"rgb(166, 84, 97)",
|
||||
"rgb(129, 55, 83)",
|
||||
"rgb(84, 31, 63)",
|
||||
]
|
||||
|
||||
# Diverging schemes
|
||||
|
||||
Armyrose = [
|
||||
"rgb(121, 130, 52)",
|
||||
"rgb(163, 173, 98)",
|
||||
"rgb(208, 211, 162)",
|
||||
"rgb(253, 251, 228)",
|
||||
"rgb(240, 198, 195)",
|
||||
"rgb(223, 145, 163)",
|
||||
"rgb(212, 103, 128)",
|
||||
]
|
||||
|
||||
Fall = [
|
||||
"rgb(61, 89, 65)",
|
||||
"rgb(119, 136, 104)",
|
||||
"rgb(181, 185, 145)",
|
||||
"rgb(246, 237, 189)",
|
||||
"rgb(237, 187, 138)",
|
||||
"rgb(222, 138, 90)",
|
||||
"rgb(202, 86, 44)",
|
||||
]
|
||||
|
||||
Geyser = [
|
||||
"rgb(0, 128, 128)",
|
||||
"rgb(112, 164, 148)",
|
||||
"rgb(180, 200, 168)",
|
||||
"rgb(246, 237, 189)",
|
||||
"rgb(237, 187, 138)",
|
||||
"rgb(222, 138, 90)",
|
||||
"rgb(202, 86, 44)",
|
||||
]
|
||||
|
||||
Temps = [
|
||||
"rgb(0, 147, 146)",
|
||||
"rgb(57, 177, 133)",
|
||||
"rgb(156, 203, 134)",
|
||||
"rgb(233, 226, 156)",
|
||||
"rgb(238, 180, 121)",
|
||||
"rgb(232, 132, 113)",
|
||||
"rgb(207, 89, 126)",
|
||||
]
|
||||
|
||||
Tealrose = [
|
||||
"rgb(0, 147, 146)",
|
||||
"rgb(114, 170, 161)",
|
||||
"rgb(177, 199, 179)",
|
||||
"rgb(241, 234, 200)",
|
||||
"rgb(229, 185, 173)",
|
||||
"rgb(217, 137, 148)",
|
||||
"rgb(208, 88, 126)",
|
||||
]
|
||||
|
||||
Tropic = [
|
||||
"rgb(0, 155, 158)",
|
||||
"rgb(66, 183, 185)",
|
||||
"rgb(167, 211, 212)",
|
||||
"rgb(241, 241, 241)",
|
||||
"rgb(228, 193, 217)",
|
||||
"rgb(214, 145, 193)",
|
||||
"rgb(199, 93, 171)",
|
||||
]
|
||||
|
||||
Earth = [
|
||||
"rgb(161, 105, 40)",
|
||||
"rgb(189, 146, 90)",
|
||||
"rgb(214, 189, 141)",
|
||||
"rgb(237, 234, 194)",
|
||||
"rgb(181, 200, 184)",
|
||||
"rgb(121, 167, 172)",
|
||||
"rgb(40, 135, 161)",
|
||||
]
|
||||
|
||||
# Qualitative palettes
|
||||
|
||||
Antique = [
|
||||
"rgb(133, 92, 117)",
|
||||
"rgb(217, 175, 107)",
|
||||
"rgb(175, 100, 88)",
|
||||
"rgb(115, 111, 76)",
|
||||
"rgb(82, 106, 131)",
|
||||
"rgb(98, 83, 119)",
|
||||
"rgb(104, 133, 92)",
|
||||
"rgb(156, 156, 94)",
|
||||
"rgb(160, 97, 119)",
|
||||
"rgb(140, 120, 93)",
|
||||
"rgb(124, 124, 124)",
|
||||
]
|
||||
|
||||
Bold = [
|
||||
"rgb(127, 60, 141)",
|
||||
"rgb(17, 165, 121)",
|
||||
"rgb(57, 105, 172)",
|
||||
"rgb(242, 183, 1)",
|
||||
"rgb(231, 63, 116)",
|
||||
"rgb(128, 186, 90)",
|
||||
"rgb(230, 131, 16)",
|
||||
"rgb(0, 134, 149)",
|
||||
"rgb(207, 28, 144)",
|
||||
"rgb(249, 123, 114)",
|
||||
"rgb(165, 170, 153)",
|
||||
]
|
||||
|
||||
Pastel = [
|
||||
"rgb(102, 197, 204)",
|
||||
"rgb(246, 207, 113)",
|
||||
"rgb(248, 156, 116)",
|
||||
"rgb(220, 176, 242)",
|
||||
"rgb(135, 197, 95)",
|
||||
"rgb(158, 185, 243)",
|
||||
"rgb(254, 136, 177)",
|
||||
"rgb(201, 219, 116)",
|
||||
"rgb(139, 224, 164)",
|
||||
"rgb(180, 151, 231)",
|
||||
"rgb(179, 179, 179)",
|
||||
]
|
||||
|
||||
Prism = [
|
||||
"rgb(95, 70, 144)",
|
||||
"rgb(29, 105, 150)",
|
||||
"rgb(56, 166, 165)",
|
||||
"rgb(15, 133, 84)",
|
||||
"rgb(115, 175, 72)",
|
||||
"rgb(237, 173, 8)",
|
||||
"rgb(225, 124, 5)",
|
||||
"rgb(204, 80, 62)",
|
||||
"rgb(148, 52, 110)",
|
||||
"rgb(111, 64, 112)",
|
||||
"rgb(102, 102, 102)",
|
||||
]
|
||||
|
||||
Safe = [
|
||||
"rgb(136, 204, 238)",
|
||||
"rgb(204, 102, 119)",
|
||||
"rgb(221, 204, 119)",
|
||||
"rgb(17, 119, 51)",
|
||||
"rgb(51, 34, 136)",
|
||||
"rgb(170, 68, 153)",
|
||||
"rgb(68, 170, 153)",
|
||||
"rgb(153, 153, 51)",
|
||||
"rgb(136, 34, 85)",
|
||||
"rgb(102, 17, 0)",
|
||||
"rgb(136, 136, 136)",
|
||||
]
|
||||
|
||||
Vivid = [
|
||||
"rgb(229, 134, 6)",
|
||||
"rgb(93, 105, 177)",
|
||||
"rgb(82, 188, 163)",
|
||||
"rgb(153, 201, 69)",
|
||||
"rgb(204, 97, 176)",
|
||||
"rgb(36, 121, 108)",
|
||||
"rgb(218, 165, 27)",
|
||||
"rgb(47, 138, 196)",
|
||||
"rgb(118, 78, 159)",
|
||||
"rgb(237, 100, 90)",
|
||||
"rgb(165, 170, 153)",
|
||||
]
|
||||
|
||||
Aggrnyl_r = Aggrnyl[::-1]
|
||||
Agsunset_r = Agsunset[::-1]
|
||||
Antique_r = Antique[::-1]
|
||||
Armyrose_r = Armyrose[::-1]
|
||||
Blugrn_r = Blugrn[::-1]
|
||||
Bluyl_r = Bluyl[::-1]
|
||||
Bold_r = Bold[::-1]
|
||||
Brwnyl_r = Brwnyl[::-1]
|
||||
Burg_r = Burg[::-1]
|
||||
Burgyl_r = Burgyl[::-1]
|
||||
Darkmint_r = Darkmint[::-1]
|
||||
Earth_r = Earth[::-1]
|
||||
Emrld_r = Emrld[::-1]
|
||||
Fall_r = Fall[::-1]
|
||||
Geyser_r = Geyser[::-1]
|
||||
Magenta_r = Magenta[::-1]
|
||||
Mint_r = Mint[::-1]
|
||||
Oryel_r = Oryel[::-1]
|
||||
Pastel_r = Pastel[::-1]
|
||||
Peach_r = Peach[::-1]
|
||||
Pinkyl_r = Pinkyl[::-1]
|
||||
Prism_r = Prism[::-1]
|
||||
Purp_r = Purp[::-1]
|
||||
Purpor_r = Purpor[::-1]
|
||||
Redor_r = Redor[::-1]
|
||||
Safe_r = Safe[::-1]
|
||||
Sunset_r = Sunset[::-1]
|
||||
Sunsetdark_r = Sunsetdark[::-1]
|
||||
Teal_r = Teal[::-1]
|
||||
Tealgrn_r = Tealgrn[::-1]
|
||||
Tealrose_r = Tealrose[::-1]
|
||||
Temps_r = Temps[::-1]
|
||||
Tropic_r = Tropic[::-1]
|
||||
Vivid_r = Vivid[::-1]
|
||||
@@ -0,0 +1,296 @@
|
||||
"""
|
||||
Color scales from the cmocean project
|
||||
|
||||
Learn more at https://matplotlib.org/cmocean/
|
||||
|
||||
cmocean is made available under an MIT license: https://github.com/matplotlib/cmocean/blob/master/LICENSE.txt
|
||||
"""
|
||||
|
||||
from ._swatches import _swatches, _swatches_continuous
|
||||
|
||||
|
||||
def swatches(template=None):
|
||||
return _swatches(__name__, globals(), template)
|
||||
|
||||
|
||||
swatches.__doc__ = _swatches.__doc__
|
||||
|
||||
|
||||
def swatches_continuous(template=None):
|
||||
return _swatches_continuous(__name__, globals(), template)
|
||||
|
||||
|
||||
swatches_continuous.__doc__ = _swatches_continuous.__doc__
|
||||
|
||||
|
||||
turbid = [
|
||||
"rgb(232, 245, 171)",
|
||||
"rgb(220, 219, 137)",
|
||||
"rgb(209, 193, 107)",
|
||||
"rgb(199, 168, 83)",
|
||||
"rgb(186, 143, 66)",
|
||||
"rgb(170, 121, 60)",
|
||||
"rgb(151, 103, 58)",
|
||||
"rgb(129, 87, 56)",
|
||||
"rgb(104, 72, 53)",
|
||||
"rgb(80, 59, 46)",
|
||||
"rgb(57, 45, 37)",
|
||||
"rgb(34, 30, 27)",
|
||||
]
|
||||
thermal = [
|
||||
"rgb(3, 35, 51)",
|
||||
"rgb(13, 48, 100)",
|
||||
"rgb(53, 50, 155)",
|
||||
"rgb(93, 62, 153)",
|
||||
"rgb(126, 77, 143)",
|
||||
"rgb(158, 89, 135)",
|
||||
"rgb(193, 100, 121)",
|
||||
"rgb(225, 113, 97)",
|
||||
"rgb(246, 139, 69)",
|
||||
"rgb(251, 173, 60)",
|
||||
"rgb(246, 211, 70)",
|
||||
"rgb(231, 250, 90)",
|
||||
]
|
||||
haline = [
|
||||
"rgb(41, 24, 107)",
|
||||
"rgb(42, 35, 160)",
|
||||
"rgb(15, 71, 153)",
|
||||
"rgb(18, 95, 142)",
|
||||
"rgb(38, 116, 137)",
|
||||
"rgb(53, 136, 136)",
|
||||
"rgb(65, 157, 133)",
|
||||
"rgb(81, 178, 124)",
|
||||
"rgb(111, 198, 107)",
|
||||
"rgb(160, 214, 91)",
|
||||
"rgb(212, 225, 112)",
|
||||
"rgb(253, 238, 153)",
|
||||
]
|
||||
solar = [
|
||||
"rgb(51, 19, 23)",
|
||||
"rgb(79, 28, 33)",
|
||||
"rgb(108, 36, 36)",
|
||||
"rgb(135, 47, 32)",
|
||||
"rgb(157, 66, 25)",
|
||||
"rgb(174, 88, 20)",
|
||||
"rgb(188, 111, 19)",
|
||||
"rgb(199, 137, 22)",
|
||||
"rgb(209, 164, 32)",
|
||||
"rgb(217, 192, 44)",
|
||||
"rgb(222, 222, 59)",
|
||||
"rgb(224, 253, 74)",
|
||||
]
|
||||
ice = [
|
||||
"rgb(3, 5, 18)",
|
||||
"rgb(25, 25, 51)",
|
||||
"rgb(44, 42, 87)",
|
||||
"rgb(58, 60, 125)",
|
||||
"rgb(62, 83, 160)",
|
||||
"rgb(62, 109, 178)",
|
||||
"rgb(72, 134, 187)",
|
||||
"rgb(89, 159, 196)",
|
||||
"rgb(114, 184, 205)",
|
||||
"rgb(149, 207, 216)",
|
||||
"rgb(192, 229, 232)",
|
||||
"rgb(234, 252, 253)",
|
||||
]
|
||||
gray = [
|
||||
"rgb(0, 0, 0)",
|
||||
"rgb(16, 16, 16)",
|
||||
"rgb(38, 38, 38)",
|
||||
"rgb(59, 59, 59)",
|
||||
"rgb(81, 80, 80)",
|
||||
"rgb(102, 101, 101)",
|
||||
"rgb(124, 123, 122)",
|
||||
"rgb(146, 146, 145)",
|
||||
"rgb(171, 171, 170)",
|
||||
"rgb(197, 197, 195)",
|
||||
"rgb(224, 224, 223)",
|
||||
"rgb(254, 254, 253)",
|
||||
]
|
||||
oxy = [
|
||||
"rgb(63, 5, 5)",
|
||||
"rgb(101, 6, 13)",
|
||||
"rgb(138, 17, 9)",
|
||||
"rgb(96, 95, 95)",
|
||||
"rgb(119, 118, 118)",
|
||||
"rgb(142, 141, 141)",
|
||||
"rgb(166, 166, 165)",
|
||||
"rgb(193, 192, 191)",
|
||||
"rgb(222, 222, 220)",
|
||||
"rgb(239, 248, 90)",
|
||||
"rgb(230, 210, 41)",
|
||||
"rgb(220, 174, 25)",
|
||||
]
|
||||
deep = [
|
||||
"rgb(253, 253, 204)",
|
||||
"rgb(206, 236, 179)",
|
||||
"rgb(156, 219, 165)",
|
||||
"rgb(111, 201, 163)",
|
||||
"rgb(86, 177, 163)",
|
||||
"rgb(76, 153, 160)",
|
||||
"rgb(68, 130, 155)",
|
||||
"rgb(62, 108, 150)",
|
||||
"rgb(62, 82, 143)",
|
||||
"rgb(64, 60, 115)",
|
||||
"rgb(54, 43, 77)",
|
||||
"rgb(39, 26, 44)",
|
||||
]
|
||||
dense = [
|
||||
"rgb(230, 240, 240)",
|
||||
"rgb(191, 221, 229)",
|
||||
"rgb(156, 201, 226)",
|
||||
"rgb(129, 180, 227)",
|
||||
"rgb(115, 154, 228)",
|
||||
"rgb(117, 127, 221)",
|
||||
"rgb(120, 100, 202)",
|
||||
"rgb(119, 74, 175)",
|
||||
"rgb(113, 50, 141)",
|
||||
"rgb(100, 31, 104)",
|
||||
"rgb(80, 20, 66)",
|
||||
"rgb(54, 14, 36)",
|
||||
]
|
||||
algae = [
|
||||
"rgb(214, 249, 207)",
|
||||
"rgb(186, 228, 174)",
|
||||
"rgb(156, 209, 143)",
|
||||
"rgb(124, 191, 115)",
|
||||
"rgb(85, 174, 91)",
|
||||
"rgb(37, 157, 81)",
|
||||
"rgb(7, 138, 78)",
|
||||
"rgb(13, 117, 71)",
|
||||
"rgb(23, 95, 61)",
|
||||
"rgb(25, 75, 49)",
|
||||
"rgb(23, 55, 35)",
|
||||
"rgb(17, 36, 20)",
|
||||
]
|
||||
matter = [
|
||||
"rgb(253, 237, 176)",
|
||||
"rgb(250, 205, 145)",
|
||||
"rgb(246, 173, 119)",
|
||||
"rgb(240, 142, 98)",
|
||||
"rgb(231, 109, 84)",
|
||||
"rgb(216, 80, 83)",
|
||||
"rgb(195, 56, 90)",
|
||||
"rgb(168, 40, 96)",
|
||||
"rgb(138, 29, 99)",
|
||||
"rgb(107, 24, 93)",
|
||||
"rgb(76, 21, 80)",
|
||||
"rgb(47, 15, 61)",
|
||||
]
|
||||
speed = [
|
||||
"rgb(254, 252, 205)",
|
||||
"rgb(239, 225, 156)",
|
||||
"rgb(221, 201, 106)",
|
||||
"rgb(194, 182, 59)",
|
||||
"rgb(157, 167, 21)",
|
||||
"rgb(116, 153, 5)",
|
||||
"rgb(75, 138, 20)",
|
||||
"rgb(35, 121, 36)",
|
||||
"rgb(11, 100, 44)",
|
||||
"rgb(18, 78, 43)",
|
||||
"rgb(25, 56, 34)",
|
||||
"rgb(23, 35, 18)",
|
||||
]
|
||||
amp = [
|
||||
"rgb(241, 236, 236)",
|
||||
"rgb(230, 209, 203)",
|
||||
"rgb(221, 182, 170)",
|
||||
"rgb(213, 156, 137)",
|
||||
"rgb(205, 129, 103)",
|
||||
"rgb(196, 102, 73)",
|
||||
"rgb(186, 74, 47)",
|
||||
"rgb(172, 44, 36)",
|
||||
"rgb(149, 19, 39)",
|
||||
"rgb(120, 14, 40)",
|
||||
"rgb(89, 13, 31)",
|
||||
"rgb(60, 9, 17)",
|
||||
]
|
||||
tempo = [
|
||||
"rgb(254, 245, 244)",
|
||||
"rgb(222, 224, 210)",
|
||||
"rgb(189, 206, 181)",
|
||||
"rgb(153, 189, 156)",
|
||||
"rgb(110, 173, 138)",
|
||||
"rgb(65, 157, 129)",
|
||||
"rgb(25, 137, 125)",
|
||||
"rgb(18, 116, 117)",
|
||||
"rgb(25, 94, 106)",
|
||||
"rgb(28, 72, 93)",
|
||||
"rgb(25, 51, 80)",
|
||||
"rgb(20, 29, 67)",
|
||||
]
|
||||
phase = [
|
||||
"rgb(167, 119, 12)",
|
||||
"rgb(197, 96, 51)",
|
||||
"rgb(217, 67, 96)",
|
||||
"rgb(221, 38, 163)",
|
||||
"rgb(196, 59, 224)",
|
||||
"rgb(153, 97, 244)",
|
||||
"rgb(95, 127, 228)",
|
||||
"rgb(40, 144, 183)",
|
||||
"rgb(15, 151, 136)",
|
||||
"rgb(39, 153, 79)",
|
||||
"rgb(119, 141, 17)",
|
||||
"rgb(167, 119, 12)",
|
||||
]
|
||||
balance = [
|
||||
"rgb(23, 28, 66)",
|
||||
"rgb(41, 58, 143)",
|
||||
"rgb(11, 102, 189)",
|
||||
"rgb(69, 144, 185)",
|
||||
"rgb(142, 181, 194)",
|
||||
"rgb(210, 216, 219)",
|
||||
"rgb(230, 210, 204)",
|
||||
"rgb(213, 157, 137)",
|
||||
"rgb(196, 101, 72)",
|
||||
"rgb(172, 43, 36)",
|
||||
"rgb(120, 14, 40)",
|
||||
"rgb(60, 9, 17)",
|
||||
]
|
||||
delta = [
|
||||
"rgb(16, 31, 63)",
|
||||
"rgb(38, 62, 144)",
|
||||
"rgb(30, 110, 161)",
|
||||
"rgb(60, 154, 171)",
|
||||
"rgb(140, 193, 186)",
|
||||
"rgb(217, 229, 218)",
|
||||
"rgb(239, 226, 156)",
|
||||
"rgb(195, 182, 59)",
|
||||
"rgb(115, 152, 5)",
|
||||
"rgb(34, 120, 36)",
|
||||
"rgb(18, 78, 43)",
|
||||
"rgb(23, 35, 18)",
|
||||
]
|
||||
curl = [
|
||||
"rgb(20, 29, 67)",
|
||||
"rgb(28, 72, 93)",
|
||||
"rgb(18, 115, 117)",
|
||||
"rgb(63, 156, 129)",
|
||||
"rgb(153, 189, 156)",
|
||||
"rgb(223, 225, 211)",
|
||||
"rgb(241, 218, 206)",
|
||||
"rgb(224, 160, 137)",
|
||||
"rgb(203, 101, 99)",
|
||||
"rgb(164, 54, 96)",
|
||||
"rgb(111, 23, 91)",
|
||||
"rgb(51, 13, 53)",
|
||||
]
|
||||
|
||||
algae_r = algae[::-1]
|
||||
amp_r = amp[::-1]
|
||||
balance_r = balance[::-1]
|
||||
curl_r = curl[::-1]
|
||||
deep_r = deep[::-1]
|
||||
delta_r = delta[::-1]
|
||||
dense_r = dense[::-1]
|
||||
gray_r = gray[::-1]
|
||||
haline_r = haline[::-1]
|
||||
ice_r = ice[::-1]
|
||||
matter_r = matter[::-1]
|
||||
oxy_r = oxy[::-1]
|
||||
phase_r = phase[::-1]
|
||||
solar_r = solar[::-1]
|
||||
speed_r = speed[::-1]
|
||||
tempo_r = tempo[::-1]
|
||||
thermal_r = thermal[::-1]
|
||||
turbid_r = turbid[::-1]
|
||||
@@ -0,0 +1,494 @@
|
||||
"""
|
||||
Color scales and sequences from the colorbrewer 2 project
|
||||
|
||||
Learn more at http://colorbrewer2.org
|
||||
|
||||
colorbrewer is made available under an Apache license: http://colorbrewer2.org/export/LICENSE.txt
|
||||
"""
|
||||
|
||||
from ._swatches import _swatches
|
||||
|
||||
|
||||
def swatches(template=None):
|
||||
return _swatches(__name__, globals(), template)
|
||||
|
||||
|
||||
swatches.__doc__ = _swatches.__doc__
|
||||
|
||||
BrBG = [
|
||||
"rgb(84,48,5)",
|
||||
"rgb(140,81,10)",
|
||||
"rgb(191,129,45)",
|
||||
"rgb(223,194,125)",
|
||||
"rgb(246,232,195)",
|
||||
"rgb(245,245,245)",
|
||||
"rgb(199,234,229)",
|
||||
"rgb(128,205,193)",
|
||||
"rgb(53,151,143)",
|
||||
"rgb(1,102,94)",
|
||||
"rgb(0,60,48)",
|
||||
]
|
||||
|
||||
PRGn = [
|
||||
"rgb(64,0,75)",
|
||||
"rgb(118,42,131)",
|
||||
"rgb(153,112,171)",
|
||||
"rgb(194,165,207)",
|
||||
"rgb(231,212,232)",
|
||||
"rgb(247,247,247)",
|
||||
"rgb(217,240,211)",
|
||||
"rgb(166,219,160)",
|
||||
"rgb(90,174,97)",
|
||||
"rgb(27,120,55)",
|
||||
"rgb(0,68,27)",
|
||||
]
|
||||
|
||||
PiYG = [
|
||||
"rgb(142,1,82)",
|
||||
"rgb(197,27,125)",
|
||||
"rgb(222,119,174)",
|
||||
"rgb(241,182,218)",
|
||||
"rgb(253,224,239)",
|
||||
"rgb(247,247,247)",
|
||||
"rgb(230,245,208)",
|
||||
"rgb(184,225,134)",
|
||||
"rgb(127,188,65)",
|
||||
"rgb(77,146,33)",
|
||||
"rgb(39,100,25)",
|
||||
]
|
||||
|
||||
PuOr = [
|
||||
"rgb(127,59,8)",
|
||||
"rgb(179,88,6)",
|
||||
"rgb(224,130,20)",
|
||||
"rgb(253,184,99)",
|
||||
"rgb(254,224,182)",
|
||||
"rgb(247,247,247)",
|
||||
"rgb(216,218,235)",
|
||||
"rgb(178,171,210)",
|
||||
"rgb(128,115,172)",
|
||||
"rgb(84,39,136)",
|
||||
"rgb(45,0,75)",
|
||||
]
|
||||
|
||||
RdBu = [
|
||||
"rgb(103,0,31)",
|
||||
"rgb(178,24,43)",
|
||||
"rgb(214,96,77)",
|
||||
"rgb(244,165,130)",
|
||||
"rgb(253,219,199)",
|
||||
"rgb(247,247,247)",
|
||||
"rgb(209,229,240)",
|
||||
"rgb(146,197,222)",
|
||||
"rgb(67,147,195)",
|
||||
"rgb(33,102,172)",
|
||||
"rgb(5,48,97)",
|
||||
]
|
||||
|
||||
RdGy = [
|
||||
"rgb(103,0,31)",
|
||||
"rgb(178,24,43)",
|
||||
"rgb(214,96,77)",
|
||||
"rgb(244,165,130)",
|
||||
"rgb(253,219,199)",
|
||||
"rgb(255,255,255)",
|
||||
"rgb(224,224,224)",
|
||||
"rgb(186,186,186)",
|
||||
"rgb(135,135,135)",
|
||||
"rgb(77,77,77)",
|
||||
"rgb(26,26,26)",
|
||||
]
|
||||
|
||||
RdYlBu = [
|
||||
"rgb(165,0,38)",
|
||||
"rgb(215,48,39)",
|
||||
"rgb(244,109,67)",
|
||||
"rgb(253,174,97)",
|
||||
"rgb(254,224,144)",
|
||||
"rgb(255,255,191)",
|
||||
"rgb(224,243,248)",
|
||||
"rgb(171,217,233)",
|
||||
"rgb(116,173,209)",
|
||||
"rgb(69,117,180)",
|
||||
"rgb(49,54,149)",
|
||||
]
|
||||
|
||||
RdYlGn = [
|
||||
"rgb(165,0,38)",
|
||||
"rgb(215,48,39)",
|
||||
"rgb(244,109,67)",
|
||||
"rgb(253,174,97)",
|
||||
"rgb(254,224,139)",
|
||||
"rgb(255,255,191)",
|
||||
"rgb(217,239,139)",
|
||||
"rgb(166,217,106)",
|
||||
"rgb(102,189,99)",
|
||||
"rgb(26,152,80)",
|
||||
"rgb(0,104,55)",
|
||||
]
|
||||
|
||||
Spectral = [
|
||||
"rgb(158,1,66)",
|
||||
"rgb(213,62,79)",
|
||||
"rgb(244,109,67)",
|
||||
"rgb(253,174,97)",
|
||||
"rgb(254,224,139)",
|
||||
"rgb(255,255,191)",
|
||||
"rgb(230,245,152)",
|
||||
"rgb(171,221,164)",
|
||||
"rgb(102,194,165)",
|
||||
"rgb(50,136,189)",
|
||||
"rgb(94,79,162)",
|
||||
]
|
||||
|
||||
Set1 = [
|
||||
"rgb(228,26,28)",
|
||||
"rgb(55,126,184)",
|
||||
"rgb(77,175,74)",
|
||||
"rgb(152,78,163)",
|
||||
"rgb(255,127,0)",
|
||||
"rgb(255,255,51)",
|
||||
"rgb(166,86,40)",
|
||||
"rgb(247,129,191)",
|
||||
"rgb(153,153,153)",
|
||||
]
|
||||
|
||||
|
||||
Pastel1 = [
|
||||
"rgb(251,180,174)",
|
||||
"rgb(179,205,227)",
|
||||
"rgb(204,235,197)",
|
||||
"rgb(222,203,228)",
|
||||
"rgb(254,217,166)",
|
||||
"rgb(255,255,204)",
|
||||
"rgb(229,216,189)",
|
||||
"rgb(253,218,236)",
|
||||
"rgb(242,242,242)",
|
||||
]
|
||||
Dark2 = [
|
||||
"rgb(27,158,119)",
|
||||
"rgb(217,95,2)",
|
||||
"rgb(117,112,179)",
|
||||
"rgb(231,41,138)",
|
||||
"rgb(102,166,30)",
|
||||
"rgb(230,171,2)",
|
||||
"rgb(166,118,29)",
|
||||
"rgb(102,102,102)",
|
||||
]
|
||||
Set2 = [
|
||||
"rgb(102,194,165)",
|
||||
"rgb(252,141,98)",
|
||||
"rgb(141,160,203)",
|
||||
"rgb(231,138,195)",
|
||||
"rgb(166,216,84)",
|
||||
"rgb(255,217,47)",
|
||||
"rgb(229,196,148)",
|
||||
"rgb(179,179,179)",
|
||||
]
|
||||
|
||||
|
||||
Pastel2 = [
|
||||
"rgb(179,226,205)",
|
||||
"rgb(253,205,172)",
|
||||
"rgb(203,213,232)",
|
||||
"rgb(244,202,228)",
|
||||
"rgb(230,245,201)",
|
||||
"rgb(255,242,174)",
|
||||
"rgb(241,226,204)",
|
||||
"rgb(204,204,204)",
|
||||
]
|
||||
|
||||
Set3 = [
|
||||
"rgb(141,211,199)",
|
||||
"rgb(255,255,179)",
|
||||
"rgb(190,186,218)",
|
||||
"rgb(251,128,114)",
|
||||
"rgb(128,177,211)",
|
||||
"rgb(253,180,98)",
|
||||
"rgb(179,222,105)",
|
||||
"rgb(252,205,229)",
|
||||
"rgb(217,217,217)",
|
||||
"rgb(188,128,189)",
|
||||
"rgb(204,235,197)",
|
||||
"rgb(255,237,111)",
|
||||
]
|
||||
|
||||
Accent = [
|
||||
"rgb(127,201,127)",
|
||||
"rgb(190,174,212)",
|
||||
"rgb(253,192,134)",
|
||||
"rgb(255,255,153)",
|
||||
"rgb(56,108,176)",
|
||||
"rgb(240,2,127)",
|
||||
"rgb(191,91,23)",
|
||||
"rgb(102,102,102)",
|
||||
]
|
||||
|
||||
|
||||
Paired = [
|
||||
"rgb(166,206,227)",
|
||||
"rgb(31,120,180)",
|
||||
"rgb(178,223,138)",
|
||||
"rgb(51,160,44)",
|
||||
"rgb(251,154,153)",
|
||||
"rgb(227,26,28)",
|
||||
"rgb(253,191,111)",
|
||||
"rgb(255,127,0)",
|
||||
"rgb(202,178,214)",
|
||||
"rgb(106,61,154)",
|
||||
"rgb(255,255,153)",
|
||||
"rgb(177,89,40)",
|
||||
]
|
||||
|
||||
|
||||
Blues = [
|
||||
"rgb(247,251,255)",
|
||||
"rgb(222,235,247)",
|
||||
"rgb(198,219,239)",
|
||||
"rgb(158,202,225)",
|
||||
"rgb(107,174,214)",
|
||||
"rgb(66,146,198)",
|
||||
"rgb(33,113,181)",
|
||||
"rgb(8,81,156)",
|
||||
"rgb(8,48,107)",
|
||||
]
|
||||
|
||||
BuGn = [
|
||||
"rgb(247,252,253)",
|
||||
"rgb(229,245,249)",
|
||||
"rgb(204,236,230)",
|
||||
"rgb(153,216,201)",
|
||||
"rgb(102,194,164)",
|
||||
"rgb(65,174,118)",
|
||||
"rgb(35,139,69)",
|
||||
"rgb(0,109,44)",
|
||||
"rgb(0,68,27)",
|
||||
]
|
||||
|
||||
BuPu = [
|
||||
"rgb(247,252,253)",
|
||||
"rgb(224,236,244)",
|
||||
"rgb(191,211,230)",
|
||||
"rgb(158,188,218)",
|
||||
"rgb(140,150,198)",
|
||||
"rgb(140,107,177)",
|
||||
"rgb(136,65,157)",
|
||||
"rgb(129,15,124)",
|
||||
"rgb(77,0,75)",
|
||||
]
|
||||
|
||||
GnBu = [
|
||||
"rgb(247,252,240)",
|
||||
"rgb(224,243,219)",
|
||||
"rgb(204,235,197)",
|
||||
"rgb(168,221,181)",
|
||||
"rgb(123,204,196)",
|
||||
"rgb(78,179,211)",
|
||||
"rgb(43,140,190)",
|
||||
"rgb(8,104,172)",
|
||||
"rgb(8,64,129)",
|
||||
]
|
||||
|
||||
Greens = [
|
||||
"rgb(247,252,245)",
|
||||
"rgb(229,245,224)",
|
||||
"rgb(199,233,192)",
|
||||
"rgb(161,217,155)",
|
||||
"rgb(116,196,118)",
|
||||
"rgb(65,171,93)",
|
||||
"rgb(35,139,69)",
|
||||
"rgb(0,109,44)",
|
||||
"rgb(0,68,27)",
|
||||
]
|
||||
|
||||
Greys = [
|
||||
"rgb(255,255,255)",
|
||||
"rgb(240,240,240)",
|
||||
"rgb(217,217,217)",
|
||||
"rgb(189,189,189)",
|
||||
"rgb(150,150,150)",
|
||||
"rgb(115,115,115)",
|
||||
"rgb(82,82,82)",
|
||||
"rgb(37,37,37)",
|
||||
"rgb(0,0,0)",
|
||||
]
|
||||
|
||||
OrRd = [
|
||||
"rgb(255,247,236)",
|
||||
"rgb(254,232,200)",
|
||||
"rgb(253,212,158)",
|
||||
"rgb(253,187,132)",
|
||||
"rgb(252,141,89)",
|
||||
"rgb(239,101,72)",
|
||||
"rgb(215,48,31)",
|
||||
"rgb(179,0,0)",
|
||||
"rgb(127,0,0)",
|
||||
]
|
||||
|
||||
Oranges = [
|
||||
"rgb(255,245,235)",
|
||||
"rgb(254,230,206)",
|
||||
"rgb(253,208,162)",
|
||||
"rgb(253,174,107)",
|
||||
"rgb(253,141,60)",
|
||||
"rgb(241,105,19)",
|
||||
"rgb(217,72,1)",
|
||||
"rgb(166,54,3)",
|
||||
"rgb(127,39,4)",
|
||||
]
|
||||
|
||||
PuBu = [
|
||||
"rgb(255,247,251)",
|
||||
"rgb(236,231,242)",
|
||||
"rgb(208,209,230)",
|
||||
"rgb(166,189,219)",
|
||||
"rgb(116,169,207)",
|
||||
"rgb(54,144,192)",
|
||||
"rgb(5,112,176)",
|
||||
"rgb(4,90,141)",
|
||||
"rgb(2,56,88)",
|
||||
]
|
||||
|
||||
PuBuGn = [
|
||||
"rgb(255,247,251)",
|
||||
"rgb(236,226,240)",
|
||||
"rgb(208,209,230)",
|
||||
"rgb(166,189,219)",
|
||||
"rgb(103,169,207)",
|
||||
"rgb(54,144,192)",
|
||||
"rgb(2,129,138)",
|
||||
"rgb(1,108,89)",
|
||||
"rgb(1,70,54)",
|
||||
]
|
||||
|
||||
PuRd = [
|
||||
"rgb(247,244,249)",
|
||||
"rgb(231,225,239)",
|
||||
"rgb(212,185,218)",
|
||||
"rgb(201,148,199)",
|
||||
"rgb(223,101,176)",
|
||||
"rgb(231,41,138)",
|
||||
"rgb(206,18,86)",
|
||||
"rgb(152,0,67)",
|
||||
"rgb(103,0,31)",
|
||||
]
|
||||
|
||||
Purples = [
|
||||
"rgb(252,251,253)",
|
||||
"rgb(239,237,245)",
|
||||
"rgb(218,218,235)",
|
||||
"rgb(188,189,220)",
|
||||
"rgb(158,154,200)",
|
||||
"rgb(128,125,186)",
|
||||
"rgb(106,81,163)",
|
||||
"rgb(84,39,143)",
|
||||
"rgb(63,0,125)",
|
||||
]
|
||||
|
||||
RdPu = [
|
||||
"rgb(255,247,243)",
|
||||
"rgb(253,224,221)",
|
||||
"rgb(252,197,192)",
|
||||
"rgb(250,159,181)",
|
||||
"rgb(247,104,161)",
|
||||
"rgb(221,52,151)",
|
||||
"rgb(174,1,126)",
|
||||
"rgb(122,1,119)",
|
||||
"rgb(73,0,106)",
|
||||
]
|
||||
|
||||
Reds = [
|
||||
"rgb(255,245,240)",
|
||||
"rgb(254,224,210)",
|
||||
"rgb(252,187,161)",
|
||||
"rgb(252,146,114)",
|
||||
"rgb(251,106,74)",
|
||||
"rgb(239,59,44)",
|
||||
"rgb(203,24,29)",
|
||||
"rgb(165,15,21)",
|
||||
"rgb(103,0,13)",
|
||||
]
|
||||
|
||||
YlGn = [
|
||||
"rgb(255,255,229)",
|
||||
"rgb(247,252,185)",
|
||||
"rgb(217,240,163)",
|
||||
"rgb(173,221,142)",
|
||||
"rgb(120,198,121)",
|
||||
"rgb(65,171,93)",
|
||||
"rgb(35,132,67)",
|
||||
"rgb(0,104,55)",
|
||||
"rgb(0,69,41)",
|
||||
]
|
||||
|
||||
YlGnBu = [
|
||||
"rgb(255,255,217)",
|
||||
"rgb(237,248,177)",
|
||||
"rgb(199,233,180)",
|
||||
"rgb(127,205,187)",
|
||||
"rgb(65,182,196)",
|
||||
"rgb(29,145,192)",
|
||||
"rgb(34,94,168)",
|
||||
"rgb(37,52,148)",
|
||||
"rgb(8,29,88)",
|
||||
]
|
||||
|
||||
YlOrBr = [
|
||||
"rgb(255,255,229)",
|
||||
"rgb(255,247,188)",
|
||||
"rgb(254,227,145)",
|
||||
"rgb(254,196,79)",
|
||||
"rgb(254,153,41)",
|
||||
"rgb(236,112,20)",
|
||||
"rgb(204,76,2)",
|
||||
"rgb(153,52,4)",
|
||||
"rgb(102,37,6)",
|
||||
]
|
||||
|
||||
YlOrRd = [
|
||||
"rgb(255,255,204)",
|
||||
"rgb(255,237,160)",
|
||||
"rgb(254,217,118)",
|
||||
"rgb(254,178,76)",
|
||||
"rgb(253,141,60)",
|
||||
"rgb(252,78,42)",
|
||||
"rgb(227,26,28)",
|
||||
"rgb(189,0,38)",
|
||||
"rgb(128,0,38)",
|
||||
]
|
||||
|
||||
Accent_r = Accent[::-1]
|
||||
Blues_r = Blues[::-1]
|
||||
BrBG_r = BrBG[::-1]
|
||||
BuGn_r = BuGn[::-1]
|
||||
BuPu_r = BuPu[::-1]
|
||||
Dark2_r = Dark2[::-1]
|
||||
GnBu_r = GnBu[::-1]
|
||||
Greens_r = Greens[::-1]
|
||||
Greys_r = Greys[::-1]
|
||||
OrRd_r = OrRd[::-1]
|
||||
Oranges_r = Oranges[::-1]
|
||||
PRGn_r = PRGn[::-1]
|
||||
Paired_r = Paired[::-1]
|
||||
Pastel1_r = Pastel1[::-1]
|
||||
Pastel2_r = Pastel2[::-1]
|
||||
PiYG_r = PiYG[::-1]
|
||||
PuBu_r = PuBu[::-1]
|
||||
PuBuGn_r = PuBuGn[::-1]
|
||||
PuOr_r = PuOr[::-1]
|
||||
PuRd_r = PuRd[::-1]
|
||||
Purples_r = Purples[::-1]
|
||||
RdBu_r = RdBu[::-1]
|
||||
RdGy_r = RdGy[::-1]
|
||||
RdPu_r = RdPu[::-1]
|
||||
RdYlBu_r = RdYlBu[::-1]
|
||||
RdYlGn_r = RdYlGn[::-1]
|
||||
Reds_r = Reds[::-1]
|
||||
Set1_r = Set1[::-1]
|
||||
Set2_r = Set2[::-1]
|
||||
Set3_r = Set3[::-1]
|
||||
Spectral_r = Spectral[::-1]
|
||||
YlGn_r = YlGn[::-1]
|
||||
YlGnBu_r = YlGnBu[::-1]
|
||||
YlOrBr_r = YlOrBr[::-1]
|
||||
YlOrRd_r = YlOrRd[::-1]
|
||||
@@ -0,0 +1,157 @@
|
||||
"""
|
||||
Cyclical color scales are appropriate for continuous data that has a natural cyclical \
|
||||
structure, such as temporal data (hour of day, day of week, day of year, seasons) or
|
||||
complex numbers or other phase data.
|
||||
"""
|
||||
|
||||
from ._swatches import _swatches, _swatches_continuous, _swatches_cyclical
|
||||
|
||||
|
||||
def swatches(template=None):
|
||||
return _swatches(__name__, globals(), template)
|
||||
|
||||
|
||||
swatches.__doc__ = _swatches.__doc__
|
||||
|
||||
|
||||
def swatches_continuous(template=None):
|
||||
return _swatches_continuous(__name__, globals(), template)
|
||||
|
||||
|
||||
swatches_continuous.__doc__ = _swatches_continuous.__doc__
|
||||
|
||||
|
||||
def swatches_cyclical(template=None):
|
||||
return _swatches_cyclical(__name__, globals(), template)
|
||||
|
||||
|
||||
swatches_cyclical.__doc__ = _swatches_cyclical.__doc__
|
||||
|
||||
|
||||
Twilight = [
|
||||
"#e2d9e2",
|
||||
"#9ebbc9",
|
||||
"#6785be",
|
||||
"#5e43a5",
|
||||
"#421257",
|
||||
"#471340",
|
||||
"#8e2c50",
|
||||
"#ba6657",
|
||||
"#ceac94",
|
||||
"#e2d9e2",
|
||||
]
|
||||
IceFire = [
|
||||
"#000000",
|
||||
"#001f4d",
|
||||
"#003786",
|
||||
"#0e58a8",
|
||||
"#217eb8",
|
||||
"#30a4ca",
|
||||
"#54c8df",
|
||||
"#9be4ef",
|
||||
"#e1e9d1",
|
||||
"#f3d573",
|
||||
"#e7b000",
|
||||
"#da8200",
|
||||
"#c65400",
|
||||
"#ac2301",
|
||||
"#820000",
|
||||
"#4c0000",
|
||||
"#000000",
|
||||
]
|
||||
Edge = [
|
||||
"#313131",
|
||||
"#3d019d",
|
||||
"#3810dc",
|
||||
"#2d47f9",
|
||||
"#2593ff",
|
||||
"#2adef6",
|
||||
"#60fdfa",
|
||||
"#aefdff",
|
||||
"#f3f3f1",
|
||||
"#fffda9",
|
||||
"#fafd5b",
|
||||
"#f7da29",
|
||||
"#ff8e25",
|
||||
"#f8432d",
|
||||
"#d90d39",
|
||||
"#97023d",
|
||||
"#313131",
|
||||
]
|
||||
Phase = [
|
||||
"rgb(167, 119, 12)",
|
||||
"rgb(197, 96, 51)",
|
||||
"rgb(217, 67, 96)",
|
||||
"rgb(221, 38, 163)",
|
||||
"rgb(196, 59, 224)",
|
||||
"rgb(153, 97, 244)",
|
||||
"rgb(95, 127, 228)",
|
||||
"rgb(40, 144, 183)",
|
||||
"rgb(15, 151, 136)",
|
||||
"rgb(39, 153, 79)",
|
||||
"rgb(119, 141, 17)",
|
||||
"rgb(167, 119, 12)",
|
||||
]
|
||||
HSV = [
|
||||
"#ff0000",
|
||||
"#ffa700",
|
||||
"#afff00",
|
||||
"#08ff00",
|
||||
"#00ff9f",
|
||||
"#00b7ff",
|
||||
"#0010ff",
|
||||
"#9700ff",
|
||||
"#ff00bf",
|
||||
"#ff0000",
|
||||
]
|
||||
mrybm = [
|
||||
"#f884f7",
|
||||
"#f968c4",
|
||||
"#ea4388",
|
||||
"#cf244b",
|
||||
"#b51a15",
|
||||
"#bd4304",
|
||||
"#cc6904",
|
||||
"#d58f04",
|
||||
"#cfaa27",
|
||||
"#a19f62",
|
||||
"#588a93",
|
||||
"#2269c4",
|
||||
"#3e3ef0",
|
||||
"#6b4ef9",
|
||||
"#956bfa",
|
||||
"#cd7dfe",
|
||||
"#f884f7",
|
||||
]
|
||||
mygbm = [
|
||||
"#ef55f1",
|
||||
"#fb84ce",
|
||||
"#fbafa1",
|
||||
"#fcd471",
|
||||
"#f0ed35",
|
||||
"#c6e516",
|
||||
"#96d310",
|
||||
"#61c10b",
|
||||
"#31ac28",
|
||||
"#439064",
|
||||
"#3d719a",
|
||||
"#284ec8",
|
||||
"#2e21ea",
|
||||
"#6324f5",
|
||||
"#9139fa",
|
||||
"#c543fa",
|
||||
"#ef55f1",
|
||||
]
|
||||
|
||||
Edge_r = Edge[::-1]
|
||||
HSV_r = HSV[::-1]
|
||||
IceFire_r = IceFire[::-1]
|
||||
Phase_r = Phase[::-1]
|
||||
Twilight_r = Twilight[::-1]
|
||||
mrybm_r = mrybm[::-1]
|
||||
mygbm_r = mygbm[::-1]
|
||||
|
||||
__all__ = [
|
||||
"swatches",
|
||||
"swatches_cyclical",
|
||||
]
|
||||
@@ -0,0 +1,75 @@
|
||||
"""
|
||||
Diverging color scales are appropriate for continuous data that has a natural midpoint \
|
||||
other otherwise informative special value, such as 0 altitude, or the boiling point
|
||||
of a liquid. The color scales in this module are \
|
||||
mostly meant to be passed in as the `color_continuous_scale` argument to various \
|
||||
functions, and to be used with the `color_continuous_midpoint` argument.
|
||||
"""
|
||||
|
||||
from .colorbrewer import ( # noqa: F401
|
||||
BrBG,
|
||||
PRGn,
|
||||
PiYG,
|
||||
PuOr,
|
||||
RdBu,
|
||||
RdGy,
|
||||
RdYlBu,
|
||||
RdYlGn,
|
||||
Spectral,
|
||||
BrBG_r,
|
||||
PRGn_r,
|
||||
PiYG_r,
|
||||
PuOr_r,
|
||||
RdBu_r,
|
||||
RdGy_r,
|
||||
RdYlBu_r,
|
||||
RdYlGn_r,
|
||||
Spectral_r,
|
||||
)
|
||||
from .cmocean import ( # noqa: F401
|
||||
balance,
|
||||
delta,
|
||||
curl,
|
||||
oxy,
|
||||
balance_r,
|
||||
delta_r,
|
||||
curl_r,
|
||||
oxy_r,
|
||||
)
|
||||
from .carto import ( # noqa: F401
|
||||
Armyrose,
|
||||
Fall,
|
||||
Geyser,
|
||||
Temps,
|
||||
Tealrose,
|
||||
Tropic,
|
||||
Earth,
|
||||
Armyrose_r,
|
||||
Fall_r,
|
||||
Geyser_r,
|
||||
Temps_r,
|
||||
Tealrose_r,
|
||||
Tropic_r,
|
||||
Earth_r,
|
||||
)
|
||||
|
||||
from .plotlyjs import Picnic, Portland, Picnic_r, Portland_r # noqa: F401
|
||||
|
||||
from ._swatches import _swatches, _swatches_continuous
|
||||
|
||||
|
||||
def swatches(template=None):
|
||||
return _swatches(__name__, globals(), template)
|
||||
|
||||
|
||||
swatches.__doc__ = _swatches.__doc__
|
||||
|
||||
|
||||
def swatches_continuous(template=None):
|
||||
return _swatches_continuous(__name__, globals(), template)
|
||||
|
||||
|
||||
swatches_continuous.__doc__ = _swatches_continuous.__doc__
|
||||
|
||||
|
||||
__all__ = ["swatches"]
|
||||
@@ -0,0 +1,180 @@
|
||||
# Copied from
|
||||
# https://github.com/plotly/plotly.js/blob/master/src/components/colorscale/scales.js
|
||||
|
||||
# NOTE: these differ slightly from plotly.colors.PLOTLY_SCALES from Plotly.js because
|
||||
# those ones don't have perfectly evenly spaced steps ...
|
||||
# not sure when this skew was introduced, possibly as early as Plotly.py v4.0
|
||||
|
||||
Blackbody = [
|
||||
"rgb(0,0,0)",
|
||||
"rgb(230,0,0)",
|
||||
"rgb(230,210,0)",
|
||||
"rgb(255,255,255)",
|
||||
"rgb(160,200,255)",
|
||||
]
|
||||
Bluered = ["rgb(0,0,255)", "rgb(255,0,0)"]
|
||||
Blues = [
|
||||
"rgb(5,10,172)",
|
||||
"rgb(40,60,190)",
|
||||
"rgb(70,100,245)",
|
||||
"rgb(90,120,245)",
|
||||
"rgb(106,137,247)",
|
||||
"rgb(220,220,220)",
|
||||
]
|
||||
Cividis = [
|
||||
"rgb(0,32,76)",
|
||||
"rgb(0,42,102)",
|
||||
"rgb(0,52,110)",
|
||||
"rgb(39,63,108)",
|
||||
"rgb(60,74,107)",
|
||||
"rgb(76,85,107)",
|
||||
"rgb(91,95,109)",
|
||||
"rgb(104,106,112)",
|
||||
"rgb(117,117,117)",
|
||||
"rgb(131,129,120)",
|
||||
"rgb(146,140,120)",
|
||||
"rgb(161,152,118)",
|
||||
"rgb(176,165,114)",
|
||||
"rgb(192,177,109)",
|
||||
"rgb(209,191,102)",
|
||||
"rgb(225,204,92)",
|
||||
"rgb(243,219,79)",
|
||||
"rgb(255,233,69)",
|
||||
]
|
||||
Earth = [
|
||||
"rgb(0,0,130)",
|
||||
"rgb(0,180,180)",
|
||||
"rgb(40,210,40)",
|
||||
"rgb(230,230,50)",
|
||||
"rgb(120,70,20)",
|
||||
"rgb(255,255,255)",
|
||||
]
|
||||
Electric = [
|
||||
"rgb(0,0,0)",
|
||||
"rgb(30,0,100)",
|
||||
"rgb(120,0,100)",
|
||||
"rgb(160,90,0)",
|
||||
"rgb(230,200,0)",
|
||||
"rgb(255,250,220)",
|
||||
]
|
||||
Greens = [
|
||||
"rgb(0,68,27)",
|
||||
"rgb(0,109,44)",
|
||||
"rgb(35,139,69)",
|
||||
"rgb(65,171,93)",
|
||||
"rgb(116,196,118)",
|
||||
"rgb(161,217,155)",
|
||||
"rgb(199,233,192)",
|
||||
"rgb(229,245,224)",
|
||||
"rgb(247,252,245)",
|
||||
]
|
||||
Greys = ["rgb(0,0,0)", "rgb(255,255,255)"]
|
||||
Hot = ["rgb(0,0,0)", "rgb(230,0,0)", "rgb(255,210,0)", "rgb(255,255,255)"]
|
||||
Jet = [
|
||||
"rgb(0,0,131)",
|
||||
"rgb(0,60,170)",
|
||||
"rgb(5,255,255)",
|
||||
"rgb(255,255,0)",
|
||||
"rgb(250,0,0)",
|
||||
"rgb(128,0,0)",
|
||||
]
|
||||
Picnic = [
|
||||
"rgb(0,0,255)",
|
||||
"rgb(51,153,255)",
|
||||
"rgb(102,204,255)",
|
||||
"rgb(153,204,255)",
|
||||
"rgb(204,204,255)",
|
||||
"rgb(255,255,255)",
|
||||
"rgb(255,204,255)",
|
||||
"rgb(255,153,255)",
|
||||
"rgb(255,102,204)",
|
||||
"rgb(255,102,102)",
|
||||
"rgb(255,0,0)",
|
||||
]
|
||||
Portland = [
|
||||
"rgb(12,51,131)",
|
||||
"rgb(10,136,186)",
|
||||
"rgb(242,211,56)",
|
||||
"rgb(242,143,56)",
|
||||
"rgb(217,30,30)",
|
||||
]
|
||||
Rainbow = [
|
||||
"rgb(150,0,90)",
|
||||
"rgb(0,0,200)",
|
||||
"rgb(0,25,255)",
|
||||
"rgb(0,152,255)",
|
||||
"rgb(44,255,150)",
|
||||
"rgb(151,255,0)",
|
||||
"rgb(255,234,0)",
|
||||
"rgb(255,111,0)",
|
||||
"rgb(255,0,0)",
|
||||
]
|
||||
RdBu = [
|
||||
"rgb(5,10,172)",
|
||||
"rgb(106,137,247)",
|
||||
"rgb(190,190,190)",
|
||||
"rgb(220,170,132)",
|
||||
"rgb(230,145,90)",
|
||||
"rgb(178,10,28)",
|
||||
]
|
||||
Reds = ["rgb(220,220,220)", "rgb(245,195,157)", "rgb(245,160,105)", "rgb(178,10,28)"]
|
||||
Viridis = [
|
||||
"#440154",
|
||||
"#48186a",
|
||||
"#472d7b",
|
||||
"#424086",
|
||||
"#3b528b",
|
||||
"#33638d",
|
||||
"#2c728e",
|
||||
"#26828e",
|
||||
"#21918c",
|
||||
"#1fa088",
|
||||
"#28ae80",
|
||||
"#3fbc73",
|
||||
"#5ec962",
|
||||
"#84d44b",
|
||||
"#addc30",
|
||||
"#d8e219",
|
||||
"#fde725",
|
||||
]
|
||||
YlGnBu = [
|
||||
"rgb(8,29,88)",
|
||||
"rgb(37,52,148)",
|
||||
"rgb(34,94,168)",
|
||||
"rgb(29,145,192)",
|
||||
"rgb(65,182,196)",
|
||||
"rgb(127,205,187)",
|
||||
"rgb(199,233,180)",
|
||||
"rgb(237,248,217)",
|
||||
"rgb(255,255,217)",
|
||||
]
|
||||
YlOrRd = [
|
||||
"rgb(128,0,38)",
|
||||
"rgb(189,0,38)",
|
||||
"rgb(227,26,28)",
|
||||
"rgb(252,78,42)",
|
||||
"rgb(253,141,60)",
|
||||
"rgb(254,178,76)",
|
||||
"rgb(254,217,118)",
|
||||
"rgb(255,237,160)",
|
||||
"rgb(255,255,204)",
|
||||
]
|
||||
|
||||
Blackbody_r = Blackbody[::-1]
|
||||
Bluered_r = Bluered[::-1]
|
||||
Blues_r = Blues[::-1]
|
||||
Cividis_r = Cividis[::-1]
|
||||
Earth_r = Earth[::-1]
|
||||
Electric_r = Electric[::-1]
|
||||
Greens_r = Greens[::-1]
|
||||
Greys_r = Greys[::-1]
|
||||
Hot_r = Hot[::-1]
|
||||
Jet_r = Jet[::-1]
|
||||
Picnic_r = Picnic[::-1]
|
||||
Portland_r = Portland[::-1]
|
||||
Rainbow_r = Rainbow[::-1]
|
||||
RdBu_r = RdBu[::-1]
|
||||
Reds_r = Reds[::-1]
|
||||
Viridis_r = Viridis[::-1]
|
||||
YlGnBu_r = YlGnBu[::-1]
|
||||
YlOrRd_r = YlOrRd[::-1]
|
||||
@@ -0,0 +1,184 @@
|
||||
"""
|
||||
Qualitative color sequences are appropriate for data that has no natural ordering, such \
|
||||
as categories, colors, names, countries etc. The color sequences in this module are \
|
||||
mostly meant to be passed in as the `color_discrete_sequence` argument to various functions.
|
||||
"""
|
||||
|
||||
from ._swatches import _swatches
|
||||
|
||||
|
||||
def swatches(template=None):
|
||||
return _swatches(__name__, globals(), template)
|
||||
|
||||
|
||||
swatches.__doc__ = _swatches.__doc__
|
||||
|
||||
Plotly = [
|
||||
"#636EFA",
|
||||
"#EF553B",
|
||||
"#00CC96",
|
||||
"#AB63FA",
|
||||
"#FFA15A",
|
||||
"#19D3F3",
|
||||
"#FF6692",
|
||||
"#B6E880",
|
||||
"#FF97FF",
|
||||
"#FECB52",
|
||||
]
|
||||
|
||||
D3 = [
|
||||
"#1F77B4",
|
||||
"#FF7F0E",
|
||||
"#2CA02C",
|
||||
"#D62728",
|
||||
"#9467BD",
|
||||
"#8C564B",
|
||||
"#E377C2",
|
||||
"#7F7F7F",
|
||||
"#BCBD22",
|
||||
"#17BECF",
|
||||
]
|
||||
G10 = [
|
||||
"#3366CC",
|
||||
"#DC3912",
|
||||
"#FF9900",
|
||||
"#109618",
|
||||
"#990099",
|
||||
"#0099C6",
|
||||
"#DD4477",
|
||||
"#66AA00",
|
||||
"#B82E2E",
|
||||
"#316395",
|
||||
]
|
||||
T10 = [
|
||||
"#4C78A8",
|
||||
"#F58518",
|
||||
"#E45756",
|
||||
"#72B7B2",
|
||||
"#54A24B",
|
||||
"#EECA3B",
|
||||
"#B279A2",
|
||||
"#FF9DA6",
|
||||
"#9D755D",
|
||||
"#BAB0AC",
|
||||
]
|
||||
Alphabet = [
|
||||
"#AA0DFE",
|
||||
"#3283FE",
|
||||
"#85660D",
|
||||
"#782AB6",
|
||||
"#565656",
|
||||
"#1C8356",
|
||||
"#16FF32",
|
||||
"#F7E1A0",
|
||||
"#E2E2E2",
|
||||
"#1CBE4F",
|
||||
"#C4451C",
|
||||
"#DEA0FD",
|
||||
"#FE00FA",
|
||||
"#325A9B",
|
||||
"#FEAF16",
|
||||
"#F8A19F",
|
||||
"#90AD1C",
|
||||
"#F6222E",
|
||||
"#1CFFCE",
|
||||
"#2ED9FF",
|
||||
"#B10DA1",
|
||||
"#C075A6",
|
||||
"#FC1CBF",
|
||||
"#B00068",
|
||||
"#FBE426",
|
||||
"#FA0087",
|
||||
]
|
||||
Dark24 = [
|
||||
"#2E91E5",
|
||||
"#E15F99",
|
||||
"#1CA71C",
|
||||
"#FB0D0D",
|
||||
"#DA16FF",
|
||||
"#222A2A",
|
||||
"#B68100",
|
||||
"#750D86",
|
||||
"#EB663B",
|
||||
"#511CFB",
|
||||
"#00A08B",
|
||||
"#FB00D1",
|
||||
"#FC0080",
|
||||
"#B2828D",
|
||||
"#6C7C32",
|
||||
"#778AAE",
|
||||
"#862A16",
|
||||
"#A777F1",
|
||||
"#620042",
|
||||
"#1616A7",
|
||||
"#DA60CA",
|
||||
"#6C4516",
|
||||
"#0D2A63",
|
||||
"#AF0038",
|
||||
]
|
||||
Light24 = [
|
||||
"#FD3216",
|
||||
"#00FE35",
|
||||
"#6A76FC",
|
||||
"#FED4C4",
|
||||
"#FE00CE",
|
||||
"#0DF9FF",
|
||||
"#F6F926",
|
||||
"#FF9616",
|
||||
"#479B55",
|
||||
"#EEA6FB",
|
||||
"#DC587D",
|
||||
"#D626FF",
|
||||
"#6E899C",
|
||||
"#00B5F7",
|
||||
"#B68E00",
|
||||
"#C9FBE5",
|
||||
"#FF0092",
|
||||
"#22FFA7",
|
||||
"#E3EE9E",
|
||||
"#86CE00",
|
||||
"#BC7196",
|
||||
"#7E7DCD",
|
||||
"#FC6955",
|
||||
"#E48F72",
|
||||
]
|
||||
|
||||
Alphabet_r = Alphabet[::-1]
|
||||
D3_r = D3[::-1]
|
||||
Dark24_r = Dark24[::-1]
|
||||
G10_r = G10[::-1]
|
||||
Light24_r = Light24[::-1]
|
||||
Plotly_r = Plotly[::-1]
|
||||
T10_r = T10[::-1]
|
||||
|
||||
from .colorbrewer import ( # noqa: E402 F401
|
||||
Set1,
|
||||
Pastel1,
|
||||
Dark2,
|
||||
Set2,
|
||||
Pastel2,
|
||||
Set3,
|
||||
Set1_r,
|
||||
Pastel1_r,
|
||||
Dark2_r,
|
||||
Set2_r,
|
||||
Pastel2_r,
|
||||
Set3_r,
|
||||
)
|
||||
from .carto import ( # noqa: E402 F401
|
||||
Antique,
|
||||
Bold,
|
||||
Pastel,
|
||||
Prism,
|
||||
Safe,
|
||||
Vivid,
|
||||
Antique_r,
|
||||
Bold_r,
|
||||
Pastel_r,
|
||||
Prism_r,
|
||||
Safe_r,
|
||||
Vivid_r,
|
||||
)
|
||||
|
||||
|
||||
__all__ = ["swatches"]
|
||||
@@ -0,0 +1,257 @@
|
||||
"""
|
||||
Sequential color scales are appropriate for most continuous data, but in some cases it \
|
||||
can be helpful to use a `plotly.colors.diverging` or \
|
||||
`plotly.colors.cyclical` scale instead. The color scales in this module are \
|
||||
mostly meant to be passed in as the `color_continuous_scale` argument to various functions.
|
||||
"""
|
||||
|
||||
from ._swatches import _swatches, _swatches_continuous
|
||||
|
||||
|
||||
def swatches(template=None):
|
||||
return _swatches(__name__, globals(), template)
|
||||
|
||||
|
||||
swatches.__doc__ = _swatches.__doc__
|
||||
|
||||
|
||||
def swatches_continuous(template=None):
|
||||
return _swatches_continuous(__name__, globals(), template)
|
||||
|
||||
|
||||
swatches_continuous.__doc__ = _swatches_continuous.__doc__
|
||||
|
||||
Plotly3 = [
|
||||
"#0508b8",
|
||||
"#1910d8",
|
||||
"#3c19f0",
|
||||
"#6b1cfb",
|
||||
"#981cfd",
|
||||
"#bf1cfd",
|
||||
"#dd2bfd",
|
||||
"#f246fe",
|
||||
"#fc67fd",
|
||||
"#fe88fc",
|
||||
"#fea5fd",
|
||||
"#febefe",
|
||||
"#fec3fe",
|
||||
]
|
||||
|
||||
Viridis = [
|
||||
"#440154",
|
||||
"#482878",
|
||||
"#3e4989",
|
||||
"#31688e",
|
||||
"#26828e",
|
||||
"#1f9e89",
|
||||
"#35b779",
|
||||
"#6ece58",
|
||||
"#b5de2b",
|
||||
"#fde725",
|
||||
]
|
||||
Cividis = [
|
||||
"#00224e",
|
||||
"#123570",
|
||||
"#3b496c",
|
||||
"#575d6d",
|
||||
"#707173",
|
||||
"#8a8678",
|
||||
"#a59c74",
|
||||
"#c3b369",
|
||||
"#e1cc55",
|
||||
"#fee838",
|
||||
]
|
||||
|
||||
Inferno = [
|
||||
"#000004",
|
||||
"#1b0c41",
|
||||
"#4a0c6b",
|
||||
"#781c6d",
|
||||
"#a52c60",
|
||||
"#cf4446",
|
||||
"#ed6925",
|
||||
"#fb9b06",
|
||||
"#f7d13d",
|
||||
"#fcffa4",
|
||||
]
|
||||
Magma = [
|
||||
"#000004",
|
||||
"#180f3d",
|
||||
"#440f76",
|
||||
"#721f81",
|
||||
"#9e2f7f",
|
||||
"#cd4071",
|
||||
"#f1605d",
|
||||
"#fd9668",
|
||||
"#feca8d",
|
||||
"#fcfdbf",
|
||||
]
|
||||
Plasma = [
|
||||
"#0d0887",
|
||||
"#46039f",
|
||||
"#7201a8",
|
||||
"#9c179e",
|
||||
"#bd3786",
|
||||
"#d8576b",
|
||||
"#ed7953",
|
||||
"#fb9f3a",
|
||||
"#fdca26",
|
||||
"#f0f921",
|
||||
]
|
||||
Turbo = [
|
||||
"#30123b",
|
||||
"#4145ab",
|
||||
"#4675ed",
|
||||
"#39a2fc",
|
||||
"#1bcfd4",
|
||||
"#24eca6",
|
||||
"#61fc6c",
|
||||
"#a4fc3b",
|
||||
"#d1e834",
|
||||
"#f3c63a",
|
||||
"#fe9b2d",
|
||||
"#f36315",
|
||||
"#d93806",
|
||||
"#b11901",
|
||||
"#7a0402",
|
||||
]
|
||||
|
||||
Cividis_r = Cividis[::-1]
|
||||
Inferno_r = Inferno[::-1]
|
||||
Magma_r = Magma[::-1]
|
||||
Plasma_r = Plasma[::-1]
|
||||
Plotly3_r = Plotly3[::-1]
|
||||
Turbo_r = Turbo[::-1]
|
||||
Viridis_r = Viridis[::-1]
|
||||
|
||||
from .plotlyjs import ( # noqa: E402 F401
|
||||
Blackbody,
|
||||
Bluered,
|
||||
Electric,
|
||||
Hot,
|
||||
Jet,
|
||||
Rainbow,
|
||||
Blackbody_r,
|
||||
Bluered_r,
|
||||
Electric_r,
|
||||
Hot_r,
|
||||
Jet_r,
|
||||
Rainbow_r,
|
||||
)
|
||||
|
||||
from .colorbrewer import ( # noqa: E402 F401
|
||||
Blues,
|
||||
BuGn,
|
||||
BuPu,
|
||||
GnBu,
|
||||
Greens,
|
||||
Greys,
|
||||
OrRd,
|
||||
Oranges,
|
||||
PuBu,
|
||||
PuBuGn,
|
||||
PuRd,
|
||||
Purples,
|
||||
RdBu,
|
||||
RdPu,
|
||||
Reds,
|
||||
YlGn,
|
||||
YlGnBu,
|
||||
YlOrBr,
|
||||
YlOrRd,
|
||||
Blues_r,
|
||||
BuGn_r,
|
||||
BuPu_r,
|
||||
GnBu_r,
|
||||
Greens_r,
|
||||
Greys_r,
|
||||
OrRd_r,
|
||||
Oranges_r,
|
||||
PuBu_r,
|
||||
PuBuGn_r,
|
||||
PuRd_r,
|
||||
Purples_r,
|
||||
RdBu_r,
|
||||
RdPu_r,
|
||||
Reds_r,
|
||||
YlGn_r,
|
||||
YlGnBu_r,
|
||||
YlOrBr_r,
|
||||
YlOrRd_r,
|
||||
)
|
||||
|
||||
from .cmocean import ( # noqa: E402 F401
|
||||
turbid,
|
||||
thermal,
|
||||
haline,
|
||||
solar,
|
||||
ice,
|
||||
gray,
|
||||
deep,
|
||||
dense,
|
||||
algae,
|
||||
matter,
|
||||
speed,
|
||||
amp,
|
||||
tempo,
|
||||
turbid_r,
|
||||
thermal_r,
|
||||
haline_r,
|
||||
solar_r,
|
||||
ice_r,
|
||||
gray_r,
|
||||
deep_r,
|
||||
dense_r,
|
||||
algae_r,
|
||||
matter_r,
|
||||
speed_r,
|
||||
amp_r,
|
||||
tempo_r,
|
||||
)
|
||||
|
||||
from .carto import ( # noqa: E402 F401
|
||||
Burg,
|
||||
Burgyl,
|
||||
Redor,
|
||||
Oryel,
|
||||
Peach,
|
||||
Pinkyl,
|
||||
Mint,
|
||||
Blugrn,
|
||||
Darkmint,
|
||||
Emrld,
|
||||
Aggrnyl,
|
||||
Bluyl,
|
||||
Teal,
|
||||
Tealgrn,
|
||||
Purp,
|
||||
Purpor,
|
||||
Sunset,
|
||||
Magenta,
|
||||
Sunsetdark,
|
||||
Agsunset,
|
||||
Brwnyl,
|
||||
Burg_r,
|
||||
Burgyl_r,
|
||||
Redor_r,
|
||||
Oryel_r,
|
||||
Peach_r,
|
||||
Pinkyl_r,
|
||||
Mint_r,
|
||||
Blugrn_r,
|
||||
Darkmint_r,
|
||||
Emrld_r,
|
||||
Aggrnyl_r,
|
||||
Bluyl_r,
|
||||
Teal_r,
|
||||
Tealgrn_r,
|
||||
Purp_r,
|
||||
Purpor_r,
|
||||
Sunset_r,
|
||||
Magenta_r,
|
||||
Sunsetdark_r,
|
||||
Agsunset_r,
|
||||
Brwnyl_r,
|
||||
)
|
||||
|
||||
__all__ = ["swatches"]
|
||||
@@ -0,0 +1,75 @@
|
||||
from io import BytesIO
|
||||
import base64
|
||||
from .png import Writer, from_array
|
||||
|
||||
try:
|
||||
from PIL import Image
|
||||
|
||||
pil_imported = True
|
||||
except ImportError:
|
||||
pil_imported = False
|
||||
|
||||
|
||||
def image_array_to_data_uri(img, backend="pil", compression=4, ext="png"):
|
||||
"""Converts a numpy array of uint8 into a base64 png or jpg string.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
img: ndarray of uint8
|
||||
array image
|
||||
backend: str
|
||||
'auto', 'pil' or 'pypng'. If 'auto', Pillow is used if installed,
|
||||
otherwise pypng.
|
||||
compression: int, between 0 and 9
|
||||
compression level to be passed to the backend
|
||||
ext: str, 'png' or 'jpg'
|
||||
compression format used to generate b64 string
|
||||
"""
|
||||
# PIL and pypng error messages are quite obscure so we catch invalid compression values
|
||||
if compression < 0 or compression > 9:
|
||||
raise ValueError("compression level must be between 0 and 9.")
|
||||
alpha = False
|
||||
if img.ndim == 2:
|
||||
mode = "L"
|
||||
elif img.ndim == 3 and img.shape[-1] == 3:
|
||||
mode = "RGB"
|
||||
elif img.ndim == 3 and img.shape[-1] == 4:
|
||||
mode = "RGBA"
|
||||
alpha = True
|
||||
else:
|
||||
raise ValueError("Invalid image shape")
|
||||
if backend == "auto":
|
||||
backend = "pil" if pil_imported else "pypng"
|
||||
if ext != "png" and backend != "pil":
|
||||
raise ValueError("jpg binary strings are only available with PIL backend")
|
||||
|
||||
if backend == "pypng":
|
||||
ndim = img.ndim
|
||||
sh = img.shape
|
||||
if ndim == 3:
|
||||
img = img.reshape((sh[0], sh[1] * sh[2]))
|
||||
w = Writer(
|
||||
sh[1], sh[0], greyscale=(ndim == 2), alpha=alpha, compression=compression
|
||||
)
|
||||
img_png = from_array(img, mode=mode)
|
||||
prefix = "data:image/png;base64,"
|
||||
with BytesIO() as stream:
|
||||
w.write(stream, img_png.rows)
|
||||
base64_string = prefix + base64.b64encode(stream.getvalue()).decode("utf-8")
|
||||
else: # pil
|
||||
if not pil_imported:
|
||||
raise ImportError(
|
||||
"pillow needs to be installed to use `backend='pil'. Please"
|
||||
"install pillow or use `backend='pypng'."
|
||||
)
|
||||
pil_img = Image.fromarray(img)
|
||||
if ext == "jpg" or ext == "jpeg":
|
||||
prefix = "data:image/jpeg;base64,"
|
||||
ext = "jpeg"
|
||||
else:
|
||||
prefix = "data:image/png;base64,"
|
||||
ext = "png"
|
||||
with BytesIO() as stream:
|
||||
pil_img.save(stream, format=ext, compress_level=compression)
|
||||
base64_string = prefix + base64.b64encode(stream.getvalue()).decode("utf-8")
|
||||
return base64_string
|
||||
@@ -0,0 +1,97 @@
|
||||
class PlotlyError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class PlotlyEmptyDataError(PlotlyError):
|
||||
pass
|
||||
|
||||
|
||||
class PlotlyGraphObjectError(PlotlyError):
|
||||
def __init__(self, message="", path=(), notes=()):
|
||||
"""
|
||||
General graph object error for validation failures.
|
||||
|
||||
:param (str|unicode) message: The error message.
|
||||
:param (iterable) path: A path pointing to the error.
|
||||
:param notes: Add additional notes, but keep default exception message.
|
||||
|
||||
"""
|
||||
self.message = message
|
||||
self.plain_message = message # for backwards compat
|
||||
self.path = list(path)
|
||||
self.notes = notes
|
||||
super(PlotlyGraphObjectError, self).__init__(message)
|
||||
|
||||
def __str__(self):
|
||||
"""This is called by Python to present the error message."""
|
||||
format_dict = {
|
||||
"message": self.message,
|
||||
"path": "[" + "][".join(repr(k) for k in self.path) + "]",
|
||||
"notes": "\n".join(self.notes),
|
||||
}
|
||||
return "{message}\n\nPath To Error: {path}\n\n{notes}".format(**format_dict)
|
||||
|
||||
|
||||
class PlotlyDictKeyError(PlotlyGraphObjectError):
|
||||
def __init__(self, obj, path, notes=()):
|
||||
"""See PlotlyGraphObjectError.__init__ for param docs."""
|
||||
format_dict = {"attribute": path[-1], "object_name": obj._name}
|
||||
message = "'{attribute}' is not allowed in '{object_name}'".format(
|
||||
**format_dict
|
||||
)
|
||||
notes = [obj.help(return_help=True)] + list(notes)
|
||||
super(PlotlyDictKeyError, self).__init__(
|
||||
message=message, path=path, notes=notes
|
||||
)
|
||||
|
||||
|
||||
class PlotlyDictValueError(PlotlyGraphObjectError):
|
||||
def __init__(self, obj, path, notes=()):
|
||||
"""See PlotlyGraphObjectError.__init__ for param docs."""
|
||||
format_dict = {"attribute": path[-1], "object_name": obj._name}
|
||||
message = "'{attribute}' has invalid value inside '{object_name}'".format(
|
||||
**format_dict
|
||||
)
|
||||
notes = [obj.help(path[-1], return_help=True)] + list(notes)
|
||||
super(PlotlyDictValueError, self).__init__(
|
||||
message=message, notes=notes, path=path
|
||||
)
|
||||
|
||||
|
||||
class PlotlyListEntryError(PlotlyGraphObjectError):
|
||||
def __init__(self, obj, path, notes=()):
|
||||
"""See PlotlyGraphObjectError.__init__ for param docs."""
|
||||
format_dict = {"index": path[-1], "object_name": obj._name}
|
||||
message = "Invalid entry found in '{object_name}' at index, '{index}'".format(
|
||||
**format_dict
|
||||
)
|
||||
notes = [obj.help(return_help=True)] + list(notes)
|
||||
super(PlotlyListEntryError, self).__init__(
|
||||
message=message, path=path, notes=notes
|
||||
)
|
||||
|
||||
|
||||
class PlotlyDataTypeError(PlotlyGraphObjectError):
|
||||
def __init__(self, obj, path, notes=()):
|
||||
"""See PlotlyGraphObjectError.__init__ for param docs."""
|
||||
format_dict = {"index": path[-1], "object_name": obj._name}
|
||||
message = "Invalid entry found in '{object_name}' at index, '{index}'".format(
|
||||
**format_dict
|
||||
)
|
||||
note = "It's invalid because it doesn't contain a valid 'type' value."
|
||||
notes = [note] + list(notes)
|
||||
super(PlotlyDataTypeError, self).__init__(
|
||||
message=message, path=path, notes=notes
|
||||
)
|
||||
|
||||
|
||||
class PlotlyKeyError(KeyError):
|
||||
"""
|
||||
KeyErrors are not printed as beautifully as other errors (this is so that
|
||||
{}[''] prints "KeyError: ''" and not "KeyError:"). So here we use
|
||||
LookupError's __str__ to make a PlotlyKeyError object which will print nicer
|
||||
error messages for KeyErrors.
|
||||
"""
|
||||
|
||||
def __str__(self):
|
||||
return LookupError.__str__(self)
|
||||
@@ -0,0 +1,37 @@
|
||||
import os
|
||||
|
||||
PLOTLY_DIR = os.environ.get(
|
||||
"PLOTLY_DIR", os.path.join(os.path.expanduser("~"), ".plotly")
|
||||
)
|
||||
TEST_FILE = os.path.join(PLOTLY_DIR, ".permission_test")
|
||||
|
||||
|
||||
def _permissions():
|
||||
try:
|
||||
if not os.path.exists(PLOTLY_DIR):
|
||||
try:
|
||||
os.mkdir(PLOTLY_DIR)
|
||||
except Exception:
|
||||
# in case of race
|
||||
if not os.path.isdir(PLOTLY_DIR):
|
||||
raise
|
||||
with open(TEST_FILE, "w") as f:
|
||||
f.write("testing\n")
|
||||
try:
|
||||
os.remove(TEST_FILE)
|
||||
except Exception:
|
||||
pass
|
||||
return True
|
||||
except Exception: # Do not trap KeyboardInterrupt.
|
||||
return False
|
||||
|
||||
|
||||
_file_permissions = None
|
||||
|
||||
|
||||
def ensure_writable_plotly_dir():
|
||||
# Cache permissions status
|
||||
global _file_permissions
|
||||
if _file_permissions is None:
|
||||
_file_permissions = _permissions()
|
||||
return _file_permissions
|
||||
@@ -0,0 +1,50 @@
|
||||
import importlib
|
||||
|
||||
|
||||
def relative_import(parent_name, rel_modules=(), rel_classes=()):
|
||||
"""
|
||||
Helper function to import submodules lazily in Python 3.7+
|
||||
|
||||
Parameters
|
||||
----------
|
||||
rel_modules: list of str
|
||||
list of submodules to import, of the form .submodule
|
||||
rel_classes: list of str
|
||||
list of submodule classes/variables to import, of the form ._submodule.Foo
|
||||
|
||||
Returns
|
||||
-------
|
||||
tuple
|
||||
Tuple that should be assigned to __all__, __getattr__ in the caller
|
||||
"""
|
||||
module_names = {rel_module.split(".")[-1]: rel_module for rel_module in rel_modules}
|
||||
class_names = {rel_path.split(".")[-1]: rel_path for rel_path in rel_classes}
|
||||
|
||||
def __getattr__(import_name):
|
||||
# In Python 3.7+, lazy import submodules
|
||||
|
||||
# Check for submodule
|
||||
if import_name in module_names:
|
||||
rel_import = module_names[import_name]
|
||||
return importlib.import_module(rel_import, parent_name)
|
||||
|
||||
# Check for submodule class
|
||||
if import_name in class_names:
|
||||
rel_path_parts = class_names[import_name].split(".")
|
||||
rel_module = ".".join(rel_path_parts[:-1])
|
||||
class_name = import_name
|
||||
class_module = importlib.import_module(rel_module, parent_name)
|
||||
return getattr(class_module, class_name)
|
||||
|
||||
raise AttributeError(
|
||||
"module {__name__!r} has no attribute {name!r}".format(
|
||||
name=import_name, __name__=parent_name
|
||||
)
|
||||
)
|
||||
|
||||
__all__ = list(module_names) + list(class_names)
|
||||
|
||||
def __dir__():
|
||||
return __all__
|
||||
|
||||
return __all__, __getattr__, __dir__
|
||||
@@ -0,0 +1,36 @@
|
||||
"""
|
||||
Stand-alone module to provide information about whether optional deps exist.
|
||||
|
||||
"""
|
||||
|
||||
from importlib import import_module
|
||||
import logging
|
||||
import sys
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
_not_importable = set()
|
||||
|
||||
|
||||
def get_module(name, should_load=True):
|
||||
"""
|
||||
Return module or None. Absolute import is required.
|
||||
|
||||
:param (str) name: Dot-separated module path. E.g., 'scipy.stats'.
|
||||
:raise: (ImportError) Only when exc_msg is defined.
|
||||
:return: (module|None) If import succeeds, the module will be returned.
|
||||
|
||||
"""
|
||||
if not should_load:
|
||||
return sys.modules.get(name, None)
|
||||
|
||||
if name not in _not_importable:
|
||||
try:
|
||||
return import_module(name)
|
||||
except ImportError:
|
||||
_not_importable.add(name)
|
||||
except Exception:
|
||||
_not_importable.add(name)
|
||||
msg = f"Error importing optional module {name}"
|
||||
logger.exception(msg)
|
||||
|
||||
return None
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,557 @@
|
||||
import base64
|
||||
import decimal
|
||||
import json as _json
|
||||
import sys
|
||||
import re
|
||||
from functools import reduce
|
||||
|
||||
from _plotly_utils.optional_imports import get_module
|
||||
from _plotly_utils.basevalidators import (
|
||||
ImageUriValidator,
|
||||
copy_to_readonly_numpy_array,
|
||||
is_homogeneous_array,
|
||||
)
|
||||
|
||||
|
||||
int8min = -128
|
||||
int8max = 127
|
||||
int16min = -32768
|
||||
int16max = 32767
|
||||
int32min = -2147483648
|
||||
int32max = 2147483647
|
||||
|
||||
uint8max = 255
|
||||
uint16max = 65535
|
||||
uint32max = 4294967295
|
||||
|
||||
plotlyjsShortTypes = {
|
||||
"int8": "i1",
|
||||
"uint8": "u1",
|
||||
"int16": "i2",
|
||||
"uint16": "u2",
|
||||
"int32": "i4",
|
||||
"uint32": "u4",
|
||||
"float32": "f4",
|
||||
"float64": "f8",
|
||||
}
|
||||
|
||||
|
||||
def to_typed_array_spec(v):
|
||||
"""
|
||||
Convert numpy array to plotly.js typed array spec
|
||||
If not possible return the original value
|
||||
"""
|
||||
v = copy_to_readonly_numpy_array(v)
|
||||
|
||||
# Skip b64 encoding if numpy is not installed,
|
||||
# or if v is not a numpy array, or if v is empty
|
||||
np = get_module("numpy", should_load=False)
|
||||
if not np or not isinstance(v, np.ndarray) or v.size == 0:
|
||||
return v
|
||||
|
||||
dtype = str(v.dtype)
|
||||
|
||||
# convert default Big Ints until we could support them in plotly.js
|
||||
if dtype == "int64":
|
||||
max = v.max()
|
||||
min = v.min()
|
||||
if max <= int8max and min >= int8min:
|
||||
v = v.astype("int8")
|
||||
elif max <= int16max and min >= int16min:
|
||||
v = v.astype("int16")
|
||||
elif max <= int32max and min >= int32min:
|
||||
v = v.astype("int32")
|
||||
else:
|
||||
return v
|
||||
|
||||
elif dtype == "uint64":
|
||||
max = v.max()
|
||||
min = v.min()
|
||||
if max <= uint8max and min >= 0:
|
||||
v = v.astype("uint8")
|
||||
elif max <= uint16max and min >= 0:
|
||||
v = v.astype("uint16")
|
||||
elif max <= uint32max and min >= 0:
|
||||
v = v.astype("uint32")
|
||||
else:
|
||||
return v
|
||||
|
||||
dtype = str(v.dtype)
|
||||
|
||||
if dtype in plotlyjsShortTypes:
|
||||
arrObj = {
|
||||
"dtype": plotlyjsShortTypes[dtype],
|
||||
"bdata": base64.b64encode(v).decode("ascii"),
|
||||
}
|
||||
|
||||
if v.ndim > 1:
|
||||
arrObj["shape"] = str(v.shape)[1:-1]
|
||||
|
||||
return arrObj
|
||||
|
||||
return v
|
||||
|
||||
|
||||
def is_skipped_key(key):
|
||||
"""
|
||||
Return whether the key is skipped for conversion to the typed array spec
|
||||
"""
|
||||
skipped_keys = ["geojson", "layer", "layers", "range"]
|
||||
return any(skipped_key == key for skipped_key in skipped_keys)
|
||||
|
||||
|
||||
def convert_to_base64(obj):
|
||||
if isinstance(obj, dict):
|
||||
for key, value in obj.items():
|
||||
if is_skipped_key(key):
|
||||
continue
|
||||
elif is_homogeneous_array(value):
|
||||
obj[key] = to_typed_array_spec(value)
|
||||
else:
|
||||
convert_to_base64(value)
|
||||
elif isinstance(obj, list) or isinstance(obj, tuple):
|
||||
for value in obj:
|
||||
convert_to_base64(value)
|
||||
|
||||
|
||||
def cumsum(x):
|
||||
"""
|
||||
Custom cumsum to avoid a numpy import.
|
||||
"""
|
||||
|
||||
def _reducer(a, x):
|
||||
if len(a) == 0:
|
||||
return [x]
|
||||
return a + [a[-1] + x]
|
||||
|
||||
ret = reduce(_reducer, x, [])
|
||||
return ret
|
||||
|
||||
|
||||
class PlotlyJSONEncoder(_json.JSONEncoder):
|
||||
"""
|
||||
Meant to be passed as the `cls` kwarg to json.dumps(obj, cls=..)
|
||||
|
||||
See PlotlyJSONEncoder.default for more implementation information.
|
||||
|
||||
Additionally, this encoder overrides nan functionality so that 'Inf',
|
||||
'NaN' and '-Inf' encode to 'null'. Which is stricter JSON than the Python
|
||||
version.
|
||||
|
||||
"""
|
||||
|
||||
def coerce_to_strict(self, const):
|
||||
"""
|
||||
This is used to ultimately *encode* into strict JSON, see `encode`
|
||||
|
||||
"""
|
||||
# before python 2.7, 'true', 'false', 'null', were include here.
|
||||
if const in ("Infinity", "-Infinity", "NaN"):
|
||||
return None
|
||||
else:
|
||||
return const
|
||||
|
||||
def encode(self, o):
|
||||
"""
|
||||
Load and then dump the result using parse_constant kwarg
|
||||
|
||||
Note that setting invalid separators will cause a failure at this step.
|
||||
|
||||
"""
|
||||
# this will raise errors in a normal-expected way
|
||||
encoded_o = super(PlotlyJSONEncoder, self).encode(o)
|
||||
# Brute force guessing whether NaN or Infinity values are in the string
|
||||
# We catch false positive cases (e.g. strings such as titles, labels etc.)
|
||||
# but this is ok since the intention is to skip the decoding / reencoding
|
||||
# step when it's completely safe
|
||||
|
||||
if not ("NaN" in encoded_o or "Infinity" in encoded_o):
|
||||
return encoded_o
|
||||
|
||||
# now:
|
||||
# 1. `loads` to switch Infinity, -Infinity, NaN to None
|
||||
# 2. `dumps` again so you get 'null' instead of extended JSON
|
||||
try:
|
||||
new_o = _json.loads(encoded_o, parse_constant=self.coerce_to_strict)
|
||||
except ValueError:
|
||||
# invalid separators will fail here. raise a helpful exception
|
||||
raise ValueError(
|
||||
"Encoding into strict JSON failed. Did you set the separators "
|
||||
"valid JSON separators?"
|
||||
)
|
||||
else:
|
||||
return _json.dumps(
|
||||
new_o,
|
||||
sort_keys=self.sort_keys,
|
||||
indent=self.indent,
|
||||
separators=(self.item_separator, self.key_separator),
|
||||
)
|
||||
|
||||
def default(self, obj):
|
||||
"""
|
||||
Accept an object (of unknown type) and try to encode with priority:
|
||||
1. builtin: user-defined objects
|
||||
2. sage: sage math cloud
|
||||
3. pandas: dataframes/series
|
||||
4. numpy: ndarrays
|
||||
5. datetime: time/datetime objects
|
||||
|
||||
Each method throws a NotEncoded exception if it fails.
|
||||
|
||||
The default method will only get hit if the object is not a type that
|
||||
is naturally encoded by json:
|
||||
|
||||
Normal objects:
|
||||
dict object
|
||||
list, tuple array
|
||||
str, unicode string
|
||||
int, long, float number
|
||||
True true
|
||||
False false
|
||||
None null
|
||||
|
||||
Extended objects:
|
||||
float('nan') 'NaN'
|
||||
float('infinity') 'Infinity'
|
||||
float('-infinity') '-Infinity'
|
||||
|
||||
Therefore, we only anticipate either unknown iterables or values here.
|
||||
|
||||
"""
|
||||
# TODO: The ordering if these methods is *very* important. Is this OK?
|
||||
encoding_methods = (
|
||||
self.encode_as_plotly,
|
||||
self.encode_as_sage,
|
||||
self.encode_as_numpy,
|
||||
self.encode_as_pandas,
|
||||
self.encode_as_datetime,
|
||||
self.encode_as_date,
|
||||
self.encode_as_list, # because some values have `tolist` do last.
|
||||
self.encode_as_decimal,
|
||||
self.encode_as_pil,
|
||||
)
|
||||
for encoding_method in encoding_methods:
|
||||
try:
|
||||
return encoding_method(obj)
|
||||
except NotEncodable:
|
||||
pass
|
||||
return _json.JSONEncoder.default(self, obj)
|
||||
|
||||
@staticmethod
|
||||
def encode_as_plotly(obj):
|
||||
"""Attempt to use a builtin `to_plotly_json` method."""
|
||||
try:
|
||||
return obj.to_plotly_json()
|
||||
except AttributeError:
|
||||
raise NotEncodable
|
||||
|
||||
@staticmethod
|
||||
def encode_as_list(obj):
|
||||
"""Attempt to use `tolist` method to convert to normal Python list."""
|
||||
if hasattr(obj, "tolist"):
|
||||
return obj.tolist()
|
||||
else:
|
||||
raise NotEncodable
|
||||
|
||||
@staticmethod
|
||||
def encode_as_sage(obj):
|
||||
"""Attempt to convert sage.all.RR to floats and sage.all.ZZ to ints"""
|
||||
sage_all = get_module("sage.all")
|
||||
if not sage_all:
|
||||
raise NotEncodable
|
||||
|
||||
if obj in sage_all.RR:
|
||||
return float(obj)
|
||||
elif obj in sage_all.ZZ:
|
||||
return int(obj)
|
||||
else:
|
||||
raise NotEncodable
|
||||
|
||||
@staticmethod
|
||||
def encode_as_pandas(obj):
|
||||
"""Attempt to convert pandas.NaT / pandas.NA"""
|
||||
pandas = get_module("pandas", should_load=False)
|
||||
if not pandas:
|
||||
raise NotEncodable
|
||||
|
||||
if obj is pandas.NaT:
|
||||
return None
|
||||
|
||||
# pandas.NA was introduced in pandas 1.0
|
||||
if hasattr(pandas, "NA") and obj is pandas.NA:
|
||||
return None
|
||||
|
||||
raise NotEncodable
|
||||
|
||||
@staticmethod
|
||||
def encode_as_numpy(obj):
|
||||
"""Attempt to convert numpy.ma.core.masked"""
|
||||
numpy = get_module("numpy", should_load=False)
|
||||
if not numpy:
|
||||
raise NotEncodable
|
||||
|
||||
if obj is numpy.ma.core.masked:
|
||||
return float("nan")
|
||||
elif isinstance(obj, numpy.ndarray) and obj.dtype.kind == "M":
|
||||
try:
|
||||
return numpy.datetime_as_string(obj).tolist()
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
raise NotEncodable
|
||||
|
||||
@staticmethod
|
||||
def encode_as_datetime(obj):
|
||||
"""Convert datetime objects to iso-format strings"""
|
||||
try:
|
||||
return obj.isoformat()
|
||||
except AttributeError:
|
||||
raise NotEncodable
|
||||
|
||||
@staticmethod
|
||||
def encode_as_date(obj):
|
||||
"""Attempt to convert to utc-iso time string using date methods."""
|
||||
try:
|
||||
time_string = obj.isoformat()
|
||||
except AttributeError:
|
||||
raise NotEncodable
|
||||
else:
|
||||
return iso_to_plotly_time_string(time_string)
|
||||
|
||||
@staticmethod
|
||||
def encode_as_decimal(obj):
|
||||
"""Attempt to encode decimal by converting it to float"""
|
||||
if isinstance(obj, decimal.Decimal):
|
||||
return float(obj)
|
||||
else:
|
||||
raise NotEncodable
|
||||
|
||||
@staticmethod
|
||||
def encode_as_pil(obj):
|
||||
"""Attempt to convert PIL.Image.Image to base64 data uri"""
|
||||
image = get_module("PIL.Image")
|
||||
if image is not None and isinstance(obj, image.Image):
|
||||
return ImageUriValidator.pil_image_to_uri(obj)
|
||||
else:
|
||||
raise NotEncodable
|
||||
|
||||
|
||||
class NotEncodable(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def iso_to_plotly_time_string(iso_string):
|
||||
"""Remove timezone info and replace 'T' delimeter with ' ' (ws)."""
|
||||
# make sure we don't send timezone info to plotly
|
||||
if (iso_string.split("-")[:3] == "00:00") or (iso_string.split("+")[0] == "00:00"):
|
||||
raise Exception(
|
||||
"Plotly won't accept timestrings with timezone info.\n"
|
||||
"All timestrings are assumed to be in UTC."
|
||||
)
|
||||
|
||||
iso_string = iso_string.replace("-00:00", "").replace("+00:00", "")
|
||||
|
||||
if iso_string.endswith("T00:00:00"):
|
||||
return iso_string.replace("T00:00:00", "")
|
||||
else:
|
||||
return iso_string.replace("T", " ")
|
||||
|
||||
|
||||
def template_doc(**names):
|
||||
def _decorator(func):
|
||||
if not sys.version_info[:2] == (3, 2):
|
||||
if func.__doc__ is not None:
|
||||
func.__doc__ = func.__doc__.format(**names)
|
||||
return func
|
||||
|
||||
return _decorator
|
||||
|
||||
|
||||
def _natural_sort_strings(vals, reverse=False):
|
||||
def key(v):
|
||||
v_parts = re.split(r"(\d+)", v)
|
||||
for i in range(len(v_parts)):
|
||||
try:
|
||||
v_parts[i] = int(v_parts[i])
|
||||
except ValueError:
|
||||
# not an int
|
||||
pass
|
||||
return tuple(v_parts)
|
||||
|
||||
return sorted(vals, key=key, reverse=reverse)
|
||||
|
||||
|
||||
def _get_int_type():
|
||||
np = get_module("numpy", should_load=False)
|
||||
if np:
|
||||
int_type = (int, np.integer)
|
||||
else:
|
||||
int_type = (int,)
|
||||
return int_type
|
||||
|
||||
|
||||
def split_multichar(ss, chars):
|
||||
"""
|
||||
Split all the strings in ss at any of the characters in chars.
|
||||
Example:
|
||||
|
||||
>>> ss = ["a.string[0].with_separators"]
|
||||
>>> chars = list(".[]_")
|
||||
>>> split_multichar(ss, chars)
|
||||
['a', 'string', '0', '', 'with', 'separators']
|
||||
|
||||
:param (list) ss: A list of strings.
|
||||
:param (list) chars: Is a list of chars (note: not a string).
|
||||
"""
|
||||
if len(chars) == 0:
|
||||
return ss
|
||||
c = chars.pop()
|
||||
ss = reduce(lambda x, y: x + y, map(lambda x: x.split(c), ss))
|
||||
return split_multichar(ss, chars)
|
||||
|
||||
|
||||
def split_string_positions(ss):
|
||||
"""
|
||||
Given a list of strings split using split_multichar, return a list of
|
||||
integers representing the indices of the first character of every string in
|
||||
the original string.
|
||||
Example:
|
||||
|
||||
>>> ss = ["a.string[0].with_separators"]
|
||||
>>> chars = list(".[]_")
|
||||
>>> ss_split = split_multichar(ss, chars)
|
||||
>>> ss_split
|
||||
['a', 'string', '0', '', 'with', 'separators']
|
||||
>>> split_string_positions(ss_split)
|
||||
[0, 2, 9, 11, 12, 17]
|
||||
|
||||
:param (list) ss: A list of strings.
|
||||
"""
|
||||
return list(
|
||||
map(
|
||||
lambda t: t[0] + t[1],
|
||||
zip(range(len(ss)), cumsum([0] + list(map(len, ss[:-1])))),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def display_string_positions(p, i=None, offset=0, length=1, char="^", trim=True):
|
||||
"""
|
||||
Return a string that is whitespace except at p[i] which is replaced with char.
|
||||
If i is None then all the indices of the string in p are replaced with char.
|
||||
|
||||
Example:
|
||||
|
||||
>>> ss = ["a.string[0].with_separators"]
|
||||
>>> chars = list(".[]_")
|
||||
>>> ss_split = split_multichar(ss, chars)
|
||||
>>> ss_split
|
||||
['a', 'string', '0', '', 'with', 'separators']
|
||||
>>> ss_pos = split_string_positions(ss_split)
|
||||
>>> ss[0]
|
||||
'a.string[0].with_separators'
|
||||
>>> display_string_positions(ss_pos,4)
|
||||
' ^'
|
||||
>>> display_string_positions(ss_pos,4,offset=1,length=3,char="~",trim=False)
|
||||
' ~~~ '
|
||||
>>> display_string_positions(ss_pos)
|
||||
'^ ^ ^ ^^ ^'
|
||||
:param (list) p: A list of integers.
|
||||
:param (integer|None) i: Optional index of p to display.
|
||||
:param (integer) offset: Allows adding a number of spaces to the replacement.
|
||||
:param (integer) length: Allows adding a replacement that is the char
|
||||
repeated length times.
|
||||
:param (str) char: allows customizing the replacement character.
|
||||
:param (boolean) trim: trims the remaining whitespace if True.
|
||||
"""
|
||||
s = [" " for _ in range(max(p) + 1 + offset + length)]
|
||||
maxaddr = 0
|
||||
if i is None:
|
||||
for p_ in p:
|
||||
for temp in range(length):
|
||||
maxaddr = p_ + offset + temp
|
||||
s[maxaddr] = char
|
||||
else:
|
||||
for temp in range(length):
|
||||
maxaddr = p[i] + offset + temp
|
||||
s[maxaddr] = char
|
||||
ret = "".join(s)
|
||||
if trim:
|
||||
ret = ret[: maxaddr + 1]
|
||||
return ret
|
||||
|
||||
|
||||
def chomp_empty_strings(strings, c, reverse=False):
|
||||
"""
|
||||
Given a list of strings, some of which are the empty string "", replace the
|
||||
empty strings with c and combine them with the closest non-empty string on
|
||||
the left or "" if it is the first string.
|
||||
Examples:
|
||||
for c="_"
|
||||
['hey', '', 'why', '', '', 'whoa', '', ''] -> ['hey_', 'why__', 'whoa__']
|
||||
['', 'hi', '', "I'm", 'bob', '', ''] -> ['_', 'hi_', "I'm", 'bob__']
|
||||
['hi', "i'm", 'a', 'good', 'string'] -> ['hi', "i'm", 'a', 'good', 'string']
|
||||
Some special cases are:
|
||||
[] -> []
|
||||
[''] -> ['']
|
||||
['', ''] -> ['_']
|
||||
['', '', '', ''] -> ['___']
|
||||
If reverse is true, empty strings are combined with closest non-empty string
|
||||
on the right or "" if it is the last string.
|
||||
"""
|
||||
|
||||
def _rev(vals):
|
||||
return [s[::-1] for s in vals][::-1]
|
||||
|
||||
if reverse:
|
||||
return _rev(chomp_empty_strings(_rev(strings), c))
|
||||
if not len(strings):
|
||||
return strings
|
||||
if sum(map(len, strings)) == 0:
|
||||
return [c * (len(strings) - 1)]
|
||||
|
||||
class _Chomper:
|
||||
def __init__(self, c):
|
||||
self.c = c
|
||||
|
||||
def __call__(self, x, y):
|
||||
# x is list up to now
|
||||
# y is next item in list
|
||||
# x should be [""] initially, and then empty strings filtered out at the
|
||||
# end
|
||||
if len(y) == 0:
|
||||
return x[:-1] + [x[-1] + self.c]
|
||||
else:
|
||||
return x + [y]
|
||||
|
||||
return list(filter(len, reduce(_Chomper(c), strings, [""])))
|
||||
|
||||
|
||||
# taken from
|
||||
# https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#Python
|
||||
def levenshtein(s1, s2):
|
||||
if len(s1) < len(s2):
|
||||
return levenshtein(s2, s1) # len(s1) >= len(s2)
|
||||
if len(s2) == 0:
|
||||
return len(s1)
|
||||
previous_row = range(len(s2) + 1)
|
||||
for i, c1 in enumerate(s1):
|
||||
current_row = [i + 1]
|
||||
for j, c2 in enumerate(s2):
|
||||
# j+1 instead of j since previous_row and current_row are one character longer
|
||||
# than s2
|
||||
insertions = previous_row[j + 1] + 1
|
||||
deletions = current_row[j] + 1
|
||||
substitutions = previous_row[j] + (c1 != c2)
|
||||
current_row.append(min(insertions, deletions, substitutions))
|
||||
previous_row = current_row
|
||||
return previous_row[-1]
|
||||
|
||||
|
||||
def find_closest_string(string, strings):
|
||||
def _key(s):
|
||||
# sort by levenshtein distance and lexographically to maintain a stable
|
||||
# sort for different keys with the same levenshtein distance
|
||||
return (levenshtein(s, string), s)
|
||||
|
||||
return sorted(strings, key=_key)[0]
|
||||
@@ -0,0 +1,33 @@
|
||||
# This is a stub package designed to roughly emulate the _yaml
|
||||
# extension module, which previously existed as a standalone module
|
||||
# and has been moved into the `yaml` package namespace.
|
||||
# It does not perfectly mimic its old counterpart, but should get
|
||||
# close enough for anyone who's relying on it even when they shouldn't.
|
||||
import yaml
|
||||
|
||||
# in some circumstances, the yaml module we imoprted may be from a different version, so we need
|
||||
# to tread carefully when poking at it here (it may not have the attributes we expect)
|
||||
if not getattr(yaml, '__with_libyaml__', False):
|
||||
from sys import version_info
|
||||
|
||||
exc = ModuleNotFoundError if version_info >= (3, 6) else ImportError
|
||||
raise exc("No module named '_yaml'")
|
||||
else:
|
||||
from yaml._yaml import *
|
||||
import warnings
|
||||
warnings.warn(
|
||||
'The _yaml extension module is now located at yaml._yaml'
|
||||
' and its location is subject to change. To use the'
|
||||
' LibYAML-based parser and emitter, import from `yaml`:'
|
||||
' `from yaml import CLoader as Loader, CDumper as Dumper`.',
|
||||
DeprecationWarning
|
||||
)
|
||||
del warnings
|
||||
# Don't `del yaml` here because yaml is actually an existing
|
||||
# namespace member of _yaml.
|
||||
|
||||
__name__ = '_yaml'
|
||||
# If the module is top-level (i.e. not a part of any specific package)
|
||||
# then the attribute should be set to ''.
|
||||
# https://docs.python.org/3.8/library/types.html
|
||||
__package__ = ''
|
||||
@@ -0,0 +1 @@
|
||||
uv
|
||||
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2013-2025 by the Babel Team, see AUTHORS for more information.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,54 @@
|
||||
Metadata-Version: 2.2
|
||||
Name: babel
|
||||
Version: 2.17.0
|
||||
Summary: Internationalization utilities
|
||||
Home-page: https://babel.pocoo.org/
|
||||
Author: Armin Ronacher
|
||||
Author-email: armin.ronacher@active-4.com
|
||||
Maintainer: Aarni Koskela
|
||||
Maintainer-email: akx@iki.fi
|
||||
License: BSD-3-Clause
|
||||
Project-URL: Source, https://github.com/python-babel/babel
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3 :: Only
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Requires-Python: >=3.8
|
||||
License-File: LICENSE
|
||||
Requires-Dist: pytz>=2015.7; python_version < "3.9"
|
||||
Provides-Extra: dev
|
||||
Requires-Dist: tzdata; sys_platform == "win32" and extra == "dev"
|
||||
Requires-Dist: backports.zoneinfo; python_version < "3.9" and extra == "dev"
|
||||
Requires-Dist: freezegun~=1.0; extra == "dev"
|
||||
Requires-Dist: jinja2>=3.0; extra == "dev"
|
||||
Requires-Dist: pytest-cov; extra == "dev"
|
||||
Requires-Dist: pytest>=6.0; extra == "dev"
|
||||
Requires-Dist: pytz; extra == "dev"
|
||||
Requires-Dist: setuptools; extra == "dev"
|
||||
Dynamic: author
|
||||
Dynamic: author-email
|
||||
Dynamic: classifier
|
||||
Dynamic: description
|
||||
Dynamic: home-page
|
||||
Dynamic: license
|
||||
Dynamic: maintainer
|
||||
Dynamic: maintainer-email
|
||||
Dynamic: project-url
|
||||
Dynamic: provides-extra
|
||||
Dynamic: requires-dist
|
||||
Dynamic: requires-python
|
||||
Dynamic: summary
|
||||
|
||||
A collection of tools for internationalizing Python applications.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: setuptools (75.8.0)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
[babel.checkers]
|
||||
num_plurals = babel.messages.checkers:num_plurals
|
||||
python_format = babel.messages.checkers:python_format
|
||||
|
||||
[babel.extractors]
|
||||
ignore = babel.messages.extract:extract_nothing
|
||||
javascript = babel.messages.extract:extract_javascript
|
||||
python = babel.messages.extract:extract_python
|
||||
|
||||
[console_scripts]
|
||||
pybabel = babel.messages.frontend:main
|
||||
|
||||
[distutils.commands]
|
||||
compile_catalog = babel.messages.setuptools_frontend:compile_catalog
|
||||
extract_messages = babel.messages.setuptools_frontend:extract_messages
|
||||
init_catalog = babel.messages.setuptools_frontend:init_catalog
|
||||
update_catalog = babel.messages.setuptools_frontend:update_catalog
|
||||
|
||||
[distutils.setup_keywords]
|
||||
message_extractors = babel.messages.setuptools_frontend:check_message_extractors
|
||||
@@ -0,0 +1 @@
|
||||
babel
|
||||
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
babel
|
||||
~~~~~
|
||||
|
||||
Integrated collection of utilities that assist in internationalizing and
|
||||
localizing applications.
|
||||
|
||||
This package is basically composed of two major parts:
|
||||
|
||||
* tools to build and work with ``gettext`` message catalogs
|
||||
* a Python interface to the CLDR (Common Locale Data Repository), providing
|
||||
access to various locale display names, localized number and date
|
||||
formatting, etc.
|
||||
|
||||
:copyright: (c) 2013-2025 by the Babel Team.
|
||||
:license: BSD, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from babel.core import (
|
||||
Locale,
|
||||
UnknownLocaleError,
|
||||
default_locale,
|
||||
get_locale_identifier,
|
||||
negotiate_locale,
|
||||
parse_locale,
|
||||
)
|
||||
|
||||
__version__ = '2.17.0'
|
||||
|
||||
__all__ = [
|
||||
'Locale',
|
||||
'UnknownLocaleError',
|
||||
'__version__',
|
||||
'default_locale',
|
||||
'get_locale_identifier',
|
||||
'negotiate_locale',
|
||||
'parse_locale',
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1,72 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from babel.core import get_global
|
||||
|
||||
|
||||
def get_official_languages(territory: str, regional: bool = False, de_facto: bool = False) -> tuple[str, ...]:
|
||||
"""
|
||||
Get the official language(s) for the given territory.
|
||||
|
||||
The language codes, if any are known, are returned in order of descending popularity.
|
||||
|
||||
If the `regional` flag is set, then languages which are regionally official are also returned.
|
||||
|
||||
If the `de_facto` flag is set, then languages which are "de facto" official are also returned.
|
||||
|
||||
.. warning:: Note that the data is as up to date as the current version of the CLDR used
|
||||
by Babel. If you need scientifically accurate information, use another source!
|
||||
|
||||
:param territory: Territory code
|
||||
:type territory: str
|
||||
:param regional: Whether to return regionally official languages too
|
||||
:type regional: bool
|
||||
:param de_facto: Whether to return de-facto official languages too
|
||||
:type de_facto: bool
|
||||
:return: Tuple of language codes
|
||||
:rtype: tuple[str]
|
||||
"""
|
||||
|
||||
territory = str(territory).upper()
|
||||
allowed_stati = {"official"}
|
||||
if regional:
|
||||
allowed_stati.add("official_regional")
|
||||
if de_facto:
|
||||
allowed_stati.add("de_facto_official")
|
||||
|
||||
languages = get_global("territory_languages").get(territory, {})
|
||||
pairs = [
|
||||
(info['population_percent'], language)
|
||||
for language, info in languages.items()
|
||||
if info.get('official_status') in allowed_stati
|
||||
]
|
||||
pairs.sort(reverse=True)
|
||||
return tuple(lang for _, lang in pairs)
|
||||
|
||||
|
||||
def get_territory_language_info(territory: str) -> dict[str, dict[str, float | str | None]]:
|
||||
"""
|
||||
Get a dictionary of language information for a territory.
|
||||
|
||||
The dictionary is keyed by language code; the values are dicts with more information.
|
||||
|
||||
The following keys are currently known for the values:
|
||||
|
||||
* `population_percent`: The percentage of the territory's population speaking the
|
||||
language.
|
||||
* `official_status`: An optional string describing the officiality status of the language.
|
||||
Known values are "official", "official_regional" and "de_facto_official".
|
||||
|
||||
.. warning:: Note that the data is as up to date as the current version of the CLDR used
|
||||
by Babel. If you need scientifically accurate information, use another source!
|
||||
|
||||
.. note:: Note that the format of the dict returned may change between Babel versions.
|
||||
|
||||
See https://www.unicode.org/cldr/charts/latest/supplemental/territory_language_information.html
|
||||
|
||||
:param territory: Territory code
|
||||
:type territory: str
|
||||
:return: Language information dictionary
|
||||
:rtype: dict[str, dict]
|
||||
"""
|
||||
territory = str(territory).upper()
|
||||
return get_global("territory_languages").get(territory, {}).copy()
|
||||
@@ -0,0 +1,132 @@
|
||||
"""
|
||||
babel.lists
|
||||
~~~~~~~~~~~
|
||||
|
||||
Locale dependent formatting of lists.
|
||||
|
||||
The default locale for the functions in this module is determined by the
|
||||
following environment variables, in that order:
|
||||
|
||||
* ``LC_ALL``, and
|
||||
* ``LANG``
|
||||
|
||||
:copyright: (c) 2015-2025 by the Babel Team.
|
||||
:license: BSD, see LICENSE for more details.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import warnings
|
||||
from collections.abc import Sequence
|
||||
from typing import Literal
|
||||
|
||||
from babel.core import Locale, default_locale
|
||||
|
||||
_DEFAULT_LOCALE = default_locale() # TODO(3.0): Remove this.
|
||||
|
||||
|
||||
def __getattr__(name):
|
||||
if name == "DEFAULT_LOCALE":
|
||||
warnings.warn(
|
||||
"The babel.lists.DEFAULT_LOCALE constant is deprecated and will be removed.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return _DEFAULT_LOCALE
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||
|
||||
|
||||
def format_list(
|
||||
lst: Sequence[str],
|
||||
style: Literal['standard', 'standard-short', 'or', 'or-short', 'unit', 'unit-short', 'unit-narrow'] = 'standard',
|
||||
locale: Locale | str | None = None,
|
||||
) -> str:
|
||||
"""
|
||||
Format the items in `lst` as a list.
|
||||
|
||||
>>> format_list(['apples', 'oranges', 'pears'], locale='en')
|
||||
u'apples, oranges, and pears'
|
||||
>>> format_list(['apples', 'oranges', 'pears'], locale='zh')
|
||||
u'apples\u3001oranges\u548cpears'
|
||||
>>> format_list(['omena', 'peruna', 'aplari'], style='or', locale='fi')
|
||||
u'omena, peruna tai aplari'
|
||||
|
||||
Not all styles are necessarily available in all locales.
|
||||
The function will attempt to fall back to replacement styles according to the rules
|
||||
set forth in the CLDR root XML file, and raise a ValueError if no suitable replacement
|
||||
can be found.
|
||||
|
||||
The following text is verbatim from the Unicode TR35-49 spec [1].
|
||||
|
||||
* standard:
|
||||
A typical 'and' list for arbitrary placeholders.
|
||||
eg. "January, February, and March"
|
||||
* standard-short:
|
||||
A short version of an 'and' list, suitable for use with short or abbreviated placeholder values.
|
||||
eg. "Jan., Feb., and Mar."
|
||||
* or:
|
||||
A typical 'or' list for arbitrary placeholders.
|
||||
eg. "January, February, or March"
|
||||
* or-short:
|
||||
A short version of an 'or' list.
|
||||
eg. "Jan., Feb., or Mar."
|
||||
* unit:
|
||||
A list suitable for wide units.
|
||||
eg. "3 feet, 7 inches"
|
||||
* unit-short:
|
||||
A list suitable for short units
|
||||
eg. "3 ft, 7 in"
|
||||
* unit-narrow:
|
||||
A list suitable for narrow units, where space on the screen is very limited.
|
||||
eg. "3′ 7″"
|
||||
|
||||
[1]: https://www.unicode.org/reports/tr35/tr35-49/tr35-general.html#ListPatterns
|
||||
|
||||
:param lst: a sequence of items to format in to a list
|
||||
:param style: the style to format the list with. See above for description.
|
||||
:param locale: the locale. Defaults to the system locale.
|
||||
"""
|
||||
locale = Locale.parse(locale or _DEFAULT_LOCALE)
|
||||
if not lst:
|
||||
return ''
|
||||
if len(lst) == 1:
|
||||
return lst[0]
|
||||
|
||||
patterns = _resolve_list_style(locale, style)
|
||||
|
||||
if len(lst) == 2 and '2' in patterns:
|
||||
return patterns['2'].format(*lst)
|
||||
|
||||
result = patterns['start'].format(lst[0], lst[1])
|
||||
for elem in lst[2:-1]:
|
||||
result = patterns['middle'].format(result, elem)
|
||||
result = patterns['end'].format(result, lst[-1])
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# Based on CLDR 45's root.xml file's `<alias>`es.
|
||||
# The root file defines both `standard` and `or`,
|
||||
# so they're always available.
|
||||
# TODO: It would likely be better to use the
|
||||
# babel.localedata.Alias mechanism for this,
|
||||
# but I'm not quite sure how it's supposed to
|
||||
# work with inheritance and data in the root.
|
||||
_style_fallbacks = {
|
||||
"or-narrow": ["or-short", "or"],
|
||||
"or-short": ["or"],
|
||||
"standard-narrow": ["standard-short", "standard"],
|
||||
"standard-short": ["standard"],
|
||||
"unit": ["unit-short", "standard"],
|
||||
"unit-narrow": ["unit-short", "unit", "standard"],
|
||||
"unit-short": ["standard"],
|
||||
}
|
||||
|
||||
|
||||
def _resolve_list_style(locale: Locale, style: str):
|
||||
for style in (style, *(_style_fallbacks.get(style, []))): # noqa: B020
|
||||
if style in locale.list_patterns:
|
||||
return locale.list_patterns[style]
|
||||
raise ValueError(
|
||||
f"Locale {locale} does not support list formatting style {style!r} "
|
||||
f"(supported are {sorted(locale.list_patterns)})",
|
||||
)
|
||||
@@ -0,0 +1,41 @@
|
||||
UNICODE LICENSE V3
|
||||
|
||||
COPYRIGHT AND PERMISSION NOTICE
|
||||
|
||||
Copyright © 2004-2025 Unicode, Inc.
|
||||
|
||||
NOTICE TO USER: Carefully read the following legal agreement. BY
|
||||
DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
|
||||
SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
|
||||
TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
|
||||
DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of data files and any associated documentation (the "Data Files") or
|
||||
software and any associated documentation (the "Software") to deal in the
|
||||
Data Files or Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, and/or sell
|
||||
copies of the Data Files or Software, and to permit persons to whom the
|
||||
Data Files or Software are furnished to do so, provided that either (a)
|
||||
this copyright and permission notice appear with all copies of the Data
|
||||
Files or Software, or (b) this copyright and permission notice appear in
|
||||
associated Documentation.
|
||||
|
||||
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
THIRD PARTY RIGHTS.
|
||||
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
|
||||
BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
|
||||
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
|
||||
FILES OR SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of a copyright holder shall
|
||||
not be used in advertising or otherwise to promote the sale, use or other
|
||||
dealings in these Data Files or Software without prior written
|
||||
authorization of the copyright holder.
|
||||
|
||||
SPDX-License-Identifier: Unicode-3.0
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user