Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .venv/Lib/site-packages/unidic/dicdir/char.bin +3 -0
- .venv/Lib/site-packages/unidic_lite/dicdir/right-id.def +0 -0
- .venv/Lib/site-packages/unidic_lite/dicdir/unidic-mecab.pdf +0 -0
- .venv/Lib/site-packages/unidic_lite/dicdir/unk.dic +0 -0
- .venv/Lib/site-packages/unidic_lite/dicdir/version +1 -0
- .venv/Lib/site-packages/urllib3-2.2.3.dist-info/INSTALLER +1 -0
- .venv/Lib/site-packages/urllib3-2.2.3.dist-info/METADATA +155 -0
- .venv/Lib/site-packages/urllib3-2.2.3.dist-info/RECORD +44 -0
- .venv/Lib/site-packages/urllib3-2.2.3.dist-info/REQUESTED +0 -0
- .venv/Lib/site-packages/urllib3-2.2.3.dist-info/WHEEL +4 -0
- .venv/Lib/site-packages/urllib3-2.2.3.dist-info/licenses/LICENSE.txt +21 -0
- .venv/Lib/site-packages/urllib3/__pycache__/__init__.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/__pycache__/_base_connection.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/__pycache__/_collections.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/__pycache__/_request_methods.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/__pycache__/_version.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/__pycache__/connection.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/__pycache__/connectionpool.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/__pycache__/exceptions.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/__pycache__/fields.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/__pycache__/filepost.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/__pycache__/poolmanager.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/__pycache__/response.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/util/__pycache__/__init__.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/util/__pycache__/response.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/util/__pycache__/retry.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/util/__pycache__/ssl_.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/util/__pycache__/ssl_match_hostname.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/util/__pycache__/ssltransport.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/util/__pycache__/timeout.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/util/__pycache__/url.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/util/__pycache__/util.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/urllib3/util/__pycache__/wait.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/wasabi/__init__.py +12 -0
- .venv/Lib/site-packages/wasabi/about.py +7 -0
- .venv/Lib/site-packages/wasabi/markdown.py +106 -0
- .venv/Lib/site-packages/wasabi/printer.py +250 -0
- .venv/Lib/site-packages/wasabi/tables.py +154 -0
- .venv/Lib/site-packages/wasabi/tests/test_markdown.py +28 -0
- .venv/Lib/site-packages/wasabi/tests/test_printer.py +239 -0
- .venv/Lib/site-packages/wasabi/tests/test_tables.py +422 -0
- .venv/Lib/site-packages/wasabi/tests/test_traceback.py +67 -0
- .venv/Lib/site-packages/wasabi/traceback_printer.py +118 -0
- .venv/Lib/site-packages/wasabi/util.py +234 -0
- .venv/Lib/site-packages/xlstm-1.0.8.dist-info/WHEEL +5 -0
- .venv/Lib/site-packages/xlstm-1.0.8.dist-info/top_level.txt +1 -0
- .venv/Lib/site-packages/xlstm/blocks/__pycache__/__init__.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/xlstm/blocks/__pycache__/xlstm_block.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/xlstm/blocks/slstm/__pycache__/__init__.cpython-39.pyc +0 -0
- .venv/Lib/site-packages/xlstm/blocks/slstm/__pycache__/block.cpython-39.pyc +0 -0
.venv/Lib/site-packages/unidic/dicdir/char.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:dd31396563d8924645b80fd3c9aa7b13ca089d7748f25553a1d6bc3f9b511ae8
|
3 |
+
size 262496
|
.venv/Lib/site-packages/unidic_lite/dicdir/right-id.def
ADDED
The diff for this file is too large to render.
See raw diff
|
|
.venv/Lib/site-packages/unidic_lite/dicdir/unidic-mecab.pdf
ADDED
Binary file (21.5 kB). View file
|
|
.venv/Lib/site-packages/unidic_lite/dicdir/unk.dic
ADDED
Binary file (5.48 kB). View file
|
|
.venv/Lib/site-packages/unidic_lite/dicdir/version
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
2.1.2
|
.venv/Lib/site-packages/urllib3-2.2.3.dist-info/INSTALLER
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
uv
|
.venv/Lib/site-packages/urllib3-2.2.3.dist-info/METADATA
ADDED
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Metadata-Version: 2.3
|
2 |
+
Name: urllib3
|
3 |
+
Version: 2.2.3
|
4 |
+
Summary: HTTP library with thread-safe connection pooling, file post, and more.
|
5 |
+
Project-URL: Changelog, https://github.com/urllib3/urllib3/blob/main/CHANGES.rst
|
6 |
+
Project-URL: Documentation, https://urllib3.readthedocs.io
|
7 |
+
Project-URL: Code, https://github.com/urllib3/urllib3
|
8 |
+
Project-URL: Issue tracker, https://github.com/urllib3/urllib3/issues
|
9 |
+
Author-email: Andrey Petrov <[email protected]>
|
10 |
+
Maintainer-email: Seth Michael Larson <[email protected]>, Quentin Pradet <[email protected]>, Illia Volochii <[email protected]>
|
11 |
+
License-File: LICENSE.txt
|
12 |
+
Keywords: filepost,http,httplib,https,pooling,ssl,threadsafe,urllib
|
13 |
+
Classifier: Environment :: Web Environment
|
14 |
+
Classifier: Intended Audience :: Developers
|
15 |
+
Classifier: License :: OSI Approved :: MIT License
|
16 |
+
Classifier: Operating System :: OS Independent
|
17 |
+
Classifier: Programming Language :: Python
|
18 |
+
Classifier: Programming Language :: Python :: 3
|
19 |
+
Classifier: Programming Language :: Python :: 3 :: Only
|
20 |
+
Classifier: Programming Language :: Python :: 3.8
|
21 |
+
Classifier: Programming Language :: Python :: 3.9
|
22 |
+
Classifier: Programming Language :: Python :: 3.10
|
23 |
+
Classifier: Programming Language :: Python :: 3.11
|
24 |
+
Classifier: Programming Language :: Python :: 3.12
|
25 |
+
Classifier: Programming Language :: Python :: 3.13
|
26 |
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
27 |
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
28 |
+
Classifier: Topic :: Internet :: WWW/HTTP
|
29 |
+
Classifier: Topic :: Software Development :: Libraries
|
30 |
+
Requires-Python: >=3.8
|
31 |
+
Provides-Extra: brotli
|
32 |
+
Requires-Dist: brotli>=1.0.9; (platform_python_implementation == 'CPython') and extra == 'brotli'
|
33 |
+
Requires-Dist: brotlicffi>=0.8.0; (platform_python_implementation != 'CPython') and extra == 'brotli'
|
34 |
+
Provides-Extra: h2
|
35 |
+
Requires-Dist: h2<5,>=4; extra == 'h2'
|
36 |
+
Provides-Extra: socks
|
37 |
+
Requires-Dist: pysocks!=1.5.7,<2.0,>=1.5.6; extra == 'socks'
|
38 |
+
Provides-Extra: zstd
|
39 |
+
Requires-Dist: zstandard>=0.18.0; extra == 'zstd'
|
40 |
+
Description-Content-Type: text/markdown
|
41 |
+
|
42 |
+
<h1 align="center">
|
43 |
+
|
44 |
+

