Linksome commited on
Commit
a8b4b01
·
verified ·
1 Parent(s): 35f26f2

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .cache/pip/http-v2/0/0/f/7/d/00f7ddf3a227e6778c0f6917d53545d95d52c61e2a4b9eadade80a1f.body +3 -0
  2. .cache/pip/http-v2/0/4/1/8/c/0418c83b80f7f7bfaec2738bfbbee53d2c1562196c0781702f6eddc8.body +3 -0
  3. .cache/pip/http-v2/0/4/4/f/2/044f2f53cdcb47194b0e9c6df3c8720ef44d4e5b4d49bedd28cc5434.body +3 -0
  4. .cache/pip/http-v2/0/4/6/5/1/04651185225d2f4f97326e1133d8157925fc8a7b89e811a1210f6558.body +3 -0
  5. .cache/pip/http-v2/0/4/8/d/6/048d618cdb8f9b2e00fa25b4d36b401928a1055a3454092f5d83e2a6.body +3 -0
  6. .cache/pip/http-v2/0/6/d/2/0/06d2035d1be597395f35709a93111f033237824a0527da81903f1e51.body +3 -0
  7. .cache/pip/http-v2/0/9/e/8/d/09e8d49d90cf63602446195abdd4acc84858ac09aa349cdf244340a8.body +3 -0
  8. .cache/pip/http-v2/0/d/e/4/3/0de43a9a62b2c4201925bcad7d9e3c7ed32696d87f53f418cc6180d6.body +3 -0
  9. .cache/pip/http-v2/1/0/9/d/5/109d5b2dca31f1c5d503eacb6150a7023dae79f0a0ffa8626cd6aebc +0 -0
  10. .cache/pip/http-v2/1/0/a/f/b/10afb50cc46801be2fc892e4233b3d2108242b1030bf5eb3ef6841b2 +0 -0
  11. .cache/pip/http-v2/1/0/a/f/b/10afb50cc46801be2fc892e4233b3d2108242b1030bf5eb3ef6841b2.body +0 -0
  12. .cache/pip/http-v2/1/0/e/d/c/10edc2fedb88f9a82f91dc7f8666c74a4e7067dbd945b9923a040482.body +3 -0
  13. .cache/pip/http-v2/1/2/2/4/d/1224d41bab5732a8d21be164d733fc715ab79618a9f55d40126a01df.body +3 -0
  14. .cache/pip/http-v2/1/4/e/c/f/14ecf6fdd241cb33c00a29ce0bebfb66e7318a08883e62befaecb50b.body +3 -0
  15. .cache/pip/http-v2/1/6/6/e/7/166e7181cd955d4375be6f62bbc18729f0ef0f67b8b38d1f1af41dd9.body +3 -0
  16. .cache/pip/http-v2/1/6/9/3/2/1693297fb9daf7bfe370bf51d371acfeb8ff40759bf8650dfd404ba4.body +3 -0
  17. .cache/pip/http-v2/1/7/4/f/6/174f6021fac0ee18a0f262b675a0951543cde2312549c5c235204100.body +0 -0
  18. .cache/pip/http-v2/1/c/8/6/4/1c86492d6acbc5af64318c535960c6d5478c385252e490d1f93b749d +0 -0
  19. .cache/pip/http-v2/1/c/8/6/4/1c86492d6acbc5af64318c535960c6d5478c385252e490d1f93b749d.body +3 -0
  20. .cache/pip/http-v2/1/e/b/f/d/1ebfddf16e338050f3c69ee3fb0551055792844fc428979435d11f85.body +3 -0
  21. .cache/pip/http-v2/3/3/9/7/4/33974f84394d9a943f68359da08431dab4af9f86c33962982ea21b5f +0 -0
  22. .cache/pip/http-v2/3/6/f/b/d/36fbd155c6f5dec2384b1e54f14634a717ea60dcc4c5c06c48e023cf.body +3 -0
  23. .cache/pip/http-v2/3/b/d/1/2/3bd12ba2f1a7c3549643aa50026e0c2f3c9bff69b82de1d294b27485.body +3 -0
  24. .cache/pip/http-v2/3/e/7/7/c/3e77c51e855cb3eade14cc9448185875f5bf39a6d82c17de40ca94d5.body +3 -0
  25. .cache/pip/http-v2/4/0/2/6/6/4026631b7adde65b73ce4a6cea321dd15108dd56fcff2185df112775 +0 -0
  26. .cache/pip/http-v2/4/0/2/6/6/4026631b7adde65b73ce4a6cea321dd15108dd56fcff2185df112775.body +3 -0
  27. .cache/pip/http-v2/4/0/8/5/1/40851de76d4978ae24522e7edfdeddaba0192993a8db34a4907aafcd +0 -0
  28. .cache/pip/http-v2/4/0/8/8/f/4088fdf0071639945ee9ad91e70a8acface70d4ed962ddd666f5454e +0 -0
  29. .cache/pip/http-v2/4/0/a/d/4/40ad437022f8fc2e168397655f44dd5afa1b97acfe941e16aa179e2c +0 -0
  30. .cache/pip/http-v2/4/0/a/d/4/40ad437022f8fc2e168397655f44dd5afa1b97acfe941e16aa179e2c.body +43 -0
  31. .cache/pip/http-v2/4/0/f/8/f/40f8f5a7325d13d318e01d17053cf2dadf6b6daa8a7e60583d48809b +0 -0
  32. .cache/pip/http-v2/4/0/f/8/f/40f8f5a7325d13d318e01d17053cf2dadf6b6daa8a7e60583d48809b.body +0 -0
  33. .cache/pip/http-v2/4/1/e/7/2/41e7263a9efb3323d3506d54d219d6a951911345e0f82c731aff5a5b +0 -0
  34. .cache/pip/http-v2/4/1/e/7/2/41e7263a9efb3323d3506d54d219d6a951911345e0f82c731aff5a5b.body +375 -0
  35. .cache/pip/http-v2/4/2/5/e/e/425ee452eddda30695488b965f5cfa22049bb8f92ad87623f545a8bb +0 -0
  36. .cache/pip/http-v2/4/2/5/e/e/425ee452eddda30695488b965f5cfa22049bb8f92ad87623f545a8bb.body +324 -0
  37. .cache/pip/http-v2/4/2/6/6/d/4266da420f80fe5b2de81f440f459cda33c49a87b4c539a917582c18.body +203 -0
  38. .cache/pip/http-v2/4/3/2/5/0/432508fca4367eb16c5bda476b8ecbf96beccd650c7aea212e59eb40 +0 -0
  39. .cache/pip/http-v2/4/3/2/5/0/432508fca4367eb16c5bda476b8ecbf96beccd650c7aea212e59eb40.body +490 -0
  40. .cache/pip/http-v2/4/3/4/e/4/434e4f9063597b6ecac7104d4d3128df26a47ab65e2f09d0f5f7b59d +0 -0
  41. .cache/pip/http-v2/4/3/4/e/4/434e4f9063597b6ecac7104d4d3128df26a47ab65e2f09d0f5f7b59d.body +408 -0
  42. .cache/pip/http-v2/4/3/6/8/4/436846b847c9c90a13539a872e2084e3f9ca23eb93b4b1cc44b55964 +0 -0
  43. .cache/pip/http-v2/4/3/6/8/4/436846b847c9c90a13539a872e2084e3f9ca23eb93b4b1cc44b55964.body +112 -0
  44. .cache/pip/http-v2/4/4/1/9/6/44196988557c6a112ae696d10605a07ed4576112a509edb0095e3b08 +0 -0
  45. .cache/pip/http-v2/4/4/1/9/6/44196988557c6a112ae696d10605a07ed4576112a509edb0095e3b08.body +3 -0
  46. .cache/pip/http-v2/4/4/6/c/5/446c514b42f8098e88d951919b55761fcef1b141bd548733adaddda2 +0 -0
  47. .cache/pip/http-v2/4/4/6/c/5/446c514b42f8098e88d951919b55761fcef1b141bd548733adaddda2.body +3 -0
  48. .cache/pip/http-v2/4/4/a/d/5/44ad51ab4fe732177892254938ca19df59a19add805fe17b3b22c658 +0 -0
  49. .cache/pip/http-v2/4/4/a/d/5/44ad51ab4fe732177892254938ca19df59a19add805fe17b3b22c658.body +1595 -0
  50. .cache/pip/http-v2/4/4/e/5/b/44e5b11a6caa92636d8ccfe658d420ba4ed8f67f7f4e835b214255aa +0 -0
.cache/pip/http-v2/0/0/f/7/d/00f7ddf3a227e6778c0f6917d53545d95d52c61e2a4b9eadade80a1f.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:729be4a976fb706dcc02d176bcda8a3f32bdf21a294e8f4b3dda6fbcbc9c1ab1
3
+ size 684411
.cache/pip/http-v2/0/4/1/8/c/0418c83b80f7f7bfaec2738bfbbee53d2c1562196c0781702f6eddc8.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b9a11a8cc2f49267984ef4fee282f8d544ceae04a4ee7b103cfa0295d1fa2dfd
3
+ size 190689
.cache/pip/http-v2/0/4/4/f/2/044f2f53cdcb47194b0e9c6df3c8720ef44d4e5b4d49bedd28cc5434.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf
3
+ size 221575
.cache/pip/http-v2/0/4/6/5/1/04651185225d2f4f97326e1133d8157925fc8a7b89e811a1210f6558.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713
3
+ size 309071
.cache/pip/http-v2/0/4/8/d/6/048d618cdb8f9b2e00fa25b4d36b401928a1055a3454092f5d83e2a6.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6a498f82e0f4d8904c4e0aea5139cdfac1f39d19a3c51d491292f63a36e83b2e
3
+ size 11616911
.cache/pip/http-v2/0/6/d/2/0/06d2035d1be597395f35709a93111f033237824a0527da81903f1e51.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:def5aac47b28e2f1386fa64f2f458a5474ba7733ab74c1765e7c67a79d1f1cbd
3
+ size 10364790
.cache/pip/http-v2/0/9/e/8/d/09e8d49d90cf63602446195abdd4acc84858ac09aa349cdf244340a8.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613
3
+ size 110502
.cache/pip/http-v2/0/d/e/4/3/0de43a9a62b2c4201925bcad7d9e3c7ed32696d87f53f418cc6180d6.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8ff903295bb61260bc27ee3be4aa55401f1ca39065109f4b127047f82f237642
3
+ size 6090015
.cache/pip/http-v2/1/0/9/d/5/109d5b2dca31f1c5d503eacb6150a7023dae79f0a0ffa8626cd6aebc ADDED
Binary file (1.2 kB). View file
 
.cache/pip/http-v2/1/0/a/f/b/10afb50cc46801be2fc892e4233b3d2108242b1030bf5eb3ef6841b2 ADDED
Binary file (1.23 kB). View file
 
.cache/pip/http-v2/1/0/a/f/b/10afb50cc46801be2fc892e4233b3d2108242b1030bf5eb3ef6841b2.body ADDED
Binary file (61.6 kB). View file
 
.cache/pip/http-v2/1/0/e/d/c/10edc2fedb88f9a82f91dc7f8666c74a4e7067dbd945b9923a040482.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:89af7581659f9044491f531d538245f272d181bdd301d7c5fbf85f913e723038
3
+ size 188905
.cache/pip/http-v2/1/2/2/4/d/1224d41bab5732a8d21be164d733fc715ab79618a9f55d40126a01df.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65
3
+ size 182523
.cache/pip/http-v2/1/4/e/c/f/14ecf6fdd241cb33c00a29ce0bebfb66e7318a08883e62befaecb50b.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:688d1c704ddecf382ea3326f21a67453d4caa95592d722b7c780a36a9d23109e
3
+ size 460919
.cache/pip/http-v2/1/6/6/e/7/166e7181cd955d4375be6f62bbc18729f0ef0f67b8b38d1f1af41dd9.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:77ccc56582d07671a867b78ced686096ca53c021d79fed38e5aaf4cebbd0450b
3
+ size 26378746
.cache/pip/http-v2/1/6/9/3/2/1693297fb9daf7bfe370bf51d371acfeb8ff40759bf8650dfd404ba4.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e6a2d23a49dba526379bfd091dc2b592cda31969301f578f0c673c9457b9f5a1
3
+ size 322045
.cache/pip/http-v2/1/7/4/f/6/174f6021fac0ee18a0f262b675a0951543cde2312549c5c235204100.body ADDED
Binary file (15.1 kB). View file
 
.cache/pip/http-v2/1/c/8/6/4/1c86492d6acbc5af64318c535960c6d5478c385252e490d1f93b749d ADDED
Binary file (1.2 kB). View file
 
.cache/pip/http-v2/1/c/8/6/4/1c86492d6acbc5af64318c535960c6d5478c385252e490d1f93b749d.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a6e9d7eeada96c93a4d69cb03836b44fa34e2854accb7244a1ece36cd4781c3f
3
+ size 117683
.cache/pip/http-v2/1/e/b/f/d/1ebfddf16e338050f3c69ee3fb0551055792844fc428979435d11f85.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1f55797419e16e7f30cf88ffb3113ce0467f00cfe3f70d5c281730b21769bfc2
3
+ size 35287115
.cache/pip/http-v2/3/3/9/7/4/33974f84394d9a943f68359da08431dab4af9f86c33962982ea21b5f ADDED
Binary file (1.8 kB). View file
 
.cache/pip/http-v2/3/6/f/b/d/36fbd155c6f5dec2384b1e54f14634a717ea60dcc4c5c06c48e023cf.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:53a0f57e59a530d18a142f4d4ba6dfc708dc5fdedce45e98ff06b44930a2a48f
3
+ size 133624
.cache/pip/http-v2/3/b/d/1/2/3bd12ba2f1a7c3549643aa50026e0c2f3c9bff69b82de1d294b27485.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a0d94420d9d52c56568159a69200af7e45eadb29615fa9d09fada140de1c38c7
3
+ size 420090
.cache/pip/http-v2/3/e/7/7/c/3e77c51e855cb3eade14cc9448185875f5bf39a6d82c17de40ca94d5.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cdca9bfb89e6f8f281890cc61a8aff2d3cecaff7e1a4d275574d96ca70098557
3
+ size 3552664
.cache/pip/http-v2/4/0/2/6/6/4026631b7adde65b73ce4a6cea321dd15108dd56fcff2185df112775 ADDED
Binary file (1.15 kB). View file
 
.cache/pip/http-v2/4/0/2/6/6/4026631b7adde65b73ce4a6cea321dd15108dd56fcff2185df112775.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6986454a854bc3bc6e5443e1369e06a3a456af9d339eda45510f517d9ea5c6bf
3
+ size 462431
.cache/pip/http-v2/4/0/8/5/1/40851de76d4978ae24522e7edfdeddaba0192993a8db34a4907aafcd ADDED
Binary file (1.17 kB). View file
 
.cache/pip/http-v2/4/0/8/8/f/4088fdf0071639945ee9ad91e70a8acface70d4ed962ddd666f5454e ADDED
Binary file (1.8 kB). View file
 
.cache/pip/http-v2/4/0/a/d/4/40ad437022f8fc2e168397655f44dd5afa1b97acfe941e16aa179e2c ADDED
Binary file (1.28 kB). View file
 