|
45 |
+
|
46 |
+
</h1>
|
47 |
+
|
48 |
+
<p align="center">
|
49 |
+
<a href="https://pypi.org/project/urllib3"><img alt="PyPI Version" src="https://img.shields.io/pypi/v/urllib3.svg?maxAge=86400" /></a>
|
50 |
+
<a href="https://pypi.org/project/urllib3"><img alt="Python Versions" src="https://img.shields.io/pypi/pyversions/urllib3.svg?maxAge=86400" /></a>
|
51 |
+
<a href="https://discord.gg/urllib3"><img alt="Join our Discord" src="https://img.shields.io/discord/756342717725933608?color=%237289da&label=discord" /></a>
|
52 |
+
<a href="https://github.com/urllib3/urllib3/actions?query=workflow%3ACI"><img alt="Coverage Status" src="https://img.shields.io/badge/coverage-100%25-success" /></a>
|
53 |
+
<a href="https://github.com/urllib3/urllib3/actions?query=workflow%3ACI"><img alt="Build Status on GitHub" src="https://github.com/urllib3/urllib3/workflows/CI/badge.svg" /></a>
|
54 |
+
<a href="https://urllib3.readthedocs.io"><img alt="Documentation Status" src="https://readthedocs.org/projects/urllib3/badge/?version=latest" /></a><br>
|
55 |
+
<a href="https://deps.dev/pypi/urllib3"><img alt="OpenSSF Scorecard" src="https://api.securityscorecards.dev/projects/github.com/urllib3/urllib3/badge" /></a>
|
56 |
+
<a href="https://slsa.dev"><img alt="SLSA 3" src="https://slsa.dev/images/gh-badge-level3.svg" /></a>
|
57 |
+
<a href="https://bestpractices.coreinfrastructure.org/projects/6227"><img alt="CII Best Practices" src="https://bestpractices.coreinfrastructure.org/projects/6227/badge" /></a>
|
58 |
+
</p>
|
59 |
+
|
60 |
+
urllib3 is a powerful, *user-friendly* HTTP client for Python. Much of the
|
61 |
+
Python ecosystem already uses urllib3 and you should too.
|
62 |
+
urllib3 brings many critical features that are missing from the Python
|
63 |
+
standard libraries:
|
64 |
+
|
65 |
+
- Thread safety.
|
66 |
+
- Connection pooling.
|
67 |
+
- Client-side SSL/TLS verification.
|
68 |
+
- File uploads with multipart encoding.
|
69 |
+
- Helpers for retrying requests and dealing with HTTP redirects.
|
70 |
+
- Support for gzip, deflate, brotli, and zstd encoding.
|
71 |
+
- Proxy support for HTTP and SOCKS.
|
72 |
+
- 100% test coverage.
|
73 |
+
|
74 |
+
urllib3 is powerful and easy to use:
|
75 |
+
|
76 |
+
```python3
|
77 |
+
>>> import urllib3
|
78 |
+
>>> resp = urllib3.request("GET", "http://httpbin.org/robots.txt")
|
79 |
+
>>> resp.status
|
80 |
+
200
|
81 |
+
>>> resp.data
|
82 |
+
b"User-agent: *\nDisallow: /deny\n"
|
83 |
+
```
|
84 |
+
|
85 |
+
## Installing
|
86 |
+
|
87 |
+
urllib3 can be installed with [pip](https://pip.pypa.io):
|
88 |
+
|
89 |
+
```bash
|
90 |
+
$ python -m pip install urllib3
|
91 |
+
```
|
92 |
+
|
93 |
+
Alternatively, you can grab the latest source code from [GitHub](https://github.com/urllib3/urllib3):
|
94 |
+
|
95 |
+
```bash
|
96 |
+
$ git clone https://github.com/urllib3/urllib3.git
|
97 |
+
$ cd urllib3
|
98 |
+
$ pip install .
|
99 |
+
```
|
100 |
+
|
101 |
+
|
102 |
+
## Documentation
|
103 |
+
|
104 |
+
urllib3 has usage and reference documentation at [urllib3.readthedocs.io](https://urllib3.readthedocs.io).
|
105 |
+
|
106 |
+
|
107 |
+
## Community
|
108 |
+
|
109 |
+
urllib3 has a [community Discord channel](https://discord.gg/urllib3) for asking questions and
|
110 |
+
collaborating with other contributors. Drop by and say hello 👋
|
111 |
+
|
112 |
+
|
113 |
+
## Contributing
|
114 |
+
|
115 |
+
urllib3 happily accepts contributions. Please see our
|
116 |
+
[contributing documentation](https://urllib3.readthedocs.io/en/latest/contributing.html)
|
117 |
+
for some tips on getting started.
|
118 |
+
|
119 |
+
|
120 |
+
## Security Disclosures
|
121 |
+
|
122 |
+
To report a security vulnerability, please use the
|
123 |
+
[Tidelift security contact](https://tidelift.com/security).
|
124 |
+
Tidelift will coordinate the fix and disclosure with maintainers.
|
125 |
+
|
126 |
+
|
127 |
+
## Maintainers
|
128 |
+
|
129 |
+
- [@sethmlarson](https://github.com/sethmlarson) (Seth M. Larson)
|
130 |
+
- [@pquentin](https://github.com/pquentin) (Quentin Pradet)
|
131 |
+
- [@illia-v](https://github.com/illia-v) (Illia Volochii)
|
132 |
+
- [@theacodes](https://github.com/theacodes) (Thea Flowers)
|
133 |
+
- [@haikuginger](https://github.com/haikuginger) (Jess Shapiro)
|
134 |
+
- [@lukasa](https://github.com/lukasa) (Cory Benfield)
|
135 |
+
- [@sigmavirus24](https://github.com/sigmavirus24) (Ian Stapleton Cordasco)
|
136 |
+
- [@shazow](https://github.com/shazow) (Andrey Petrov)
|
137 |
+
|
138 |
+
👋
|
139 |
+
|
140 |
+
|
141 |
+
## Sponsorship
|
142 |
+
|
143 |
+
If your company benefits from this library, please consider [sponsoring its
|
144 |
+
development](https://urllib3.readthedocs.io/en/latest/sponsors.html).
|
145 |
+
|
146 |
+
|
147 |
+
## For Enterprise
|
148 |
+
|
149 |
+
Professional support for urllib3 is available as part of the [Tidelift
|
150 |
+
Subscription][1]. Tidelift gives software development teams a single source for
|
151 |
+
purchasing and maintaining their software, with professional grade assurances
|
152 |
+
from the experts who know it best, while seamlessly integrating with existing
|
153 |
+
tools.
|
154 |
+
|
155 |
+
[1]: https://tidelift.com/subscription/pkg/pypi-urllib3?utm_source=pypi-urllib3&utm_medium=referral&utm_campaign=readme
|
.venv/Lib/site-packages/urllib3-2.2.3.dist-info/RECORD
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
urllib3-2.2.3.dist-info/METADATA,sha256=NpyLMYu-QoAmQK6pmmgoZRuq0HPt-lf_J9zIuCGMRNY,6485
|
2 |
+
urllib3-2.2.3.dist-info/RECORD,,
|
3 |
+
urllib3-2.2.3.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
4 |
+
urllib3-2.2.3.dist-info/licenses/LICENSE.txt,sha256=Ew46ZNX91dCWp1JpRjSn2d8oRGnehuVzIQAmgEHj1oY,1093
|
5 |
+
urllib3-2.2.3.dist-info\INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2
|
6 |
+
urllib3-2.2.3.dist-info\REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7 |
+
urllib3/__init__.py,sha256=JMo1tg1nIV1AeJ2vENC_Txfl0e5h6Gzl9DGVk1rWRbo,6979
|
8 |
+
urllib3/_base_connection.py,sha256=tH0ZlOxWKika-S9NW-MuIlI_PLFQUUmSnoE_9MeywkM,5652
|
9 |
+
urllib3/_collections.py,sha256=aGhh9zCYce3o-5FW9DPSUay6O9LjHx8z6T7wDtdhrkY,17370
|
10 |
+
urllib3/_request_methods.py,sha256=LTDxHenEP5XX-tVWBNkEkAgizCERkZF0JK-F-wCxqwI,9938
|
11 |
+
urllib3/_version.py,sha256=gF7zM8AsdLRqhgteXesNHb7_t8ukr2zzkok2g1nvvhA,411
|
12 |
+
urllib3/connection.py,sha256=QAwhOV5GOVdsFnMvX5Vv6fQ8f47EzfrROAArfxRdQOY,39508
|
13 |
+
urllib3/connectionpool.py,sha256=5fPIHypPwlbKBASMs6bESTEJVEGlsj9FOY9_GGU2GpM,43393
|
14 |
+
urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15 |
+
urllib3/contrib/emscripten/__init__.py,sha256=u6KNgzjlFZbuAAXa_ybCR7gQ71VJESnF-IIdDA73brw,733
|
16 |
+
urllib3/contrib/emscripten/connection.py,sha256=kaBe2tWt7Yy9vNUFRBV7CSyDnfhCYILGxju9KTZj8Sw,8755
|
17 |
+
urllib3/contrib/emscripten/emscripten_fetch_worker.js,sha256=CDfYF_9CDobtx2lGidyJ1zjDEvwNT5F-dchmVWXDh0E,3655
|
18 |
+
urllib3/contrib/emscripten/fetch.py,sha256=ymwJlHBBuw6WTpKgPHpdmmrNBxlsr75HqoD4Rn27YXk,14131
|
19 |
+
urllib3/contrib/emscripten/request.py,sha256=mL28szy1KvE3NJhWor5jNmarp8gwplDU-7gwGZY5g0Q,566
|
20 |
+
urllib3/contrib/emscripten/response.py,sha256=wEYWPHCL-JsgCtpCpfnWGYA1-DcjDGpFGqWCXZLwbHY,10017
|
21 |
+
urllib3/contrib/pyopenssl.py,sha256=9iP4j8JafA4hqtX9AgJ9zxrqI-icohGrqFqAMryoNdA,19338
|
22 |
+
urllib3/contrib/socks.py,sha256=-iardc61GypsJzD6W6yuRS7KVCyfowcQrl_719H7lIM,7549
|
23 |
+
urllib3/exceptions.py,sha256=RDaiudtR7rqbVKTKpLSgZBBtwaIqV7eZtervZV_mZag,9393
|
24 |
+
urllib3/fields.py,sha256=8vi0PeRo_pE5chPmJA07LZtMkVls4UrBS1k2xM506jM,10843
|
25 |
+
urllib3/filepost.py,sha256=-9qJT11cNGjO9dqnI20-oErZuTvNaM18xZZPCjZSbOE,2395
|
26 |
+
urllib3/http2/__init__.py,sha256=xzrASH7R5ANRkPJOot5lGnATOq3KKuyXzI42rcnwmqs,1741
|
27 |
+
urllib3/http2/connection.py,sha256=GNlp9BjI3DmfSKe1W0b9IqRBeM8Q13xd2MA3ROcJ3dY,12668
|
28 |
+
urllib3/http2/probe.py,sha256=nnAkqbhAakOiF75rz7W0udZ38Eeh_uD8fjV74N73FEI,3014
|
29 |
+
urllib3/poolmanager.py,sha256=2_L2AjVDgoQ0qBmYbX9u9QqyU1u5J37zQbtv_-ueZQA,22913
|
30 |
+
urllib3/py.typed,sha256=UaCuPFa3H8UAakbt-5G8SPacldTOGvJv18pPjUJ5gDY,93
|
31 |
+
urllib3/response.py,sha256=NS0rqwRmtwWtC_6XDqgDJN_uo-jEmBVzx0V6KCsHlwg,44801
|
32 |
+
urllib3/util/__init__.py,sha256=-qeS0QceivazvBEKDNFCAI-6ACcdDOE4TMvo7SLNlAQ,1001
|
33 |
+
urllib3/util/connection.py,sha256=0o79-5NbRfpBDyoehGPLmCA544sCSiXvx0mF9xy3GG0,4458
|
34 |
+
urllib3/util/proxy.py,sha256=seP8-Q5B6bB0dMtwPj-YcZZQ30vHuLqRu-tI0JZ2fzs,1148
|
35 |
+
urllib3/util/request.py,sha256=UrZ2g3y3stGpH8rm-Sx8-ollgeiiKI496DZXRCwxb9o,8064
|
36 |
+
urllib3/util/response.py,sha256=vQE639uoEhj1vpjEdxu5lNIhJCSUZkd7pqllUI0BZOA,3374
|
37 |
+
urllib3/util/retry.py,sha256=bj-2YUqblxLlv8THg5fxww-DM54XCbjgZXIQ71XioCY,18459
|
38 |
+
urllib3/util/ssl_.py,sha256=WN8a6KPPcvukbZ0MUlBAOkGil8bYKY8NoIYOw7QeOLI,19238
|
39 |
+
urllib3/util/ssl_match_hostname.py,sha256=gaWqixoYtQ_GKO8fcRGFj3VXeMoqyxQQuUTPgWeiL_M,5812
|
40 |
+
urllib3/util/ssltransport.py,sha256=wprBvhkgjddhhMwwEbHyP4lygHpP6SS-45Euh7oe48k,8887
|
41 |
+
urllib3/util/timeout.py,sha256=4eT1FVeZZU7h7mYD1Jq2OXNe4fxekdNvhoWUkZusRpA,10346
|
42 |
+
urllib3/util/url.py,sha256=wHORhp80RAXyTlAIkTqLFzSrkU7J34ZDxX-tN65MBZk,15213
|
43 |
+
urllib3/util/util.py,sha256=j3lbZK1jPyiwD34T8IgJzdWEZVT-4E-0vYIJi9UjeNA,1146
|
44 |
+
urllib3/util/wait.py,sha256=_ph8IrUR3sqPqi0OopQgJUlH4wzkGeM5CiyA7XGGtmI,4423
|
.venv/Lib/site-packages/urllib3-2.2.3.dist-info/REQUESTED
ADDED
File without changes
|
.venv/Lib/site-packages/urllib3-2.2.3.dist-info/WHEEL
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Wheel-Version: 1.0
|
2 |
+
Generator: hatchling 1.25.0
|
3 |
+
Root-Is-Purelib: true
|
4 |
+
Tag: py3-none-any
|
.venv/Lib/site-packages/urllib3-2.2.3.dist-info/licenses/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2008-2020 Andrey Petrov and contributors.
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
.venv/Lib/site-packages/urllib3/__pycache__/__init__.cpython-39.pyc
ADDED
Binary file (6 kB). View file
|
|
.venv/Lib/site-packages/urllib3/__pycache__/_base_connection.cpython-39.pyc
ADDED
Binary file (5.46 kB). View file
|
|
.venv/Lib/site-packages/urllib3/__pycache__/_collections.cpython-39.pyc
ADDED
Binary file (15.8 kB). View file
|
|
.venv/Lib/site-packages/urllib3/__pycache__/_request_methods.cpython-39.pyc
ADDED
Binary file (8.94 kB). View file
|
|
.venv/Lib/site-packages/urllib3/__pycache__/_version.cpython-39.pyc
ADDED
Binary file (502 Bytes). View file
|
|
.venv/Lib/site-packages/urllib3/__pycache__/connection.cpython-39.pyc
ADDED
Binary file (23.3 kB). View file
|
|
.venv/Lib/site-packages/urllib3/__pycache__/connectionpool.cpython-39.pyc
ADDED
Binary file (28.6 kB). View file
|
|
.venv/Lib/site-packages/urllib3/__pycache__/exceptions.cpython-39.pyc
ADDED
Binary file (13.6 kB). View file
|
|
.venv/Lib/site-packages/urllib3/__pycache__/fields.cpython-39.pyc
ADDED
Binary file (9.64 kB). View file
|
|
.venv/Lib/site-packages/urllib3/__pycache__/filepost.cpython-39.pyc
ADDED
Binary file (2.32 kB). View file
|
|
.venv/Lib/site-packages/urllib3/__pycache__/poolmanager.cpython-39.pyc
ADDED
Binary file (17.8 kB). View file
|
|
.venv/Lib/site-packages/urllib3/__pycache__/response.cpython-39.pyc
ADDED
Binary file (33.1 kB). View file
|
|
.venv/Lib/site-packages/urllib3/util/__pycache__/__init__.cpython-39.pyc
ADDED
Binary file (967 Bytes). View file
|
|
.venv/Lib/site-packages/urllib3/util/__pycache__/response.cpython-39.pyc
ADDED
Binary file (2.31 kB). View file
|
|
.venv/Lib/site-packages/urllib3/util/__pycache__/retry.cpython-39.pyc
ADDED
Binary file (15.3 kB). View file
|
|
.venv/Lib/site-packages/urllib3/util/__pycache__/ssl_.cpython-39.pyc
ADDED
Binary file (12.1 kB). View file
|
|
.venv/Lib/site-packages/urllib3/util/__pycache__/ssl_match_hostname.cpython-39.pyc
ADDED
Binary file (3.66 kB). View file
|
|
.venv/Lib/site-packages/urllib3/util/__pycache__/ssltransport.cpython-39.pyc
ADDED
Binary file (9.16 kB). View file
|
|
.venv/Lib/site-packages/urllib3/util/__pycache__/timeout.cpython-39.pyc
ADDED
Binary file (9.53 kB). View file
|
|
.venv/Lib/site-packages/urllib3/util/__pycache__/url.cpython-39.pyc
ADDED
Binary file (11 kB). View file
|
|
.venv/Lib/site-packages/urllib3/util/__pycache__/util.cpython-39.pyc
ADDED
Binary file (1.25 kB). View file
|
|
.venv/Lib/site-packages/urllib3/util/__pycache__/wait.cpython-39.pyc
ADDED
Binary file (2.39 kB). View file
|
|
.venv/Lib/site-packages/wasabi/__init__.py
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# coding: utf8
|
2 |
+
from __future__ import unicode_literals
|
3 |
+
|
4 |
+
from .printer import Printer # noqa
|
5 |
+
from .tables import table, row # noqa
|
6 |
+
from .traceback_printer import TracebackPrinter # noqa
|
7 |
+
from .markdown import MarkdownRenderer # noqa
|
8 |
+
from .util import color, wrap, get_raw_input, format_repr, diff_strings # noqa
|
9 |
+
from .util import MESSAGES # noqa
|
10 |
+
from .about import __version__ # noqa
|
11 |
+
|
12 |
+
msg = Printer()
|
.venv/Lib/site-packages/wasabi/about.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
__title__ = "wasabi"
|
2 |
+
__version__ = "0.10.1"
|
3 |
+
__summary__ = "A lightweight console printing and formatting toolkit"
|
4 |
+
__uri__ = "https://ines.io"
|
5 |
+
__author__ = "Ines Montani"
|
6 |
+
__email__ = "[email protected]"
|
7 |
+
__license__ = "MIT"
|
.venv/Lib/site-packages/wasabi/markdown.py
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# coding: utf8
|
2 |
+
from __future__ import unicode_literals, print_function
|
3 |
+
|
4 |
+
|
5 |
+
class MarkdownRenderer:
|
6 |
+
"""Simple helper for generating raw Markdown."""
|
7 |
+
|
8 |
+
def __init__(self, no_emoji=False):
|
9 |
+
"""Initialize the renderer.
|
10 |
+
|
11 |
+
no_emoji (bool): Don't show emoji in titles etc.
|
12 |
+
"""
|
13 |
+
self.data = []
|
14 |
+
self.no_emoji = no_emoji
|
15 |
+
|
16 |
+
@property
|
17 |
+
def text(self):
|
18 |
+
"""RETURNS (str): The Markdown document."""
|
19 |
+
return "\n\n".join(self.data)
|
20 |
+
|
21 |
+
def add(self, content):
|
22 |
+
"""Add a string to the Markdown document.
|
23 |
+
|
24 |
+
content (str): Add content to the document.
|
25 |
+
"""
|
26 |
+
self.data.append(content)
|
27 |
+
|
28 |
+
def table(self, data, header, aligns=None):
|
29 |
+
"""Create a Markdown table.
|
30 |
+
|
31 |
+
data (Iterable[Iterable[str]]): The body, one iterable per row,
|
32 |
+
containig an interable of column contents.
|
33 |
+
header (Iterable[str]): The column names.
|
34 |
+
RETURNS (str): The rendered table.
|
35 |
+
"""
|
36 |
+
if aligns is None:
|
37 |
+
aligns = ["l"] * len(header)
|
38 |
+
if len(aligns) != len(header):
|
39 |
+
err = "Invalid aligns: {} (header length: {})".format(aligns, len(header))
|
40 |
+
raise ValueError(err)
|
41 |
+
get_divider = lambda a: ":---:" if a == "c" else "---:" if a == "r" else "---"
|
42 |
+
head = "| {} |".format(" | ".join(header))
|
43 |
+
divider = "| {} |".format(
|
44 |
+
" | ".join(get_divider(aligns[i]) for i in range(len(header)))
|
45 |
+
)
|
46 |
+
body = "\n".join("| {} |".format(" | ".join(row)) for row in data)
|
47 |
+
return "{}\n{}\n{}".format(head, divider, body)
|
48 |
+
|
49 |
+
def title(self, level, text, emoji=None):
|
50 |
+
"""Create a Markdown heading.
|
51 |
+
|
52 |
+
level (int): The heading level, e.g. 3 for ###
|
53 |
+
text (str): The heading text.
|
54 |
+
emoji (str): Optional emoji to show before heading text, if enabled.
|
55 |
+
RETURNS (str): The rendered title.
|
56 |
+
"""
|
57 |
+
prefix = "{} ".format(emoji) if emoji and not self.no_emoji else ""
|
58 |
+
return "{} {}{}".format("#" * level, prefix, text)
|
59 |
+
|
60 |
+
def list(self, items, numbered=False):
|
61 |
+
"""Create a non-nested list.
|
62 |
+
|
63 |
+
items (Iterable[str]): The list items.
|
64 |
+
numbered (bool): Whether to use a numbered list.
|
65 |
+
RETURNS (str): The rendered list.
|
66 |
+
"""
|
67 |
+
content = []
|
68 |
+
for i, item in enumerate(items):
|
69 |
+
if numbered:
|
70 |
+
content.append("{}. {}".format(i + 1, item))
|
71 |
+
else:
|
72 |
+
content.append("- {}".format(item))
|
73 |
+
return "\n".join(content)
|
74 |
+
|
75 |
+
def link(self, text, url):
|
76 |
+
"""Create a Markdown link.
|
77 |
+
|
78 |
+
text (str): The link text.
|
79 |
+
url (str): The link URL.
|
80 |
+
RETURNS (str): The rendered link.
|
81 |
+
"""
|
82 |
+
return "[{}]({})".format(text, url)
|
83 |
+
|
84 |
+
def code_block(self, text, lang=""):
|
85 |
+
"""Create a Markdown code block.
|
86 |
+
|
87 |
+
text (str): The code text.
|
88 |
+
lang (str): Optional code language.
|
89 |
+
RETURNS (str): The rendered code block.
|
90 |
+
"""
|
91 |
+
return "```{}\n{}\n```".format(lang, text)
|
92 |
+
|
93 |
+
def code(self, text):
|
94 |
+
"""Create Markdown inline code."""
|
95 |
+
return self._wrap(text, "`")
|
96 |
+
|
97 |
+
def bold(self, text):
|
98 |
+
"""Create bold text."""
|
99 |
+
return self._wrap(text, "**")
|
100 |
+
|
101 |
+
def italic(self, text):
|
102 |
+
"""Create italic text."""
|
103 |
+
return self._wrap(text, "_")
|
104 |
+
|
105 |
+
def _wrap(self, text, marker):
|
106 |
+
return "{}{}{}".format(marker, text, marker)
|
.venv/Lib/site-packages/wasabi/printer.py
ADDED
@@ -0,0 +1,250 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# coding: utf8
|
2 |
+
from __future__ import unicode_literals, print_function
|
3 |
+
|
4 |
+
import datetime
|
5 |
+
from collections import Counter
|
6 |
+
from contextlib import contextmanager
|
7 |
+
from multiprocessing import Process
|
8 |
+
import itertools
|
9 |
+
import sys
|
10 |
+
import time
|
11 |
+
import os
|
12 |
+
import traceback
|
13 |
+
|
14 |
+
from .tables import table, row
|
15 |
+
from .util import wrap, supports_ansi, can_render, locale_escape
|
16 |
+
from .util import MESSAGES, COLORS, ICONS
|
17 |
+
from .util import color as _color
|
18 |
+
|
19 |
+
|
20 |
+
class Printer(object):
|
21 |
+
def __init__(
|
22 |
+
self,
|
23 |
+
pretty=True,
|
24 |
+
no_print=False,
|
25 |
+
colors=None,
|
26 |
+
icons=None,
|
27 |
+
line_max=80,
|
28 |
+
animation="⠙⠹⠸⠼⠴⠦⠧⠇⠏",
|
29 |
+
animation_ascii="|/-\\",
|
30 |
+
hide_animation=False,
|
31 |
+
ignore_warnings=False,
|
32 |
+
env_prefix="WASABI",
|
33 |
+
timestamp=False,
|
34 |
+
):
|
35 |
+
"""Initialize the command-line printer.
|
36 |
+
|
37 |
+
pretty (bool): Pretty-print output (colors, icons).
|
38 |
+
no_print (bool): Don't actually print, just return.
|
39 |
+
colors (dict): Add or overwrite color values, name mapped to value.
|
40 |
+
icons (dict): Add or overwrite icons. Name mapped to unicode icon.
|
41 |
+
line_max (int): Maximum line length (for divider).
|
42 |
+
animation (unicode): Steps of loading animation for loading() method.
|
43 |
+
animation_ascii (unicode): Alternative animation for ASCII terminals.
|
44 |
+
hide_animation (bool): Don't display animation, e.g. for logs.
|
45 |
+
ignore_warnings (bool): Do not output messages of type MESSAGE.WARN.
|
46 |
+
env_prefix (unicode): Prefix for environment variables, e.g.
|
47 |
+
WASABI_LOG_FRIENDLY.
|
48 |
+
timestamp (bool): Print a timestamp (default False).
|
49 |
+
RETURNS (Printer): The initialized printer.
|
50 |
+
"""
|
51 |
+
env_log_friendly = os.getenv("{}_LOG_FRIENDLY".format(env_prefix), False)
|
52 |
+
env_no_pretty = os.getenv("{}_NO_PRETTY".format(env_prefix), False)
|
53 |
+
self._counts = Counter()
|
54 |
+
self.pretty = pretty and not env_no_pretty
|
55 |
+
self.no_print = no_print
|
56 |
+
self.show_color = supports_ansi() and not env_log_friendly
|
57 |
+
self.hide_animation = hide_animation or env_log_friendly
|
58 |
+
self.ignore_warnings = ignore_warnings
|
59 |
+
self.line_max = line_max
|
60 |
+
self.colors = dict(COLORS)
|
61 |
+
self.icons = dict(ICONS)
|
62 |
+
self.timestamp = timestamp
|
63 |
+
if colors:
|
64 |
+
self.colors.update(colors)
|
65 |
+
if icons:
|
66 |
+
self.icons.update(icons)
|
67 |
+
self.anim = animation if can_render(animation) else animation_ascii
|
68 |
+
|
69 |
+
@property
|
70 |
+
def counts(self):
|
71 |
+
"""Get the counts of how often the special printers were fired,
|
72 |
+
e.g. MESSAGES.GOOD. Can be used to print an overview like "X warnings".
|
73 |
+
"""
|
74 |
+
return self._counts
|
75 |
+
|
76 |
+
def good(self, title="", text="", show=True, spaced=False, exits=None):
|
77 |
+
"""Print a success message."""
|
78 |
+
return self._get_msg(
|
79 |
+
title, text, style=MESSAGES.GOOD, show=show, spaced=spaced, exits=exits
|
80 |
+
)
|
81 |
+
|
82 |
+
def fail(self, title="", text="", show=True, spaced=False, exits=None):
|
83 |
+
"""Print an error message."""
|
84 |
+
return self._get_msg(
|
85 |
+
title, text, style=MESSAGES.FAIL, show=show, spaced=spaced, exits=exits
|
86 |
+
)
|
87 |
+
|
88 |
+
def warn(self, title="", text="", show=True, spaced=False, exits=None):
|
89 |
+
"""Print a warning message."""
|
90 |
+
return self._get_msg(
|
91 |
+
title, text, style=MESSAGES.WARN, show=show, spaced=spaced, exits=exits
|
92 |
+
)
|
93 |
+
|
94 |
+
def info(self, title="", text="", show=True, spaced=False, exits=None):
|
95 |
+
"""Print an informational message."""
|
96 |
+
return self._get_msg(
|
97 |
+
title, text, style=MESSAGES.INFO, show=show, spaced=spaced, exits=exits
|
98 |
+
)
|
99 |
+
|
100 |
+
def text(
|
101 |
+
self,
|
102 |
+
title="",
|
103 |
+
text="",
|
104 |
+
color=None,
|
105 |
+
bg_color=None,
|
106 |
+
icon=None,
|
107 |
+
spaced=False,
|
108 |
+
show=True,
|
109 |
+
no_print=False,
|
110 |
+
exits=None,
|
111 |
+
):
|
112 |
+
"""Print a message.
|
113 |
+
|
114 |
+
title (unicode): The main text to print.
|
115 |
+
text (unicode): Optional additional text to print.
|
116 |
+
color (unicode / int): Foreground color.
|
117 |
+
bg_color (unicode / int): Background color.
|
118 |
+
icon (unicode): Name of icon to add.
|
119 |
+
spaced (unicode): Whether to add newlines around the output.
|
120 |
+
show (bool): Whether to print or not. Can be used to only output
|
121 |
+
messages under certain condition, e.g. if --verbose flag is set.
|
122 |
+
no_print (bool): Don't actually print, just return.
|
123 |
+
exits (int): Perform a system exit.
|
124 |
+
"""
|
125 |
+
if not show:
|
126 |
+
return
|
127 |
+
if self.pretty:
|
128 |
+
color = self.colors.get(color, color)
|
129 |
+
bg_color = self.colors.get(bg_color, bg_color)
|
130 |
+
icon = self.icons.get(icon)
|
131 |
+
if icon:
|
132 |
+
title = locale_escape("{} {}".format(icon, title)).strip()
|
133 |
+
if self.show_color:
|
134 |
+
title = _color(title, fg=color, bg=bg_color)
|
135 |
+
title = wrap(title, indent=0)
|
136 |
+
if text:
|
137 |
+
title = "{}\n{}".format(title, wrap(text, indent=0))
|
138 |
+
if self.timestamp:
|
139 |
+
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
140 |
+
title = "{}\t{}".format(now, title)
|
141 |
+
if exits is not None or spaced:
|
142 |
+
title = "\n{}\n".format(title)
|
143 |
+
if not self.no_print and not no_print:
|
144 |
+
print(title)
|
145 |
+
if exits is not None:
|
146 |
+
sys.stdout.flush()
|
147 |
+
sys.stderr.flush()
|
148 |
+
if self.no_print or no_print and exits != 0:
|
149 |
+
try:
|
150 |
+
raise RuntimeError(title.strip())
|
151 |
+
except Exception as e:
|
152 |
+
# Remove wasabi from the traceback and re-raise
|
153 |
+
tb = "\n".join(traceback.format_stack()[:-3])
|
154 |
+
raise SystemExit("{}\n{}".format(tb, e))
|
155 |
+
sys.exit(exits)
|
156 |
+
if self.no_print or no_print:
|
157 |
+
return title
|
158 |
+
|
159 |
+
def divider(self, text="", char="=", show=True, icon=None):
|
160 |
+
"""Print a divider with a headline:
|
161 |
+
============================ Headline here ===========================
|
162 |
+
|
163 |
+
text (unicode): Headline text. If empty, only the line is printed.
|
164 |
+
char (unicode): Line character to repeat, e.g. =.
|
165 |
+
show (bool): Whether to print or not.
|
166 |
+
icon (unicode): Optional icon to display with title.
|
167 |
+
"""
|
168 |
+
if not show:
|
169 |
+
return
|
170 |
+
if len(char) != 1:
|
171 |
+
raise ValueError(
|
172 |
+
"Divider chars need to be one character long. "
|
173 |
+
"Received: {}".format(char)
|
174 |
+
)
|
175 |
+
if self.pretty:
|
176 |
+
icon = self.icons.get(icon)
|
177 |
+
if icon:
|
178 |
+
text = locale_escape("{} {}".format(icon, text)).strip()
|
179 |
+
deco = char * (int(round((self.line_max - len(text))) / 2) - 2)
|
180 |
+
text = " {} ".format(text) if text else ""
|
181 |
+
text = _color(
|
182 |
+
"\n{deco}{text}{deco}".format(deco=deco, text=text), bold=True
|
183 |
+
)
|
184 |
+
if len(text) < self.line_max:
|
185 |
+
text = text + char * (self.line_max - len(text))
|
186 |
+
if self.no_print:
|
187 |
+
return text
|
188 |
+
print(text)
|
189 |
+
|
190 |
+
def table(self, data, **kwargs):
|
191 |
+
"""Print data as a table.
|
192 |
+
|
193 |
+
data (iterable / dict): The data to render. Either a list of lists
|
194 |
+
(one per row) or a dict for two-column tables.
|
195 |
+
kwargs: Table settings. See tables.table for details.
|
196 |
+
"""
|
197 |
+
title = kwargs.pop("title", None)
|
198 |
+
text = table(data, **kwargs)
|
199 |
+
if title:
|
200 |
+
self.divider(title)
|
201 |
+
if self.no_print:
|
202 |
+
return text
|
203 |
+
print(text)
|
204 |
+
|
205 |
+
def row(self, data, **kwargs):
|
206 |
+
"""Print a table row.
|
207 |
+
|
208 |
+
data (iterable): The individual columns to format.
|
209 |
+
kwargs: Row settings. See tables.row for details.
|
210 |
+
"""
|
211 |
+
text = row(data, **kwargs)
|
212 |
+
if self.no_print:
|
213 |
+
return text
|
214 |
+
print(text)
|
215 |
+
|
216 |
+
@contextmanager
|
217 |
+
def loading(self, text="Loading..."):
|
218 |
+
if self.no_print:
|
219 |
+
yield
|
220 |
+
elif self.hide_animation:
|
221 |
+
print(text)
|
222 |
+
yield
|
223 |
+
else:
|
224 |
+
sys.stdout.flush()
|
225 |
+
t = Process(target=self._spinner, args=(text,))
|
226 |
+
t.start()
|
227 |
+
try:
|
228 |
+
yield
|
229 |
+
except Exception as e:
|
230 |
+
# Handle exception inside the with block
|
231 |
+
t.terminate()
|
232 |
+
sys.stdout.write("\n")
|
233 |
+
raise (e)
|
234 |
+
t.terminate()
|
235 |
+
sys.stdout.write("\r\x1b[2K") # erase line
|
236 |
+
sys.stdout.flush()
|
237 |
+
|
238 |
+
def _spinner(self, text="Loading..."):
|
239 |
+
for char in itertools.cycle(self.anim):
|
240 |
+
sys.stdout.write("\r{} {}".format(char, text))
|
241 |
+
sys.stdout.flush()
|
242 |
+
time.sleep(0.1)
|
243 |
+
|
244 |
+
def _get_msg(self, title, text, style=None, show=None, spaced=False, exits=None):
|
245 |
+
if self.ignore_warnings and style == MESSAGES.WARN:
|
246 |
+
show = False
|
247 |
+
self._counts[style] += 1
|
248 |
+
return self.text(
|
249 |
+
title, text, color=style, icon=style, show=show, spaced=spaced, exits=exits
|
250 |
+
)
|
.venv/Lib/site-packages/wasabi/tables.py
ADDED
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# coding: utf8
|
2 |
+
from __future__ import unicode_literals, print_function
|
3 |
+
import os
|
4 |
+
|
5 |
+
from .util import COLORS
|
6 |
+
from .util import color as _color
|
7 |
+
from .util import supports_ansi, to_string, zip_longest, basestring_
|
8 |
+
|
9 |
+
|
10 |
+
ALIGN_MAP = {"l": "<", "r": ">", "c": "^"}
|
11 |
+
|
12 |
+
|
13 |
+
def table(
|
14 |
+
data,
|
15 |
+
header=None,
|
16 |
+
footer=None,
|
17 |
+
divider=False,
|
18 |
+
widths="auto",
|
19 |
+
max_col=30,
|
20 |
+
spacing=3,
|
21 |
+
aligns=None,
|
22 |
+
multiline=False,
|
23 |
+
env_prefix="WASABI",
|
24 |
+
color_values=None,
|
25 |
+
fg_colors=None,
|
26 |
+
bg_colors=None,
|
27 |
+
):
|
28 |
+
"""Format tabular data.
|
29 |
+
|
30 |
+
data (iterable / dict): The data to render. Either a list of lists (one per
|
31 |
+
row) or a dict for two-column tables.
|
32 |
+
header (iterable): The header columns.
|
33 |
+
footer (iterable): The footer columns.
|
34 |
+
divider (bool): Show a divider line between header/footer and body.
|
35 |
+
widths (iterable or 'auto'): Column widths in order. If "auto", widths
|
36 |
+
will be calculated automatically based on the largest value.
|
37 |
+
max_col (int): Maximum column width.
|
38 |
+
spacing (int): Spacing between columns, in spaces.
|
39 |
+
aligns (iterable / unicode): Column alignments in order. 'l' (left,
|
40 |
+
default), 'r' (right) or 'c' (center). If a string, value is used
|
41 |
+
for all columns.
|
42 |
+
multiline (bool): If a cell value is a list of a tuple, render it on
|
43 |
+
multiple lines, with one value per line.
|
44 |
+
env_prefix (unicode): Prefix for environment variables, e.g.
|
45 |
+
WASABI_LOG_FRIENDLY.
|
46 |
+
color_values (dict): Add or overwrite color values, name mapped to value.
|
47 |
+
fg_colors (iterable): Foreground colors, one per column. None can be specified
|
48 |
+
for individual columns to retain the default foreground color.
|
49 |
+
bg_colors (iterable): Background colors, one per column. None can be specified
|
50 |
+
for individual columns to retain the default background color.
|
51 |
+
RETURNS (unicode): The formatted table.
|
52 |
+
"""
|
53 |
+
if fg_colors is not None or bg_colors is not None:
|
54 |
+
colors = dict(COLORS)
|
55 |
+
if color_values is not None:
|
56 |
+
colors.update(color_values)
|
57 |
+
if fg_colors is not None:
|
58 |
+
fg_colors = [colors.get(fg_color, fg_color) for fg_color in fg_colors]
|
59 |
+
if bg_colors is not None:
|
60 |
+
bg_colors = [colors.get(bg_color, bg_color) for bg_color in bg_colors]
|
61 |
+
if isinstance(data, dict):
|
62 |
+
data = list(data.items())
|
63 |
+
if multiline:
|
64 |
+
zipped_data = []
|
65 |
+
for i, item in enumerate(data):
|
66 |
+
vals = [v if isinstance(v, (list, tuple)) else [v] for v in item]
|
67 |
+
zipped_data.extend(list(zip_longest(*vals, fillvalue="")))
|
68 |
+
if i < len(data) - 1:
|
69 |
+
zipped_data.append(["" for i in item])
|
70 |
+
data = zipped_data
|
71 |
+
if widths == "auto":
|
72 |
+
widths = _get_max_widths(data, header, footer, max_col)
|
73 |
+
settings = {
|
74 |
+
"widths": widths,
|
75 |
+
"spacing": spacing,
|
76 |
+
"aligns": aligns,
|
77 |
+
"env_prefix": env_prefix,
|
78 |
+
"fg_colors": fg_colors,
|
79 |
+
"bg_colors": bg_colors,
|
80 |
+
}
|
81 |
+
divider_row = row(["-" * width for width in widths], **settings)
|
82 |
+
rows = []
|
83 |
+
if header:
|
84 |
+
rows.append(row(header, **settings))
|
85 |
+
if divider:
|
86 |
+
rows.append(divider_row)
|
87 |
+
for i, item in enumerate(data):
|
88 |
+
rows.append(row(item, **settings))
|
89 |
+
if footer:
|
90 |
+
if divider:
|
91 |
+
rows.append(divider_row)
|
92 |
+
rows.append(row(footer, **settings))
|
93 |
+
return "\n{}\n".format("\n".join(rows))
|
94 |
+
|
95 |
+
|
96 |
+
def row(
|
97 |
+
data,
|
98 |
+
widths="auto",
|
99 |
+
spacing=3,
|
100 |
+
aligns=None,
|
101 |
+
env_prefix="WASABI",
|
102 |
+
fg_colors=None,
|
103 |
+
bg_colors=None,
|
104 |
+
):
|
105 |
+
"""Format data as a table row.
|
106 |
+
|
107 |
+
data (iterable): The individual columns to format.
|
108 |
+
widths (list, int or 'auto'): Column widths, either one integer for all
|
109 |
+
columns or an iterable of values. If "auto", widths will be calculated
|
110 |
+
automatically based on the largest value.
|
111 |
+
spacing (int): Spacing between columns, in spaces.
|
112 |
+
aligns (list / unicode): Column alignments in order. 'l' (left,
|
113 |
+
default), 'r' (right) or 'c' (center). If a string, value is used
|
114 |
+
for all columns.
|
115 |
+
env_prefix (unicode): Prefix for environment variables, e.g.
|
116 |
+
WASABI_LOG_FRIENDLY.
|
117 |
+
fg_colors (list): Foreground colors for the columns, in order. None can be
|
118 |
+
specified for individual columns to retain the default foreground color.
|
119 |
+
bg_colors (list): Background colors for the columns, in order. None can be
|
120 |
+
specified for individual columns to retain the default background color.
|
121 |
+
RETURNS (unicode): The formatted row.
|
122 |
+
"""
|
123 |
+
env_log_friendly = os.getenv("{}_LOG_FRIENDLY".format(env_prefix), False)
|
124 |
+
show_colors = (
|
125 |
+
supports_ansi()
|
126 |
+
and not env_log_friendly
|
127 |
+
and (fg_colors is not None or bg_colors is not None)
|
128 |
+
)
|
129 |
+
cols = []
|
130 |
+
if isinstance(aligns, basestring_): # single align value
|
131 |
+
aligns = [aligns for _ in data]
|
132 |
+
if not hasattr(widths, "__iter__") and widths != "auto": # single number
|
133 |
+
widths = [widths for _ in range(len(data))]
|
134 |
+
for i, col in enumerate(data):
|
135 |
+
align = ALIGN_MAP.get(aligns[i] if aligns and i < len(aligns) else "l")
|
136 |
+
col_width = len(col) if widths == "auto" else widths[i]
|
137 |
+
tpl = "{:%s%d}" % (align, col_width)
|
138 |
+
col = tpl.format(to_string(col))
|
139 |
+
if show_colors:
|
140 |
+
fg = fg_colors[i] if fg_colors is not None else None
|
141 |
+
bg = bg_colors[i] if bg_colors is not None else None
|
142 |
+
col = _color(col, fg=fg, bg=bg)
|
143 |
+
cols.append(col)
|
144 |
+
return (" " * spacing).join(cols)
|
145 |
+
|
146 |
+
|
147 |
+
def _get_max_widths(data, header, footer, max_col):
|
148 |
+
all_data = list(data)
|
149 |
+
if header:
|
150 |
+
all_data.append(header)
|
151 |
+
if footer:
|
152 |
+
all_data.append(footer)
|
153 |
+
widths = [[len(to_string(col)) for col in item] for item in all_data]
|
154 |
+
return [min(max(w), max_col) for w in list(zip(*widths))]
|
.venv/Lib/site-packages/wasabi/tests/test_markdown.py
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# coding: utf8
|
2 |
+
from __future__ import unicode_literals, print_function
|
3 |
+
|
4 |
+
from wasabi.markdown import MarkdownRenderer
|
5 |
+
import pytest
|
6 |
+
|
7 |
+
|
8 |
+
def test_markdown():
|
9 |
+
md = MarkdownRenderer()
|
10 |
+
md.add(md.title(1, "Title"))
|
11 |
+
md.add("Paragraph with {}".format(md.bold("bold")))
|
12 |
+
md.add(md.list(["foo", "bar"]))
|
13 |
+
md.add(md.table([("a", "b"), ("c", "d")], ["foo", "bar"]))
|
14 |
+
md.add(md.code_block('import spacy\n\nnlp = spacy.blank("en")', "python"))
|
15 |
+
md.add(md.list(["first", "second"], numbered=True))
|
16 |
+
expected = """# Title\n\nParagraph with **bold**\n\n- foo\n- bar\n\n| foo | bar |\n| --- | --- |\n| a | b |\n| c | d |\n\n```python\nimport spacy\n\nnlp = spacy.blank("en")\n```\n\n1. first\n2. second"""
|
17 |
+
assert md.text == expected
|
18 |
+
|
19 |
+
|
20 |
+
def test_markdown_table_aligns():
|
21 |
+
md = MarkdownRenderer()
|
22 |
+
md.add(md.table([("a", "b", "c")], ["foo", "bar", "baz"], aligns=("c", "r", "l")))
|
23 |
+
expected = """| foo | bar | baz |\n| :---: | ---: | --- |\n| a | b | c |"""
|
24 |
+
assert md.text == expected
|
25 |
+
with pytest.raises(ValueError):
|
26 |
+
md.table([("a", "b", "c")], ["foo", "bar", "baz"], aligns=("c", "r"))
|
27 |
+
with pytest.raises(ValueError):
|
28 |
+
md.table([("a", "b", "c")], ["foo", "bar", "baz"], aligns=("c", "r", "l", "l"))
|
.venv/Lib/site-packages/wasabi/tests/test_printer.py
ADDED
@@ -0,0 +1,239 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# coding: utf8
|
2 |
+
from __future__ import unicode_literals, print_function
|
3 |
+
|
4 |
+
import re
|
5 |
+
|
6 |
+
import pytest
|
7 |
+
import time
|
8 |
+
import os
|
9 |
+
from wasabi.printer import Printer
|
10 |
+
from wasabi.util import MESSAGES, NO_UTF8, supports_ansi
|
11 |
+
|
12 |
+
|
13 |
+
SUPPORTS_ANSI = supports_ansi()
|
14 |
+
|
15 |
+
|
16 |
+
def test_printer():
|
17 |
+
p = Printer(no_print=True)
|
18 |
+
text = "This is a test."
|
19 |
+
good = p.good(text)
|
20 |
+
fail = p.fail(text)
|
21 |
+
warn = p.warn(text)
|
22 |
+
info = p.info(text)
|
23 |
+
assert p.text(text) == text
|
24 |
+
if SUPPORTS_ANSI and not NO_UTF8:
|
25 |
+
assert good == "\x1b[38;5;2m\u2714 {}\x1b[0m".format(text)
|
26 |
+
assert fail == "\x1b[38;5;1m\u2718 {}\x1b[0m".format(text)
|
27 |
+
assert warn == "\x1b[38;5;3m\u26a0 {}\x1b[0m".format(text)
|
28 |
+
assert info == "\x1b[38;5;4m\u2139 {}\x1b[0m".format(text)
|
29 |
+
if SUPPORTS_ANSI and NO_UTF8:
|
30 |
+
assert good == "\x1b[38;5;2m[+] {}\x1b[0m".format(text)
|
31 |
+
assert fail == "\x1b[38;5;1m[x] {}\x1b[0m".format(text)
|
32 |
+
assert warn == "\x1b[38;5;3m[!] {}\x1b[0m".format(text)
|
33 |
+
assert info == "\x1b[38;5;4m[i] {}\x1b[0m".format(text)
|
34 |
+
if not SUPPORTS_ANSI and not NO_UTF8:
|
35 |
+
assert good == "\u2714 {}".format(text)
|
36 |
+
assert fail == "\u2718 {}".format(text)
|
37 |
+
assert warn == "\u26a0 {}".format(text)
|
38 |
+
assert info == "\u2139 {}".format(text)
|
39 |
+
if not SUPPORTS_ANSI and NO_UTF8:
|
40 |
+
assert good == "[+] {}".format(text)
|
41 |
+
assert fail == "[x] {}".format(text)
|
42 |
+
assert warn == "[!] {}".format(text)
|
43 |
+
assert info == "[i] {}".format(text)
|
44 |
+
|
45 |
+
|
46 |
+
def test_printer_print():
|
47 |
+
p = Printer()
|
48 |
+
text = "This is a test."
|
49 |
+
p.good(text)
|
50 |
+
p.fail(text)
|
51 |
+
p.info(text)
|
52 |
+
p.text(text)
|
53 |
+
|
54 |
+
|
55 |
+
def test_printer_print_timestamp():
|
56 |
+
p = Printer(no_print=True, timestamp=True)
|
57 |
+
result = p.info("Hello world")
|
58 |
+
matches = re.match("^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}", result)
|
59 |
+
assert matches
|
60 |
+
|
61 |
+
|
62 |
+
def test_printer_no_pretty():
|
63 |
+
p = Printer(no_print=True, pretty=False)
|
64 |
+
text = "This is a test."
|
65 |
+
assert p.good(text) == text
|
66 |
+
assert p.fail(text) == text
|
67 |
+
assert p.warn(text) == text
|
68 |
+
assert p.info(text) == text
|
69 |
+
assert p.text(text) == text
|
70 |
+
|
71 |
+
|
72 |
+
def test_printer_custom():
|
73 |
+
colors = {"yellow": 220, "purple": 99}
|
74 |
+
icons = {"warn": "\u26a0\ufe0f", "question": "?"}
|
75 |
+
p = Printer(no_print=True, colors=colors, icons=icons)
|
76 |
+
text = "This is a test."
|
77 |
+
purple_question = p.text(text, color="purple", icon="question")
|
78 |
+
warning = p.warn(text)
|
79 |
+
if SUPPORTS_ANSI and not NO_UTF8:
|
80 |
+
assert purple_question == "\x1b[38;5;99m? {}\x1b[0m".format(text)
|
81 |
+
assert warning == "\x1b[38;5;3m\u26a0\ufe0f {}\x1b[0m".format(text)
|
82 |
+
if SUPPORTS_ANSI and NO_UTF8:
|
83 |
+
assert purple_question == "\x1b[38;5;99m? {}\x1b[0m".format(text)
|
84 |
+
assert warning == "\x1b[38;5;3m?? {}\x1b[0m".format(text)
|
85 |
+
if not SUPPORTS_ANSI and not NO_UTF8:
|
86 |
+
assert purple_question == "? {}".format(text)
|
87 |
+
assert warning == "\u26a0\ufe0f {}".format(text)
|
88 |
+
if not SUPPORTS_ANSI and NO_UTF8:
|
89 |
+
assert purple_question == "? {}".format(text)
|
90 |
+
assert warning == "?? {}".format(text)
|
91 |
+
|
92 |
+
|
93 |
+
def test_color_as_int():
|
94 |
+
p = Printer(no_print=True)
|
95 |
+
text = "This is a text."
|
96 |
+
result = p.text(text, color=220)
|
97 |
+
if SUPPORTS_ANSI:
|
98 |
+
assert result == "\x1b[38;5;220mThis is a text.\x1b[0m"
|
99 |
+
else:
|
100 |
+
assert result == "This is a text."
|
101 |
+
|
102 |
+
|
103 |
+
def test_bg_color():
|
104 |
+
p = Printer(no_print=True)
|
105 |
+
text = "This is a text."
|
106 |
+
result = p.text(text, bg_color="red")
|
107 |
+
print(result)
|
108 |
+
if SUPPORTS_ANSI:
|
109 |
+
assert result == "\x1b[48;5;1mThis is a text.\x1b[0m"
|
110 |
+
else:
|
111 |
+
assert result == "This is a text."
|
112 |
+
|
113 |
+
|
114 |
+
def test_bg_color_as_int():
|
115 |
+
p = Printer(no_print=True)
|
116 |
+
text = "This is a text."
|
117 |
+
result = p.text(text, bg_color=220)
|
118 |
+
print(result)
|
119 |
+
if SUPPORTS_ANSI:
|
120 |
+
assert result == "\x1b[48;5;220mThis is a text.\x1b[0m"
|
121 |
+
else:
|
122 |
+
assert result == "This is a text."
|
123 |
+
|
124 |
+
|
125 |
+
def test_color_and_bc_color():
|
126 |
+
p = Printer(no_print=True)
|
127 |
+
text = "This is a text."
|
128 |
+
result = p.text(text, color="green", bg_color="yellow")
|
129 |
+
print(result)
|
130 |
+
if SUPPORTS_ANSI:
|
131 |
+
assert result == "\x1b[38;5;2;48;5;3mThis is a text.\x1b[0m"
|
132 |
+
else:
|
133 |
+
assert result == "This is a text."
|
134 |
+
|
135 |
+
|
136 |
+
def test_printer_counts():
|
137 |
+
p = Printer()
|
138 |
+
text = "This is a test."
|
139 |
+
for i in range(2):
|
140 |
+
p.good(text)
|
141 |
+
for i in range(1):
|
142 |
+
p.fail(text)
|
143 |
+
for i in range(4):
|
144 |
+
p.warn(text)
|
145 |
+
assert p.counts[MESSAGES.GOOD] == 2
|
146 |
+
assert p.counts[MESSAGES.FAIL] == 1
|
147 |
+
assert p.counts[MESSAGES.WARN] == 4
|
148 |
+
|
149 |
+
|
150 |
+
def test_printer_spaced():
|
151 |
+
p = Printer(no_print=True, pretty=False)
|
152 |
+
text = "This is a test."
|
153 |
+
assert p.good(text) == text
|
154 |
+
assert p.good(text, spaced=True) == "\n{}\n".format(text)
|
155 |
+
|
156 |
+
|
157 |
+
def test_printer_divider():
|
158 |
+
p = Printer(line_max=20, no_print=True)
|
159 |
+
p.divider() == "\x1b[1m\n================\x1b[0m"
|
160 |
+
p.divider("test") == "\x1b[1m\n====== test ======\x1b[0m"
|
161 |
+
p.divider("test", char="*") == "\x1b[1m\n****** test ******\x1b[0m"
|
162 |
+
assert (
|
163 |
+
p.divider("This is a very long text, it is very long")
|
164 |
+
== "\x1b[1m\n This is a very long text, it is very long \x1b[0m"
|
165 |
+
)
|
166 |
+
with pytest.raises(ValueError):
|
167 |
+
p.divider("test", char="~.")
|
168 |
+
|
169 |
+
|
170 |
+
@pytest.mark.parametrize("hide_animation", [False, True])
|
171 |
+
def test_printer_loading(hide_animation):
|
172 |
+
p = Printer(hide_animation=hide_animation)
|
173 |
+
print("\n")
|
174 |
+
with p.loading("Loading..."):
|
175 |
+
time.sleep(1)
|
176 |
+
p.good("Success!")
|
177 |
+
|
178 |
+
with p.loading("Something else..."):
|
179 |
+
time.sleep(2)
|
180 |
+
p.good("Yo!")
|
181 |
+
|
182 |
+
with p.loading("Loading..."):
|
183 |
+
time.sleep(1)
|
184 |
+
p.good("Success!")
|
185 |
+
|
186 |
+
|
187 |
+
def test_printer_loading_raises_exception():
|
188 |
+
def loading_with_exception():
|
189 |
+
p = Printer()
|
190 |
+
print("\n")
|
191 |
+
with p.loading():
|
192 |
+
raise Exception("This is an error.")
|
193 |
+
|
194 |
+
with pytest.raises(Exception):
|
195 |
+
loading_with_exception()
|
196 |
+
|
197 |
+
|
198 |
+
def test_printer_loading_no_print():
|
199 |
+
p = Printer(no_print=True)
|
200 |
+
with p.loading("Loading..."):
|
201 |
+
time.sleep(1)
|
202 |
+
p.good("Success!")
|
203 |
+
|
204 |
+
|
205 |
+
def test_printer_log_friendly():
|
206 |
+
text = "This is a test."
|
207 |
+
ENV_LOG_FRIENDLY = "WASABI_LOG_FRIENDLY"
|
208 |
+
os.environ[ENV_LOG_FRIENDLY] = "True"
|
209 |
+
p = Printer(no_print=True)
|
210 |
+
assert p.good(text) in ("\u2714 This is a test.", "[+] This is a test.")
|
211 |
+
del os.environ[ENV_LOG_FRIENDLY]
|
212 |
+
|
213 |
+
|
214 |
+
def test_printer_log_friendly_prefix():
|
215 |
+
text = "This is a test."
|
216 |
+
ENV_LOG_FRIENDLY = "CUSTOM_LOG_FRIENDLY"
|
217 |
+
os.environ[ENV_LOG_FRIENDLY] = "True"
|
218 |
+
p = Printer(no_print=True, env_prefix="CUSTOM")
|
219 |
+
assert p.good(text) in ("\u2714 This is a test.", "[+] This is a test.")
|
220 |
+
print(p.good(text))
|
221 |
+
del os.environ[ENV_LOG_FRIENDLY]
|
222 |
+
|
223 |
+
|
224 |
+
@pytest.mark.skip(reason="Now seems to raise TypeError: readonly attribute?")
|
225 |
+
def test_printer_none_encoding(monkeypatch):
|
226 |
+
"""Test that printer works even if sys.stdout.encoding is set to None. This
|
227 |
+
previously caused a very confusing error."""
|
228 |
+
monkeypatch.setattr("sys.stdout.encoding", None)
|
229 |
+
p = Printer() # noqa: F841
|
230 |
+
|
231 |
+
|
232 |
+
def test_printer_no_print_raise_on_exit():
|
233 |
+
"""Test that the printer raises if a non-zero exit code is provided, even
|
234 |
+
if no_print is set to True."""
|
235 |
+
err = "This is an error."
|
236 |
+
p = Printer(no_print=True, pretty=False)
|
237 |
+
with pytest.raises(SystemExit) as e:
|
238 |
+
p.fail(err, exits=True)
|
239 |
+
assert str(e.value).strip()[-len(err) :] == err
|
.venv/Lib/site-packages/wasabi/tests/test_tables.py
ADDED
@@ -0,0 +1,422 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# coding: utf8
|
2 |
+
from __future__ import unicode_literals, print_function
|
3 |
+
|
4 |
+
import os
|
5 |
+
import pytest
|
6 |
+
from wasabi.tables import table, row
|
7 |
+
from wasabi.util import supports_ansi
|
8 |
+
|
9 |
+
SUPPORTS_ANSI = supports_ansi()
|
10 |
+
|
11 |
+
|
12 |
+
@pytest.fixture()
|
13 |
+
def data():
|
14 |
+
return [("Hello", "World", "12344342"), ("This is a test", "World", "1234")]
|
15 |
+
|
16 |
+
|
17 |
+
@pytest.fixture()
|
18 |
+
def header():
|
19 |
+
return ["COL A", "COL B", "COL 3"]
|
20 |
+
|
21 |
+
|
22 |
+
@pytest.fixture()
|
23 |
+
def footer():
|
24 |
+
return ["", "", "2030203.00"]
|
25 |
+
|
26 |
+
|
27 |
+
@pytest.fixture()
|
28 |
+
def fg_colors():
|
29 |
+
return ["", "yellow", "87"]
|
30 |
+
|
31 |
+
|
32 |
+
@pytest.fixture()
|
33 |
+
def bg_colors():
|
34 |
+
return ["green", "23", ""]
|
35 |
+
|
36 |
+
|
37 |
+
def test_table_default(data):
|
38 |
+
result = table(data)
|
39 |
+
assert (
|
40 |
+
result
|
41 |
+
== "\nHello World 12344342\nThis is a test World 1234 \n"
|
42 |
+
)
|
43 |
+
|
44 |
+
|
45 |
+
def test_table_header(data, header):
|
46 |
+
result = table(data, header=header)
|
47 |
+
assert (
|
48 |
+
result
|
49 |
+
== "\nCOL A COL B COL 3 \nHello World 12344342\nThis is a test World 1234 \n"
|
50 |
+
)
|
51 |
+
|
52 |
+
|
53 |
+
def test_table_header_footer_divider(data, header, footer):
|
54 |
+
result = table(data, header=header, footer=footer, divider=True)
|
55 |
+
assert (
|
56 |
+
result
|
57 |
+
== "\nCOL A COL B COL 3 \n-------------- ----- ----------\nHello World 12344342 \nThis is a test World 1234 \n-------------- ----- ----------\n 2030203.00\n"
|
58 |
+
)
|
59 |
+
|
60 |
+
|
61 |
+
def test_table_aligns(data):
|
62 |
+
result = table(data, aligns=("r", "c", "l"))
|
63 |
+
assert (
|
64 |
+
result
|
65 |
+
== "\n Hello World 12344342\nThis is a test World 1234 \n"
|
66 |
+
)
|
67 |
+
|
68 |
+
|
69 |
+
def test_table_aligns_single(data):
|
70 |
+
result = table(data, aligns="r")
|
71 |
+
assert (
|
72 |
+
result
|
73 |
+
== "\n Hello World 12344342\nThis is a test World 1234\n"
|
74 |
+
)
|
75 |
+
|
76 |
+
|
77 |
+
def test_table_widths():
|
78 |
+
data = [("a", "bb", "ccc"), ("d", "ee", "fff")]
|
79 |
+
widths = (5, 2, 10)
|
80 |
+
result = table(data, widths=widths)
|
81 |
+
assert result == "\na bb ccc \nd ee fff \n"
|
82 |
+
|
83 |
+
|
84 |
+
def test_row_single_widths():
|
85 |
+
data = ("a", "bb", "ccc")
|
86 |
+
result = row(data, widths=10)
|
87 |
+
assert result == "a bb ccc "
|
88 |
+
|
89 |
+
|
90 |
+
def test_table_multiline(header):
|
91 |
+
data = [
|
92 |
+
("hello", ["foo", "bar", "baz"], "world"),
|
93 |
+
("hello", "world", ["world 1", "world 2"]),
|
94 |
+
]
|
95 |
+
result = table(data, header=header, divider=True, multiline=True)
|
96 |
+
assert (
|
97 |
+
result
|
98 |
+
== "\nCOL A COL B COL 3 \n----- ----- -------\nhello foo world \n bar \n baz \n \nhello world world 1\n world 2\n"
|
99 |
+
)
|
100 |
+
|
101 |
+
|
102 |
+
def test_row_fg_colors(fg_colors):
|
103 |
+
result = row(("Hello", "World", "12344342"), fg_colors=fg_colors)
|
104 |
+
if SUPPORTS_ANSI:
|
105 |
+
assert (
|
106 |
+
result == "Hello \x1b[38;5;3mWorld\x1b[0m \x1b[38;5;87m12344342\x1b[0m"
|
107 |
+
)
|
108 |
+
else:
|
109 |
+
assert result == "Hello World 12344342"
|
110 |
+
|
111 |
+
|
112 |
+
def test_row_bg_colors(bg_colors):
|
113 |
+
result = row(("Hello", "World", "12344342"), bg_colors=bg_colors)
|
114 |
+
if SUPPORTS_ANSI:
|
115 |
+
assert (
|
116 |
+
result == "\x1b[48;5;2mHello\x1b[0m \x1b[48;5;23mWorld\x1b[0m 12344342"
|
117 |
+
)
|
118 |
+
else:
|
119 |
+
assert result == "Hello World 12344342"
|
120 |
+
|
121 |
+
|
122 |
+
def test_row_fg_colors_and_bg_colors(fg_colors, bg_colors):
|
123 |
+
result = row(
|
124 |
+
("Hello", "World", "12344342"), fg_colors=fg_colors, bg_colors=bg_colors
|
125 |
+
)
|
126 |
+
if SUPPORTS_ANSI:
|
127 |
+
assert (
|
128 |
+
result
|
129 |
+
== "\x1b[48;5;2mHello\x1b[0m \x1b[38;5;3;48;5;23mWorld\x1b[0m \x1b[38;5;87m12344342\x1b[0m"
|
130 |
+
)
|
131 |
+
else:
|
132 |
+
assert result == "Hello World 12344342"
|
133 |
+
|
134 |
+
|
135 |
+
def test_row_fg_colors_and_bg_colors_log_friendly(fg_colors, bg_colors):
|
136 |
+
ENV_LOG_FRIENDLY = "WASABI_LOG_FRIENDLY"
|
137 |
+
os.environ[ENV_LOG_FRIENDLY] = "True"
|
138 |
+
result = row(
|
139 |
+
("Hello", "World", "12344342"), fg_colors=fg_colors, bg_colors=bg_colors
|
140 |
+
)
|
141 |
+
assert result == "Hello World 12344342"
|
142 |
+
del os.environ[ENV_LOG_FRIENDLY]
|
143 |
+
|
144 |
+
|
145 |
+
def test_row_fg_colors_and_bg_colors_log_friendly_prefix(fg_colors, bg_colors):
|
146 |
+
ENV_LOG_FRIENDLY = "CUSTOM_LOG_FRIENDLY"
|
147 |
+
os.environ[ENV_LOG_FRIENDLY] = "True"
|
148 |
+
result = row(
|
149 |
+
("Hello", "World", "12344342"),
|
150 |
+
fg_colors=fg_colors,
|
151 |
+
bg_colors=bg_colors,
|
152 |
+
env_prefix="CUSTOM",
|
153 |
+
)
|
154 |
+
assert result == "Hello World 12344342"
|
155 |
+
del os.environ[ENV_LOG_FRIENDLY]
|
156 |
+
|
157 |
+
|
158 |
+
def test_row_fg_colors_and_bg_colors_supports_ansi_false(fg_colors, bg_colors):
|
159 |
+
os.environ["ANSI_COLORS_DISABLED"] = "True"
|
160 |
+
result = row(
|
161 |
+
("Hello", "World", "12344342"), fg_colors=fg_colors, bg_colors=bg_colors
|
162 |
+
)
|
163 |
+
assert result == "Hello World 12344342"
|
164 |
+
del os.environ["ANSI_COLORS_DISABLED"]
|
165 |
+
|
166 |
+
|
167 |
+
def test_colors_whole_table_with_automatic_widths(
|
168 |
+
data, header, footer, fg_colors, bg_colors
|
169 |
+
):
|
170 |
+
result = table(
|
171 |
+
data,
|
172 |
+
header=header,
|
173 |
+
footer=footer,
|
174 |
+
divider=True,
|
175 |
+
fg_colors=fg_colors,
|
176 |
+
bg_colors=bg_colors,
|
177 |
+
)
|
178 |
+
if SUPPORTS_ANSI:
|
179 |
+
assert (
|
180 |
+
result
|
181 |
+
== "\n\x1b[48;5;2mCOL A \x1b[0m \x1b[38;5;3;48;5;23mCOL B\x1b[0m \x1b[38;5;87mCOL 3 \x1b[0m\n\x1b[48;5;2m--------------\x1b[0m \x1b[38;5;3;48;5;23m-----\x1b[0m \x1b[38;5;87m----------\x1b[0m\n\x1b[48;5;2mHello \x1b[0m \x1b[38;5;3;48;5;23mWorld\x1b[0m \x1b[38;5;87m12344342 \x1b[0m\n\x1b[48;5;2mThis is a test\x1b[0m \x1b[38;5;3;48;5;23mWorld\x1b[0m \x1b[38;5;87m1234 \x1b[0m\n\x1b[48;5;2m--------------\x1b[0m \x1b[38;5;3;48;5;23m-----\x1b[0m \x1b[38;5;87m----------\x1b[0m\n\x1b[48;5;2m \x1b[0m \x1b[38;5;3;48;5;23m \x1b[0m \x1b[38;5;87m2030203.00\x1b[0m\n"
|
182 |
+
)
|
183 |
+
else:
|
184 |
+
assert (
|
185 |
+
result
|
186 |
+
== "\nCOL A COL B COL 3 \n-------------- ----- ----------\nHello World 12344342 \nThis is a test World 1234 \n-------------- ----- ----------\n 2030203.00\n"
|
187 |
+
)
|
188 |
+
|
189 |
+
|
190 |
+
def test_colors_whole_table_only_fg_colors(data, header, footer, fg_colors):
|
191 |
+
result = table(
|
192 |
+
data,
|
193 |
+
header=header,
|
194 |
+
footer=footer,
|
195 |
+
divider=True,
|
196 |
+
fg_colors=fg_colors,
|
197 |
+
)
|
198 |
+
if SUPPORTS_ANSI:
|
199 |
+
assert (
|
200 |
+
result
|
201 |
+
== "\nCOL A \x1b[38;5;3mCOL B\x1b[0m \x1b[38;5;87mCOL 3 \x1b[0m\n-------------- \x1b[38;5;3m-----\x1b[0m \x1b[38;5;87m----------\x1b[0m\nHello \x1b[38;5;3mWorld\x1b[0m \x1b[38;5;87m12344342 \x1b[0m\nThis is a test \x1b[38;5;3mWorld\x1b[0m \x1b[38;5;87m1234 \x1b[0m\n-------------- \x1b[38;5;3m-----\x1b[0m \x1b[38;5;87m----------\x1b[0m\n \x1b[38;5;3m \x1b[0m \x1b[38;5;87m2030203.00\x1b[0m\n"
|
202 |
+
)
|
203 |
+
else:
|
204 |
+
assert (
|
205 |
+
result
|
206 |
+
== "\nCOL A COL B COL 3 \n-------------- ----- ----------\nHello World 12344342 \nThis is a test World 1234 \n-------------- ----- ----------\n 2030203.00\n"
|
207 |
+
)
|
208 |
+
|
209 |
+
|
210 |
+
def test_colors_whole_table_only_bg_colors(data, header, footer, bg_colors):
|
211 |
+
result = table(
|
212 |
+
data,
|
213 |
+
header=header,
|
214 |
+
footer=footer,
|
215 |
+
divider=True,
|
216 |
+
bg_colors=bg_colors,
|
217 |
+
)
|
218 |
+
if SUPPORTS_ANSI:
|
219 |
+
assert (
|
220 |
+
result
|
221 |
+
== "\n\x1b[48;5;2mCOL A \x1b[0m \x1b[48;5;23mCOL B\x1b[0m COL 3 \n\x1b[48;5;2m--------------\x1b[0m \x1b[48;5;23m-----\x1b[0m ----------\n\x1b[48;5;2mHello \x1b[0m \x1b[48;5;23mWorld\x1b[0m 12344342 \n\x1b[48;5;2mThis is a test\x1b[0m \x1b[48;5;23mWorld\x1b[0m 1234 \n\x1b[48;5;2m--------------\x1b[0m \x1b[48;5;23m-----\x1b[0m ----------\n\x1b[48;5;2m \x1b[0m \x1b[48;5;23m \x1b[0m 2030203.00\n"
|
222 |
+
)
|
223 |
+
else:
|
224 |
+
assert (
|
225 |
+
result
|
226 |
+
== "\nCOL A COL B COL 3 \n-------------- ----- ----------\nHello World 12344342 \nThis is a test World 1234 \n-------------- ----- ----------\n 2030203.00\n"
|
227 |
+
)
|
228 |
+
|
229 |
+
|
230 |
+
def test_colors_whole_table_with_supplied_spacing(
|
231 |
+
data, header, footer, fg_colors, bg_colors
|
232 |
+
):
|
233 |
+
result = table(
|
234 |
+
data,
|
235 |
+
header=header,
|
236 |
+
footer=footer,
|
237 |
+
divider=True,
|
238 |
+
fg_colors=fg_colors,
|
239 |
+
bg_colors=bg_colors,
|
240 |
+
spacing=5,
|
241 |
+
)
|
242 |
+
if SUPPORTS_ANSI:
|
243 |
+
assert (
|
244 |
+
result
|
245 |
+
== "\n\x1b[48;5;2mCOL A \x1b[0m \x1b[38;5;3;48;5;23mCOL B\x1b[0m \x1b[38;5;87mCOL 3 \x1b[0m\n\x1b[48;5;2m--------------\x1b[0m \x1b[38;5;3;48;5;23m-----\x1b[0m \x1b[38;5;87m----------\x1b[0m\n\x1b[48;5;2mHello \x1b[0m \x1b[38;5;3;48;5;23mWorld\x1b[0m \x1b[38;5;87m12344342 \x1b[0m\n\x1b[48;5;2mThis is a test\x1b[0m \x1b[38;5;3;48;5;23mWorld\x1b[0m \x1b[38;5;87m1234 \x1b[0m\n\x1b[48;5;2m--------------\x1b[0m \x1b[38;5;3;48;5;23m-----\x1b[0m \x1b[38;5;87m----------\x1b[0m\n\x1b[48;5;2m \x1b[0m \x1b[38;5;3;48;5;23m \x1b[0m \x1b[38;5;87m2030203.00\x1b[0m\n"
|
246 |
+
)
|
247 |
+
else:
|
248 |
+
assert (
|
249 |
+
result
|
250 |
+
== "\nCOL A COL B COL 3 \n-------------- ----- ----------\nHello World 12344342 \nThis is a test World 1234 \n-------------- ----- ----------\n 2030203.00\n"
|
251 |
+
)
|
252 |
+
|
253 |
+
|
254 |
+
def test_colors_whole_table_with_supplied_widths(
|
255 |
+
data, header, footer, fg_colors, bg_colors
|
256 |
+
):
|
257 |
+
result = table(
|
258 |
+
data,
|
259 |
+
header=header,
|
260 |
+
footer=footer,
|
261 |
+
divider=True,
|
262 |
+
fg_colors=fg_colors,
|
263 |
+
bg_colors=bg_colors,
|
264 |
+
widths=(5, 2, 10),
|
265 |
+
)
|
266 |
+
if SUPPORTS_ANSI:
|
267 |
+
assert (
|
268 |
+
result
|
269 |
+
== "\n\x1b[48;5;2mCOL A\x1b[0m \x1b[38;5;3;48;5;23mCOL B\x1b[0m \x1b[38;5;87mCOL 3 \x1b[0m\n\x1b[48;5;2m-----\x1b[0m \x1b[38;5;3;48;5;23m--\x1b[0m \x1b[38;5;87m----------\x1b[0m\n\x1b[48;5;2mHello\x1b[0m \x1b[38;5;3;48;5;23mWorld\x1b[0m \x1b[38;5;87m12344342 \x1b[0m\n\x1b[48;5;2mThis is a test\x1b[0m \x1b[38;5;3;48;5;23mWorld\x1b[0m \x1b[38;5;87m1234 \x1b[0m\n\x1b[48;5;2m-----\x1b[0m \x1b[38;5;3;48;5;23m--\x1b[0m \x1b[38;5;87m----------\x1b[0m\n\x1b[48;5;2m \x1b[0m \x1b[38;5;3;48;5;23m \x1b[0m \x1b[38;5;87m2030203.00\x1b[0m\n"
|
270 |
+
)
|
271 |
+
else:
|
272 |
+
assert (
|
273 |
+
result
|
274 |
+
== "\nCOL A COL B COL 3 \n----- -- ----------\nHello World 12344342 \nThis is a test World 1234 \n----- -- ----------\n 2030203.00\n"
|
275 |
+
)
|
276 |
+
|
277 |
+
|
278 |
+
def test_colors_whole_table_with_single_alignment(
|
279 |
+
data, header, footer, fg_colors, bg_colors
|
280 |
+
):
|
281 |
+
result = table(
|
282 |
+
data,
|
283 |
+
header=header,
|
284 |
+
footer=footer,
|
285 |
+
divider=True,
|
286 |
+
fg_colors=fg_colors,
|
287 |
+
bg_colors=bg_colors,
|
288 |
+
aligns="r",
|
289 |
+
)
|
290 |
+
if SUPPORTS_ANSI:
|
291 |
+
assert (
|
292 |
+
result
|
293 |
+
== "\n\x1b[48;5;2m COL A\x1b[0m \x1b[38;5;3;48;5;23mCOL B\x1b[0m \x1b[38;5;87m COL 3\x1b[0m\n\x1b[48;5;2m--------------\x1b[0m \x1b[38;5;3;48;5;23m-----\x1b[0m \x1b[38;5;87m----------\x1b[0m\n\x1b[48;5;2m Hello\x1b[0m \x1b[38;5;3;48;5;23mWorld\x1b[0m \x1b[38;5;87m 12344342\x1b[0m\n\x1b[48;5;2mThis is a test\x1b[0m \x1b[38;5;3;48;5;23mWorld\x1b[0m \x1b[38;5;87m 1234\x1b[0m\n\x1b[48;5;2m--------------\x1b[0m \x1b[38;5;3;48;5;23m-----\x1b[0m \x1b[38;5;87m----------\x1b[0m\n\x1b[48;5;2m \x1b[0m \x1b[38;5;3;48;5;23m \x1b[0m \x1b[38;5;87m2030203.00\x1b[0m\n"
|
294 |
+
)
|
295 |
+
else:
|
296 |
+
assert (
|
297 |
+
result
|
298 |
+
== "\n COL A COL B COL 3\n-------------- ----- ----------\n Hello World 12344342\nThis is a test World 1234\n-------------- ----- ----------\n 2030203.00\n"
|
299 |
+
)
|
300 |
+
|
301 |
+
|
302 |
+
def test_colors_whole_table_with_multiple_alignment(
|
303 |
+
data, header, footer, fg_colors, bg_colors
|
304 |
+
):
|
305 |
+
result = table(
|
306 |
+
data,
|
307 |
+
header=header,
|
308 |
+
footer=footer,
|
309 |
+
divider=True,
|
310 |
+
fg_colors=fg_colors,
|
311 |
+
bg_colors=bg_colors,
|
312 |
+
aligns=("c", "r", "l"),
|
313 |
+
)
|
314 |
+
if SUPPORTS_ANSI:
|
315 |
+
assert (
|
316 |
+
result
|
317 |
+
== "\n\x1b[48;5;2m COL A \x1b[0m \x1b[38;5;3;48;5;23mCOL B\x1b[0m \x1b[38;5;87mCOL 3 \x1b[0m\n\x1b[48;5;2m--------------\x1b[0m \x1b[38;5;3;48;5;23m-----\x1b[0m \x1b[38;5;87m----------\x1b[0m\n\x1b[48;5;2m Hello \x1b[0m \x1b[38;5;3;48;5;23mWorld\x1b[0m \x1b[38;5;87m12344342 \x1b[0m\n\x1b[48;5;2mThis is a test\x1b[0m \x1b[38;5;3;48;5;23mWorld\x1b[0m \x1b[38;5;87m1234 \x1b[0m\n\x1b[48;5;2m--------------\x1b[0m \x1b[38;5;3;48;5;23m-----\x1b[0m \x1b[38;5;87m----------\x1b[0m\n\x1b[48;5;2m \x1b[0m \x1b[38;5;3;48;5;23m \x1b[0m \x1b[38;5;87m2030203.00\x1b[0m\n"
|
318 |
+
)
|
319 |
+
else:
|
320 |
+
assert (
|
321 |
+
result
|
322 |
+
== "\n COL A COL B COL 3 \n-------------- ----- ----------\n Hello World 12344342 \nThis is a test World 1234 \n-------------- ----- ----------\n 2030203.00\n"
|
323 |
+
)
|
324 |
+
|
325 |
+
|
326 |
+
def test_colors_whole_table_with_multiline(data, header, footer, fg_colors, bg_colors):
|
327 |
+
result = table(
|
328 |
+
data=((["Charles", "Quinton", "Murphy"], "my", "brother"), ("1", "2", "3")),
|
329 |
+
fg_colors=fg_colors,
|
330 |
+
bg_colors=bg_colors,
|
331 |
+
multiline=True,
|
332 |
+
)
|
333 |
+
if SUPPORTS_ANSI:
|
334 |
+
assert (
|
335 |
+
result
|
336 |
+
== "\n\x1b[48;5;2mCharles\x1b[0m \x1b[38;5;3;48;5;23mmy\x1b[0m \x1b[38;5;87mbrother\x1b[0m\n\x1b[48;5;2mQuinton\x1b[0m \x1b[38;5;3;48;5;23m \x1b[0m \x1b[38;5;87m \x1b[0m\n\x1b[48;5;2mMurphy \x1b[0m \x1b[38;5;3;48;5;23m \x1b[0m \x1b[38;5;87m \x1b[0m\n\x1b[48;5;2m \x1b[0m \x1b[38;5;3;48;5;23m \x1b[0m \x1b[38;5;87m \x1b[0m\n\x1b[48;5;2m1 \x1b[0m \x1b[38;5;3;48;5;23m2 \x1b[0m \x1b[38;5;87m3 \x1b[0m\n"
|
337 |
+
)
|
338 |
+
else:
|
339 |
+
assert (
|
340 |
+
result
|
341 |
+
== "\nCharles my brother\nQuinton \nMurphy \n \n1 2 3 \n"
|
342 |
+
)
|
343 |
+
|
344 |
+
|
345 |
+
def test_colors_whole_table_log_friendly(data, header, footer, fg_colors, bg_colors):
|
346 |
+
ENV_LOG_FRIENDLY = "WASABI_LOG_FRIENDLY"
|
347 |
+
os.environ[ENV_LOG_FRIENDLY] = "True"
|
348 |
+
result = table(
|
349 |
+
data,
|
350 |
+
header=header,
|
351 |
+
footer=footer,
|
352 |
+
divider=True,
|
353 |
+
fg_colors=fg_colors,
|
354 |
+
bg_colors=bg_colors,
|
355 |
+
)
|
356 |
+
assert (
|
357 |
+
result
|
358 |
+
== "\nCOL A COL B COL 3 \n-------------- ----- ----------\nHello World 12344342 \nThis is a test World 1234 \n-------------- ----- ----------\n 2030203.00\n"
|
359 |
+
)
|
360 |
+
del os.environ[ENV_LOG_FRIENDLY]
|
361 |
+
|
362 |
+
|
363 |
+
def test_colors_whole_table_log_friendly_prefix(
|
364 |
+
data, header, footer, fg_colors, bg_colors
|
365 |
+
):
|
366 |
+
ENV_LOG_FRIENDLY = "CUSTOM_LOG_FRIENDLY"
|
367 |
+
os.environ[ENV_LOG_FRIENDLY] = "True"
|
368 |
+
result = table(
|
369 |
+
data,
|
370 |
+
header=header,
|
371 |
+
footer=footer,
|
372 |
+
divider=True,
|
373 |
+
fg_colors=fg_colors,
|
374 |
+
bg_colors=bg_colors,
|
375 |
+
env_prefix="CUSTOM",
|
376 |
+
)
|
377 |
+
assert (
|
378 |
+
result
|
379 |
+
== "\nCOL A COL B COL 3 \n-------------- ----- ----------\nHello World 12344342 \nThis is a test World 1234 \n-------------- ----- ----------\n 2030203.00\n"
|
380 |
+
)
|
381 |
+
del os.environ[ENV_LOG_FRIENDLY]
|
382 |
+
|
383 |
+
|
384 |
+
def test_colors_whole_table_supports_ansi_false(
|
385 |
+
data, header, footer, fg_colors, bg_colors
|
386 |
+
):
|
387 |
+
os.environ["ANSI_COLORS_DISABLED"] = "True"
|
388 |
+
result = table(
|
389 |
+
data,
|
390 |
+
header=header,
|
391 |
+
footer=footer,
|
392 |
+
divider=True,
|
393 |
+
fg_colors=fg_colors,
|
394 |
+
bg_colors=bg_colors,
|
395 |
+
)
|
396 |
+
assert (
|
397 |
+
result
|
398 |
+
== "\nCOL A COL B COL 3 \n-------------- ----- ----------\nHello World 12344342 \nThis is a test World 1234 \n-------------- ----- ----------\n 2030203.00\n"
|
399 |
+
)
|
400 |
+
del os.environ["ANSI_COLORS_DISABLED"]
|
401 |
+
|
402 |
+
|
403 |
+
def test_colors_whole_table_color_values(data, header, footer, fg_colors, bg_colors):
|
404 |
+
result = table(
|
405 |
+
data,
|
406 |
+
header=header,
|
407 |
+
footer=footer,
|
408 |
+
divider=True,
|
409 |
+
fg_colors=fg_colors,
|
410 |
+
bg_colors=bg_colors,
|
411 |
+
color_values={"yellow": 11},
|
412 |
+
)
|
413 |
+
if SUPPORTS_ANSI:
|
414 |
+
assert (
|
415 |
+
result
|
416 |
+
== "\n\x1b[48;5;2mCOL A \x1b[0m \x1b[38;5;11;48;5;23mCOL B\x1b[0m \x1b[38;5;87mCOL 3 \x1b[0m\n\x1b[48;5;2m--------------\x1b[0m \x1b[38;5;11;48;5;23m-----\x1b[0m \x1b[38;5;87m----------\x1b[0m\n\x1b[48;5;2mHello \x1b[0m \x1b[38;5;11;48;5;23mWorld\x1b[0m \x1b[38;5;87m12344342 \x1b[0m\n\x1b[48;5;2mThis is a test\x1b[0m \x1b[38;5;11;48;5;23mWorld\x1b[0m \x1b[38;5;87m1234 \x1b[0m\n\x1b[48;5;2m--------------\x1b[0m \x1b[38;5;11;48;5;23m-----\x1b[0m \x1b[38;5;87m----------\x1b[0m\n\x1b[48;5;2m \x1b[0m \x1b[38;5;11;48;5;23m \x1b[0m \x1b[38;5;87m2030203.00\x1b[0m\n"
|
417 |
+
)
|
418 |
+
else:
|
419 |
+
assert (
|
420 |
+
result
|
421 |
+
== "\nCOL A COL B COL 3 \n-------------- ----- ----------\nHello World 12344342 \nThis is a test World 1234 \n-------------- ----- ----------\n 2030203.00\n"
|
422 |
+
)
|
.venv/Lib/site-packages/wasabi/tests/test_traceback.py
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# coding: utf8
|
2 |
+
from __future__ import unicode_literals, print_function
|
3 |
+
|
4 |
+
import pytest
|
5 |
+
import traceback
|
6 |
+
from wasabi.traceback_printer import TracebackPrinter
|
7 |
+
|
8 |
+
|
9 |
+
@pytest.fixture
|
10 |
+
def tb():
|
11 |
+
return traceback.extract_stack()
|
12 |
+
|
13 |
+
|
14 |
+
def test_traceback_printer(tb):
|
15 |
+
tbp = TracebackPrinter(tb_base="wasabi")
|
16 |
+
msg = tbp("Hello world", "This is a test", tb=tb)
|
17 |
+
print(msg)
|
18 |
+
|
19 |
+
|
20 |
+
def test_traceback_printer_highlight(tb):
|
21 |
+
tbp = TracebackPrinter(tb_base="wasabi")
|
22 |
+
msg = tbp("Hello world", "This is a test", tb=tb, highlight="kwargs")
|
23 |
+
print(msg)
|
24 |
+
|
25 |
+
|
26 |
+
def test_traceback_printer_custom_colors(tb):
|
27 |
+
tbp = TracebackPrinter(
|
28 |
+
tb_base="wasabi", color_error="blue", color_highlight="green", color_tb="yellow"
|
29 |
+
)
|
30 |
+
msg = tbp("Hello world", "This is a test", tb=tb, highlight="kwargs")
|
31 |
+
print(msg)
|
32 |
+
|
33 |
+
|
34 |
+
def test_traceback_printer_only_title(tb):
|
35 |
+
tbp = TracebackPrinter(tb_base="wasabi")
|
36 |
+
msg = tbp("Hello world", tb=tb)
|
37 |
+
print(msg)
|
38 |
+
|
39 |
+
|
40 |
+
def test_traceback_dot_relative_path_tb_base(tb):
|
41 |
+
tbp = TracebackPrinter(tb_base=".")
|
42 |
+
msg = tbp("Hello world", tb=tb)
|
43 |
+
print(msg)
|
44 |
+
|
45 |
+
|
46 |
+
def test_traceback_tb_base_none(tb):
|
47 |
+
tbp = TracebackPrinter()
|
48 |
+
msg = tbp("Hello world", tb=tb)
|
49 |
+
print(msg)
|
50 |
+
|
51 |
+
|
52 |
+
def test_traceback_printer_no_tb():
|
53 |
+
tbp = TracebackPrinter(tb_base="wasabi")
|
54 |
+
msg = tbp("Hello world", "This is a test")
|
55 |
+
print(msg)
|
56 |
+
|
57 |
+
|
58 |
+
def test_traceback_printer_custom_tb_range():
|
59 |
+
tbp = TracebackPrinter(tb_range_start=-10, tb_range_end=-3)
|
60 |
+
msg = tbp("Hello world", "This is a test")
|
61 |
+
print(msg)
|
62 |
+
|
63 |
+
|
64 |
+
def test_traceback_printer_custom_tb_range_start():
|
65 |
+
tbp = TracebackPrinter(tb_range_start=-1)
|
66 |
+
msg = tbp("Hello world", "This is a test")
|
67 |
+
print(msg)
|
.venv/Lib/site-packages/wasabi/traceback_printer.py
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# coding: utf8
|
2 |
+
from __future__ import unicode_literals, print_function
|
3 |
+
import os
|
4 |
+
from .util import color, supports_ansi, NO_UTF8
|
5 |
+
|
6 |
+
|
7 |
+
LINE_EDGE = "└─" if not NO_UTF8 else "|_"
|
8 |
+
LINE_FORK = "├─" if not NO_UTF8 else "|__"
|
9 |
+
LINE_PATH = "──" if not NO_UTF8 else "__"
|
10 |
+
|
11 |
+
|
12 |
+
class TracebackPrinter(object):
|
13 |
+
def __init__(
|
14 |
+
self,
|
15 |
+
color_error="red",
|
16 |
+
color_tb="blue",
|
17 |
+
color_highlight="yellow",
|
18 |
+
indent=2,
|
19 |
+
tb_base=None,
|
20 |
+
tb_exclude=tuple(),
|
21 |
+
tb_range_start=-5,
|
22 |
+
tb_range_end=-2,
|
23 |
+
):
|
24 |
+
"""Initialize a traceback printer.
|
25 |
+
|
26 |
+
color_error (unicode / int): Color name or code for errors.
|
27 |
+
color_tb (unicode / int): Color name or code for traceback headline.
|
28 |
+
color_highlight (unicode / int): Color name or code for highlights.
|
29 |
+
indent (int): Indentation in spaces.
|
30 |
+
tb_base (unicode): Name of directory to use to show relative paths. For
|
31 |
+
example, "thinc" will look for the last occurence of "/thinc/" in
|
32 |
+
a path and only show path to the right of it.
|
33 |
+
tb_exclude (tuple): List of filenames to exclude from traceback.
|
34 |
+
tb_range_start (int): The starting index from a traceback to include.
|
35 |
+
tb_range_end (int): The final index from a traceback to include. If None
|
36 |
+
the traceback will continue until the last record.
|
37 |
+
RETURNS (TracebackPrinter): The traceback printer.
|
38 |
+
"""
|
39 |
+
self.color_error = color_error
|
40 |
+
self.color_tb = color_tb
|
41 |
+
self.color_highlight = color_highlight
|
42 |
+
self.indent = " " * indent
|
43 |
+
if tb_base == ".":
|
44 |
+
tb_base = "{}{}".format(os.getcwd(), os.path.sep)
|
45 |
+
elif tb_base is not None:
|
46 |
+
tb_base = "/{}/".format(tb_base)
|
47 |
+
self.tb_base = tb_base
|
48 |
+
self.tb_exclude = tuple(tb_exclude)
|
49 |
+
self.tb_range_start = tb_range_start
|
50 |
+
self.tb_range_end = tb_range_end
|
51 |
+
self.supports_ansi = supports_ansi()
|
52 |
+
|
53 |
+
def __call__(self, title, *texts, **settings):
|
54 |
+
"""Output custom formatted tracebacks and errors.
|
55 |
+
|
56 |
+
title (unicode): The message title.
|
57 |
+
*texts (unicode): The texts to print (one per line).
|
58 |
+
highlight (unicode): Optional sequence to highlight in the traceback,
|
59 |
+
e.g. the bad value that caused the error.
|
60 |
+
tb (iterable): The traceback, e.g. generated by traceback.extract_stack().
|
61 |
+
RETURNS (unicode): The formatted traceback. Can be printed or raised
|
62 |
+
by custom exception.
|
63 |
+
"""
|
64 |
+
highlight = settings.get("highlight", False)
|
65 |
+
tb = settings.get("tb", None)
|
66 |
+
if self.supports_ansi: # use first line as title
|
67 |
+
title = color(title, fg=self.color_error, bold=True)
|
68 |
+
info = "\n" + "\n".join([self.indent + text for text in texts]) if texts else ""
|
69 |
+
tb = self._get_traceback(tb, highlight) if tb else ""
|
70 |
+
msg = "\n\n{}{}{}{}\n".format(self.indent, title, info, tb)
|
71 |
+
return msg
|
72 |
+
|
73 |
+
def _get_traceback(self, tb, highlight):
|
74 |
+
# Exclude certain file names from traceback
|
75 |
+
tb = [record for record in tb if not record[0].endswith(self.tb_exclude)]
|
76 |
+
tb_range = (
|
77 |
+
tb[self.tb_range_start : self.tb_range_end]
|
78 |
+
if self.tb_range_end is not None
|
79 |
+
else tb[self.tb_range_start :]
|
80 |
+
)
|
81 |
+
tb_list = [
|
82 |
+
self._format_traceback(path, line, fn, text, i, len(tb_range), highlight)
|
83 |
+
for i, (path, line, fn, text) in enumerate(tb_range)
|
84 |
+
]
|
85 |
+
tb_data = "\n".join(tb_list).strip()
|
86 |
+
title = "Traceback:"
|
87 |
+
if self.supports_ansi:
|
88 |
+
title = color(title, fg=self.color_tb, bold=True)
|
89 |
+
return "\n\n{indent}{title}\n{indent}{tb}".format(
|
90 |
+
title=title, tb=tb_data, indent=self.indent
|
91 |
+
)
|
92 |
+
|
93 |
+
def _format_traceback(self, path, line, fn, text, i, count, highlight):
|
94 |
+
template = "{base_indent}{indent} {fn} in {path}:{line}{text}"
|
95 |
+
indent = (LINE_EDGE if i == count - 1 else LINE_FORK) + LINE_PATH * i
|
96 |
+
if self.tb_base and self.tb_base in path:
|
97 |
+
path = path.rsplit(self.tb_base, 1)[1]
|
98 |
+
text = self._format_user_error(text, i, highlight) if i == count - 1 else ""
|
99 |
+
if self.supports_ansi:
|
100 |
+
fn = color(fn, bold=True)
|
101 |
+
path = color(path, underline=True)
|
102 |
+
return template.format(
|
103 |
+
base_indent=self.indent,
|
104 |
+
line=line,
|
105 |
+
indent=indent,
|
106 |
+
text=text,
|
107 |
+
fn=fn,
|
108 |
+
path=path,
|
109 |
+
)
|
110 |
+
|
111 |
+
def _format_user_error(self, text, i, highlight):
|
112 |
+
spacing = " " * i + " >>>"
|
113 |
+
if self.supports_ansi:
|
114 |
+
spacing = color(spacing, fg=self.color_error)
|
115 |
+
if highlight and self.supports_ansi:
|
116 |
+
formatted_highlight = color(highlight, fg=self.color_highlight)
|
117 |
+
text = text.replace(highlight, formatted_highlight)
|
118 |
+
return "\n{} {} {}".format(self.indent, spacing, text)
|
.venv/Lib/site-packages/wasabi/util.py
ADDED
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# coding: utf8
|
2 |
+
from __future__ import unicode_literals, print_function
|
3 |
+
|
4 |
+
import os
|
5 |
+
import sys
|
6 |
+
import textwrap
|
7 |
+
import difflib
|
8 |
+
import itertools
|
9 |
+
|
10 |
+
|
11 |
+
STDOUT_ENCODING = sys.stdout.encoding if hasattr(sys.stdout, "encoding") else None
|
12 |
+
ENCODING = STDOUT_ENCODING or "ascii"
|
13 |
+
NO_UTF8 = ENCODING.lower() not in ("utf8", "utf-8")
|
14 |
+
|
15 |
+
|
16 |
+
# Environment variables
|
17 |
+
ENV_ANSI_DISABLED = "ANSI_COLORS_DISABLED" # no colors
|
18 |
+
|
19 |
+
|
20 |
+
class MESSAGES(object):
|
21 |
+
GOOD = "good"
|
22 |
+
FAIL = "fail"
|
23 |
+
WARN = "warn"
|
24 |
+
INFO = "info"
|
25 |
+
|
26 |
+
|
27 |
+
COLORS = {
|
28 |
+
MESSAGES.GOOD: 2,
|
29 |
+
MESSAGES.FAIL: 1,
|
30 |
+
MESSAGES.WARN: 3,
|
31 |
+
MESSAGES.INFO: 4,
|
32 |
+
"red": 1,
|
33 |
+
"green": 2,
|
34 |
+
"yellow": 3,
|
35 |
+
"blue": 4,
|
36 |
+
"pink": 5,
|
37 |
+
"cyan": 6,
|
38 |
+
"white": 7,
|
39 |
+
"grey": 8,
|
40 |
+
"black": 16,
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
ICONS = {
|
45 |
+
MESSAGES.GOOD: "\u2714" if not NO_UTF8 else "[+]",
|
46 |
+
MESSAGES.FAIL: "\u2718" if not NO_UTF8 else "[x]",
|
47 |
+
MESSAGES.WARN: "\u26a0" if not NO_UTF8 else "[!]",
|
48 |
+
MESSAGES.INFO: "\u2139" if not NO_UTF8 else "[i]",
|
49 |
+
}
|
50 |
+
|
51 |
+
INSERT_SYMBOL = "+"
|
52 |
+
DELETE_SYMBOL = "-"
|
53 |
+
|
54 |
+
|
55 |
+
# Python 2 compatibility
|
56 |
+
IS_PYTHON_2 = sys.version_info[0] == 2
|
57 |
+
|
58 |
+
if IS_PYTHON_2:
|
59 |
+
basestring_ = basestring # noqa: F821
|
60 |
+
input_ = raw_input # noqa: F821
|
61 |
+
zip_longest = itertools.izip_longest # noqa: F821
|
62 |
+
else:
|
63 |
+
basestring_ = str
|
64 |
+
input_ = input
|
65 |
+
zip_longest = itertools.zip_longest
|
66 |
+
|
67 |
+
|
68 |
+
def color(text, fg=None, bg=None, bold=False, underline=False):
|
69 |
+
"""Color text by applying ANSI escape sequence.
|
70 |
+
|
71 |
+
text (unicode): The text to be formatted.
|
72 |
+
fg (unicode / int): Foreground color. String name or 0 - 256 (see COLORS).
|
73 |
+
bg (unicode / int): Background color. String name or 0 - 256 (see COLORS).
|
74 |
+
bold (bool): Format text in bold.
|
75 |
+
underline (bool): Underline text.
|
76 |
+
RETURNS (unicode): The formatted text.
|
77 |
+
"""
|
78 |
+
fg = COLORS.get(fg, fg)
|
79 |
+
bg = COLORS.get(bg, bg)
|
80 |
+
if not any([fg, bg, bold]):
|
81 |
+
return text
|
82 |
+
styles = []
|
83 |
+
if bold:
|
84 |
+
styles.append("1")
|
85 |
+
if underline:
|
86 |
+
styles.append("4")
|
87 |
+
if fg:
|
88 |
+
styles.append("38;5;{}".format(fg))
|
89 |
+
if bg:
|
90 |
+
styles.append("48;5;{}".format(bg))
|
91 |
+
return "\x1b[{}m{}\x1b[0m".format(";".join(styles), text)
|
92 |
+
|
93 |
+
|
94 |
+
def wrap(text, wrap_max=80, indent=4):
|
95 |
+
"""Wrap text at given width using textwrap module.
|
96 |
+
|
97 |
+
text (unicode): The text to wrap.
|
98 |
+
wrap_max (int): Maximum line width, including indentation. Defaults to 80.
|
99 |
+
indent (int): Number of spaces used for indentation. Defaults to 4.
|
100 |
+
RETURNS (unicode): The wrapped text with line breaks.
|
101 |
+
"""
|
102 |
+
indent = indent * " "
|
103 |
+
wrap_width = wrap_max - len(indent)
|
104 |
+
text = to_string(text)
|
105 |
+
return textwrap.fill(
|
106 |
+
text,
|
107 |
+
width=wrap_width,
|
108 |
+
initial_indent=indent,
|
109 |
+
subsequent_indent=indent,
|
110 |
+
break_long_words=False,
|
111 |
+
break_on_hyphens=False,
|
112 |
+
)
|
113 |
+
|
114 |
+
|
115 |
+
def format_repr(obj, max_len=50, ellipsis="..."):
|
116 |
+
"""Wrapper around `repr()` to print shortened and formatted string version.
|
117 |
+
|
118 |
+
obj: The object to represent.
|
119 |
+
max_len (int): Maximum string length. Longer strings will be cut in the
|
120 |
+
middle so only the beginning and end is displayed, separated by ellipsis.
|
121 |
+
ellipsis (unicode): Ellipsis character(s), e.g. "...".
|
122 |
+
RETURNS (unicode): The formatted representation.
|
123 |
+
"""
|
124 |
+
string = repr(obj)
|
125 |
+
if len(string) >= max_len:
|
126 |
+
half = int(max_len / 2)
|
127 |
+
return "{} {} {}".format(string[:half], ellipsis, string[-half:])
|
128 |
+
else:
|
129 |
+
return string
|
130 |
+
|
131 |
+
|
132 |
+
def diff_strings(a, b, fg="black", bg=("green", "red"), add_symbols=False):
|
133 |
+
"""Compare two strings and return a colored diff with red/green background
|
134 |
+
for deletion and insertions.
|
135 |
+
|
136 |
+
a (unicode): The first string to diff.
|
137 |
+
b (unicode): The second string to diff.
|
138 |
+
fg (unicode / int): Foreground color. String name or 0 - 256 (see COLORS).
|
139 |
+
bg (tuple): Background colors as (insert, delete) tuple of string name or
|
140 |
+
0 - 256 (see COLORS).
|
141 |
+
add_symbols (bool): Whether to add symbols before the diff lines. Uses '+'
|
142 |
+
for inserts and '-' for deletions. Default is False.
|
143 |
+
RETURNS (unicode): The formatted diff.
|
144 |
+
"""
|
145 |
+
a = a.split("\n")
|
146 |
+
b = b.split("\n")
|
147 |
+
output = []
|
148 |
+
matcher = difflib.SequenceMatcher(None, a, b)
|
149 |
+
for opcode, a0, a1, b0, b1 in matcher.get_opcodes():
|
150 |
+
if opcode == "equal":
|
151 |
+
for item in a[a0:a1]:
|
152 |
+
output.append(item)
|
153 |
+
if opcode == "insert" or opcode == "replace":
|
154 |
+
for item in b[b0:b1]:
|
155 |
+
item = "{} {}".format(INSERT_SYMBOL, item) if add_symbols else item
|
156 |
+
output.append(color(item, fg=fg, bg=bg[0]))
|
157 |
+
if opcode == "delete" or opcode == "replace":
|
158 |
+
for item in a[a0:a1]:
|
159 |
+
item = "{} {}".format(DELETE_SYMBOL, item) if add_symbols else item
|
160 |
+
output.append(color(item, fg=fg, bg=bg[1]))
|
161 |
+
return "\n".join(output)
|
162 |
+
|
163 |
+
|
164 |
+
def get_raw_input(description, default=False, indent=4):
|
165 |
+
"""Get user input from the command line via raw_input / input.
|
166 |
+
|
167 |
+
description (unicode): Text to display before prompt.
|
168 |
+
default (unicode or False/None): Default value to display with prompt.
|
169 |
+
indent (int): Indentation in spaces.
|
170 |
+
RETURNS (unicode): User input.
|
171 |
+
"""
|
172 |
+
additional = " (default: {})".format(default) if default else ""
|
173 |
+
prompt = wrap("{}{}: ".format(description, additional), indent=indent)
|
174 |
+
user_input = input_(prompt)
|
175 |
+
return user_input
|
176 |
+
|
177 |
+
|
178 |
+
def locale_escape(string, errors="replace"):
|
179 |
+
"""Mangle non-supported characters, for savages with ASCII terminals.
|
180 |
+
|
181 |
+
string (unicode): The string to escape.
|
182 |
+
errors (unicode): The str.encode errors setting. Defaults to `"replace"`.
|
183 |
+
RETURNS (unicode): The escaped string.
|
184 |
+
"""
|
185 |
+
string = to_string(string)
|
186 |
+
string = string.encode(ENCODING, errors).decode("utf8")
|
187 |
+
return string
|
188 |
+
|
189 |
+
|
190 |
+
def can_render(string):
|
191 |
+
"""Check if terminal can render unicode characters, e.g. special loading
|
192 |
+
icons. Can be used to display fallbacks for ASCII terminals.
|
193 |
+
|
194 |
+
string (unicode): The string to render.
|
195 |
+
RETURNS (bool): Whether the terminal can render the text.
|
196 |
+
"""
|
197 |
+
try:
|
198 |
+
string.encode(ENCODING)
|
199 |
+
return True
|
200 |
+
except UnicodeEncodeError:
|
201 |
+
return False
|
202 |
+
|
203 |
+
|
204 |
+
def supports_ansi():
|
205 |
+
"""Returns True if the running system's terminal supports ANSI escape
|
206 |
+
sequences for color, formatting etc. and False otherwise. Inspired by
|
207 |
+
Django's solution – hacky, but an okay approximation.
|
208 |
+
|
209 |
+
RETURNS (bool): Whether the terminal supports ANSI colors.
|
210 |
+
"""
|
211 |
+
if os.getenv(ENV_ANSI_DISABLED):
|
212 |
+
return False
|
213 |
+
# See: https://stackoverflow.com/q/7445658/6400719
|
214 |
+
supported_platform = sys.platform != "Pocket PC" and (
|
215 |
+
sys.platform != "win32" or "ANSICON" in os.environ
|
216 |
+
)
|
217 |
+
if not supported_platform:
|
218 |
+
return False
|
219 |
+
return True
|
220 |
+
|
221 |
+
|
222 |
+
def to_string(text):
|
223 |
+
"""Minimal compat helper to make sure text is unicode. Mostly used to
|
224 |
+
convert Paths and other Python objects.
|
225 |
+
|
226 |
+
text: The text/object to be converted.
|
227 |
+
RETURNS (unicode): The converted string.
|
228 |
+
"""
|
229 |
+
if not isinstance(text, basestring_):
|
230 |
+
if IS_PYTHON_2:
|
231 |
+
text = str(text).decode("utf8")
|
232 |
+
else:
|
233 |
+
text = str(text)
|
234 |
+
return text
|
.venv/Lib/site-packages/xlstm-1.0.8.dist-info/WHEEL
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Wheel-Version: 1.0
|
2 |
+
Generator: setuptools (75.3.0)
|
3 |
+
Root-Is-Purelib: true
|
4 |
+
Tag: py3-none-any
|
5 |
+
|
.venv/Lib/site-packages/xlstm-1.0.8.dist-info/top_level.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
xlstm
|
.venv/Lib/site-packages/xlstm/blocks/__pycache__/__init__.cpython-39.pyc
ADDED
Binary file (184 Bytes). View file
|
|
.venv/Lib/site-packages/xlstm/blocks/__pycache__/xlstm_block.cpython-39.pyc
ADDED
Binary file (3.12 kB). View file
|
|
.venv/Lib/site-packages/xlstm/blocks/slstm/__pycache__/__init__.cpython-39.pyc
ADDED
Binary file (190 Bytes). View file
|
|
.venv/Lib/site-packages/xlstm/blocks/slstm/__pycache__/block.cpython-39.pyc
ADDED
Binary file (1.52 kB). View file
|
|