.cache/pip/http-v2/4/0/a/d/4/40ad437022f8fc2e168397655f44dd5afa1b97acfe941e16aa179e2c.body ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: python-multipart
3
+ Version: 0.0.27
4
+ Summary: A streaming multipart parser for Python
5
+ Project-URL: Homepage, https://github.com/Kludex/python-multipart
6
+ Project-URL: Documentation, https://kludex.github.io/python-multipart/
7
+ Project-URL: Changelog, https://github.com/Kludex/python-multipart/blob/master/CHANGELOG.md
8
+ Project-URL: Source, https://github.com/Kludex/python-multipart
9
+ Author-email: Andrew Dunham <andrew@du.nham.ca>
10
+ Maintainer-email: Marcelo Trylesinski <marcelotryle@gmail.com>
11
+ License-Expression: Apache-2.0
12
+ License-File: LICENSE.txt
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Environment :: Web Environment
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: Apache Software License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Programming Language :: Python :: 3.14
25
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+
29
+ # [Python-Multipart](https://kludex.github.io/python-multipart/)
30
+
31
+ [![Build Status](https://github.com/Kludex/python-multipart/workflows/CI/badge.svg)](https://github.com/Kludex/python-multipart/actions)
32
+ [![Package version](https://badge.fury.io/py/python-multipart.svg)](https://pypi.python.org/pypi/python-multipart)
33
+ [![Supported Python Version](https://img.shields.io/pypi/pyversions/python-multipart.svg?color=%2334D058)](https://pypi.org/project/python-multipart)
34
+ [![Discord](https://img.shields.io/discord/1051468649518616576?logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/RxKUF5JuHs)
35
+
36
+ ---
37
+
38
+ `python-multipart` is an Apache2-licensed streaming multipart parser for Python.
39
+ Test coverage is currently 100%.
40
+
41
+ ## Why?
42
+
43
+ Because streaming uploads are awesome for large files.
.cache/pip/http-v2/4/0/f/8/f/40f8f5a7325d13d318e01d17053cf2dadf6b6daa8a7e60583d48809b ADDED
Binary file (1.8 kB). View file
 
.cache/pip/http-v2/4/0/f/8/f/40f8f5a7325d13d318e01d17053cf2dadf6b6daa8a7e60583d48809b.body ADDED
Binary file (4.77 kB). View file
 
.cache/pip/http-v2/4/1/e/7/2/41e7263a9efb3323d3506d54d219d6a951911345e0f82c731aff5a5b ADDED
Binary file (1.29 kB). View file
 
.cache/pip/http-v2/4/1/e/7/2/41e7263a9efb3323d3506d54d219d6a951911345e0f82c731aff5a5b.body ADDED
@@ -0,0 +1,375 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: pathspec
3
+ Version: 1.1.0
4
+ Summary: Utility library for gitignore style pattern matching of file paths.
5
+ Author-email: "Caleb P. Burns" <cpburnz@gmail.com>
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/x-rst
8
+ Classifier: Development Status :: 5 - Production/Stable
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Programming Language :: Python :: Implementation :: CPython
21
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Topic :: Utilities
24
+ License-File: LICENSE
25
+ Requires-Dist: hyperscan >=0.7 ; extra == "hyperscan"
26
+ Requires-Dist: typing-extensions >=4 ; extra == "optional"
27
+ Requires-Dist: google-re2 >=1.1 ; extra == "re2"
28
+ Project-URL: Change Log, https://python-path-specification.readthedocs.io/en/latest/changes.html
29
+ Project-URL: Documentation, https://python-path-specification.readthedocs.io/en/latest/index.html
30
+ Project-URL: Issue Tracker, https://github.com/cpburnz/python-pathspec/issues
31
+ Project-URL: Source Code, https://github.com/cpburnz/python-pathspec
32
+ Provides-Extra: hyperscan
33
+ Provides-Extra: optional
34
+ Provides-Extra: re2
35
+
36
+
37
+ PathSpec
38
+ ========
39
+
40
+ *pathspec* is a utility library for pattern matching of file paths. So far this
41
+ only includes Git's `gitignore`_ pattern matching.
42
+
43
+ .. _`gitignore`: http://git-scm.com/docs/gitignore
44
+
45
+
46
+ Tutorial
47
+ --------
48
+
49
+ Say you have a "Projects" directory and you want to back it up, but only
50
+ certain files, and ignore others depending on certain conditions::
51
+
52
+ >>> from pathspec import PathSpec
53
+ >>> # The gitignore-style patterns for files to select, but we're including
54
+ >>> # instead of ignoring.
55
+ >>> spec_text = """
56
+ ...
57
+ ... # This is a comment because the line begins with a hash: "#"
58
+ ...
59
+ ... # Include several project directories (and all descendants) relative to
60
+ ... # the current directory. To reference only a directory you must end with a
61
+ ... # slash: "/"
62
+ ... /project-a/
63
+ ... /project-b/
64
+ ... /project-c/
65
+ ...
66
+ ... # Patterns can be negated by prefixing with exclamation mark: "!"
67
+ ...
68
+ ... # Ignore temporary files beginning or ending with "~" and ending with
69
+ ... # ".swp".
70
+ ... !~*
71
+ ... !*~
72
+ ... !*.swp
73
+ ...
74
+ ... # These are python projects so ignore compiled python files from
75
+ ... # testing.
76
+ ... !*.pyc
77
+ ...
78
+ ... # Ignore the build directories but only directly under the project
79
+ ... # directories.
80
+ ... !/*/build/
81
+ ...
82
+ ... """
83
+
84
+ The ``PathSpec`` class provides an abstraction around pattern implementations,
85
+ and we want to compile our patterns as "gitignore" patterns. You could call it a
86
+ wrapper for a list of compiled patterns::
87
+
88
+ >>> spec = PathSpec.from_lines('gitignore', spec_text.splitlines())
89
+
90
+ If we wanted to manually compile the patterns, we can use the ``GitIgnoreBasicPattern``
91
+ class directly. It is used in the background for "gitignore" which internally
92
+ converts patterns to regular expressions::
93
+
94
+ >>> from pathspec.patterns.gitignore.basic import GitIgnoreBasicPattern
95
+ >>> patterns = map(GitIgnoreBasicPattern, spec_text.splitlines())
96
+ >>> spec = PathSpec(patterns)
97
+
98
+ ``PathSpec.from_lines()`` is a class method which simplifies that.
99
+
100
+ If you want to load the patterns from file, you can pass the file object
101
+ directly as well::
102
+
103
+ >>> with open('patterns.list', 'r') as fh:
104
+ >>> spec = PathSpec.from_lines('gitignore', fh)
105
+
106
+ You can perform matching on a whole directory tree with::
107
+
108
+ >>> matches = set(spec.match_tree_files('path/to/directory'))
109
+
110
+ Or you can perform matching on a specific set of file paths with::
111
+
112
+ >>> matches = set(spec.match_files(file_paths))
113
+
114
+ Or check to see if an individual file matches::
115
+
116
+ >>> is_matched = spec.match_file(file_path)
117
+
118
+ There's actually two implementations of "gitignore". The basic implementation is
119
+ used by ``PathSpec`` and follows patterns as documented by `gitignore`_.
120
+ However, Git's behavior differs from the documented patterns. There's some
121
+ edge-cases, and in particular, Git allows including files from excluded
122
+ directories which appears to contradict the documentation. ``GitIgnoreSpec``
123
+ handles these cases to more closely replicate Git's behavior::
124
+
125
+ >>> from pathspec import GitIgnoreSpec
126
+ >>> spec = GitIgnoreSpec.from_lines(spec_text.splitlines())
127
+
128
+ You do not specify the style of pattern for ``GitIgnoreSpec`` because it should
129
+ always use ``GitIgnoreSpecPattern`` internally.
130
+
131
+
132
+ Performance
133
+ -----------
134
+
135
+ Running lots of regular expression matches against thousands of files in Python
136
+ is slow. Alternate regular expression backends can be used to improve
137
+ performance. ``PathSpec`` and ``GitIgnoreSpec`` both accept a ``backend``
138
+ parameter to control the backend. The default is "best" to automatically choose
139
+ the best available backend. There are currently 3 backends.
140
+
141
+ The "simple" backend is the default and it simply uses Python's ``re.Pattern``
142
+ objects that are normally created. This can be the fastest when there's only 1
143
+ or 2 patterns.
144
+
145
+ The "hyperscan" backend uses the `hyperscan`_ library. Hyperscan tends to be at
146
+ least 2 times faster than "simple", and generally slower than "re2". This can be
147
+ faster than "re2" under the right conditions with pattern counts of 1-25.
148
+
149
+ The "re2" backend uses the `google-re2`_ library (not to be confused with the
150
+ *re2* library on PyPI which is unrelated and abandoned). Google's re2 tends to
151
+ be significantly faster than "simple", and 3 times faster than "hyperscan" at
152
+ high pattern counts.
153
+
154
+ See `benchmarks_backends.md`_ for comparisons between native Python regular
155
+ expressions and the optional backends.
156
+
157
+
158
+ .. _`benchmarks_backends.md`: https://github.com/cpburnz/python-pathspec/blob/master/benchmarks_backends.md
159
+ .. _`google-re2`: https://pypi.org/project/google-re2/
160
+ .. _`hyperscan`: https://pypi.org/project/hyperscan/
161
+
162
+
163
+ FAQ
164
+ ---
165
+
166
+
167
+ 1. How do I ignore files like *.gitignore*?
168
+ +++++++++++++++++++++++++++++++++++++++++++
169
+
170
+ ``GitIgnoreSpec`` (and ``PathSpec``) positively match files by default. To find
171
+ the files to keep, and exclude files like *.gitignore*, you need to set
172
+ ``negate=True`` to flip the results::
173
+
174
+ >>> from pathspec import GitIgnoreSpec
175
+ >>> spec = GitIgnoreSpec.from_lines([...])
176
+ >>> keep_files = set(spec.match_tree_files('path/to/directory', negate=True))
177
+ >>> ignore_files = set(spec.match_tree_files('path/to/directory'))
178
+
179
+
180
+ License
181
+ -------
182
+
183
+ *pathspec* is licensed under the `Mozilla Public License Version 2.0`_. See
184
+ `LICENSE`_ or the `FAQ`_ for more information.
185
+
186
+ In summary, you may use *pathspec* with any closed or open source project
187
+ without affecting the license of the larger work so long as you:
188
+
189
+ - give credit where credit is due,
190
+
191
+ - and release any custom changes made to *pathspec*.
192
+
193
+ .. _`Mozilla Public License Version 2.0`: http://www.mozilla.org/MPL/2.0
194
+ .. _`LICENSE`: LICENSE
195
+ .. _`FAQ`: http://www.mozilla.org/MPL/2.0/FAQ.html
196
+
197
+
198
+ Source
199
+ ------
200
+
201
+ The source code for *pathspec* is available from the GitHub repo
202
+ `cpburnz/python-pathspec`_.
203
+
204
+ .. _`cpburnz/python-pathspec`: https://github.com/cpburnz/python-pathspec
205
+
206
+
207
+ Installation
208
+ ------------
209
+
210
+ *pathspec* is available for install through `PyPI`_::
211
+
212
+ pip install pathspec
213
+
214
+ *pathspec* can also be built from source. The following packages will be
215
+ required:
216
+
217
+ - `build`_ (>=0.6.0)
218
+
219
+ *pathspec* can then be built and installed with::
220
+
221
+ python -m build
222
+ pip install dist/pathspec-*-py3-none-any.whl
223
+
224
+ The following optional dependencies can be installed:
225
+
226
+ - `google-re2`_: Enables optional "re2" backend.
227
+ - `hyperscan`_: Enables optional "hyperscan" backend.
228
+ - `typing-extensions`_: Improves some type hints.
229
+
230
+ .. _`PyPI`: http://pypi.python.org/pypi/pathspec
231
+ .. _`build`: https://pypi.org/project/build/
232
+ .. _`typing-extensions`: https://pypi.org/project/typing-extensions/
233
+
234
+
235
+ Documentation
236
+ -------------
237
+
238
+ Documentation for *pathspec* is available on `Read the Docs`_.
239
+
240
+ The full change history can be found in `CHANGES.rst`_ and `Change History`_.
241
+
242
+ An upgrade guide is available in `UPGRADING.rst`_ and `Upgrade Guide`_.
243
+
244
+ .. _`CHANGES.rst`: https://github.com/cpburnz/python-pathspec/blob/master/CHANGES.rst
245
+ .. _`Change History`: https://python-path-specification.readthedocs.io/en/stable/changes.html
246
+ .. _`Read the Docs`: https://python-path-specification.readthedocs.io
247
+ .. _`UPGRADING.rst`: https://github.com/cpburnz/python-pathspec/blob/master/UPGRADING.rst
248
+ .. _`Upgrade Guide`: https://python-path-specification.readthedocs.io/en/stable/upgrading.html
249
+
250
+
251
+ Other Languages
252
+ ---------------
253
+
254
+ The related project `pathspec-ruby`_ (by *highb*) provides a similar library as
255
+ a `Ruby gem`_.
256
+
257
+ .. _`pathspec-ruby`: https://github.com/highb/pathspec-ruby
258
+ .. _`Ruby gem`: https://rubygems.org/gems/pathspec
259
+
260
+
261
+ Change History
262
+ ==============
263
+
264
+
265
+ 1.1.0 (2026-04-22)
266
+ ------------------
267
+
268
+ Bug fixes:
269
+
270
+ - `Issue #93`_: Git discards invalid range notation. `GitIgnoreSpecPattern` now discards patterns with invalid range notation like Git.
271
+ - `Pull #106`_: Fix escape() not escaping backslash characters.
272
+
273
+ Improvements:
274
+
275
+ - `Issue #108`_: Specialize pattern type for `PathSpec` as `PathSpec[TPattern]` for better debugging of `PathSpec().patterns`.
276
+ - `Pull #110`_: Nicer debug print outs (and str for regex pattern).
277
+
278
+
279
+ .. _`Pull #106`: https://github.com/cpburnz/python-pathspec/pull/106
280
+ .. _`Issue #108`: https://github.com/cpburnz/python-pathspec/issues/108
281
+ .. _`Pull #110`: https://github.com/cpburnz/python-pathspec/pull/110
282
+
283
+
284
+ 1.0.4 (2026-01-26)
285
+ ------------------
286
+
287
+ Bug fixes:
288
+
289
+ - `Issue #103`_: Using re2 fails if pyre2 is also installed.
290
+
291
+ .. _`Issue #103`: https://github.com/cpburnz/python-pathspec/issues/103
292
+
293
+
294
+ 1.0.3 (2026-01-09)
295
+ ------------------
296
+
297
+ Bug fixes:
298
+
299
+ - `Issue #101`_: pyright strict errors with pathspec >= 1.0.0.
300
+ - `Issue #102`_: No module named 'tomllib'.
301
+
302
+
303
+ .. _`Issue #101`: https://github.com/cpburnz/python-pathspec/issues/101
304
+ .. _`Issue #102`: https://github.com/cpburnz/python-pathspec/issues/102
305
+
306
+
307
+ 1.0.2 (2026-01-07)
308
+ ------------------
309
+
310
+ Bug fixes:
311
+
312
+ - Type hint `collections.abc.Callable` does not properly replace `typing.Callable` until Python 3.9.2.
313
+
314
+
315
+ 1.0.1 (2026-01-06)
316
+ ------------------
317
+
318
+ Bug fixes:
319
+
320
+ - `Issue #100`_: ValueError(f"{patterns=!r} cannot be empty.") when using black.
321
+
322
+
323
+ .. _`Issue #100`: https://github.com/cpburnz/python-pathspec/issues/100
324
+
325
+
326
+ 1.0.0 (2026-01-05)
327
+ ------------------
328
+
329
+ Major changes:
330
+
331
+ - `Issue #91`_: Dropped support of EoL Python 3.8.
332
+ - Added concept of backends to allow for faster regular expression matching. The backend can be controlled using the `backend` argument to `PathSpec()`, `PathSpec.from_lines()`, `GitIgnoreSpec()`, and `GitIgnoreSpec.from_lines()`.
333
+ - Renamed "gitwildmatch" pattern back to "gitignore". The "gitignore" pattern behaves slightly differently when used with `PathSpec` (*gitignore* as documented) than with `GitIgnoreSpec` (replicates *Git*'s edge cases).
334
+
335
+ API changes:
336
+
337
+ - Breaking: protected method `pathspec.pathspec.PathSpec._match_file()` (with a leading underscore) has been removed and replaced by backends. This does not affect normal usage of `PathSpec` or `GitIgnoreSpec`. Only custom subclasses will be affected. If this breaks your usage, let me know by `opening an issue <https://github.com/cpburnz/python-pathspec/issues>`_.
338
+ - Deprecated: "gitwildmatch" is now an alias for "gitignore".
339
+ - Deprecated: `pathspec.patterns.GitWildMatchPattern` is now an alias for `pathspec.patterns.gitignore.spec.GitIgnoreSpecPattern`.
340
+ - Deprecated: `pathspec.patterns.gitwildmatch` module has been replaced by the `pathspec.patterns.gitignore` package.
341
+ - Deprecated: `pathspec.patterns.gitwildmatch.GitWildMatchPattern` is now an alias for `pathspec.patterns.gitignore.spec.GitIgnoreSpecPattern`.
342
+ - Deprecated: `pathspec.patterns.gitwildmatch.GitWildMatchPatternError` is now an alias for `pathspec.patterns.gitignore.GitIgnorePatternError`.
343
+ - Removed: `pathspec.patterns.gitwildmatch.GitIgnorePattern` has been deprecated since v0.4 (2016-07-15).
344
+ - Signature of method `pathspec.pattern.RegexPattern.match_file()` has been changed from `def match_file(self, file: str) -> RegexMatchResult | None` to `def match_file(self, file: AnyStr) -> RegexMatchResult | None` to reflect usage.
345
+ - Signature of class method `pathspec.pattern.RegexPattern.pattern_to_regex()` has been changed from `def pattern_to_regex(cls, pattern: str) -> tuple[str, bool]` to `def pattern_to_regex(cls, pattern: AnyStr) -> tuple[AnyStr | None, bool | None]` to reflect usage and documentation.
346
+
347
+ New features:
348
+
349
+ - Added optional "hyperscan" backend using `hyperscan`_ library. It will automatically be used when installed. This dependency can be installed with ``pip install 'pathspec[hyperscan]'``.
350
+ - Added optional "re2" backend using the `google-re2`_ library. It will automatically be used when installed. This dependency can be installed with ``pip install 'pathspec[re2]'``.
351
+ - Added optional dependency on `typing-extensions`_ library to improve some type hints.
352
+
353
+ Bug fixes:
354
+
355
+ - `Issue #93`_: Do not remove leading spaces.
356
+ - `Issue #95`_: Matching for files inside folder does not seem to behave like .gitignore's.
357
+ - `Issue #98`_: UnboundLocalError in RegexPattern when initialized with `pattern=None`.
358
+ - Type hint on return value of `pathspec.pattern.RegexPattern.match_file()` to match documentation.
359
+
360
+ Improvements:
361
+
362
+ - Mark Python 3.13 and 3.14 as supported.
363
+ - No-op patterns are now filtered out when matching files, slightly improving performance.
364
+ - Fix performance regression in `iter_tree_files()` from v0.10.
365
+
366
+
367
+ .. _`Issue #38`: https://github.com/cpburnz/python-pathspec/issues/38
368
+ .. _`Issue #91`: https://github.com/cpburnz/python-pathspec/issues/91
369
+ .. _`Issue #93`: https://github.com/cpburnz/python-pathspec/issues/93
370
+ .. _`Issue #95`: https://github.com/cpburnz/python-pathspec/issues/95
371
+ .. _`Issue #98`: https://github.com/cpburnz/python-pathspec/issues/98
372
+ .. _`google-re2`: https://pypi.org/project/google-re2/
373
+ .. _`hyperscan`: https://pypi.org/project/hyperscan/
374
+ .. _`typing-extensions`: https://pypi.org/project/typing-extensions/
375
+
.cache/pip/http-v2/4/2/5/e/e/425ee452eddda30695488b965f5cfa22049bb8f92ad87623f545a8bb ADDED
Binary file (1.22 kB). View file
 
.cache/pip/http-v2/4/2/5/e/e/425ee452eddda30695488b965f5cfa22049bb8f92ad87623f545a8bb.body ADDED
@@ -0,0 +1,324 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: huggingface_hub
3
+ Version: 1.9.1
4
+ Summary: Client library to download and publish models, datasets and other repos on the huggingface.co hub
5
+ Home-page: https://github.com/huggingface/huggingface_hub
6
+ Author: Hugging Face, Inc.
7
+ Author-email: julien@huggingface.co
8
+ License: Apache-2.0
9
+ Keywords: model-hub machine-learning models natural-language-processing deep-learning pytorch pretrained-models
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Intended Audience :: Education
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Requires-Python: >=3.10.0
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: filelock>=3.10.0
27
+ Requires-Dist: fsspec>=2023.5.0
28
+ Requires-Dist: hf-xet<2.0.0,>=1.4.3; platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "arm64" or platform_machine == "aarch64"
29
+ Requires-Dist: httpx<1,>=0.23.0
30
+ Requires-Dist: packaging>=20.9
31
+ Requires-Dist: pyyaml>=5.1
32
+ Requires-Dist: tqdm>=4.42.1
33
+ Requires-Dist: typer
34
+ Requires-Dist: typing-extensions>=4.1.0
35
+ Provides-Extra: oauth
36
+ Requires-Dist: authlib>=1.3.2; extra == "oauth"
37
+ Requires-Dist: fastapi; extra == "oauth"
38
+ Requires-Dist: httpx; extra == "oauth"
39
+ Requires-Dist: itsdangerous; extra == "oauth"
40
+ Provides-Extra: torch
41
+ Requires-Dist: torch; extra == "torch"
42
+ Requires-Dist: safetensors[torch]; extra == "torch"
43
+ Provides-Extra: fastai
44
+ Requires-Dist: toml; extra == "fastai"
45
+ Requires-Dist: fastai>=2.4; extra == "fastai"
46
+ Requires-Dist: fastcore>=1.3.27; extra == "fastai"
47
+ Provides-Extra: hf-xet
48
+ Requires-Dist: hf-xet<2.0.0,>=1.4.3; extra == "hf-xet"
49
+ Provides-Extra: mcp
50
+ Requires-Dist: mcp>=1.8.0; extra == "mcp"
51
+ Provides-Extra: testing
52
+ Requires-Dist: authlib>=1.3.2; extra == "testing"
53
+ Requires-Dist: fastapi; extra == "testing"
54
+ Requires-Dist: httpx; extra == "testing"
55
+ Requires-Dist: itsdangerous; extra == "testing"
56
+ Requires-Dist: jedi; extra == "testing"
57
+ Requires-Dist: Jinja2; extra == "testing"
58
+ Requires-Dist: pytest>=8.4.2; extra == "testing"
59
+ Requires-Dist: pytest-cov; extra == "testing"
60
+ Requires-Dist: pytest-env; extra == "testing"
61
+ Requires-Dist: pytest-xdist; extra == "testing"
62
+ Requires-Dist: pytest-vcr; extra == "testing"
63
+ Requires-Dist: pytest-asyncio; extra == "testing"
64
+ Requires-Dist: pytest-rerunfailures<16.0; extra == "testing"
65
+ Requires-Dist: pytest-mock; extra == "testing"
66
+ Requires-Dist: urllib3<2.0; extra == "testing"
67
+ Requires-Dist: soundfile; extra == "testing"
68
+ Requires-Dist: Pillow; extra == "testing"
69
+ Requires-Dist: numpy; extra == "testing"
70
+ Requires-Dist: duckdb; extra == "testing"
71
+ Requires-Dist: fastapi; extra == "testing"
72
+ Provides-Extra: gradio
73
+ Requires-Dist: gradio>=5.0.0; extra == "gradio"
74
+ Requires-Dist: requests; extra == "gradio"
75
+ Provides-Extra: typing
76
+ Requires-Dist: typing-extensions>=4.8.0; extra == "typing"
77
+ Requires-Dist: types-PyYAML; extra == "typing"
78
+ Requires-Dist: types-simplejson; extra == "typing"
79
+ Requires-Dist: types-toml; extra == "typing"
80
+ Requires-Dist: types-tqdm; extra == "typing"
81
+ Requires-Dist: types-urllib3; extra == "typing"
82
+ Provides-Extra: quality
83
+ Requires-Dist: ruff>=0.9.0; extra == "quality"
84
+ Requires-Dist: mypy==1.15.0; extra == "quality"
85
+ Requires-Dist: libcst>=1.4.0; extra == "quality"
86
+ Requires-Dist: ty; extra == "quality"
87
+ Provides-Extra: all
88
+ Requires-Dist: authlib>=1.3.2; extra == "all"
89
+ Requires-Dist: fastapi; extra == "all"
90
+ Requires-Dist: httpx; extra == "all"
91
+ Requires-Dist: itsdangerous; extra == "all"
92
+ Requires-Dist: jedi; extra == "all"
93
+ Requires-Dist: Jinja2; extra == "all"
94
+ Requires-Dist: pytest>=8.4.2; extra == "all"
95
+ Requires-Dist: pytest-cov; extra == "all"
96
+ Requires-Dist: pytest-env; extra == "all"
97
+ Requires-Dist: pytest-xdist; extra == "all"
98
+ Requires-Dist: pytest-vcr; extra == "all"
99
+ Requires-Dist: pytest-asyncio; extra == "all"
100
+ Requires-Dist: pytest-rerunfailures<16.0; extra == "all"
101
+ Requires-Dist: pytest-mock; extra == "all"
102
+ Requires-Dist: urllib3<2.0; extra == "all"
103
+ Requires-Dist: soundfile; extra == "all"
104
+ Requires-Dist: Pillow; extra == "all"
105
+ Requires-Dist: numpy; extra == "all"
106
+ Requires-Dist: duckdb; extra == "all"
107
+ Requires-Dist: fastapi; extra == "all"
108
+ Requires-Dist: ruff>=0.9.0; extra == "all"
109
+ Requires-Dist: mypy==1.15.0; extra == "all"
110
+ Requires-Dist: libcst>=1.4.0; extra == "all"
111
+ Requires-Dist: ty; extra == "all"
112
+ Requires-Dist: typing-extensions>=4.8.0; extra == "all"
113
+ Requires-Dist: types-PyYAML; extra == "all"
114
+ Requires-Dist: types-simplejson; extra == "all"
115
+ Requires-Dist: types-toml; extra == "all"
116
+ Requires-Dist: types-tqdm; extra == "all"
117
+ Requires-Dist: types-urllib3; extra == "all"
118
+ Provides-Extra: dev
119
+ Requires-Dist: authlib>=1.3.2; extra == "dev"
120
+ Requires-Dist: fastapi; extra == "dev"
121
+ Requires-Dist: httpx; extra == "dev"
122
+ Requires-Dist: itsdangerous; extra == "dev"
123
+ Requires-Dist: jedi; extra == "dev"
124
+ Requires-Dist: Jinja2; extra == "dev"
125
+ Requires-Dist: pytest>=8.4.2; extra == "dev"
126
+ Requires-Dist: pytest-cov; extra == "dev"
127
+ Requires-Dist: pytest-env; extra == "dev"
128
+ Requires-Dist: pytest-xdist; extra == "dev"
129
+ Requires-Dist: pytest-vcr; extra == "dev"
130
+ Requires-Dist: pytest-asyncio; extra == "dev"
131
+ Requires-Dist: pytest-rerunfailures<16.0; extra == "dev"
132
+ Requires-Dist: pytest-mock; extra == "dev"
133
+ Requires-Dist: urllib3<2.0; extra == "dev"
134
+ Requires-Dist: soundfile; extra == "dev"
135
+ Requires-Dist: Pillow; extra == "dev"
136
+ Requires-Dist: numpy; extra == "dev"
137
+ Requires-Dist: duckdb; extra == "dev"
138
+ Requires-Dist: fastapi; extra == "dev"
139
+ Requires-Dist: ruff>=0.9.0; extra == "dev"
140
+ Requires-Dist: mypy==1.15.0; extra == "dev"
141
+ Requires-Dist: libcst>=1.4.0; extra == "dev"
142
+ Requires-Dist: ty; extra == "dev"
143
+ Requires-Dist: typing-extensions>=4.8.0; extra == "dev"
144
+ Requires-Dist: types-PyYAML; extra == "dev"
145
+ Requires-Dist: types-simplejson; extra == "dev"
146
+ Requires-Dist: types-toml; extra == "dev"
147
+ Requires-Dist: types-tqdm; extra == "dev"
148
+ Requires-Dist: types-urllib3; extra == "dev"
149
+ Dynamic: author
150
+ Dynamic: author-email
151
+ Dynamic: classifier
152
+ Dynamic: description
153
+ Dynamic: description-content-type
154
+ Dynamic: home-page
155
+ Dynamic: keywords
156
+ Dynamic: license
157
+ Dynamic: license-file
158
+ Dynamic: provides-extra
159
+ Dynamic: requires-dist
160
+ Dynamic: requires-python
161
+ Dynamic: summary
162
+
163
+ <p align="center">
164
+ <picture>
165
+ <source media="(prefers-color-scheme: dark)" srcset="https://huggingface.co/datasets/huggingface/documentation-images/raw/main/huggingface_hub-dark.svg">
166
+ <source media="(prefers-color-scheme: light)" srcset="https://huggingface.co/datasets/huggingface/documentation-images/raw/main/huggingface_hub.svg">
167
+ <img alt="huggingface_hub library logo" src="https://huggingface.co/datasets/huggingface/documentation-images/raw/main/huggingface_hub.svg" width="352" height="59" style="max-width: 100%">
168
+ </picture>
169
+ <br/>
170
+ <br/>
171
+ </p>
172
+
173
+ <p align="center">
174
+ <i>The official Python client for the Huggingface Hub.</i>
175
+ </p>
176
+
177
+ <p align="center">
178
+ <a href="https://huggingface.co/docs/huggingface_hub/en/index"><img alt="Documentation" src="https://img.shields.io/website/http/huggingface.co/docs/huggingface_hub/index.svg?down_color=red&down_message=offline&up_message=online&label=doc"></a>
179
+ <a href="https://github.com/huggingface/huggingface_hub/releases"><img alt="GitHub release" src="https://img.shields.io/github/release/huggingface/huggingface_hub.svg"></a>
180
+ <a href="https://github.com/huggingface/huggingface_hub"><img alt="PyPi version" src="https://img.shields.io/pypi/pyversions/huggingface_hub.svg"></a>
181
+ <a href="https://pypi.org/project/huggingface-hub"><img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/huggingface_hub"></a>
182
+ <a href="https://codecov.io/gh/huggingface/huggingface_hub"><img alt="Code coverage" src="https://codecov.io/gh/huggingface/huggingface_hub/branch/main/graph/badge.svg?token=RXP95LE2XL"></a>
183
+ </p>
184
+
185
+ <h4 align="center">
186
+ <p>
187
+ <b>English</b> |
188
+ <a href="https://github.com/huggingface/huggingface_hub/blob/main/i18n/README_de.md">Deutsch</a> |
189
+ <a href="https://github.com/huggingface/huggingface_hub/blob/main/i18n/README_fr.md">Français</a> |
190
+ <a href="https://github.com/huggingface/huggingface_hub/blob/main/i18n/README_hi.md">हिंदी</a> |
191
+ <a href="https://github.com/huggingface/huggingface_hub/blob/main/i18n/README_ko.md">한국어</a> |
192
+ <a href="https://github.com/huggingface/huggingface_hub/blob/main/i18n/README_cn.md">中文 (简体)</a>
193
+ <p>
194
+ </h4>
195
+
196
+ ---
197
+
198
+ **Documentation**: <a href="https://hf.co/docs/huggingface_hub" target="_blank">https://hf.co/docs/huggingface_hub</a>
199
+
200
+ **Source Code**: <a href="https://github.com/huggingface/huggingface_hub" target="_blank">https://github.com/huggingface/huggingface_hub</a>
201
+
202
+ ---
203
+
204
+ ## Welcome to the huggingface_hub library
205
+
206
+ The `huggingface_hub` library allows you to interact with the [Hugging Face Hub](https://huggingface.co/), a platform democratizing open-source Machine Learning for creators and collaborators. Discover pre-trained models and datasets for your projects or play with the thousands of machine learning apps hosted on the Hub. You can also create and share your own models, datasets and demos with the community. The `huggingface_hub` library provides a simple way to do all these things with Python.
207
+
208
+ ## Key features
209
+
210
+ - [Download files](https://huggingface.co/docs/huggingface_hub/en/guides/download) from the Hub.
211
+ - [Upload files](https://huggingface.co/docs/huggingface_hub/en/guides/upload) to the Hub.
212
+ - [Manage your repositories](https://huggingface.co/docs/huggingface_hub/en/guides/repository).
213
+ - [Run Inference](https://huggingface.co/docs/huggingface_hub/en/guides/inference) on deployed models.
214
+ - [Search](https://huggingface.co/docs/huggingface_hub/en/guides/search) for models, datasets and Spaces.
215
+ - [Share Model Cards](https://huggingface.co/docs/huggingface_hub/en/guides/model-cards) to document your models.
216
+ - [Engage with the community](https://huggingface.co/docs/huggingface_hub/en/guides/community) through PRs and comments.
217
+
218
+ ## Installation
219
+
220
+ Install the `huggingface_hub` package with [pip](https://pypi.org/project/huggingface-hub/):
221
+
222
+ ```bash
223
+ pip install huggingface_hub
224
+ ```
225
+
226
+ If you prefer, you can also install it with [conda](https://huggingface.co/docs/huggingface_hub/en/installation#install-with-conda).
227
+
228
+ In order to keep the package minimal by default, `huggingface_hub` comes with optional dependencies useful for some use cases. For example, if you want to use the MCP module, run:
229
+
230
+ ```bash
231
+ pip install "huggingface_hub[mcp]"
232
+ ```
233
+
234
+ To learn more installation and optional dependencies, check out the [installation guide](https://huggingface.co/docs/huggingface_hub/en/installation).
235
+
236
+ ## Quick start
237
+
238
+ ### Download files
239
+
240
+ Download a single file
241
+
242
+ ```py
243
+ from huggingface_hub import hf_hub_download
244
+
245
+ hf_hub_download(repo_id="tiiuae/falcon-7b-instruct", filename="config.json")
246
+ ```
247
+
248
+ Or an entire repository
249
+
250
+ ```py
251
+ from huggingface_hub import snapshot_download
252
+
253
+ snapshot_download("stabilityai/stable-diffusion-2-1")
254
+ ```
255
+
256
+ Files will be downloaded in a local cache folder. More details in [this guide](https://huggingface.co/docs/huggingface_hub/en/guides/manage-cache).
257
+
258
+ ### Login
259
+
260
+ The Hugging Face Hub uses tokens to authenticate applications (see [docs](https://huggingface.co/docs/hub/security-tokens)). To log in your machine, run the following CLI:
261
+
262
+ ```bash
263
+ hf auth login
264
+ # or using an environment variable
265
+ hf auth login --token $HUGGINGFACE_TOKEN
266
+ ```
267
+
268
+ ### Create a repository
269
+
270
+ ```py
271
+ from huggingface_hub import create_repo
272
+
273
+ create_repo(repo_id="super-cool-model")
274
+ ```
275
+
276
+ ### Upload files
277
+
278
+ Upload a single file
279
+
280
+ ```py
281
+ from huggingface_hub import upload_file
282
+
283
+ upload_file(
284
+ path_or_fileobj="/home/lysandre/dummy-test/README.md",
285
+ path_in_repo="README.md",
286
+ repo_id="lysandre/test-model",
287
+ )
288
+ ```
289
+
290
+ Or an entire folder
291
+
292
+ ```py
293
+ from huggingface_hub import upload_folder
294
+
295
+ upload_folder(
296
+ folder_path="/path/to/local/space",
297
+ repo_id="username/my-cool-space",
298
+ repo_type="space",
299
+ )
300
+ ```
301
+
302
+ For details in the [upload guide](https://huggingface.co/docs/huggingface_hub/en/guides/upload).
303
+
304
+ ## Integrating to the Hub.
305
+
306
+ We're partnering with cool open source ML libraries to provide free model hosting and versioning. You can find the existing integrations [here](https://huggingface.co/docs/hub/libraries).
307
+
308
+ The advantages are:
309
+
310
+ - Free model or dataset hosting for libraries and their users.
311
+ - Built-in file versioning, even with very large files, thanks to a git-based approach.
312
+ - In-browser widgets to play with the uploaded models.
313
+ - Anyone can upload a new model for your library, they just need to add the corresponding tag for the model to be discoverable.
314
+ - Fast downloads! We use Cloudfront (a CDN) to geo-replicate downloads so they're blazing fast from anywhere on the globe.
315
+ - Usage stats and more features to come.
316
+
317
+ If you would like to integrate your library, feel free to open an issue to begin the discussion. We wrote a [step-by-step guide](https://huggingface.co/docs/hub/adding-a-library) with ❤️ showing how to do this integration.
318
+
319
+ ## Contributions (feature requests, bugs, etc.) are super welcome 💙💚💛💜🧡❤️
320
+
321
+ Everyone is welcome to contribute, and we value everybody's contribution. Code is not the only way to help the community.
322
+ Answering questions, helping others, reaching out and improving the documentations are immensely valuable to the community.
323
+ We wrote a [contribution guide](https://github.com/huggingface/huggingface_hub/blob/main/CONTRIBUTING.md) to summarize
324
+ how to get started to contribute to this repository.
.cache/pip/http-v2/4/2/6/6/d/4266da420f80fe5b2de81f440f459cda33c49a87b4c539a917582c18.body ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.1
2
+ Name: multiprocess
3
+ Version: 0.70.16
4
+ Summary: better multiprocessing and multithreading in Python
5
+ Home-page: https://github.com/uqfoundation/multiprocess
6
+ Download-URL: https://pypi.org/project/multiprocess/#files
7
+ Author: Mike McKerns
8
+ Author-email: mmckerns@uqfoundation.org
9
+ Maintainer: Mike McKerns
10
+ Maintainer-email: mmckerns@uqfoundation.org
11
+ License: BSD-3-Clause
12
+ Project-URL: Documentation, http://multiprocess.rtfd.io
13
+ Project-URL: Source Code, https://github.com/uqfoundation/multiprocess
14
+ Project-URL: Bug Tracker, https://github.com/uqfoundation/multiprocess/issues
15
+ Platform: Linux
16
+ Platform: Windows
17
+ Platform: Mac
18
+ Classifier: Development Status :: 5 - Production/Stable
19
+ Classifier: Intended Audience :: Developers
20
+ Classifier: Intended Audience :: Science/Research
21
+ Classifier: License :: OSI Approved :: BSD License
22
+ Classifier: Programming Language :: Python :: 3
23
+ Classifier: Programming Language :: Python :: 3.8
24
+ Classifier: Programming Language :: Python :: 3.9
25
+ Classifier: Programming Language :: Python :: 3.10
26
+ Classifier: Programming Language :: Python :: 3.11
27
+ Classifier: Programming Language :: Python :: 3.12
28
+ Classifier: Programming Language :: Python :: Implementation :: CPython
29
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
30
+ Classifier: Topic :: Scientific/Engineering
31
+ Classifier: Topic :: Software Development
32
+ Requires-Python: >=3.8
33
+ License-File: LICENSE
34
+ License-File: COPYING
35
+ Requires-Dist: dill (>=0.3.8)
36
+
37
+ -----------------------------------------------------------------
38
+ multiprocess: better multiprocessing and multithreading in Python
39
+ -----------------------------------------------------------------
40
+
41
+ About Multiprocess
42
+ ==================
43
+
44
+ ``multiprocess`` is a fork of ``multiprocessing``. ``multiprocess`` extends ``multiprocessing`` to provide enhanced serialization, using `dill`. ``multiprocess`` leverages ``multiprocessing`` to support the spawning of processes using the API of the Python standard library's ``threading`` module. ``multiprocessing`` has been distributed as part of the standard library since Python 2.6.
45
+
46
+ ``multiprocess`` is part of ``pathos``, a Python framework for heterogeneous computing.
47
+ ``multiprocess`` is in active development, so any user feedback, bug reports, comments,
48
+ or suggestions are highly appreciated. A list of issues is located at https://github.com/uqfoundation/multiprocess/issues, with a legacy list maintained at https://uqfoundation.github.io/project/pathos/query.
49
+
50
+
51
+ Major Features
52
+ ==============
53
+
54
+ ``multiprocess`` enables:
55
+
56
+ - objects to be transferred between processes using pipes or multi-producer/multi-consumer queues
57
+ - objects to be shared between processes using a server process or (for simple data) shared memory
58
+
59
+ ``multiprocess`` provides:
60
+
61
+ - equivalents of all the synchronization primitives in ``threading``
62
+ - a ``Pool`` class to facilitate submitting tasks to worker processes
63
+ - enhanced serialization, using ``dill``
64
+
65
+
66
+ Current Release
67
+ ===============
68
+
69
+ The latest released version of ``multiprocess`` is available from:
70
+
71
+ https://pypi.org/project/multiprocess
72
+
73
+ ``multiprocess`` is distributed under a 3-clause BSD license, and is a fork of ``multiprocessing``.
74
+
75
+
76
+ Development Version
77
+ ===================
78
+
79
+ You can get the latest development version with all the shiny new features at:
80
+
81
+ https://github.com/uqfoundation
82
+
83
+ If you have a new contribution, please submit a pull request.
84
+
85
+
86
+ Installation
87
+ ============
88
+
89
+ ``multiprocess`` can be installed with ``pip``::
90
+
91
+ $ pip install multiprocess
92
+
93
+ For Python 2, a C compiler is required to build the included extension module from source. Python 3 and binary installs do not require a C compiler.
94
+
95
+
96
+ Requirements
97
+ ============
98
+
99
+ ``multiprocess`` requires:
100
+
101
+ - ``python`` (or ``pypy``), **>=3.8**
102
+ - ``setuptools``, **>=42**
103
+ - ``dill``, **>=0.3.8**
104
+
105
+
106
+ Basic Usage
107
+ ===========
108
+
109
+ The ``multiprocess.Process`` class follows the API of ``threading.Thread``.
110
+ For example ::
111
+
112
+ from multiprocess import Process, Queue
113
+
114
+ def f(q):
115
+ q.put('hello world')
116
+
117
+ if __name__ == '__main__':
118
+ q = Queue()
119
+ p = Process(target=f, args=[q])
120
+ p.start()
121
+ print (q.get())
122
+ p.join()
123
+
124
+ Synchronization primitives like locks, semaphores and conditions are
125
+ available, for example ::
126
+
127
+ >>> from multiprocess import Condition
128
+ >>> c = Condition()
129
+ >>> print (c)
130
+ <Condition(<RLock(None, 0)>), 0>
131
+ >>> c.acquire()
132
+ True
133
+ >>> print (c)
134
+ <Condition(<RLock(MainProcess, 1)>), 0>
135
+
136
+ One can also use a manager to create shared objects either in shared
137
+ memory or in a server process, for example ::
138
+
139
+ >>> from multiprocess import Manager
140
+ >>> manager = Manager()
141
+ >>> l = manager.list(range(10))
142
+ >>> l.reverse()
143
+ >>> print (l)
144
+ [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
145
+ >>> print (repr(l))
146
+ <Proxy[list] object at 0x00E1B3B0>
147
+
148
+ Tasks can be offloaded to a pool of worker processes in various ways,
149
+ for example ::
150
+
151
+ >>> from multiprocess import Pool
152
+ >>> def f(x): return x*x
153
+ ...
154
+ >>> p = Pool(4)
155
+ >>> result = p.map_async(f, range(10))
156
+ >>> print (result.get(timeout=1))
157
+ [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
158
+
159
+ When ``dill`` is installed, serialization is extended to most objects,
160
+ for example ::
161
+
162
+ >>> from multiprocess import Pool
163
+ >>> p = Pool(4)
164
+ >>> print (p.map(lambda x: (lambda y:y**2)(x) + x, xrange(10)))
165
+ [0, 2, 6, 12, 20, 30, 42, 56, 72, 90]
166
+
167
+
168
+ More Information
169
+ ================
170
+
171
+ Probably the best way to get started is to look at the documentation at
172
+ http://multiprocess.rtfd.io. Also see ``multiprocess.tests`` for scripts that
173
+ demonstrate how ``multiprocess`` can be used to leverge multiple processes
174
+ to execute Python in parallel. You can run the test suite with
175
+ ``python -m multiprocess.tests``. As ``multiprocess`` conforms to the
176
+ ``multiprocessing`` interface, the examples and documentation found at
177
+ http://docs.python.org/library/multiprocessing.html also apply to
178
+ ``multiprocess`` if one will ``import multiprocessing as multiprocess``.
179
+ See https://github.com/uqfoundation/multiprocess/tree/master/py3.12/examples
180
+ for a set of examples that demonstrate some basic use cases and benchmarking
181
+ for running Python code in parallel. Please feel free to submit a ticket on
182
+ github, or ask a question on stackoverflow (**@Mike McKerns**). If you would
183
+ like to share how you use ``multiprocess`` in your work, please send an email
184
+ (to **mmckerns at uqfoundation dot org**).
185
+
186
+
187
+ Citation
188
+ ========
189
+
190
+ If you use ``multiprocess`` to do research that leads to publication, we ask that you
191
+ acknowledge use of ``multiprocess`` by citing the following in your publication::
192
+
193
+ M.M. McKerns, L. Strand, T. Sullivan, A. Fang, M.A.G. Aivazis,
194
+ "Building a framework for predictive science", Proceedings of
195
+ the 10th Python in Science Conference, 2011;
196
+ http://arxiv.org/pdf/1202.1056
197
+
198
+ Michael McKerns and Michael Aivazis,
199
+ "pathos: a framework for heterogeneous computing", 2010- ;
200
+ https://uqfoundation.github.io/project/pathos
201
+
202
+ Please see https://uqfoundation.github.io/project/pathos or
203
+ http://arxiv.org/pdf/1202.1056 for further information.
.cache/pip/http-v2/4/3/2/5/0/432508fca4367eb16c5bda476b8ecbf96beccd650c7aea212e59eb40 ADDED
Binary file (1.31 kB). View file
 
.cache/pip/http-v2/4/3/2/5/0/432508fca4367eb16c5bda476b8ecbf96beccd650c7aea212e59eb40.body ADDED
@@ -0,0 +1,490 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: sse-starlette
3
+ Version: 3.4.1
4
+ Summary: SSE plugin for Starlette
5
+ Author-email: sysid <sysid@gmx.de>
6
+ License-Expression: BSD-3-Clause
7
+ Project-URL: Source, https://github.com/sysid/sse-starlette
8
+ Classifier: Development Status :: 5 - Production/Stable
9
+ Classifier: Environment :: Web Environment
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Internet :: WWW/HTTP
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ License-File: AUTHORS
22
+ Requires-Dist: starlette>=0.49.1
23
+ Requires-Dist: anyio>=4.7.0
24
+ Provides-Extra: examples
25
+ Requires-Dist: uvicorn>=0.34.0; extra == "examples"
26
+ Requires-Dist: fastapi>=0.115.12; extra == "examples"
27
+ Requires-Dist: pydantic>=2; extra == "examples"
28
+ Provides-Extra: examples-db
29
+ Requires-Dist: sqlalchemy[asyncio]>=2.0.41; extra == "examples-db"
30
+ Requires-Dist: aiosqlite>=0.21.0; extra == "examples-db"
31
+ Provides-Extra: uvicorn
32
+ Requires-Dist: uvicorn>=0.34.0; extra == "uvicorn"
33
+ Provides-Extra: granian
34
+ Requires-Dist: granian>=2.3.1; extra == "granian"
35
+ Provides-Extra: daphne
36
+ Requires-Dist: daphne>=4.2.0; extra == "daphne"
37
+ Dynamic: license-file
38
+
39
+ # Server-Sent Events for [Starlette](https://github.com/encode/starlette) and [FastAPI](https://fastapi.tiangolo.com/)
40
+
41
+ [![Downloads](https://static.pepy.tech/badge/sse-starlette/week)](https://pepy.tech/project/sse-starlette)
42
+ [![PyPI Version][pypi-image]][pypi-url]
43
+ [![Build Status][build-image]][build-url]
44
+
45
+ > Background: https://sysid.github.io/server-sent-events/
46
+
47
+ Production ready Server-Sent Events implementation for Starlette and FastAPI following the [W3C SSE specification](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events).
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ pip install sse-starlette
53
+ uv add sse-starlette
54
+
55
+ # To run the examples (fastapi, uvicorn, pydantic)
56
+ uv add sse-starlette[examples]
57
+
58
+ # Example 03 also needs the DB extras (sqlalchemy, aiosqlite)
59
+ uv add sse-starlette[examples,examples-db]
60
+
61
+ # Recommended ASGI server
62
+ uv add sse-starlette[uvicorn,granian,daphne]
63
+ ```
64
+
65
+ ## Quick Start
66
+
67
+ ```python
68
+ import asyncio
69
+ from starlette.applications import Starlette
70
+ from starlette.routing import Route
71
+ from sse_starlette import EventSourceResponse
72
+
73
+ async def generate_events():
74
+ for i in range(10):
75
+ yield {"data": f"Event {i}"}
76
+ await asyncio.sleep(1)
77
+
78
+ async def sse_endpoint(request):
79
+ return EventSourceResponse(generate_events())
80
+
81
+ app = Starlette(routes=[Route("/events", sse_endpoint)])
82
+ ```
83
+
84
+ ## Core Features
85
+
86
+ - **Standards Compliant**: Full SSE specification implementation
87
+ - **Framework Integration**: Native Starlette and FastAPI support
88
+ - **Async/Await**: Built on modern Python async patterns
89
+ - **Connection Management**: Automatic client disconnect detection
90
+ - **Graceful Shutdown**: Proper cleanup on server termination with cooperative shutdown support
91
+ - **Thread Safety**: Context-local event management for multi-threaded applications
92
+ - **Multi-Loop Support**: Works correctly with multiple asyncio event loops
93
+
94
+ For a detailed look at the internal task coordination, shutdown detection, and cancellation
95
+ flows, see [ARCHITECTURE.md](ARCHITECTURE.md).
96
+
97
+ ## Key Components
98
+
99
+ ### EventSourceResponse
100
+
101
+ The main response class that handles SSE streaming:
102
+
103
+ ```python
104
+ from sse_starlette import EventSourceResponse
105
+
106
+ # Basic usage
107
+ async def stream_data():
108
+ for item in data:
109
+ yield {"data": item, "event": "update", "id": str(item.id)}
110
+
111
+ return EventSourceResponse(stream_data())
112
+ ```
113
+
114
+ ### ServerSentEvent
115
+
116
+ For structured event creation:
117
+
118
+ ```python
119
+ from sse_starlette import ServerSentEvent
120
+
121
+ event = ServerSentEvent(
122
+ data="Custom message",
123
+ event="notification",
124
+ id="msg-123",
125
+ retry=5000
126
+ )
127
+ ```
128
+
129
+ ### JSONServerSentEvent
130
+
131
+ For an easy way to send json data as SSE events:
132
+
133
+ ```python
134
+ from sse_starlette import JSONServerSentEvent
135
+
136
+ event = JSONServerSentEvent(
137
+ data={"field":"value"}, # Anything serializable with json.dumps
138
+ )
139
+ ```
140
+
141
+ ## Advanced Usage
142
+
143
+ ### Custom Ping Configuration
144
+
145
+ ```python
146
+ from sse_starlette import ServerSentEvent
147
+
148
+ def custom_ping():
149
+ return ServerSentEvent(comment="Custom ping message")
150
+
151
+ return EventSourceResponse(
152
+ generate_events(),
153
+ ping=10, # Ping every 10 seconds
154
+ ping_message_factory=custom_ping
155
+ )
156
+ ```
157
+
158
+ ### Multi-Threaded Usage
159
+
160
+ sse-starlette now supports usage in multi-threaded applications and with multiple asyncio event loops:
161
+
162
+ ```python
163
+ import threading
164
+ import asyncio
165
+ from sse_starlette import EventSourceResponse
166
+
167
+ def run_sse_in_thread():
168
+ """SSE streaming works correctly in separate threads"""
169
+ loop = asyncio.new_event_loop()
170
+ asyncio.set_event_loop(loop)
171
+
172
+ async def thread_events():
173
+ for i in range(5):
174
+ yield {"data": f"Thread event {i}"}
175
+ await asyncio.sleep(1)
176
+
177
+ # This works without "Event bound to different loop" errors
178
+ response = EventSourceResponse(thread_events())
179
+ loop.close()
180
+
181
+ # Start SSE in multiple threads
182
+ for i in range(3):
183
+ thread = threading.Thread(target=run_sse_in_thread)
184
+ thread.start()
185
+ ```
186
+
187
+ ### Database Streaming (Thread-Safe)
188
+
189
+ ```python
190
+ async def stream_database_results(request):
191
+ # CORRECT: Create session within generator context
192
+ async with AsyncSession() as session:
193
+ results = await session.execute(select(User))
194
+ for row in results:
195
+ if await request.is_disconnected():
196
+ break
197
+ yield {"data": row.name, "id": str(row.id)}
198
+
199
+ return EventSourceResponse(stream_database_results(request))
200
+ ```
201
+
202
+ ### Error Handling and Timeouts
203
+
204
+ ```python
205
+ async def robust_stream(request):
206
+ try:
207
+ for i in range(100):
208
+ if await request.is_disconnected():
209
+ break
210
+ yield {"data": f"Item {i}"}
211
+ await asyncio.sleep(0.5)
212
+ except asyncio.CancelledError:
213
+ # Client disconnected - perform cleanup
214
+ raise
215
+
216
+ return EventSourceResponse(
217
+ robust_stream(request),
218
+ send_timeout=30, # Timeout hanging sends
219
+ headers={"Cache-Control": "no-cache"}
220
+ )
221
+ ```
222
+
223
+ ### Memory Channels Alternative
224
+
225
+ For complex data flows, use memory channels instead of generators:
226
+
227
+ ```python
228
+ import anyio
229
+ from functools import partial
230
+
231
+ async def data_producer(send_channel):
232
+ async with send_channel:
233
+ for i in range(10):
234
+ await send_channel.send({"data": f"Item {i}"})
235
+ await anyio.sleep(1)
236
+
237
+ async def channel_endpoint(request):
238
+ send_channel, receive_channel = anyio.create_memory_object_stream(10)
239
+
240
+ return EventSourceResponse(
241
+ receive_channel,
242
+ data_sender_callable=partial(data_producer, send_channel)
243
+ )
244
+ ```
245
+
246
+ ### Cooperative Shutdown
247
+
248
+ By default, generators receive `CancelledError` immediately when the server shuts down. With
249
+ cooperative shutdown, generators can detect the shutdown signal, send farewell events to clients,
250
+ and exit gracefully within a configurable grace period.
251
+
252
+ ```python
253
+ import anyio
254
+ from sse_starlette import EventSourceResponse
255
+
256
+ async def graceful_stream(request):
257
+ shutdown_event = anyio.Event()
258
+
259
+ async def generate():
260
+ try:
261
+ while not shutdown_event.is_set():
262
+ yield {"data": "tick"}
263
+ # Check for shutdown between iterations
264
+ with anyio.move_on_after(1.0):
265
+ await shutdown_event.wait()
266
+ # Shutdown detected — send farewell event
267
+ yield {"event": "shutdown", "data": "Server is shutting down"}
268
+ except anyio.get_cancelled_exc_class():
269
+ # Grace period expired — generator force-cancelled
270
+ raise
271
+
272
+ return EventSourceResponse(
273
+ generate(),
274
+ shutdown_event=shutdown_event, # Library sets this on shutdown
275
+ shutdown_grace_period=5.0, # Seconds to wait before force-cancel
276
+ )
277
+ ```
278
+
279
+ **How it works:**
280
+
281
+ 1. On server shutdown, the library sets your `shutdown_event`
282
+ 2. Your generator sees the event and can yield final events
283
+ 3. If the generator exits within `shutdown_grace_period`, shutdown is clean (no `CancelledError`)
284
+ 4. If the generator doesn't exit in time, it is force-cancelled as before
285
+
286
+ **Important:** `shutdown_grace_period` should be less than your ASGI server's graceful shutdown
287
+ timeout (e.g. uvicorn's `--timeout-graceful-shutdown`), otherwise the process is killed before the
288
+ grace period expires.
289
+
290
+ Without `shutdown_event` (the default), behavior is identical to previous versions: immediate
291
+ cancellation on server shutdown.
292
+
293
+ ## Configuration Options
294
+
295
+ ### EventSourceResponse Parameters
296
+
297
+ | Parameter | Type | Default | Description |
298
+ |-----------|------|---------|-------------|
299
+ | `content` | `ContentStream` | Required | Async generator or iterable |
300
+ | `ping` | `int` | 15 | Ping interval in seconds (0 to disable) |
301
+ | `sep` | `str` | `"\r\n"` | Line separator (`\r\n`, `\r`, `\n`) |
302
+ | `send_timeout` | `float` | `None` | Send operation timeout in seconds |
303
+ | `headers` | `dict` | `None` | Additional HTTP headers |
304
+ | `ping_message_factory` | `Callable` | `None` | Custom ping message creator |
305
+ | `shutdown_event` | `anyio.Event` | `None` | Event set by library on server shutdown |
306
+ | `shutdown_grace_period` | `float` | `0` | Seconds to wait after setting `shutdown_event` before force-cancel |
307
+
308
+ ### Client Disconnection
309
+
310
+ ```python
311
+ async def monitored_stream(request):
312
+ events_sent = 0
313
+ try:
314
+ while events_sent < 100:
315
+ if await request.is_disconnected():
316
+ print(f"Client disconnected after {events_sent} events")
317
+ break
318
+
319
+ yield {"data": f"Event {events_sent}"}
320
+ events_sent += 1
321
+ await asyncio.sleep(1)
322
+
323
+ except asyncio.CancelledError:
324
+ print("Stream cancelled")
325
+ raise
326
+ ```
327
+
328
+ ## Testing
329
+
330
+ sse-starlette includes now comprehensive test isolation without manual setup. The library automatically handles event loop contexts, eliminating the need for manual state resets:
331
+
332
+ ```python
333
+ # this is deprecated and not needed since version 3.0.0
334
+ import pytest
335
+ from sse_starlette import EventSourceResponse
336
+
337
+ @pytest.fixture
338
+ def reset_sse_app_status():
339
+ AppStatus.should_exit_event = None
340
+ yield
341
+ AppStatus.should_exit_event = None
342
+ ```
343
+
344
+ ## Production Considerations
345
+
346
+ ### Performance Limits
347
+
348
+ - **Memory**: Each connection maintains a buffer. Monitor memory usage.
349
+ - **Connections**: Limited by system file descriptors and application design.
350
+ - **Network**: High-frequency events can saturate bandwidth.
351
+
352
+ ### Error Recovery
353
+
354
+ Implement client-side reconnection logic:
355
+
356
+ ```javascript
357
+ function createEventSource(url) {
358
+ const eventSource = new EventSource(url);
359
+
360
+ eventSource.onerror = function() {
361
+ setTimeout(() => {
362
+ createEventSource(url); // Reconnect after delay
363
+ }, 5000);
364
+ };
365
+
366
+ return eventSource;
367
+ }
368
+ ```
369
+
370
+ ## Learning Resources
371
+
372
+ ### Examples Directory
373
+
374
+ The `examples/` directory contains production-ready patterns:
375
+
376
+ - **`01_basic_sse.py`**: Fundamental SSE concepts
377
+ - **`02_message_broadcasting.py`**: Multi-client message distribution
378
+ - **`03_database_streaming.py`**: Thread-safe database integration
379
+ - **`04_advanced_features.py`**: Custom protocols and error handling
380
+
381
+ ### Demonstrations Directory
382
+
383
+ The `examples/demonstrations/` directory provides educational scenarios:
384
+
385
+ **Basic Patterns** (`basic_patterns/`):
386
+ - Client disconnect detection and cleanup
387
+ - Graceful server shutdown behavior
388
+
389
+ **Production Scenarios** (`production_scenarios/`):
390
+ - Load testing with concurrent clients
391
+ - Network interruption handling
392
+
393
+ **Advanced Patterns** (`advanced_patterns/`):
394
+ - Memory channels vs generators
395
+ - Error recovery and circuit breakers
396
+ - Custom protocol development
397
+
398
+ Run any demonstration:
399
+ ```bash
400
+ python examples/demonstrations/basic_patterns/client_disconnect.py
401
+ python examples/demonstrations/production_scenarios/load_simulations.py
402
+ python examples/demonstrations/advanced_patterns/error_recovery.py
403
+ ```
404
+
405
+ ## Troubleshooting
406
+
407
+ ### Common Issues
408
+
409
+ **Database session errors with async generators**
410
+ - Create database sessions inside generators, not as dependencies
411
+
412
+ **Hanging connections after client disconnect**
413
+ - Always check `await request.is_disconnected()` in loops
414
+ - Use `send_timeout` parameter to detect dead connections
415
+
416
+ If you are using Postman, please see: https://github.com/sysid/sse-starlette/issues/47#issuecomment-1445953826
417
+
418
+ ### Performance Optimization
419
+
420
+ ```python
421
+ # Connection limits
422
+ class ConnectionLimiter:
423
+ def __init__(self, max_connections=100):
424
+ self.semaphore = asyncio.Semaphore(max_connections)
425
+
426
+ async def limited_endpoint(self, request):
427
+ async with self.semaphore:
428
+ return EventSourceResponse(generate_events())
429
+ ```
430
+
431
+ ## Network-Level Gotchas
432
+
433
+ Network infrastructure components can buffer SSE streams, breaking real-time delivery. Here are the most common issues and solutions:
434
+
435
+ ### Reverse Proxy Buffering (Nginx/Apache)
436
+
437
+ **Problem**: Nginx buffers responses by default, delaying SSE events until ~16KB accumulates.
438
+
439
+ **Solution**: Add the `X-Accel-Buffering: no` header.
440
+
441
+ **Nginx Configuration** (if you can't modify app headers):
442
+ ```nginx
443
+ location /events {
444
+ proxy_pass http://localhost:8000;
445
+ proxy_http_version 1.1;
446
+ proxy_set_header Connection '';
447
+ proxy_buffering off; # Disable for this location
448
+ chunked_transfer_encoding off;
449
+ }
450
+ ```
451
+
452
+ ### CDN Issues
453
+
454
+ **Cloudflare**: Buffers ~100KB before flushing to clients, breaking real-time delivery.
455
+ **Akamai**: Edge servers buffer by default.
456
+
457
+ ### Load Balancer Problems
458
+
459
+ **HAProxy**: Timeout settings must exceed heartbeat frequency.
460
+ ```haproxy
461
+ # Ensure timeouts > ping interval
462
+ timeout client 60s # If ping every 45s
463
+ timeout server 60s
464
+ ```
465
+
466
+ **F5 Load Balancers**: Buffer responses by default.
467
+
468
+ ## Contributing
469
+
470
+ See examples and demonstrations for implementation patterns. Run tests with:
471
+
472
+ ```bash
473
+ make test-unit # Unit tests only (default dev install)
474
+ make test # Unit + docker integration tests
475
+ make test-experimentation # Optional experimentation tests (multi-consumer load tests)
476
+ # Requires the `experimentation` dependency group:
477
+ # uv sync --group experimentation
478
+ ```
479
+
480
+ The `experimentation` group is opt-in (kept out of the default `dev` install) to keep the
481
+ contributor footprint small. See `tests/experimentation/` for the tests it enables.
482
+
483
+ <!-- Badges -->
484
+ [pypi-image]: https://badge.fury.io/py/sse-starlette.svg
485
+ [pypi-url]: https://pypi.org/project/sse-starlette/
486
+ [build-image]: https://github.com/sysid/sse-starlette/actions/workflows/build.yml/badge.svg
487
+ [build-url]: https://github.com/sysid/sse-starlette/actions/workflows/build.yml
488
+ [coverage-image]: https://codecov.io/gh/sysid/sse-starlette/branch/master/graph/badge.svg
489
+ <!--[coverage-url]: https://codecov.io/gh/sysid/sse-starlette-->
490
+
.cache/pip/http-v2/4/3/4/e/4/434e4f9063597b6ecac7104d4d3128df26a47ab65e2f09d0f5f7b59d ADDED
Binary file (1.29 kB). View file
 
.cache/pip/http-v2/4/3/4/e/4/434e4f9063597b6ecac7104d4d3128df26a47ab65e2f09d0f5f7b59d.body ADDED
@@ -0,0 +1,408 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: typer
3
+ Version: 0.25.0
4
+ Summary: Typer, build great CLIs. Easy to code. Based on Python type hints.
5
+ Author-Email: =?utf-8?q?Sebasti=C3=A1n_Ram=C3=ADrez?= <tiangolo@gmail.com>
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Classifier: Intended Audience :: Information Technology
9
+ Classifier: Intended Audience :: System Administrators
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Classifier: Topic :: Software Development :: Libraries
16
+ Classifier: Topic :: Software Development
17
+ Classifier: Typing :: Typed
18
+ Classifier: Development Status :: 4 - Beta
19
+ Classifier: Intended Audience :: Developers
20
+ Classifier: Programming Language :: Python :: 3 :: Only
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
26
+ Project-URL: Homepage, https://github.com/fastapi/typer
27
+ Project-URL: Documentation, https://typer.tiangolo.com
28
+ Project-URL: Repository, https://github.com/fastapi/typer
29
+ Project-URL: Issues, https://github.com/fastapi/typer/issues
30
+ Project-URL: Changelog, https://typer.tiangolo.com/release-notes/
31
+ Requires-Python: >=3.10
32
+ Requires-Dist: click>=8.2.1
33
+ Requires-Dist: shellingham>=1.3.0
34
+ Requires-Dist: rich>=13.8.0
35
+ Requires-Dist: annotated-doc>=0.0.2
36
+ Description-Content-Type: text/markdown
37
+
38
+ <p align="center">
39
+ <a href="https://typer.tiangolo.com"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg#only-light" alt="Typer"></a>
40
+
41
+ </p>
42
+ <p align="center">
43
+ <em>Typer, build great CLIs. Easy to code. Based on Python type hints.</em>
44
+ </p>
45
+ <p align="center">
46
+ <a href="https://github.com/fastapi/typer/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
47
+ <img src="https://github.com/fastapi/typer/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Test">
48
+ </a>
49
+ <a href="https://github.com/fastapi/typer/actions?query=workflow%3APublish" target="_blank">
50
+ <img src="https://github.com/fastapi/typer/workflows/Publish/badge.svg" alt="Publish">
51
+ </a>
52
+ <a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/typer" target="_blank">
53
+ <img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/typer.svg" alt="Coverage">
54
+ <a href="https://pypi.org/project/typer" target="_blank">
55
+ <img src="https://img.shields.io/pypi/v/typer?color=%2334D058&label=pypi%20package" alt="Package version">
56
+ </a>
57
+ </p>
58
+
59
+ ---
60
+
61
+ **Documentation**: <a href="https://typer.tiangolo.com" target="_blank">https://typer.tiangolo.com</a>
62
+
63
+ **Source Code**: <a href="https://github.com/fastapi/typer" target="_blank">https://github.com/fastapi/typer</a>
64
+
65
+ ---
66
+
67
+ Typer is a library for building <abbr title="command line interface, programs executed from a terminal">CLI</abbr> applications that users will **love using** and developers will **love creating**. Based on Python type hints.
68
+
69
+ It's also a command line tool to run scripts, automatically converting them to CLI applications.
70
+
71
+ The key features are:
72
+
73
+ * **Intuitive to write**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging. Designed to be easy to use and learn. Less time reading docs.
74
+ * **Easy to use**: It's easy to use for the final users. Automatic help, and automatic completion for all shells.
75
+ * **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
76
+ * **Start simple**: The simplest example adds only 2 lines of code to your app: **1 import, 1 function call**.
77
+ * **Grow large**: Grow in complexity as much as you want, create arbitrarily complex trees of commands and groups of subcommands, with options and arguments.
78
+ * **Run scripts**: Typer includes a `typer` command/program that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally.
79
+
80
+ ## FastAPI of CLIs
81
+
82
+ **Typer** is <a href="https://fastapi.tiangolo.com" class="external-link" target="_blank">FastAPI</a>'s little sibling, it's the FastAPI of CLIs.
83
+
84
+ ## Installation
85
+
86
+ Create and activate a <a href="https://typer.tiangolo.com/virtual-environments/" class="external-link" target="_blank">virtual environment</a> and then install **Typer**:
87
+
88
+ <div class="termy">
89
+
90
+ ```console
91
+ $ pip install typer
92
+ ---> 100%
93
+ Successfully installed typer rich shellingham
94
+ ```
95
+
96
+ </div>
97
+
98
+ ## Example
99
+
100
+ ### The absolute minimum
101
+
102
+ * Create a file `main.py` with:
103
+
104
+ ```Python
105
+ def main(name: str):
106
+ print(f"Hello {name}")
107
+ ```
108
+
109
+ This script doesn't even use Typer internally. But you can use the `typer` command to run it as a CLI application.
110
+
111
+ ### Run it
112
+
113
+ Run your application with the `typer` command:
114
+
115
+ <div class="termy">
116
+
117
+ ```console
118
+ // Run your application
119
+ $ typer main.py run
120
+
121
+ // You get a nice error, you are missing NAME
122
+ Usage: typer [PATH_OR_MODULE] run [OPTIONS] NAME
123
+ Try 'typer [PATH_OR_MODULE] run --help' for help.
124
+ ╭─ Error ───────────────────────────────────────────╮
125
+ │ Missing argument 'NAME'. │
126
+ ╰───────────────────────────────────────────────────╯
127
+
128
+
129
+ // You get a --help for free
130
+ $ typer main.py run --help
131
+
132
+ Usage: typer [PATH_OR_MODULE] run [OPTIONS] NAME
133
+
134
+ Run the provided Typer app.
135
+
136
+ ╭─ Arguments ───────────────────────────────────────╮
137
+ │ * name TEXT [default: None] [required] |
138
+ ╰───────────────────────────────────────────────────╯
139
+ ╭─ Options ─────────────────────────────────────────╮
140
+ │ --help Show this message and exit. │
141
+ ╰───────────────────────────────────────────────────╯
142
+
143
+ // Now pass the NAME argument
144
+ $ typer main.py run Camila
145
+
146
+ Hello Camila
147
+
148
+ // It works! 🎉
149
+ ```
150
+
151
+ </div>
152
+
153
+ This is the simplest use case, not even using Typer internally, but it can already be quite useful for simple scripts.
154
+
155
+ **Note**: auto-completion works when you create a Python package and run it with `--install-completion` or when you use the `typer` command.
156
+
157
+ ## Use Typer in your code
158
+
159
+ Now let's start using Typer in your own code, update `main.py` with:
160
+
161
+ ```Python
162
+ import typer
163
+
164
+
165
+ def main(name: str):
166
+ print(f"Hello {name}")
167
+
168
+
169
+ if __name__ == "__main__":
170
+ typer.run(main)
171
+ ```
172
+
173
+ Now you could run it with Python directly:
174
+
175
+ <div class="termy">
176
+
177
+ ```console
178
+ // Run your application
179
+ $ python main.py
180
+
181
+ // You get a nice error, you are missing NAME
182
+ Usage: main.py [OPTIONS] NAME
183
+ Try 'main.py --help' for help.
184
+ ╭─ Error ───────────────────────────────────────────╮
185
+ │ Missing argument 'NAME'. │
186
+ ╰───────────────────────────────────────────────────╯
187
+
188
+
189
+ // You get a --help for free
190
+ $ python main.py --help
191
+
192
+ Usage: main.py [OPTIONS] NAME
193
+
194
+ ╭─ Arguments ───────────────────────────────────────╮
195
+ │ * name TEXT [default: None] [required] |
196
+ ╰───────────────────────────────────────────────────╯
197
+ ╭─ Options ─────────────────────────────────────────╮
198
+ │ --help Show this message and exit. │
199
+ ╰───────────────────────────────────────────────────╯
200
+
201
+ // Now pass the NAME argument
202
+ $ python main.py Camila
203
+
204
+ Hello Camila
205
+
206
+ // It works! 🎉
207
+ ```
208
+
209
+ </div>
210
+
211
+ **Note**: you can also call this same script with the `typer` command, but you don't need to.
212
+
213
+ ## Example upgrade
214
+
215
+ This was the simplest example possible.
216
+
217
+ Now let's see one a bit more complex.
218
+
219
+ ### An example with two subcommands
220
+
221
+ Modify the file `main.py`.
222
+
223
+ Create a `typer.Typer()` app, and create two subcommands with their parameters.
224
+
225
+ ```Python hl_lines="3 6 11 20"
226
+ import typer
227
+
228
+ app = typer.Typer()
229
+
230
+
231
+ @app.command()
232
+ def hello(name: str):
233
+ print(f"Hello {name}")
234
+
235
+
236
+ @app.command()
237
+ def goodbye(name: str, formal: bool = False):
238
+ if formal:
239
+ print(f"Goodbye Ms. {name}. Have a good day.")
240
+ else:
241
+ print(f"Bye {name}!")
242
+
243
+
244
+ if __name__ == "__main__":
245
+ app()
246
+ ```
247
+
248
+ And that will:
249
+
250
+ * Explicitly create a `typer.Typer` app.
251
+ * The previous `typer.run` actually creates one implicitly for you.
252
+ * Add two subcommands with `@app.command()`.
253
+ * Execute the `app()` itself, as if it was a function (instead of `typer.run`).
254
+
255
+ ### Run the upgraded example
256
+
257
+ Check the new help:
258
+
259
+ <div class="termy">
260
+
261
+ ```console
262
+ $ python main.py --help
263
+
264
+ Usage: main.py [OPTIONS] COMMAND [ARGS]...
265
+
266
+ ╭─ Options ─────────────────────────────────────────╮
267
+ │ --install-completion Install completion │
268
+ │ for the current │
269
+ │ shell. │
270
+ │ --show-completion Show completion for │
271
+ │ the current shell, │
272
+ │ to copy it or │
273
+ │ customize the │
274
+ │ installation. │
275
+ │ --help Show this message │
276
+ │ and exit. │
277
+ ╰───────────────────────────────────────────────────╯
278
+ ╭─ Commands ────────────────────────────────────────╮
279
+ │ goodbye │
280
+ │ hello │
281
+ ╰───────────────────────────────────────────────────╯
282
+
283
+ // When you create a package you get ✨ auto-completion ✨ for free, installed with --install-completion
284
+
285
+ // You have 2 subcommands (the 2 functions): goodbye and hello
286
+ ```
287
+
288
+ </div>
289
+
290
+ Now check the help for the `hello` command:
291
+
292
+ <div class="termy">
293
+
294
+ ```console
295
+ $ python main.py hello --help
296
+
297
+ Usage: main.py hello [OPTIONS] NAME
298
+
299
+ ╭─ Arguments ───────────────────────────────────────╮
300
+ │ * name TEXT [default: None] [required] │
301
+ ╰───────────────────────────────────────────────────╯
302
+ ╭─ Options ─────────────────────────────────────────╮
303
+ │ --help Show this message and exit. │
304
+ ╰───────────────────────────────────────────────────╯
305
+ ```
306
+
307
+ </div>
308
+
309
+ And now check the help for the `goodbye` command:
310
+
311
+ <div class="termy">
312
+
313
+ ```console
314
+ $ python main.py goodbye --help
315
+
316
+ Usage: main.py goodbye [OPTIONS] NAME
317
+
318
+ ╭─ Arguments ───────────────────────────────────────╮
319
+ │ * name TEXT [default: None] [required] │
320
+ ╰───────────────────────────────────────────────────╯
321
+ ╭─ Options ─────────────────────────────────────────╮
322
+ │ --formal --no-formal [default: no-formal] │
323
+ │ --help Show this message │
324
+ │ and exit. │
325
+ ╰───────────────────────────────────────────────────╯
326
+
327
+ // Automatic --formal and --no-formal for the bool option 🎉
328
+ ```
329
+
330
+ </div>
331
+
332
+ Now you can try out the new command line application:
333
+
334
+ <div class="termy">
335
+
336
+ ```console
337
+ // Use it with the hello command
338
+
339
+ $ python main.py hello Camila
340
+
341
+ Hello Camila
342
+
343
+ // And with the goodbye command
344
+
345
+ $ python main.py goodbye Camila
346
+
347
+ Bye Camila!
348
+
349
+ // And with --formal
350
+
351
+ $ python main.py goodbye --formal Camila
352
+
353
+ Goodbye Ms. Camila. Have a good day.
354
+ ```
355
+
356
+ </div>
357
+
358
+ **Note**: If your app only has one command, by default the command name is **omitted** in usage: `python main.py Camila`. However, when there are multiple commands, you must **explicitly include the command name**: `python main.py hello Camila`. See [One or Multiple Commands](https://typer.tiangolo.com/tutorial/commands/one-or-multiple/) for more details.
359
+
360
+ ### Recap
361
+
362
+ In summary, you declare **once** the types of parameters (*CLI arguments* and *CLI options*) as function parameters.
363
+
364
+ You do that with standard modern Python types.
365
+
366
+ You don't have to learn a new syntax, the methods or classes of a specific library, etc.
367
+
368
+ Just standard **Python**.
369
+
370
+ For example, for an `int`:
371
+
372
+ ```Python
373
+ total: int
374
+ ```
375
+
376
+ or for a `bool` flag:
377
+
378
+ ```Python
379
+ force: bool
380
+ ```
381
+
382
+ And similarly for **files**, **paths**, **enums** (choices), etc. And there are tools to create **groups of subcommands**, add metadata, extra **validation**, etc.
383
+
384
+ **You get**: great editor support, including **completion** and **type checks** everywhere.
385
+
386
+ **Your users get**: automatic **`--help`**, **auto-completion** in their terminal (Bash, Zsh, Fish, PowerShell) when they install your package or when using the `typer` command.
387
+
388
+ For a more complete example including more features, see the <a href="https://typer.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
389
+
390
+ ## Dependencies
391
+
392
+ **Typer** stands on the shoulders of giants. It has three required dependencies:
393
+
394
+ * <a href="https://click.palletsprojects.com/" class="external-link" target="_blank">Click</a>: a popular tool for building CLIs in Python. Typer is based on it.
395
+ * <a href="https://rich.readthedocs.io/en/stable/index.html" class="external-link" target="_blank"><code>rich</code></a>: to show nicely formatted errors automatically.
396
+ * <a href="https://github.com/sarugaku/shellingham" class="external-link" target="_blank"><code>shellingham</code></a>: to automatically detect the current shell when installing completion.
397
+
398
+ ### `typer-slim`
399
+
400
+ There used to be a slimmed-down version of Typer called `typer-slim`, which didn't include the dependencies `rich` and `shellingham`, nor the `typer` command.
401
+
402
+ However, since version 0.22.0, we have stopped supporting this, and `typer-slim` now simply installs (all of) Typer.
403
+
404
+ If you want to disable Rich globally, you can set an environmental variable `TYPER_USE_RICH` to `False` or `0`.
405
+
406
+ ## License
407
+
408
+ This project is licensed under the terms of the MIT license.
.cache/pip/http-v2/4/3/6/8/4/436846b847c9c90a13539a872e2084e3f9ca23eb93b4b1cc44b55964 ADDED
Binary file (1.27 kB). View file
 
.cache/pip/http-v2/4/3/6/8/4/436846b847c9c90a13539a872e2084e3f9ca23eb93b4b1cc44b55964.body ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: packaging
3
+ Version: 26.2
4
+ Summary: Core utilities for Python packages
5
+ Author-email: Donald Stufft <donald@stufft.io>
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/x-rst
8
+ License-Expression: Apache-2.0 OR BSD-2-Clause
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Programming Language :: Python :: Implementation :: CPython
22
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
23
+ Classifier: Programming Language :: Python :: Free Threading :: 4 - Resilient
24
+ Classifier: Typing :: Typed
25
+ License-File: LICENSE
26
+ License-File: LICENSE.APACHE
27
+ License-File: LICENSE.BSD
28
+ Project-URL: Documentation, https://packaging.pypa.io/
29
+ Project-URL: Source, https://github.com/pypa/packaging
30
+
31
+ packaging
32
+ =========
33
+
34
+ .. start-intro
35
+
36
+ Reusable core utilities for various Python Packaging
37
+ `interoperability specifications <https://packaging.python.org/specifications/>`_.
38
+
39
+ This library provides utilities that implement the interoperability
40
+ specifications which have clearly one correct behaviour (eg: :pep:`440`)
41
+ or benefit greatly from having a single shared implementation (eg: :pep:`425`).
42
+
43
+ .. end-intro
44
+
45
+ The ``packaging`` project includes the following: version handling, specifiers,
46
+ markers, requirements, tags, metadata, lockfiles, utilities.
47
+
48
+ Documentation
49
+ -------------
50
+
51
+ The `documentation`_ provides information and the API for the following:
52
+
53
+ - Version Handling
54
+ - Specifiers
55
+ - Markers
56
+ - Licenses
57
+ - Requirements
58
+ - Metadata
59
+ - Tags
60
+ - Lockfiles (pylock)
61
+ - Direct URL helpers
62
+ - Dependency groups
63
+ - Errors
64
+ - Utilities
65
+
66
+ Installation
67
+ ------------
68
+
69
+ Use ``pip`` to install these utilities::
70
+
71
+ pip install packaging
72
+
73
+ The ``packaging`` library uses calendar-based versioning (``YY.N``).
74
+
75
+ Discussion
76
+ ----------
77
+
78
+ If you run into bugs, you can file them in our `issue tracker`_.
79
+
80
+ You can also join discussions on `GitHub Discussions`_ to ask questions or get involved.
81
+
82
+ .. _`documentation`: https://packaging.pypa.io/
83
+ .. _`issue tracker`: https://github.com/pypa/packaging/issues
84
+ .. _`GitHub Discussions`: https://github.com/pypa/packaging/discussions
85
+
86
+
87
+ Code of Conduct
88
+ ---------------
89
+
90
+ Everyone interacting in the packaging project's codebases, issue trackers, chat
91
+ rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_.
92
+
93
+ .. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md
94
+
95
+ Contributing
96
+ ------------
97
+
98
+ The ``CONTRIBUTING.rst`` file outlines how to contribute to this project as
99
+ well as how to report a potential security issue. The documentation for this
100
+ project also covers information about `project development`_ and `security`_.
101
+
102
+ .. _`project development`: https://packaging.pypa.io/en/latest/development/
103
+ .. _`security`: https://packaging.pypa.io/en/latest/security/
104
+
105
+ Project History
106
+ ---------------
107
+
108
+ Please review the ``CHANGELOG.rst`` file or the `Changelog documentation`_ for
109
+ recent changes and project history.
110
+
111
+ .. _`Changelog documentation`: https://packaging.pypa.io/en/latest/changelog/
112
+
.cache/pip/http-v2/4/4/1/9/6/44196988557c6a112ae696d10605a07ed4576112a509edb0095e3b08 ADDED
Binary file (1.13 kB). View file
 
.cache/pip/http-v2/4/4/1/9/6/44196988557c6a112ae696d10605a07ed4576112a509edb0095e3b08.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:813d99f31275919c383aab17f0f455a04f5a429c261cc411b1e9a8f5e4aaaa05
3
+ size 47586063
.cache/pip/http-v2/4/4/6/c/5/446c514b42f8098e88d951919b55761fcef1b141bd548733adaddda2 ADDED
Binary file (1.2 kB). View file
 
.cache/pip/http-v2/4/4/6/c/5/446c514b42f8098e88d951919b55761fcef1b141bd548733adaddda2.body ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:27f61d13a86c3c1648dec666dd5a64f79772dd6a84b446f11866601ecab24f6f
3
+ size 490586
.cache/pip/http-v2/4/4/a/d/5/44ad51ab4fe732177892254938ca19df59a19add805fe17b3b22c658 ADDED
Binary file (1.19 kB). View file
 
.cache/pip/http-v2/4/4/a/d/5/44ad51ab4fe732177892254938ca19df59a19add805fe17b3b22c658.body ADDED
@@ -0,0 +1,1595 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: tqdm
3
+ Version: 4.67.3
4
+ Summary: Fast, Extensible Progress Meter
5
+ Maintainer-email: tqdm developers <devs@tqdm.ml>
6
+ License: MPL-2.0 AND MIT
7
+ Project-URL: homepage, https://tqdm.github.io
8
+ Project-URL: repository, https://github.com/tqdm/tqdm
9
+ Project-URL: changelog, https://tqdm.github.io/releases
10
+ Project-URL: wiki, https://github.com/tqdm/tqdm/wiki
11
+ Keywords: progressbar,progressmeter,progress,bar,meter,rate,eta,console,terminal,time
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Environment :: Console
14
+ Classifier: Environment :: MacOS X
15
+ Classifier: Environment :: Other Environment
16
+ Classifier: Environment :: Win32 (MS Windows)
17
+ Classifier: Environment :: X11 Applications
18
+ Classifier: Framework :: IPython
19
+ Classifier: Framework :: Jupyter
20
+ Classifier: Intended Audience :: Developers
21
+ Classifier: Intended Audience :: Education
22
+ Classifier: Intended Audience :: End Users/Desktop
23
+ Classifier: Intended Audience :: Other Audience
24
+ Classifier: Intended Audience :: System Administrators
25
+ Classifier: Operating System :: MacOS
26
+ Classifier: Operating System :: MacOS :: MacOS X
27
+ Classifier: Operating System :: Microsoft
28
+ Classifier: Operating System :: Microsoft :: MS-DOS
29
+ Classifier: Operating System :: Microsoft :: Windows
30
+ Classifier: Operating System :: POSIX
31
+ Classifier: Operating System :: POSIX :: BSD
32
+ Classifier: Operating System :: POSIX :: BSD :: FreeBSD
33
+ Classifier: Operating System :: POSIX :: Linux
34
+ Classifier: Operating System :: POSIX :: SunOS/Solaris
35
+ Classifier: Operating System :: Unix
36
+ Classifier: Programming Language :: Python
37
+ Classifier: Programming Language :: Python :: 3
38
+ Classifier: Programming Language :: Python :: 3.7
39
+ Classifier: Programming Language :: Python :: 3.8
40
+ Classifier: Programming Language :: Python :: 3.9
41
+ Classifier: Programming Language :: Python :: 3.10
42
+ Classifier: Programming Language :: Python :: 3.11
43
+ Classifier: Programming Language :: Python :: 3.12
44
+ Classifier: Programming Language :: Python :: 3.13
45
+ Classifier: Programming Language :: Python :: 3 :: Only
46
+ Classifier: Programming Language :: Python :: Implementation
47
+ Classifier: Programming Language :: Python :: Implementation :: IronPython
48
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
49
+ Classifier: Programming Language :: Unix Shell
50
+ Classifier: Topic :: Desktop Environment
51
+ Classifier: Topic :: Education :: Computer Aided Instruction (CAI)
52
+ Classifier: Topic :: Education :: Testing
53
+ Classifier: Topic :: Office/Business
54
+ Classifier: Topic :: Other/Nonlisted Topic
55
+ Classifier: Topic :: Software Development :: Build Tools
56
+ Classifier: Topic :: Software Development :: Libraries
57
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
58
+ Classifier: Topic :: Software Development :: Pre-processors
59
+ Classifier: Topic :: Software Development :: User Interfaces
60
+ Classifier: Topic :: System :: Installation/Setup
61
+ Classifier: Topic :: System :: Logging
62
+ Classifier: Topic :: System :: Monitoring
63
+ Classifier: Topic :: System :: Shells
64
+ Classifier: Topic :: Terminals
65
+ Classifier: Topic :: Utilities
66
+ Requires-Python: >=3.7
67
+ Description-Content-Type: text/x-rst
68
+ License-File: LICENCE
69
+ Requires-Dist: colorama; platform_system == "Windows"
70
+ Requires-Dist: importlib_metadata; python_version < "3.8"
71
+ Provides-Extra: dev
72
+ Requires-Dist: pytest>=6; extra == "dev"
73
+ Requires-Dist: pytest-cov; extra == "dev"
74
+ Requires-Dist: pytest-timeout; extra == "dev"
75
+ Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
76
+ Requires-Dist: nbval; extra == "dev"
77
+ Provides-Extra: discord
78
+ Requires-Dist: requests; extra == "discord"
79
+ Provides-Extra: slack
80
+ Requires-Dist: slack-sdk; extra == "slack"
81
+ Provides-Extra: telegram
82
+ Requires-Dist: requests; extra == "telegram"
83
+ Provides-Extra: notebook
84
+ Requires-Dist: ipywidgets>=6; extra == "notebook"
85
+ Dynamic: license-file
86
+
87
+ |Logo|
88
+
89
+ tqdm
90
+ ====
91
+
92
+ |Py-Versions| |Versions| |Conda-Forge-Status| |Docker| |Snapcraft|
93
+
94
+ |Build-Status| |Coverage-Status| |Branch-Coverage-Status| |Codacy-Grade| |Libraries-Rank| |PyPI-Downloads|
95
+
96
+ |LICENCE| |OpenHub-Status| |binder-demo| |awesome-python|
97
+
98
+ ``tqdm`` derives from the Arabic word *taqaddum* (تقدّم) which can mean "progress,"
99
+ and is an abbreviation for "I love you so much" in Spanish (*te quiero demasiado*).
100
+
101
+ Instantly make your loops show a smart progress meter - just wrap any
102
+ iterable with ``tqdm(iterable)``, and you're done!
103
+
104
+ .. code:: python
105
+
106
+ from tqdm import tqdm
107
+ for i in tqdm(range(10000)):
108
+ ...
109
+
110
+ ``76%|████████████████████████        | 7568/10000 [00:33<00:10, 229.00it/s]``
111
+
112
+ ``trange(N)`` can be also used as a convenient shortcut for
113
+ ``tqdm(range(N))``.
114
+
115
+ |Screenshot|
116
+ |Video| |Slides| |Merch|
117
+
118
+ It can also be executed as a module with pipes:
119
+
120
+ .. code:: sh
121
+
122
+ $ seq 9999999 | tqdm --bytes | wc -l
123
+ 75.2MB [00:00, 217MB/s]
124
+ 9999999
125
+
126
+ $ tar -zcf - docs/ | tqdm --bytes --total `du -sb docs/ | cut -f1` \
127
+ > backup.tgz
128
+ 32%|██████████▍ | 8.89G/27.9G [00:42<01:31, 223MB/s]
129
+
130
+ Overhead is low -- about 60ns per iteration (80ns with ``tqdm.gui``), and is
131
+ unit tested against performance regression.
132
+ By comparison, the well-established
133
+ `ProgressBar <https://github.com/niltonvolpato/python-progressbar>`__ has
134
+ an 800ns/iter overhead.
135
+
136
+ In addition to its low overhead, ``tqdm`` uses smart algorithms to predict
137
+ the remaining time and to skip unnecessary iteration displays, which allows
138
+ for a negligible overhead in most cases.
139
+
140
+ ``tqdm`` works on any platform
141
+ (Linux, Windows, Mac, FreeBSD, NetBSD, Solaris/SunOS),
142
+ in any console or in a GUI, and is also friendly with IPython/Jupyter notebooks.
143
+
144
+ ``tqdm`` does not require any dependencies (not even ``curses``!), just
145
+ Python and an environment supporting ``carriage return \r`` and
146
+ ``line feed \n`` control characters.
147
+
148
+ ------------------------------------------
149
+
150
+ .. contents:: Table of contents
151
+ :backlinks: top
152
+ :local:
153
+
154
+
155
+ Installation
156
+ ------------
157
+
158
+ Latest PyPI stable release
159
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
160
+
161
+ |Versions| |PyPI-Downloads| |Libraries-Dependents|
162
+
163
+ .. code:: sh
164
+
165
+ pip install tqdm
166
+
167
+ Latest development release on GitHub
168
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
169
+
170
+ |GitHub-Status| |GitHub-Stars| |GitHub-Commits| |GitHub-Forks| |GitHub-Updated|
171
+
172
+ Pull and install pre-release ``devel`` branch:
173
+
174
+ .. code:: sh
175
+
176
+ pip install "git+https://github.com/tqdm/tqdm.git@devel#egg=tqdm"
177
+
178
+ Latest Conda release
179
+ ~~~~~~~~~~~~~~~~~~~~
180
+
181
+ |Conda-Forge-Status|
182
+
183
+ .. code:: sh
184
+
185
+ conda install -c conda-forge tqdm
186
+
187
+ Latest Snapcraft release
188
+ ~~~~~~~~~~~~~~~~~~~~~~~~
189
+
190
+ |Snapcraft|
191
+
192
+ There are 3 channels to choose from:
193
+
194
+ .. code:: sh
195
+
196
+ snap install tqdm # implies --stable, i.e. latest tagged release
197
+ snap install tqdm --candidate # master branch
198
+ snap install tqdm --edge # devel branch
199
+
200
+ Note that ``snap`` binaries are purely for CLI use (not ``import``-able), and
201
+ automatically set up ``bash`` tab-completion.
202
+
203
+ Latest Docker release
204
+ ~~~~~~~~~~~~~~~~~~~~~
205
+
206
+ |Docker|
207
+
208
+ .. code:: sh
209
+
210
+ docker pull tqdm/tqdm
211
+ docker run -i --rm tqdm/tqdm --help
212
+
213
+ Other
214
+ ~~~~~
215
+
216
+ There are other (unofficial) places where ``tqdm`` may be downloaded, particularly for CLI use:
217
+
218
+ |Repology|
219
+
220
+ .. |Repology| image:: https://repology.org/badge/tiny-repos/python:tqdm.svg
221
+ :target: https://repology.org/project/python:tqdm/versions
222
+
223
+ Changelog
224
+ ---------
225
+
226
+ The list of all changes is available either on GitHub's Releases:
227
+ |GitHub-Status|, on the
228
+ `wiki <https://github.com/tqdm/tqdm/wiki/Releases>`__, or on the
229
+ `website <https://tqdm.github.io/releases>`__.
230
+
231
+
232
+ Usage
233
+ -----
234
+
235
+ ``tqdm`` is very versatile and can be used in a number of ways.
236
+ The three main ones are given below.
237
+
238
+ Iterable-based
239
+ ~~~~~~~~~~~~~~
240
+
241
+ Wrap ``tqdm()`` around any iterable:
242
+
243
+ .. code:: python
244
+
245
+ from tqdm import tqdm
246
+ from time import sleep
247
+
248
+ text = ""
249
+ for char in tqdm(["a", "b", "c", "d"]):
250
+ sleep(0.25)
251
+ text = text + char
252
+
253
+ ``trange(i)`` is a special optimised instance of ``tqdm(range(i))``:
254
+
255
+ .. code:: python
256
+
257
+ from tqdm import trange
258
+
259
+ for i in trange(100):
260
+ sleep(0.01)
261
+
262
+ Instantiation outside of the loop allows for manual control over ``tqdm()``:
263
+
264
+ .. code:: python
265
+
266
+ pbar = tqdm(["a", "b", "c", "d"])
267
+ for char in pbar:
268
+ sleep(0.25)
269
+ pbar.set_description("Processing %s" % char)
270
+
271
+ Manual
272
+ ~~~~~~
273
+
274
+ Manual control of ``tqdm()`` updates using a ``with`` statement:
275
+
276
+ .. code:: python
277
+
278
+ with tqdm(total=100) as pbar:
279
+ for i in range(10):
280
+ sleep(0.1)
281
+ pbar.update(10)
282
+
283
+ If the optional variable ``total`` (or an iterable with ``len()``) is
284
+ provided, predictive stats are displayed.
285
+
286
+ ``with`` is also optional (you can just assign ``tqdm()`` to a variable,
287
+ but in this case don't forget to ``del`` or ``close()`` at the end:
288
+
289
+ .. code:: python
290
+
291
+ pbar = tqdm(total=100)
292
+ for i in range(10):
293
+ sleep(0.1)
294
+ pbar.update(10)
295
+ pbar.close()
296
+
297
+ Module
298
+ ~~~~~~
299
+
300
+ Perhaps the most wonderful use of ``tqdm`` is in a script or on the command
301
+ line. Simply inserting ``tqdm`` (or ``python -m tqdm``) between pipes will pass
302
+ through all ``stdin`` to ``stdout`` while printing progress to ``stderr``.
303
+
304
+ The example below demonstrate counting the number of lines in all Python files
305
+ in the current directory, with timing information included.
306
+
307
+ .. code:: sh
308
+
309
+ $ time find . -name '*.py' -type f -exec cat \{} \; | wc -l
310
+ 857365
311
+
312
+ real 0m3.458s
313
+ user 0m0.274s
314
+ sys 0m3.325s
315
+
316
+ $ time find . -name '*.py' -type f -exec cat \{} \; | tqdm | wc -l
317
+ 857366it [00:03, 246471.31it/s]
318
+ 857365
319
+
320
+ real 0m3.585s
321
+ user 0m0.862s
322
+ sys 0m3.358s
323
+
324
+ Note that the usual arguments for ``tqdm`` can also be specified.
325
+
326
+ .. code:: sh
327
+
328
+ $ find . -name '*.py' -type f -exec cat \{} \; |
329
+ tqdm --unit loc --unit_scale --total 857366 >> /dev/null
330
+ 100%|█████████████████████████████████| 857K/857K [00:04<00:00, 246Kloc/s]
331
+
332
+ Backing up a large directory?
333
+
334
+ .. code:: sh
335
+
336
+ $ tar -zcf - docs/ | tqdm --bytes --total `du -sb docs/ | cut -f1` \
337
+ > backup.tgz
338
+ 44%|██████████████▊ | 153M/352M [00:14<00:18, 11.0MB/s]
339
+
340
+ This can be beautified further:
341
+
342
+ .. code:: sh
343
+
344
+ $ BYTES=$(du -sb docs/ | cut -f1)
345
+ $ tar -cf - docs/ \
346
+ | tqdm --bytes --total "$BYTES" --desc Processing | gzip \
347
+ | tqdm --bytes --total "$BYTES" --desc Compressed --position 1 \
348
+ > ~/backup.tgz
349
+ Processing: 100%|██████████████████████| 352M/352M [00:14<00:00, 30.2MB/s]
350
+ Compressed: 42%|█████████▎ | 148M/352M [00:14<00:19, 10.9MB/s]
351
+
352
+ Or done on a file level using 7-zip:
353
+
354
+ .. code:: sh
355
+
356
+ $ 7z a -bd -r backup.7z docs/ | grep Compressing \
357
+ | tqdm --total $(find docs/ -type f | wc -l) --unit files \
358
+ | grep -v Compressing
359
+ 100%|██████████████████████████▉| 15327/15327 [01:00<00:00, 712.96files/s]
360
+
361
+ Pre-existing CLI programs already outputting basic progress information will
362
+ benefit from ``tqdm``'s ``--update`` and ``--update_to`` flags:
363
+
364
+ .. code:: sh
365
+
366
+ $ seq 3 0.1 5 | tqdm --total 5 --update_to --null
367
+ 100%|████████████████████████████████████| 5.0/5 [00:00<00:00, 9673.21it/s]
368
+ $ seq 10 | tqdm --update --null # 1 + 2 + ... + 10 = 55 iterations
369
+ 55it [00:00, 90006.52it/s]
370
+
371
+ FAQ and Known Issues
372
+ --------------------
373
+
374
+ |GitHub-Issues|
375
+
376
+ The most common issues relate to excessive output on multiple lines, instead
377
+ of a neat one-line progress bar.
378
+
379
+ - Consoles in general: require support for carriage return (``CR``, ``\r``).
380
+
381
+ * Some cloud logging consoles which don't support ``\r`` properly
382
+ (`cloudwatch <https://github.com/tqdm/tqdm/issues/966>`__,
383
+ `K8s <https://github.com/tqdm/tqdm/issues/1319>`__) may benefit from
384
+ ``export TQDM_POSITION=-1``.
385
+
386
+ - Nested progress bars:
387
+
388
+ * Consoles in general: require support for moving cursors up to the
389
+ previous line. For example,
390
+ `IDLE <https://github.com/tqdm/tqdm/issues/191#issuecomment-230168030>`__,
391
+ `ConEmu <https://github.com/tqdm/tqdm/issues/254>`__ and
392
+ `PyCharm <https://github.com/tqdm/tqdm/issues/203>`__ (also
393
+ `here <https://github.com/tqdm/tqdm/issues/208>`__,
394
+ `here <https://github.com/tqdm/tqdm/issues/307>`__, and
395
+ `here <https://github.com/tqdm/tqdm/issues/454#issuecomment-335416815>`__)
396
+ lack full support.
397
+ * Windows: additionally may require the Python module ``colorama``
398
+ to ensure nested bars stay within their respective lines.
399
+
400
+ - Unicode:
401
+
402
+ * Environments which report that they support unicode will have solid smooth
403
+ progressbars. The fallback is an ``ascii``-only bar.
404
+ * Windows consoles often only partially support unicode and thus
405
+ `often require explicit ascii=True <https://github.com/tqdm/tqdm/issues/454#issuecomment-335416815>`__
406
+ (also `here <https://github.com/tqdm/tqdm/issues/499>`__). This is due to
407
+ either normal-width unicode characters being incorrectly displayed as
408
+ "wide", or some unicode characters not rendering.
409
+
410
+ - Wrapping generators:
411
+
412
+ * Generator wrapper functions tend to hide the length of iterables.
413
+ ``tqdm`` does not.
414
+ * Replace ``tqdm(enumerate(...))`` with ``enumerate(tqdm(...))`` or
415
+ ``tqdm(enumerate(x), total=len(x), ...)``.
416
+ The same applies to ``numpy.ndenumerate``.
417
+ * Replace ``tqdm(zip(a, b))`` with ``zip(tqdm(a), b)`` or even
418
+ ``zip(tqdm(a), tqdm(b))``.
419
+ * The same applies to ``itertools``.
420
+ * Some useful convenience functions can be found under ``tqdm.contrib``.
421
+
422
+ - `No intermediate output in docker-compose <https://github.com/tqdm/tqdm/issues/771>`__:
423
+ use ``docker-compose run`` instead of ``docker-compose up`` and ``tty: true``.
424
+
425
+ - Overriding defaults via environment variables:
426
+ e.g. in CI/cloud jobs, ``export TQDM_MININTERVAL=5`` to avoid log spam.
427
+ This override logic is handled by the ``tqdm.utils.envwrap`` decorator
428
+ (useful independent of ``tqdm``).
429
+
430
+ If you come across any other difficulties, browse and file |GitHub-Issues|.
431
+
432
+ Documentation
433
+ -------------
434
+
435
+ |Py-Versions| |README-Hits| (Since 19 May 2016)
436
+
437
+ .. code:: python
438
+
439
+ class tqdm():
440
+ """
441
+ Decorate an iterable object, returning an iterator which acts exactly
442
+ like the original iterable, but prints a dynamically updating
443
+ progressbar every time a value is requested.
444
+ """
445
+
446
+ @envwrap("TQDM_") # override defaults via env vars
447
+ def __init__(self, iterable=None, desc=None, total=None, leave=True,
448
+ file=None, ncols=None, mininterval=0.1,
449
+ maxinterval=10.0, miniters=None, ascii=None, disable=False,
450
+ unit='it', unit_scale=False, dynamic_ncols=False,
451
+ smoothing=0.3, bar_format=None, initial=0, position=None,
452
+ postfix=None, unit_divisor=1000, write_bytes=False,
453
+ lock_args=None, nrows=None, colour=None, delay=0):
454
+
455
+ Parameters
456
+ ~~~~~~~~~~
457
+
458
+ * iterable : iterable, optional
459
+ Iterable to decorate with a progressbar.
460
+ Leave blank to manually manage the updates.
461
+ * desc : str, optional
462
+ Prefix for the progressbar.
463
+ * total : int or float, optional
464
+ The number of expected iterations. If unspecified,
465
+ len(iterable) is used if possible. If float("inf") or as a last
466
+ resort, only basic progress statistics are displayed
467
+ (no ETA, no progressbar).
468
+ If ``gui`` is True and this parameter needs subsequent updating,
469
+ specify an initial arbitrary large positive number,
470
+ e.g. 9e9.
471
+ * leave : bool, optional
472
+ If [default: True], keeps all traces of the progressbar
473
+ upon termination of iteration.
474
+ If ``None``, will leave only if ``position`` is ``0``.
475
+ * file : ``io.TextIOWrapper`` or ``io.StringIO``, optional
476
+ Specifies where to output the progress messages
477
+ (default: sys.stderr). Uses ``file.write(str)`` and ``file.flush()``
478
+ methods. For encoding, see ``write_bytes``.
479
+ * ncols : int, optional
480
+ The width of the entire output message. If specified,
481
+ dynamically resizes the progressbar to stay within this bound.
482
+ If unspecified, attempts to use environment width. The
483
+ fallback is a meter width of 10 and no limit for the counter and
484
+ statistics. If 0, will not print any meter (only stats).
485
+ * mininterval : float, optional
486
+ Minimum progress display update interval [default: 0.1] seconds.
487
+ * maxinterval : float, optional
488
+ Maximum progress display update interval [default: 10] seconds.
489
+ Automatically adjusts ``miniters`` to correspond to ``mininterval``
490
+ after long display update lag. Only works if ``dynamic_miniters``
491
+ or monitor thread is enabled.
492
+ * miniters : int or float, optional
493
+ Minimum progress display update interval, in iterations.
494
+ If 0 and ``dynamic_miniters``, will automatically adjust to equal
495
+ ``mininterval`` (more CPU efficient, good for tight loops).
496
+ If > 0, will skip display of specified number of iterations.
497
+ Tweak this and ``mininterval`` to get very efficient loops.
498
+ If your progress is erratic with both fast and slow iterations
499
+ (network, skipping items, etc) you should set miniters=1.
500
+ * ascii : bool or str, optional
501
+ If unspecified or False, use unicode (smooth blocks) to fill
502
+ the meter. The fallback is to use ASCII characters " 123456789#".
503
+ * disable : bool, optional
504
+ Whether to disable the entire progressbar wrapper
505
+ [default: False]. If set to None, disable on non-TTY.
506
+ * unit : str, optional
507
+ String that will be used to define the unit of each iteration
508
+ [default: it].
509
+ * unit_scale : bool or int or float, optional
510
+ If 1 or True, the number of iterations will be reduced/scaled
511
+ automatically and a metric prefix following the
512
+ International System of Units standard will be added
513
+ (kilo, mega, etc.) [default: False]. If any other non-zero
514
+ number, will scale ``total`` and ``n``.
515
+ * dynamic_ncols : bool, optional
516
+ If set, constantly alters ``ncols`` and ``nrows`` to the
517
+ environment (allowing for window resizes) [default: False].
518
+ * smoothing : float, optional
519
+ Exponential moving average smoothing factor for speed estimates
520
+ (ignored in GUI mode). Ranges from 0 (average speed) to 1
521
+ (current/instantaneous speed) [default: 0.3].
522
+ * bar_format : str, optional
523
+ Specify a custom bar string formatting. May impact performance.
524
+ [default: '{l_bar}{bar}{r_bar}'], where
525
+ l_bar='{desc}: {percentage:3.0f}%|' and
526
+ r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, '
527
+ '{rate_fmt}{postfix}]'
528
+ Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt,
529
+ percentage, elapsed, elapsed_s, ncols, nrows, desc, unit,
530
+ rate, rate_fmt, rate_noinv, rate_noinv_fmt,
531
+ rate_inv, rate_inv_fmt, postfix, unit_divisor,
532
+ remaining, remaining_s, eta.
533
+ Note that a trailing ": " is automatically removed after {desc}
534
+ if the latter is empty.
535
+ * initial : int or float, optional
536
+ The initial counter value. Useful when restarting a progress
537
+ bar [default: 0]. If using float, consider specifying ``{n:.3f}``
538
+ or similar in ``bar_format``, or specifying ``unit_scale``.
539
+ * position : int, optional
540
+ Specify the line offset to print this bar (starting from 0)
541
+ Automatic if unspecified.
542
+ Useful to manage multiple bars at once (eg, from threads).
543
+ * postfix : dict or ``*``, optional
544
+ Specify additional stats to display at the end of the bar.
545
+ Calls ``set_postfix(**postfix)`` if possible (dict).
546
+ * unit_divisor : float, optional
547
+ [default: 1000], ignored unless ``unit_scale`` is True.
548
+ * write_bytes : bool, optional
549
+ Whether to write bytes. If (default: False) will write unicode.
550
+ * lock_args : tuple, optional
551
+ Passed to ``refresh`` for intermediate output
552
+ (initialisation, iterating, and updating).
553
+ * nrows : int, optional
554
+ The screen height. If specified, hides nested bars outside this
555
+ bound. If unspecified, attempts to use environment height.
556
+ The fallback is 20.
557
+ * colour : str, optional
558
+ Bar colour (e.g. 'green', '#00ff00').
559
+ * delay : float, optional
560
+ Don't display until [default: 0] seconds have elapsed.
561
+
562
+ Extra CLI Options
563
+ ~~~~~~~~~~~~~~~~~
564
+
565
+ * delim : chr, optional
566
+ Delimiting character [default: '\n']. Use '\0' for null.
567
+ N.B.: on Windows systems, Python converts '\n' to '\r\n'.
568
+ * buf_size : int, optional
569
+ String buffer size in bytes [default: 256]
570
+ used when ``delim`` is specified.
571
+ * bytes : bool, optional
572
+ If true, will count bytes, ignore ``delim``, and default
573
+ ``unit_scale`` to True, ``unit_divisor`` to 1024, and ``unit`` to 'B'.
574
+ * tee : bool, optional
575
+ If true, passes ``stdin`` to both ``stderr`` and ``stdout``.
576
+ * update : bool, optional
577
+ If true, will treat input as newly elapsed iterations,
578
+ i.e. numbers to pass to ``update()``. Note that this is slow
579
+ (~2e5 it/s) since every input must be decoded as a number.
580
+ * update_to : bool, optional
581
+ If true, will treat input as total elapsed iterations,
582
+ i.e. numbers to assign to ``self.n``. Note that this is slow
583
+ (~2e5 it/s) since every input must be decoded as a number.
584
+ * null : bool, optional
585
+ If true, will discard input (no stdout).
586
+ * manpath : str, optional
587
+ Directory in which to install tqdm man pages.
588
+ * comppath : str, optional
589
+ Directory in which to place tqdm completion.
590
+ * log : str, optional
591
+ CRITICAL|FATAL|ERROR|WARN(ING)|[default: 'INFO']|DEBUG|NOTSET.
592
+
593
+ Returns
594
+ ~~~~~~~
595
+
596
+ * out : decorated iterator.
597
+
598
+ .. code:: python
599
+
600
+ class tqdm():
601
+ def update(self, n=1):
602
+ """
603
+ Manually update the progress bar, useful for streams
604
+ such as reading files.
605
+ E.g.:
606
+ >>> t = tqdm(total=filesize) # Initialise
607
+ >>> for current_buffer in stream:
608
+ ... ...
609
+ ... t.update(len(current_buffer))
610
+ >>> t.close()
611
+ The last line is highly recommended, but possibly not necessary if
612
+ ``t.update()`` will be called in such a way that ``filesize`` will be
613
+ exactly reached and printed.
614
+
615
+ Parameters
616
+ ----------
617
+ n : int or float, optional
618
+ Increment to add to the internal counter of iterations
619
+ [default: 1]. If using float, consider specifying ``{n:.3f}``
620
+ or similar in ``bar_format``, or specifying ``unit_scale``.
621
+
622
+ Returns
623
+ -------
624
+ out : bool or None
625
+ True if a ``display()`` was triggered.
626
+ """
627
+
628
+ def close(self):
629
+ """Cleanup and (if leave=False) close the progressbar."""
630
+
631
+ def clear(self, nomove=False):
632
+ """Clear current bar display."""
633
+
634
+ def refresh(self):
635
+ """
636
+ Force refresh the display of this bar.
637
+
638
+ Parameters
639
+ ----------
640
+ nolock : bool, optional
641
+ If ``True``, does not lock.
642
+ If [default: ``False``]: calls ``acquire()`` on internal lock.
643
+ lock_args : tuple, optional
644
+ Passed to internal lock's ``acquire()``.
645
+ If specified, will only ``display()`` if ``acquire()`` returns ``True``.
646
+ """
647
+
648
+ def unpause(self):
649
+ """Restart tqdm timer from last print time."""
650
+
651
+ def reset(self, total=None):
652
+ """
653
+ Resets to 0 iterations for repeated use.
654
+
655
+ Consider combining with ``leave=True``.
656
+
657
+ Parameters
658
+ ----------
659
+ total : int or float, optional. Total to use for the new bar.
660
+ """
661
+
662
+ def set_description(self, desc=None, refresh=True):
663
+ """
664
+ Set/modify description of the progress bar.
665
+
666
+ Parameters
667
+ ----------
668
+ desc : str, optional
669
+ refresh : bool, optional
670
+ Forces refresh [default: True].
671
+ """
672
+
673
+ def set_postfix(self, ordered_dict=None, refresh=True, **tqdm_kwargs):
674
+ """
675
+ Set/modify postfix (additional stats)
676
+ with automatic formatting based on datatype.
677
+
678
+ Parameters
679
+ ----------
680
+ ordered_dict : dict or OrderedDict, optional
681
+ refresh : bool, optional
682
+ Forces refresh [default: True].
683
+ kwargs : dict, optional
684
+ """
685
+
686
+ @classmethod
687
+ def write(cls, s, file=sys.stdout, end="\n"):
688
+ """Print a message via tqdm (without overlap with bars)."""
689
+
690
+ @property
691
+ def format_dict(self):
692
+ """Public API for read-only member access."""
693
+
694
+ def display(self, msg=None, pos=None):
695
+ """
696
+ Use ``self.sp`` to display ``msg`` in the specified ``pos``.
697
+
698
+ Consider overloading this function when inheriting to use e.g.:
699
+ ``self.some_frontend(**self.format_dict)`` instead of ``self.sp``.
700
+
701
+ Parameters
702
+ ----------
703
+ msg : str, optional. What to display (default: ``repr(self)``).
704
+ pos : int, optional. Position to ``moveto``
705
+ (default: ``abs(self.pos)``).
706
+ """
707
+
708
+ @classmethod
709
+ @contextmanager
710
+ def wrapattr(cls, stream, method, total=None, bytes=True, **tqdm_kwargs):
711
+ """
712
+ stream : file-like object.
713
+ method : str, "read" or "write". The result of ``read()`` and
714
+ the first argument of ``write()`` should have a ``len()``.
715
+
716
+ >>> with tqdm.wrapattr(file_obj, "read", total=file_obj.size) as fobj:
717
+ ... while True:
718
+ ... chunk = fobj.read(chunk_size)
719
+ ... if not chunk:
720
+ ... break
721
+ """
722
+
723
+ @classmethod
724
+ def pandas(cls, *targs, **tqdm_kwargs):
725
+ """Registers the current `tqdm` class with `pandas`."""
726
+
727
+ def trange(*args, **tqdm_kwargs):
728
+ """Shortcut for `tqdm(range(*args), **tqdm_kwargs)`."""
729
+
730
+ Convenience Functions
731
+ ~~~~~~~~~~~~~~~~~~~~~
732
+
733
+ .. code:: python
734
+
735
+ def tqdm.contrib.tenumerate(iterable, start=0, total=None,
736
+ tqdm_class=tqdm.auto.tqdm, **tqdm_kwargs):
737
+ """Equivalent of `numpy.ndenumerate` or builtin `enumerate`."""
738
+
739
+ def tqdm.contrib.tzip(iter1, *iter2plus, **tqdm_kwargs):
740
+ """Equivalent of builtin `zip`."""
741
+
742
+ def tqdm.contrib.tmap(function, *sequences, **tqdm_kwargs):
743
+ """Equivalent of builtin `map`."""
744
+
745
+ Submodules
746
+ ~~~~~~~~~~
747
+
748
+ .. code:: python
749
+
750
+ class tqdm.notebook.tqdm(tqdm.tqdm):
751
+ """IPython/Jupyter Notebook widget."""
752
+
753
+ class tqdm.auto.tqdm(tqdm.tqdm):
754
+ """Automatically chooses beween `tqdm.notebook` and `tqdm.tqdm`."""
755
+
756
+ class tqdm.asyncio.tqdm(tqdm.tqdm):
757
+ """Asynchronous version."""
758
+ @classmethod
759
+ def as_completed(cls, fs, *, loop=None, timeout=None, total=None,
760
+ **tqdm_kwargs):
761
+ """Wrapper for `asyncio.as_completed`."""
762
+
763
+ class tqdm.gui.tqdm(tqdm.tqdm):
764
+ """Matplotlib GUI version."""
765
+
766
+ class tqdm.tk.tqdm(tqdm.tqdm):
767
+ """Tkinter GUI version."""
768
+
769
+ class tqdm.rich.tqdm(tqdm.tqdm):
770
+ """`rich.progress` version."""
771
+
772
+ class tqdm.keras.TqdmCallback(keras.callbacks.Callback):
773
+ """Keras callback for epoch and batch progress."""
774
+
775
+ class tqdm.dask.TqdmCallback(dask.callbacks.Callback):
776
+ """Dask callback for task progress."""
777
+
778
+
779
+ ``contrib``
780
+ +++++++++++
781
+
782
+ The ``tqdm.contrib`` package also contains experimental modules:
783
+
784
+ - ``tqdm.contrib.itertools``: Thin wrappers around ``itertools``
785
+ - ``tqdm.contrib.concurrent``: Thin wrappers around ``concurrent.futures``
786
+ - ``tqdm.contrib.slack``: Posts to `Slack <https://slack.com>`__ bots
787
+ - ``tqdm.contrib.discord``: Posts to `Discord <https://discord.com>`__ bots
788
+ - ``tqdm.contrib.telegram``: Posts to `Telegram <https://telegram.org>`__ bots
789
+ - ``tqdm.contrib.bells``: Automagically enables all optional features
790
+
791
+ * ``auto``, ``pandas``, ``slack``, ``discord``, ``telegram``
792
+
793
+ Examples and Advanced Usage
794
+ ---------------------------
795
+
796
+ - See the `examples <https://github.com/tqdm/tqdm/tree/master/examples>`__
797
+ folder;
798
+ - import the module and run ``help()``;
799
+ - consult the `wiki <https://github.com/tqdm/tqdm/wiki>`__;
800
+
801
+ * this has an
802
+ `excellent article <https://github.com/tqdm/tqdm/wiki/How-to-make-a-great-Progress-Bar>`__
803
+ on how to make a **great** progressbar;
804
+
805
+ - check out the `slides from PyData London <https://tqdm.github.io/PyData2019/slides.html>`__, or
806
+ - run the |binder-demo|.
807
+
808
+ Description and additional stats
809
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
810
+
811
+ Custom information can be displayed and updated dynamically on ``tqdm`` bars
812
+ with the ``desc`` and ``postfix`` arguments:
813
+
814
+ .. code:: python
815
+
816
+ from tqdm import tqdm, trange
817
+ from random import random, randint
818
+ from time import sleep
819
+
820
+ with trange(10) as t:
821
+ for i in t:
822
+ # Description will be displayed on the left
823
+ t.set_description('GEN %i' % i)
824
+ # Postfix will be displayed on the right,
825
+ # formatted automatically based on argument's datatype
826
+ t.set_postfix(loss=random(), gen=randint(1,999), str='h',
827
+ lst=[1, 2])
828
+ sleep(0.1)
829
+
830
+ with tqdm(total=10, bar_format="{postfix[0]} {postfix[1][value]:>8.2g}",
831
+ postfix=["Batch", {"value": 0}]) as t:
832
+ for i in range(10):
833
+ sleep(0.1)
834
+ t.postfix[1]["value"] = i / 2
835
+ t.update()
836
+
837
+ Points to remember when using ``{postfix[...]}`` in the ``bar_format`` string:
838
+
839
+ - ``postfix`` also needs to be passed as an initial argument in a compatible
840
+ format, and
841
+ - ``postfix`` will be auto-converted to a string if it is a ``dict``-like
842
+ object. To prevent this behaviour, insert an extra item into the dictionary
843
+ where the key is not a string.
844
+
845
+ Additional ``bar_format`` parameters may also be defined by overriding
846
+ ``format_dict``, and the bar itself may be modified using ``ascii``:
847
+
848
+ .. code:: python
849
+
850
+ from tqdm import tqdm
851
+ class TqdmExtraFormat(tqdm):
852
+ """Provides a `total_time` format parameter"""
853
+ @property
854
+ def format_dict(self):
855
+ d = super().format_dict
856
+ total_time = d["elapsed"] * (d["total"] or 0) / max(d["n"], 1)
857
+ d.update(total_time=self.format_interval(total_time) + " in total")
858
+ return d
859
+
860
+ for i in TqdmExtraFormat(
861
+ range(9), ascii=" .oO0",
862
+ bar_format="{total_time}: {percentage:.0f}%|{bar}{r_bar}"):
863
+ if i == 4:
864
+ break
865
+
866
+ .. code::
867
+
868
+ 00:00 in total: 44%|0000. | 4/9 [00:00<00:00, 962.93it/s]
869
+
870
+ Note that ``{bar}`` also supports a format specifier ``[width][type]``.
871
+
872
+ - ``width``
873
+
874
+ * unspecified (default): automatic to fill ``ncols``
875
+ * ``int >= 0``: fixed width overriding ``ncols`` logic
876
+ * ``int < 0``: subtract from the automatic default
877
+
878
+ - ``type``
879
+
880
+ * ``a``: ascii (``ascii=True`` override)
881
+ * ``u``: unicode (``ascii=False`` override)
882
+ * ``b``: blank (``ascii=" "`` override)
883
+
884
+ This means a fixed bar with right-justified text may be created by using:
885
+ ``bar_format="{l_bar}{bar:10}|{bar:-10b}right-justified"``
886
+
887
+ Nested progress bars
888
+ ~~~~~~~~~~~~~~~~~~~~
889
+
890
+ ``tqdm`` supports nested progress bars. Here's an example:
891
+
892
+ .. code:: python
893
+
894
+ from tqdm.auto import trange
895
+ from time import sleep
896
+
897
+ for i in trange(4, desc='1st loop'):
898
+ for j in trange(5, desc='2nd loop'):
899
+ for k in trange(50, desc='3rd loop', leave=False):
900
+ sleep(0.01)
901
+
902
+ For manual control over positioning (e.g. for multi-processing use),
903
+ you may specify ``position=n`` where ``n=0`` for the outermost bar,
904
+ ``n=1`` for the next, and so on.
905
+ However, it's best to check if ``tqdm`` can work without manual ``position``
906
+ first.
907
+
908
+ .. code:: python
909
+
910
+ from time import sleep
911
+ from tqdm import trange, tqdm
912
+ from multiprocessing import Pool, RLock, freeze_support
913
+
914
+ L = list(range(9))
915
+
916
+ def progresser(n):
917
+ interval = 0.001 / (n + 2)
918
+ total = 5000
919
+ text = f"#{n}, est. {interval * total:<04.2}s"
920
+ for _ in trange(total, desc=text, position=n):
921
+ sleep(interval)
922
+
923
+ if __name__ == '__main__':
924
+ freeze_support() # for Windows support
925
+ tqdm.set_lock(RLock()) # for managing output contention
926
+ p = Pool(initializer=tqdm.set_lock, initargs=(tqdm.get_lock(),))
927
+ p.map(progresser, L)
928
+
929
+ Note that in Python 3, ``tqdm.write`` is thread-safe:
930
+
931
+ .. code:: python
932
+
933
+ from time import sleep
934
+ from tqdm import tqdm, trange
935
+ from concurrent.futures import ThreadPoolExecutor
936
+
937
+ L = list(range(9))
938
+
939
+ def progresser(n):
940
+ interval = 0.001 / (n + 2)
941
+ total = 5000
942
+ text = f"#{n}, est. {interval * total:<04.2}s"
943
+ for _ in trange(total, desc=text):
944
+ sleep(interval)
945
+ if n == 6:
946
+ tqdm.write("n == 6 completed.")
947
+ tqdm.write("`tqdm.write()` is thread-safe in py3!")
948
+
949
+ if __name__ == '__main__':
950
+ with ThreadPoolExecutor() as p:
951
+ p.map(progresser, L)
952
+
953
+ Hooks and callbacks
954
+ ~~~~~~~~~~~~~~~~~~~
955
+
956
+ ``tqdm`` can easily support callbacks/hooks and manual updates.
957
+ Here's an example with ``urllib``:
958
+
959
+ **``urllib.urlretrieve`` documentation**
960
+
961
+ | [...]
962
+ | If present, the hook function will be called once
963
+ | on establishment of the network connection and once after each block read
964
+ | thereafter. The hook will be passed three arguments; a count of blocks
965
+ | transferred so far, a block size in bytes, and the total size of the file.
966
+ | [...]
967
+
968
+ .. code:: python
969
+
970
+ import urllib, os
971
+ from tqdm import tqdm
972
+ urllib = getattr(urllib, 'request', urllib)
973
+
974
+ class TqdmUpTo(tqdm):
975
+ """Provides `update_to(n)` which uses `tqdm.update(delta_n)`."""
976
+ def update_to(self, b=1, bsize=1, tsize=None):
977
+ """
978
+ b : int, optional
979
+ Number of blocks transferred so far [default: 1].
980
+ bsize : int, optional
981
+ Size of each block (in tqdm units) [default: 1].
982
+ tsize : int, optional
983
+ Total size (in tqdm units). If [default: None] remains unchanged.
984
+ """
985
+ if tsize is not None:
986
+ self.total = tsize
987
+ return self.update(b * bsize - self.n) # also sets self.n = b * bsize
988
+
989
+ eg_link = "https://caspersci.uk.to/matryoshka.zip"
990
+ with TqdmUpTo(unit='B', unit_scale=True, unit_divisor=1024, miniters=1,
991
+ desc=eg_link.split('/')[-1]) as t: # all optional kwargs
992
+ urllib.urlretrieve(eg_link, filename=os.devnull,
993
+ reporthook=t.update_to, data=None)
994
+ t.total = t.n
995
+
996
+ Inspired by `twine#242 <https://github.com/pypa/twine/pull/242>`__.
997
+ Functional alternative in
998
+ `examples/tqdm_wget.py <https://github.com/tqdm/tqdm/blob/master/examples/tqdm_wget.py>`__.
999
+
1000
+ It is recommend to use ``miniters=1`` whenever there is potentially
1001
+ large differences in iteration speed (e.g. downloading a file over
1002
+ a patchy connection).
1003
+
1004
+ **Wrapping read/write methods**
1005
+
1006
+ To measure throughput through a file-like object's ``read`` or ``write``
1007
+ methods, use ``CallbackIOWrapper``:
1008
+
1009
+ .. code:: python
1010
+
1011
+ from tqdm.auto import tqdm
1012
+ from tqdm.utils import CallbackIOWrapper
1013
+
1014
+ with tqdm(total=file_obj.size,
1015
+ unit='B', unit_scale=True, unit_divisor=1024) as t:
1016
+ fobj = CallbackIOWrapper(t.update, file_obj, "read")
1017
+ while True:
1018
+ chunk = fobj.read(chunk_size)
1019
+ if not chunk:
1020
+ break
1021
+ t.reset()
1022
+ # ... continue to use `t` for something else
1023
+
1024
+ Alternatively, use the even simpler ``wrapattr`` convenience function,
1025
+ which would condense both the ``urllib`` and ``CallbackIOWrapper`` examples
1026
+ down to:
1027
+
1028
+ .. code:: python
1029
+
1030
+ import urllib, os
1031
+ from tqdm import tqdm
1032
+
1033
+ eg_link = "https://caspersci.uk.to/matryoshka.zip"
1034
+ response = getattr(urllib, 'request', urllib).urlopen(eg_link)
1035
+ with tqdm.wrapattr(open(os.devnull, "wb"), "write",
1036
+ miniters=1, desc=eg_link.split('/')[-1],
1037
+ total=getattr(response, 'length', None)) as fout:
1038
+ for chunk in response:
1039
+ fout.write(chunk)
1040
+
1041
+ The ``requests`` equivalent is nearly identical:
1042
+
1043
+ .. code:: python
1044
+
1045
+ import requests, os
1046
+ from tqdm import tqdm
1047
+
1048
+ eg_link = "https://caspersci.uk.to/matryoshka.zip"
1049
+ response = requests.get(eg_link, stream=True)
1050
+ with tqdm.wrapattr(open(os.devnull, "wb"), "write",
1051
+ miniters=1, desc=eg_link.split('/')[-1],
1052
+ total=int(response.headers.get('content-length', 0))) as fout:
1053
+ for chunk in response.iter_content(chunk_size=4096):
1054
+ fout.write(chunk)
1055
+
1056
+ **Custom callback**
1057
+
1058
+ ``tqdm`` is known for intelligently skipping unnecessary displays. To make a
1059
+ custom callback take advantage of this, simply use the return value of
1060
+ ``update()``. This is set to ``True`` if a ``display()`` was triggered.
1061
+
1062
+ .. code:: python
1063
+
1064
+ from tqdm.auto import tqdm as std_tqdm
1065
+
1066
+ def external_callback(*args, **kwargs):
1067
+ ...
1068
+
1069
+ class TqdmExt(std_tqdm):
1070
+ def update(self, n=1):
1071
+ displayed = super().update(n)
1072
+ if displayed:
1073
+ external_callback(**self.format_dict)
1074
+ return displayed
1075
+
1076
+ ``asyncio``
1077
+ ~~~~~~~~~~~
1078
+
1079
+ Note that ``break`` isn't currently caught by asynchronous iterators.
1080
+ This means that ``tqdm`` cannot clean up after itself in this case:
1081
+
1082
+ .. code:: python
1083
+
1084
+ from tqdm.asyncio import tqdm
1085
+
1086
+ async for i in tqdm(range(9)):
1087
+ if i == 2:
1088
+ break
1089
+
1090
+ Instead, either call ``pbar.close()`` manually or use the context manager syntax:
1091
+
1092
+ .. code:: python
1093
+
1094
+ from tqdm.asyncio import tqdm
1095
+
1096
+ with tqdm(range(9)) as pbar:
1097
+ async for i in pbar:
1098
+ if i == 2:
1099
+ break
1100
+
1101
+ Pandas Integration
1102
+ ~~~~~~~~~~~~~~~~~~
1103
+
1104
+ Due to popular demand we've added support for ``pandas`` -- here's an example
1105
+ for ``DataFrame.progress_apply`` and ``DataFrameGroupBy.progress_apply``:
1106
+
1107
+ .. code:: python
1108
+
1109
+ import pandas as pd
1110
+ import numpy as np
1111
+ from tqdm import tqdm
1112
+
1113
+ df = pd.DataFrame(np.random.randint(0, 100, (100000, 6)))
1114
+
1115
+ # Register `pandas.progress_apply` and `pandas.Series.map_apply` with `tqdm`
1116
+ # (can use `tqdm.gui.tqdm`, `tqdm.notebook.tqdm`, optional kwargs, etc.)
1117
+ tqdm.pandas(desc="my bar!")
1118
+
1119
+ # Now you can use `progress_apply` instead of `apply`
1120
+ # and `progress_map` instead of `map`
1121
+ df.progress_apply(lambda x: x**2)
1122
+ # can also groupby:
1123
+ # df.groupby(0).progress_apply(lambda x: x**2)
1124
+
1125
+ In case you're interested in how this works (and how to modify it for your
1126
+ own callbacks), see the
1127
+ `examples <https://github.com/tqdm/tqdm/tree/master/examples>`__
1128
+ folder or import the module and run ``help()``.
1129
+
1130
+ Keras Integration
1131
+ ~~~~~~~~~~~~~~~~~
1132
+
1133
+ A ``keras`` callback is also available:
1134
+
1135
+ .. code:: python
1136
+
1137
+ from tqdm.keras import TqdmCallback
1138
+
1139
+ ...
1140
+
1141
+ model.fit(..., verbose=0, callbacks=[TqdmCallback()])
1142
+
1143
+ Dask Integration
1144
+ ~~~~~~~~~~~~~~~~
1145
+
1146
+ A ``dask`` callback is also available:
1147
+
1148
+ .. code:: python
1149
+
1150
+ from tqdm.dask import TqdmCallback
1151
+
1152
+ with TqdmCallback(desc="compute"):
1153
+ ...
1154
+ arr.compute()
1155
+
1156
+ # or use callback globally
1157
+ cb = TqdmCallback(desc="global")
1158
+ cb.register()
1159
+ arr.compute()
1160
+
1161
+ IPython/Jupyter Integration
1162
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1163
+
1164
+ IPython/Jupyter is supported via the ``tqdm.notebook`` submodule:
1165
+
1166
+ .. code:: python
1167
+
1168
+ from tqdm.notebook import trange, tqdm
1169
+ from time import sleep
1170
+
1171
+ for i in trange(3, desc='1st loop'):
1172
+ for j in tqdm(range(100), desc='2nd loop'):
1173
+ sleep(0.01)
1174
+
1175
+ In addition to ``tqdm`` features, the submodule provides a native Jupyter
1176
+ widget (compatible with IPython v1-v4 and Jupyter), fully working nested bars
1177
+ and colour hints (blue: normal, green: completed, red: error/interrupt,
1178
+ light blue: no ETA); as demonstrated below.
1179
+
1180
+ |Screenshot-Jupyter1|
1181
+ |Screenshot-Jupyter2|
1182
+ |Screenshot-Jupyter3|
1183
+
1184
+ The ``notebook`` version supports percentage or pixels for overall width
1185
+ (e.g.: ``ncols='100%'`` or ``ncols='480px'``).
1186
+
1187
+ It is also possible to let ``tqdm`` automatically choose between
1188
+ console or notebook versions by using the ``autonotebook`` submodule:
1189
+
1190
+ .. code:: python
1191
+
1192
+ from tqdm.autonotebook import tqdm
1193
+ tqdm.pandas()
1194
+
1195
+ Note that this will issue a ``TqdmExperimentalWarning`` if run in a notebook
1196
+ since it is not meant to be possible to distinguish between ``jupyter notebook``
1197
+ and ``jupyter console``. Use ``auto`` instead of ``autonotebook`` to suppress
1198
+ this warning.
1199
+
1200
+ Note that notebooks will display the bar in the cell where it was created.
1201
+ This may be a different cell from the one where it is used.
1202
+ If this is not desired, either
1203
+
1204
+ - delay the creation of the bar to the cell where it must be displayed, or
1205
+ - create the bar with ``display=False``, and in a later cell call
1206
+ ``display(bar.container)``:
1207
+
1208
+ .. code:: python
1209
+
1210
+ from tqdm.notebook import tqdm
1211
+ pbar = tqdm(..., display=False)
1212
+
1213
+ .. code:: python
1214
+
1215
+ # different cell
1216
+ display(pbar.container)
1217
+
1218
+ The ``keras`` callback has a ``display()`` method which can be used likewise:
1219
+
1220
+ .. code:: python
1221
+
1222
+ from tqdm.keras import TqdmCallback
1223
+ cbk = TqdmCallback(display=False)
1224
+
1225
+ .. code:: python
1226
+
1227
+ # different cell
1228
+ cbk.display()
1229
+ model.fit(..., verbose=0, callbacks=[cbk])
1230
+
1231
+ Another possibility is to have a single bar (near the top of the notebook)
1232
+ which is constantly re-used (using ``reset()`` rather than ``close()``).
1233
+ For this reason, the notebook version (unlike the CLI version) does not
1234
+ automatically call ``close()`` upon ``Exception``.
1235
+
1236
+ .. code:: python
1237
+
1238
+ from tqdm.notebook import tqdm
1239
+ pbar = tqdm()
1240
+
1241
+ .. code:: python
1242
+
1243
+ # different cell
1244
+ iterable = range(100)
1245
+ pbar.reset(total=len(iterable)) # initialise with new `total`
1246
+ for i in iterable:
1247
+ pbar.update()
1248
+ pbar.refresh() # force print final status but don't `close()`
1249
+
1250
+ Custom Integration
1251
+ ~~~~~~~~~~~~~~~~~~
1252
+
1253
+ To change the default arguments (such as making ``dynamic_ncols=True``),
1254
+ simply use built-in Python magic:
1255
+
1256
+ .. code:: python
1257
+
1258
+ from functools import partial
1259
+ from tqdm import tqdm as std_tqdm
1260
+ tqdm = partial(std_tqdm, dynamic_ncols=True)
1261
+
1262
+ For further customisation,
1263
+ ``tqdm`` may be inherited from to create custom callbacks (as with the
1264
+ ``TqdmUpTo`` example `above <#hooks-and-callbacks>`__) or for custom frontends
1265
+ (e.g. GUIs such as notebook or plotting packages). In the latter case:
1266
+
1267
+ 1. ``def __init__()`` to call ``super().__init__(..., gui=True)`` to disable
1268
+ terminal ``status_printer`` creation.
1269
+ 2. Redefine: ``close()``, ``clear()``, ``display()``.
1270
+
1271
+ Consider overloading ``display()`` to use e.g.
1272
+ ``self.frontend(**self.format_dict)`` instead of ``self.sp(repr(self))``.
1273
+
1274
+ Some submodule examples of inheritance:
1275
+
1276
+ - `tqdm/notebook.py <https://github.com/tqdm/tqdm/blob/master/tqdm/notebook.py>`__
1277
+ - `tqdm/gui.py <https://github.com/tqdm/tqdm/blob/master/tqdm/gui.py>`__
1278
+ - `tqdm/tk.py <https://github.com/tqdm/tqdm/blob/master/tqdm/tk.py>`__
1279
+ - `tqdm/contrib/slack.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/slack.py>`__
1280
+ - `tqdm/contrib/discord.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/discord.py>`__
1281
+ - `tqdm/contrib/telegram.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/telegram.py>`__
1282
+
1283
+ Dynamic Monitor/Meter
1284
+ ~~~~~~~~~~~~~~~~~~~~~
1285
+
1286
+ You can use a ``tqdm`` as a meter which is not monotonically increasing.
1287
+ This could be because ``n`` decreases (e.g. a CPU usage monitor) or ``total``
1288
+ changes.
1289
+
1290
+ One example would be recursively searching for files. The ``total`` is the
1291
+ number of objects found so far, while ``n`` is the number of those objects which
1292
+ are files (rather than folders):
1293
+
1294
+ .. code:: python
1295
+
1296
+ from tqdm import tqdm
1297
+ import os.path
1298
+
1299
+ def find_files_recursively(path, show_progress=True):
1300
+ files = []
1301
+ # total=1 assumes `path` is a file
1302
+ t = tqdm(total=1, unit="file", disable=not show_progress)
1303
+ if not os.path.exists(path):
1304
+ raise IOError("Cannot find:" + path)
1305
+
1306
+ def append_found_file(f):
1307
+ files.append(f)
1308
+ t.update()
1309
+
1310
+ def list_found_dir(path):
1311
+ """returns os.listdir(path) assuming os.path.isdir(path)"""
1312
+ listing = os.listdir(path)
1313
+ # subtract 1 since a "file" we found was actually this directory
1314
+ t.total += len(listing) - 1
1315
+ # fancy way to give info without forcing a refresh
1316
+ t.set_postfix(dir=path[-10:], refresh=False)
1317
+ t.update(0) # may trigger a refresh
1318
+ return listing
1319
+
1320
+ def recursively_search(path):
1321
+ if os.path.isdir(path):
1322
+ for f in list_found_dir(path):
1323
+ recursively_search(os.path.join(path, f))
1324
+ else:
1325
+ append_found_file(path)
1326
+
1327
+ recursively_search(path)
1328
+ t.set_postfix(dir=path)
1329
+ t.close()
1330
+ return files
1331
+
1332
+ Using ``update(0)`` is a handy way to let ``tqdm`` decide when to trigger a
1333
+ display refresh to avoid console spamming.
1334
+
1335
+ Writing messages
1336
+ ~~~~~~~~~~~~~~~~
1337
+
1338
+ This is a work in progress (see
1339
+ `#737 <https://github.com/tqdm/tqdm/issues/737>`__).
1340
+
1341
+ Since ``tqdm`` uses a simple printing mechanism to display progress bars,
1342
+ you should not write any message in the terminal using ``print()`` while
1343
+ a progressbar is open.
1344
+
1345
+ To write messages in the terminal without any collision with ``tqdm`` bar
1346
+ display, a ``.write()`` method is provided:
1347
+
1348
+ .. code:: python
1349
+
1350
+ from tqdm.auto import tqdm, trange
1351
+ from time import sleep
1352
+
1353
+ bar = trange(10)
1354
+ for i in bar:
1355
+ # Print using tqdm class method .write()
1356
+ sleep(0.1)
1357
+ if not (i % 3):
1358
+ tqdm.write("Done task %i" % i)
1359
+ # Can also use bar.write()
1360
+
1361
+ By default, this will print to standard output ``sys.stdout``. but you can
1362
+ specify any file-like object using the ``file`` argument. For example, this
1363
+ can be used to redirect the messages writing to a log file or class.
1364
+
1365
+ Redirecting writing
1366
+ ~~~~~~~~~~~~~~~~~~~
1367
+
1368
+ If using a library that can print messages to the console, editing the library
1369
+ by replacing ``print()`` with ``tqdm.write()`` may not be desirable.
1370
+ In that case, redirecting ``sys.stdout`` to ``tqdm.write()`` is an option.
1371
+
1372
+ To redirect ``sys.stdout``, create a file-like class that will write
1373
+ any input string to ``tqdm.write()``, and supply the arguments
1374
+ ``file=sys.stdout, dynamic_ncols=True``.
1375
+
1376
+ A reusable canonical example is given below:
1377
+
1378
+ .. code:: python
1379
+
1380
+ from time import sleep
1381
+ import contextlib
1382
+ import sys
1383
+ from tqdm import tqdm
1384
+ from tqdm.contrib import DummyTqdmFile
1385
+
1386
+
1387
+ @contextlib.contextmanager
1388
+ def std_out_err_redirect_tqdm():
1389
+ orig_out_err = sys.stdout, sys.stderr
1390
+ try:
1391
+ sys.stdout, sys.stderr = map(DummyTqdmFile, orig_out_err)
1392
+ yield orig_out_err[0]
1393
+ # Relay exceptions
1394
+ except Exception as exc:
1395
+ raise exc
1396
+ # Always restore sys.stdout/err if necessary
1397
+ finally:
1398
+ sys.stdout, sys.stderr = orig_out_err
1399
+
1400
+ def some_fun(i):
1401
+ print("Fee, fi, fo,".split()[i])
1402
+
1403
+ # Redirect stdout to tqdm.write() (don't forget the `as save_stdout`)
1404
+ with std_out_err_redirect_tqdm() as orig_stdout:
1405
+ # tqdm needs the original stdout
1406
+ # and dynamic_ncols=True to autodetect console width
1407
+ for i in tqdm(range(3), file=orig_stdout, dynamic_ncols=True):
1408
+ sleep(.5)
1409
+ some_fun(i)
1410
+
1411
+ # After the `with`, printing is restored
1412
+ print("Done!")
1413
+
1414
+ Redirecting ``logging``
1415
+ ~~~~~~~~~~~~~~~~~~~~~~~
1416
+
1417
+ Similar to ``sys.stdout``/``sys.stderr`` as detailed above, console ``logging``
1418
+ may also be redirected to ``tqdm.write()``.
1419
+
1420
+ Warning: if also redirecting ``sys.stdout``/``sys.stderr``, make sure to
1421
+ redirect ``logging`` first if needed.
1422
+
1423
+ Helper methods are available in ``tqdm.contrib.logging``. For example:
1424
+
1425
+ .. code:: python
1426
+
1427
+ import logging
1428
+ from tqdm import trange
1429
+ from tqdm.contrib.logging import logging_redirect_tqdm
1430
+
1431
+ LOG = logging.getLogger(__name__)
1432
+
1433
+ if __name__ == '__main__':
1434
+ logging.basicConfig(level=logging.INFO)
1435
+ with logging_redirect_tqdm():
1436
+ for i in trange(9):
1437
+ if i == 4:
1438
+ LOG.info("console logging redirected to `tqdm.write()`")
1439
+ # logging restored
1440
+
1441
+ Monitoring thread, intervals and miniters
1442
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1443
+
1444
+ ``tqdm`` implements a few tricks to increase efficiency and reduce overhead.
1445
+
1446
+ - Avoid unnecessary frequent bar refreshing: ``mininterval`` defines how long
1447
+ to wait between each refresh. ``tqdm`` always gets updated in the background,
1448
+ but it will display only every ``mininterval``.
1449
+ - Reduce number of calls to check system clock/time.
1450
+ - ``mininterval`` is more intuitive to configure than ``miniters``.
1451
+ A clever adjustment system ``dynamic_miniters`` will automatically adjust
1452
+ ``miniters`` to the amount of iterations that fit into time ``mininterval``.
1453
+ Essentially, ``tqdm`` will check if it's time to print without actually
1454
+ checking time. This behaviour can be still be bypassed by manually setting
1455
+ ``miniters``.
1456
+
1457
+ However, consider a case with a combination of fast and slow iterations.
1458
+ After a few fast iterations, ``dynamic_miniters`` will set ``miniters`` to a
1459
+ large number. When iteration rate subsequently slows, ``miniters`` will
1460
+ remain large and thus reduce display update frequency. To address this:
1461
+
1462
+ - ``maxinterval`` defines the maximum time between display refreshes.
1463
+ A concurrent monitoring thread checks for overdue updates and forces one
1464
+ where necessary.
1465
+
1466
+ The monitoring thread should not have a noticeable overhead, and guarantees
1467
+ updates at least every 10 seconds by default.
1468
+ This value can be directly changed by setting the ``monitor_interval`` of
1469
+ any ``tqdm`` instance (i.e. ``t = tqdm.tqdm(...); t.monitor_interval = 2``).
1470
+ The monitor thread may be disabled application-wide by setting
1471
+ ``tqdm.tqdm.monitor_interval = 0`` before instantiation of any ``tqdm`` bar.
1472
+
1473
+
1474
+ Merch
1475
+ -----
1476
+
1477
+ You can buy `tqdm branded merch <https://tqdm.github.io/merch>`__ now!
1478
+
1479
+ Contributions
1480
+ -------------
1481
+
1482
+ |GitHub-Commits| |GitHub-Issues| |GitHub-PRs| |OpenHub-Status| |GitHub-Contributions| |CII Best Practices|
1483
+
1484
+ All source code is hosted on `GitHub <https://github.com/tqdm/tqdm>`__.
1485
+ Contributions are welcome.
1486
+
1487
+ See the
1488
+ `CONTRIBUTING <https://github.com/tqdm/tqdm/blob/master/CONTRIBUTING.md>`__
1489
+ file for more information.
1490
+
1491
+ Developers who have made significant contributions, ranked by *SLoC*
1492
+ (surviving lines of code,
1493
+ `git fame <https://github.com/casperdcl/git-fame>`__ ``-wMC --excl '\.(png|gif|jpg)$'``),
1494
+ are:
1495
+
1496
+ ==================== ======================================================== ==== ================================
1497
+ Name ID SLoC Notes
1498
+ ==================== ======================================================== ==== ================================
1499
+ Casper da Costa-Luis `casperdcl <https://github.com/casperdcl>`__ ~80% primary maintainer |Gift-Casper|
1500
+ Stephen Larroque `lrq3000 <https://github.com/lrq3000>`__ ~9% team member
1501
+ Martin Zugnoni `martinzugnoni <https://github.com/martinzugnoni>`__ ~3%
1502
+ Daniel Ecer `de-code <https://github.com/de-code>`__ ~2%
1503
+ Richard Sheridan `richardsheridan <https://github.com/richardsheridan>`__ ~1%
1504
+ Guangshuo Chen `chengs <https://github.com/chengs>`__ ~1%
1505
+ Helio Machado `0x2b3bfa0 <https://github.com/0x2b3bfa0>`__ ~1%
1506
+ Kyle Altendorf `altendky <https://github.com/altendky>`__ <1%
1507
+ Noam Yorav-Raphael `noamraph <https://github.com/noamraph>`__ <1% original author
1508
+ Matthew Stevens `mjstevens777 <https://github.com/mjstevens777>`__ <1%
1509
+ Hadrien Mary `hadim <https://github.com/hadim>`__ <1% team member
1510
+ Mikhail Korobov `kmike <https://github.com/kmike>`__ <1% team member
1511
+ ==================== ======================================================== ==== ================================
1512
+
1513
+ Ports to Other Languages
1514
+ ~~~~~~~~~~~~~~~~~~~~~~~~
1515
+
1516
+ A list is available on
1517
+ `this wiki page <https://github.com/tqdm/tqdm/wiki/tqdm-ports>`__.
1518
+
1519
+
1520
+ LICENCE
1521
+ -------
1522
+
1523
+ Open Source (OSI approved): |LICENCE|
1524
+
1525
+ Citation information: |DOI|
1526
+
1527
+ |README-Hits| (Since 19 May 2016)
1528
+
1529
+ .. |Logo| image:: https://tqdm.github.io/img/logo.gif
1530
+ .. |Screenshot| image:: https://tqdm.github.io/img/tqdm.gif
1531
+ .. |Video| image:: https://tqdm.github.io/img/video.jpg
1532
+ :target: https://tqdm.github.io/video
1533
+ .. |Slides| image:: https://tqdm.github.io/img/slides.jpg
1534
+ :target: https://tqdm.github.io/PyData2019/slides.html
1535
+ .. |Merch| image:: https://tqdm.github.io/img/merch.jpg
1536
+ :target: https://tqdm.github.io/merch
1537
+ .. |Build-Status| image:: https://img.shields.io/github/actions/workflow/status/tqdm/tqdm/test.yml?branch=master&label=tqdm&logo=GitHub
1538
+ :target: https://github.com/tqdm/tqdm/actions/workflows/test.yml
1539
+ .. |Coverage-Status| image:: https://img.shields.io/coveralls/github/tqdm/tqdm/master?logo=coveralls
1540
+ :target: https://coveralls.io/github/tqdm/tqdm
1541
+ .. |Branch-Coverage-Status| image:: https://codecov.io/gh/tqdm/tqdm/branch/master/graph/badge.svg
1542
+ :target: https://codecov.io/gh/tqdm/tqdm
1543
+ .. |Codacy-Grade| image:: https://app.codacy.com/project/badge/Grade/3f965571598f44549c7818f29cdcf177
1544
+ :target: https://www.codacy.com/gh/tqdm/tqdm/dashboard
1545
+ .. |CII Best Practices| image:: https://bestpractices.coreinfrastructure.org/projects/3264/badge
1546
+ :target: https://bestpractices.coreinfrastructure.org/projects/3264
1547
+ .. |GitHub-Status| image:: https://img.shields.io/github/tag/tqdm/tqdm.svg?maxAge=86400&logo=github&logoColor=white
1548
+ :target: https://github.com/tqdm/tqdm/releases
1549
+ .. |GitHub-Forks| image:: https://img.shields.io/github/forks/tqdm/tqdm.svg?logo=github&logoColor=white
1550
+ :target: https://github.com/tqdm/tqdm/network
1551
+ .. |GitHub-Stars| image:: https://img.shields.io/github/stars/tqdm/tqdm.svg?logo=github&logoColor=white
1552
+ :target: https://github.com/tqdm/tqdm/stargazers
1553
+ .. |GitHub-Commits| image:: https://img.shields.io/github/commit-activity/y/tqdm/tqdm.svg?logo=git&logoColor=white
1554
+ :target: https://github.com/tqdm/tqdm/graphs/commit-activity
1555
+ .. |GitHub-Issues| image:: https://img.shields.io/github/issues-closed/tqdm/tqdm.svg?logo=github&logoColor=white
1556
+ :target: https://github.com/tqdm/tqdm/issues?q=
1557
+ .. |GitHub-PRs| image:: https://img.shields.io/github/issues-pr-closed/tqdm/tqdm.svg?logo=github&logoColor=white
1558
+ :target: https://github.com/tqdm/tqdm/pulls
1559
+ .. |GitHub-Contributions| image:: https://img.shields.io/github/contributors/tqdm/tqdm.svg?logo=github&logoColor=white
1560
+ :target: https://github.com/tqdm/tqdm/graphs/contributors
1561
+ .. |GitHub-Updated| image:: https://img.shields.io/github/last-commit/tqdm/tqdm/master.svg?logo=github&logoColor=white&label=pushed
1562
+ :target: https://github.com/tqdm/tqdm/pulse
1563
+ .. |Gift-Casper| image:: https://img.shields.io/badge/dynamic/json.svg?color=ff69b4&label=gifts%20received&prefix=%C2%A3&query=%24..sum&url=https%3A%2F%2Fcaspersci.uk.to%2Fgifts.json
1564
+ :target: https://cdcl.ml/sponsor
1565
+ .. |Versions| image:: https://img.shields.io/pypi/v/tqdm.svg
1566
+ :target: https://tqdm.github.io/releases
1567
+ .. |PyPI-Downloads| image:: https://img.shields.io/pypi/dm/tqdm.svg?label=pypi%20downloads&logo=PyPI&logoColor=white
1568
+ :target: https://pepy.tech/project/tqdm
1569
+ .. |Py-Versions| image:: https://img.shields.io/pypi/pyversions/tqdm.svg?logo=python&logoColor=white
1570
+ :target: https://pypi.org/project/tqdm
1571
+ .. |Conda-Forge-Status| image:: https://img.shields.io/conda/v/conda-forge/tqdm.svg?label=conda-forge&logo=conda-forge
1572
+ :target: https://anaconda.org/conda-forge/tqdm
1573
+ .. |Snapcraft| image:: https://img.shields.io/badge/snap-install-82BEA0.svg?logo=snapcraft
1574
+ :target: https://snapcraft.io/tqdm
1575
+ .. |Docker| image:: https://img.shields.io/badge/docker-pull-blue.svg?logo=docker&logoColor=white
1576
+ :target: https://hub.docker.com/r/tqdm/tqdm
1577
+ .. |Libraries-Rank| image:: https://img.shields.io/librariesio/sourcerank/pypi/tqdm.svg?logo=koding&logoColor=white
1578
+ :target: https://libraries.io/pypi/tqdm
1579
+ .. |Libraries-Dependents| image:: https://img.shields.io/librariesio/dependent-repos/pypi/tqdm.svg?logo=koding&logoColor=white
1580
+ :target: https://github.com/tqdm/tqdm/network/dependents
1581
+ .. |OpenHub-Status| image:: https://www.openhub.net/p/tqdm/widgets/project_thin_badge?format=gif
1582
+ :target: https://www.openhub.net/p/tqdm?ref=Thin+badge
1583
+ .. |awesome-python| image:: https://awesome.re/mentioned-badge.svg
1584
+ :target: https://github.com/vinta/awesome-python
1585
+ .. |LICENCE| image:: https://img.shields.io/pypi/l/tqdm.svg
1586
+ :target: https://raw.githubusercontent.com/tqdm/tqdm/master/LICENCE
1587
+ .. |DOI| image:: https://img.shields.io/badge/DOI-10.5281/zenodo.595120-blue.svg
1588
+ :target: https://doi.org/10.5281/zenodo.595120
1589
+ .. |binder-demo| image:: https://mybinder.org/badge_logo.svg
1590
+ :target: https://mybinder.org/v2/gh/tqdm/tqdm/master?filepath=DEMO.ipynb
1591
+ .. |Screenshot-Jupyter1| image:: https://tqdm.github.io/img/jupyter-1.gif
1592
+ .. |Screenshot-Jupyter2| image:: https://tqdm.github.io/img/jupyter-2.gif
1593
+ .. |Screenshot-Jupyter3| image:: https://tqdm.github.io/img/jupyter-3.gif
1594
+ .. |README-Hits| image:: https://cgi.cdcl.ml/hits?q=tqdm&style=social&r=https://github.com/tqdm/tqdm&l=https://tqdm.github.io/img/favicon.png&f=https://tqdm.github.io/img/logo.gif
1595
+ :target: https://cgi.cdcl.ml/hits?q=tqdm&a=plot&r=https://github.com/tqdm/tqdm&l=https://tqdm.github.io/img/favicon.png&f=https://tqdm.github.io/img/logo.gif&style=social
.cache/pip/http-v2/4/4/e/5/b/44e5b11a6caa92636d8ccfe658d420ba4ed8f67f7f4e835b214255aa ADDED
Binary file (1.8 kB). View file