update devchat 11.15
This commit is contained in:
parent
ce89bf904f
commit
e6983c11d7
BIN
site-packages/.DS_Store
vendored
BIN
site-packages/.DS_Store
vendored
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
../../../bin/pygmentize,sha256=wsADOQiAcHvmlzoSNLltpIj4Ojmnqr6civ8b6z776Fo,246
|
||||
../../../bin/pygmentize,sha256=OIIEh-Vdkj0JRZedbDaff_MLhLrP2UiVlOFKMU24hr8,246
|
||||
Pygments-2.16.1.dist-info/AUTHORS,sha256=dK80VJCrS-ONy4SVzPGhUP1zA_Jb1xbVKkNJbq8jEOw,10205
|
||||
Pygments-2.16.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
Pygments-2.16.1.dist-info/LICENSE,sha256=qdZvHVJt8C4p3Oc0NtNOVuhjL0bCdbvf_HBWnogvnxc,1331
|
||||
|
BIN
site-packages/_yaml/.DS_Store
vendored
BIN
site-packages/_yaml/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/anyio/.DS_Store
vendored
BIN
site-packages/anyio/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/anyio/_backends/.DS_Store
vendored
BIN
site-packages/anyio/_backends/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/anyio/_core/.DS_Store
vendored
BIN
site-packages/anyio/_core/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/anyio/abc/.DS_Store
vendored
BIN
site-packages/anyio/abc/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/anyio/streams/.DS_Store
vendored
BIN
site-packages/anyio/streams/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/certifi/.DS_Store
vendored
BIN
site-packages/certifi/.DS_Store
vendored
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
../../../bin/normalizer,sha256=YB3DZvwaeDaco97__ogRgzUD6BWcQfR4FIDywnfeBc0,264
|
||||
../../../bin/normalizer,sha256=kihdyWtCGlWGyMKjHiPs_eLP1DXyuK3r8cvuk2gln6Y,264
|
||||
charset_normalizer-3.3.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
charset_normalizer-3.3.2.dist-info/LICENSE,sha256=6zGgxaT7Cbik4yBV0lweX5w1iidS_vPNcgIT0cz-4kE,1070
|
||||
charset_normalizer-3.3.2.dist-info/METADATA,sha256=cfLhl5A6SI-F0oclm8w8ux9wshL1nipdeCdVnYb4AaA,33550
|
||||
|
BIN
site-packages/charset_normalizer/.DS_Store
vendored
BIN
site-packages/charset_normalizer/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/charset_normalizer/cli/.DS_Store
vendored
BIN
site-packages/charset_normalizer/cli/.DS_Store
vendored
Binary file not shown.
@ -2,7 +2,6 @@ click-8.1.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvF
|
||||
click-8.1.7.dist-info/LICENSE.rst,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475
|
||||
click-8.1.7.dist-info/METADATA,sha256=qIMevCxGA9yEmJOM_4WHuUJCwWpsIEVbCPOhs45YPN4,3014
|
||||
click-8.1.7.dist-info/RECORD,,
|
||||
click-8.1.7.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
click-8.1.7.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
|
||||
click-8.1.7.dist-info/top_level.txt,sha256=J1ZQogalYS4pphY_lPECoNMfw0HzTSrZglC4Yfwo4xA,6
|
||||
click/__init__.py,sha256=YDDbjm406dTOA0V8bTtdGnhN7zj5j-_dFRewZF_pLvw,3138
|
||||
|
441
site-packages/colorama-0.4.6.dist-info/METADATA
Normal file
441
site-packages/colorama-0.4.6.dist-info/METADATA
Normal file
@ -0,0 +1,441 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: colorama
|
||||
Version: 0.4.6
|
||||
Summary: Cross-platform colored terminal text.
|
||||
Project-URL: Homepage, https://github.com/tartley/colorama
|
||||
Author-email: Jonathan Hartley <tartley@tartley.com>
|
||||
License-File: LICENSE.txt
|
||||
Keywords: ansi,color,colour,crossplatform,terminal,text,windows,xplatform
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: Terminals
|
||||
Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7
|
||||
Description-Content-Type: text/x-rst
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/colorama.svg
|
||||
:target: https://pypi.org/project/colorama/
|
||||
:alt: Latest Version
|
||||
|
||||
.. image:: https://img.shields.io/pypi/pyversions/colorama.svg
|
||||
:target: https://pypi.org/project/colorama/
|
||||
:alt: Supported Python versions
|
||||
|
||||
.. image:: https://github.com/tartley/colorama/actions/workflows/test.yml/badge.svg
|
||||
:target: https://github.com/tartley/colorama/actions/workflows/test.yml
|
||||
:alt: Build Status
|
||||
|
||||
Colorama
|
||||
========
|
||||
|
||||
Makes ANSI escape character sequences (for producing colored terminal text and
|
||||
cursor positioning) work under MS Windows.
|
||||
|
||||
.. |donate| image:: https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif
|
||||
:target: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=2MZ9D2GMLYCUJ&item_name=Colorama¤cy_code=USD
|
||||
:alt: Donate with Paypal
|
||||
|
||||
`PyPI for releases <https://pypi.org/project/colorama/>`_ |
|
||||
`Github for source <https://github.com/tartley/colorama>`_ |
|
||||
`Colorama for enterprise on Tidelift <https://github.com/tartley/colorama/blob/master/ENTERPRISE.md>`_
|
||||
|
||||
If you find Colorama useful, please |donate| to the authors. Thank you!
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Tested on CPython 2.7, 3.7, 3.8, 3.9 and 3.10 and Pypy 2.7 and 3.8.
|
||||
|
||||
No requirements other than the standard library.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install colorama
|
||||
# or
|
||||
conda install -c anaconda colorama
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
ANSI escape character sequences have long been used to produce colored terminal
|
||||
text and cursor positioning on Unix and Macs. Colorama makes this work on
|
||||
Windows, too, by wrapping ``stdout``, stripping ANSI sequences it finds (which
|
||||
would appear as gobbledygook in the output), and converting them into the
|
||||
appropriate win32 calls to modify the state of the terminal. On other platforms,
|
||||
Colorama does nothing.
|
||||
|
||||
This has the upshot of providing a simple cross-platform API for printing
|
||||
colored terminal text from Python, and has the happy side-effect that existing
|
||||
applications or libraries which use ANSI sequences to produce colored output on
|
||||
Linux or Macs can now also work on Windows, simply by calling
|
||||
``colorama.just_fix_windows_console()`` (since v0.4.6) or ``colorama.init()``
|
||||
(all versions, but may have other side-effects – see below).
|
||||
|
||||
An alternative approach is to install ``ansi.sys`` on Windows machines, which
|
||||
provides the same behaviour for all applications running in terminals. Colorama
|
||||
is intended for situations where that isn't easy (e.g., maybe your app doesn't
|
||||
have an installer.)
|
||||
|
||||
Demo scripts in the source code repository print some colored text using
|
||||
ANSI sequences. Compare their output under Gnome-terminal's built in ANSI
|
||||
handling, versus on Windows Command-Prompt using Colorama:
|
||||
|
||||
.. image:: https://github.com/tartley/colorama/raw/master/screenshots/ubuntu-demo.png
|
||||
:width: 661
|
||||
:height: 357
|
||||
:alt: ANSI sequences on Ubuntu under gnome-terminal.
|
||||
|
||||
.. image:: https://github.com/tartley/colorama/raw/master/screenshots/windows-demo.png
|
||||
:width: 668
|
||||
:height: 325
|
||||
:alt: Same ANSI sequences on Windows, using Colorama.
|
||||
|
||||
These screenshots show that, on Windows, Colorama does not support ANSI 'dim
|
||||
text'; it looks the same as 'normal text'.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Initialisation
|
||||
..............
|
||||
|
||||
If the only thing you want from Colorama is to get ANSI escapes to work on
|
||||
Windows, then run:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from colorama import just_fix_windows_console
|
||||
just_fix_windows_console()
|
||||
|
||||
If you're on a recent version of Windows 10 or better, and your stdout/stderr
|
||||
are pointing to a Windows console, then this will flip the magic configuration
|
||||
switch to enable Windows' built-in ANSI support.
|
||||
|
||||
If you're on an older version of Windows, and your stdout/stderr are pointing to
|
||||
a Windows console, then this will wrap ``sys.stdout`` and/or ``sys.stderr`` in a
|
||||
magic file object that intercepts ANSI escape sequences and issues the
|
||||
appropriate Win32 calls to emulate them.
|
||||
|
||||
In all other circumstances, it does nothing whatsoever. Basically the idea is
|
||||
that this makes Windows act like Unix with respect to ANSI escape handling.
|
||||
|
||||
It's safe to call this function multiple times. It's safe to call this function
|
||||
on non-Windows platforms, but it won't do anything. It's safe to call this
|
||||
function when one or both of your stdout/stderr are redirected to a file – it
|
||||
won't do anything to those streams.
|
||||
|
||||
Alternatively, you can use the older interface with more features (but also more
|
||||
potential footguns):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from colorama import init
|
||||
init()
|
||||
|
||||
This does the same thing as ``just_fix_windows_console``, except for the
|
||||
following differences:
|
||||
|
||||
- It's not safe to call ``init`` multiple times; you can end up with multiple
|
||||
layers of wrapping and broken ANSI support.
|
||||
|
||||
- Colorama will apply a heuristic to guess whether stdout/stderr support ANSI,
|
||||
and if it thinks they don't, then it will wrap ``sys.stdout`` and
|
||||
``sys.stderr`` in a magic file object that strips out ANSI escape sequences
|
||||
before printing them. This happens on all platforms, and can be convenient if
|
||||
you want to write your code to emit ANSI escape sequences unconditionally, and
|
||||
let Colorama decide whether they should actually be output. But note that
|
||||
Colorama's heuristic is not particularly clever.
|
||||
|
||||
- ``init`` also accepts explicit keyword args to enable/disable various
|
||||
functionality – see below.
|
||||
|
||||
To stop using Colorama before your program exits, simply call ``deinit()``.
|
||||
This will restore ``stdout`` and ``stderr`` to their original values, so that
|
||||
Colorama is disabled. To resume using Colorama again, call ``reinit()``; it is
|
||||
cheaper than calling ``init()`` again (but does the same thing).
|
||||
|
||||
Most users should depend on ``colorama >= 0.4.6``, and use
|
||||
``just_fix_windows_console``. The old ``init`` interface will be supported
|
||||
indefinitely for backwards compatibility, but we don't plan to fix any issues
|
||||
with it, also for backwards compatibility.
|
||||
|
||||
Colored Output
|
||||
..............
|
||||
|
||||
Cross-platform printing of colored text can then be done using Colorama's
|
||||
constant shorthand for ANSI escape sequences. These are deliberately
|
||||
rudimentary, see below.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from colorama import Fore, Back, Style
|
||||
print(Fore.RED + 'some red text')
|
||||
print(Back.GREEN + 'and with a green background')
|
||||
print(Style.DIM + 'and in dim text')
|
||||
print(Style.RESET_ALL)
|
||||
print('back to normal now')
|
||||
|
||||
...or simply by manually printing ANSI sequences from your own code:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
print('\033[31m' + 'some red text')
|
||||
print('\033[39m') # and reset to default color
|
||||
|
||||
...or, Colorama can be used in conjunction with existing ANSI libraries
|
||||
such as the venerable `Termcolor <https://pypi.org/project/termcolor/>`_
|
||||
the fabulous `Blessings <https://pypi.org/project/blessings/>`_,
|
||||
or the incredible `_Rich <https://pypi.org/project/rich/>`_.
|
||||
|
||||
If you wish Colorama's Fore, Back and Style constants were more capable,
|
||||
then consider using one of the above highly capable libraries to generate
|
||||
colors, etc, and use Colorama just for its primary purpose: to convert
|
||||
those ANSI sequences to also work on Windows:
|
||||
|
||||
SIMILARLY, do not send PRs adding the generation of new ANSI types to Colorama.
|
||||
We are only interested in converting ANSI codes to win32 API calls, not
|
||||
shortcuts like the above to generate ANSI characters.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from colorama import just_fix_windows_console
|
||||
from termcolor import colored
|
||||
|
||||
# use Colorama to make Termcolor work on Windows too
|
||||
just_fix_windows_console()
|
||||
|
||||
# then use Termcolor for all colored text output
|
||||
print(colored('Hello, World!', 'green', 'on_red'))
|
||||
|
||||
Available formatting constants are::
|
||||
|
||||
Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
|
||||
Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
|
||||
Style: DIM, NORMAL, BRIGHT, RESET_ALL
|
||||
|
||||
``Style.RESET_ALL`` resets foreground, background, and brightness. Colorama will
|
||||
perform this reset automatically on program exit.
|
||||
|
||||
These are fairly well supported, but not part of the standard::
|
||||
|
||||
Fore: LIGHTBLACK_EX, LIGHTRED_EX, LIGHTGREEN_EX, LIGHTYELLOW_EX, LIGHTBLUE_EX, LIGHTMAGENTA_EX, LIGHTCYAN_EX, LIGHTWHITE_EX
|
||||
Back: LIGHTBLACK_EX, LIGHTRED_EX, LIGHTGREEN_EX, LIGHTYELLOW_EX, LIGHTBLUE_EX, LIGHTMAGENTA_EX, LIGHTCYAN_EX, LIGHTWHITE_EX
|
||||
|
||||
Cursor Positioning
|
||||
..................
|
||||
|
||||
ANSI codes to reposition the cursor are supported. See ``demos/demo06.py`` for
|
||||
an example of how to generate them.
|
||||
|
||||
Init Keyword Args
|
||||
.................
|
||||
|
||||
``init()`` accepts some ``**kwargs`` to override default behaviour.
|
||||
|
||||
init(autoreset=False):
|
||||
If you find yourself repeatedly sending reset sequences to turn off color
|
||||
changes at the end of every print, then ``init(autoreset=True)`` will
|
||||
automate that:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from colorama import init
|
||||
init(autoreset=True)
|
||||
print(Fore.RED + 'some red text')
|
||||
print('automatically back to default color again')
|
||||
|
||||
init(strip=None):
|
||||
Pass ``True`` or ``False`` to override whether ANSI codes should be
|
||||
stripped from the output. The default behaviour is to strip if on Windows
|
||||
or if output is redirected (not a tty).
|
||||
|
||||
init(convert=None):
|
||||
Pass ``True`` or ``False`` to override whether to convert ANSI codes in the
|
||||
output into win32 calls. The default behaviour is to convert if on Windows
|
||||
and output is to a tty (terminal).
|
||||
|
||||
init(wrap=True):
|
||||
On Windows, Colorama works by replacing ``sys.stdout`` and ``sys.stderr``
|
||||
with proxy objects, which override the ``.write()`` method to do their work.
|
||||
If this wrapping causes you problems, then this can be disabled by passing
|
||||
``init(wrap=False)``. The default behaviour is to wrap if ``autoreset`` or
|
||||
``strip`` or ``convert`` are True.
|
||||
|
||||
When wrapping is disabled, colored printing on non-Windows platforms will
|
||||
continue to work as normal. To do cross-platform colored output, you can
|
||||
use Colorama's ``AnsiToWin32`` proxy directly:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import sys
|
||||
from colorama import init, AnsiToWin32
|
||||
init(wrap=False)
|
||||
stream = AnsiToWin32(sys.stderr).stream
|
||||
|
||||
# Python 2
|
||||
print >>stream, Fore.BLUE + 'blue text on stderr'
|
||||
|
||||
# Python 3
|
||||
print(Fore.BLUE + 'blue text on stderr', file=stream)
|
||||
|
||||
Recognised ANSI Sequences
|
||||
.........................
|
||||
|
||||
ANSI sequences generally take the form::
|
||||
|
||||
ESC [ <param> ; <param> ... <command>
|
||||
|
||||
Where ``<param>`` is an integer, and ``<command>`` is a single letter. Zero or
|
||||
more params are passed to a ``<command>``. If no params are passed, it is
|
||||
generally synonymous with passing a single zero. No spaces exist in the
|
||||
sequence; they have been inserted here simply to read more easily.
|
||||
|
||||
The only ANSI sequences that Colorama converts into win32 calls are::
|
||||
|
||||
ESC [ 0 m # reset all (colors and brightness)
|
||||
ESC [ 1 m # bright
|
||||
ESC [ 2 m # dim (looks same as normal brightness)
|
||||
ESC [ 22 m # normal brightness
|
||||
|
||||
# FOREGROUND:
|
||||
ESC [ 30 m # black
|
||||
ESC [ 31 m # red
|
||||
ESC [ 32 m # green
|
||||
ESC [ 33 m # yellow
|
||||
ESC [ 34 m # blue
|
||||
ESC [ 35 m # magenta
|
||||
ESC [ 36 m # cyan
|
||||
ESC [ 37 m # white
|
||||
ESC [ 39 m # reset
|
||||
|
||||
# BACKGROUND
|
||||
ESC [ 40 m # black
|
||||
ESC [ 41 m # red
|
||||
ESC [ 42 m # green
|
||||
ESC [ 43 m # yellow
|
||||
ESC [ 44 m # blue
|
||||
ESC [ 45 m # magenta
|
||||
ESC [ 46 m # cyan
|
||||
ESC [ 47 m # white
|
||||
ESC [ 49 m # reset
|
||||
|
||||
# cursor positioning
|
||||
ESC [ y;x H # position cursor at x across, y down
|
||||
ESC [ y;x f # position cursor at x across, y down
|
||||
ESC [ n A # move cursor n lines up
|
||||
ESC [ n B # move cursor n lines down
|
||||
ESC [ n C # move cursor n characters forward
|
||||
ESC [ n D # move cursor n characters backward
|
||||
|
||||
# clear the screen
|
||||
ESC [ mode J # clear the screen
|
||||
|
||||
# clear the line
|
||||
ESC [ mode K # clear the line
|
||||
|
||||
Multiple numeric params to the ``'m'`` command can be combined into a single
|
||||
sequence::
|
||||
|
||||
ESC [ 36 ; 45 ; 1 m # bright cyan text on magenta background
|
||||
|
||||
All other ANSI sequences of the form ``ESC [ <param> ; <param> ... <command>``
|
||||
are silently stripped from the output on Windows.
|
||||
|
||||
Any other form of ANSI sequence, such as single-character codes or alternative
|
||||
initial characters, are not recognised or stripped. It would be cool to add
|
||||
them though. Let me know if it would be useful for you, via the Issues on
|
||||
GitHub.
|
||||
|
||||
Status & Known Problems
|
||||
-----------------------
|
||||
|
||||
I've personally only tested it on Windows XP (CMD, Console2), Ubuntu
|
||||
(gnome-terminal, xterm), and OS X.
|
||||
|
||||
Some valid ANSI sequences aren't recognised.
|
||||
|
||||
If you're hacking on the code, see `README-hacking.md`_. ESPECIALLY, see the
|
||||
explanation there of why we do not want PRs that allow Colorama to generate new
|
||||
types of ANSI codes.
|
||||
|
||||
See outstanding issues and wish-list:
|
||||
https://github.com/tartley/colorama/issues
|
||||
|
||||
If anything doesn't work for you, or doesn't do what you expected or hoped for,
|
||||
I'd love to hear about it on that issues list, would be delighted by patches,
|
||||
and would be happy to grant commit access to anyone who submits a working patch
|
||||
or two.
|
||||
|
||||
.. _README-hacking.md: README-hacking.md
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Copyright Jonathan Hartley & Arnon Yaari, 2013-2020. BSD 3-Clause license; see
|
||||
LICENSE file.
|
||||
|
||||
Professional support
|
||||
--------------------
|
||||
|
||||
.. |tideliftlogo| image:: https://cdn2.hubspot.net/hubfs/4008838/website/logos/logos_for_download/Tidelift_primary-shorthand-logo.png
|
||||
:alt: Tidelift
|
||||
:target: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme
|
||||
|
||||
.. list-table::
|
||||
:widths: 10 100
|
||||
|
||||
* - |tideliftlogo|
|
||||
- Professional support for colorama is available as part of the
|
||||
`Tidelift Subscription`_.
|
||||
Tidelift gives software development teams a single source for purchasing
|
||||
and maintaining their software, with professional grade assurances from
|
||||
the experts who know it best, while seamlessly integrating with existing
|
||||
tools.
|
||||
|
||||
.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme
|
||||
|
||||
Thanks
|
||||
------
|
||||
|
||||
See the CHANGELOG for more thanks!
|
||||
|
||||
* Marc Schlaich (schlamar) for a ``setup.py`` fix for Python2.5.
|
||||
* Marc Abramowitz, reported & fixed a crash on exit with closed ``stdout``,
|
||||
providing a solution to issue #7's setuptools/distutils debate,
|
||||
and other fixes.
|
||||
* User 'eryksun', for guidance on correctly instantiating ``ctypes.windll``.
|
||||
* Matthew McCormick for politely pointing out a longstanding crash on non-Win.
|
||||
* Ben Hoyt, for a magnificent fix under 64-bit Windows.
|
||||
* Jesse at Empty Square for submitting a fix for examples in the README.
|
||||
* User 'jamessp', an observant documentation fix for cursor positioning.
|
||||
* User 'vaal1239', Dave Mckee & Lackner Kristof for a tiny but much-needed Win7
|
||||
fix.
|
||||
* Julien Stuyck, for wisely suggesting Python3 compatible updates to README.
|
||||
* Daniel Griffith for multiple fabulous patches.
|
||||
* Oscar Lesta for a valuable fix to stop ANSI chars being sent to non-tty
|
||||
output.
|
||||
* Roger Binns, for many suggestions, valuable feedback, & bug reports.
|
||||
* Tim Golden for thought and much appreciated feedback on the initial idea.
|
||||
* User 'Zearin' for updates to the README file.
|
||||
* John Szakmeister for adding support for light colors
|
||||
* Charles Merriam for adding documentation to demos
|
||||
* Jurko for a fix on 64-bit Windows CPython2.5 w/o ctypes
|
||||
* Florian Bruhin for a fix when stdout or stderr are None
|
||||
* Thomas Weininger for fixing ValueError on Windows
|
||||
* Remi Rampin for better Github integration and fixes to the README file
|
||||
* Simeon Visser for closing a file handle using 'with' and updating classifiers
|
||||
to include Python 3.3 and 3.4
|
||||
* Andy Neff for fixing RESET of LIGHT_EX colors.
|
||||
* Jonathan Hartley for the initial idea and implementation.
|
31
site-packages/colorama-0.4.6.dist-info/RECORD
Normal file
31
site-packages/colorama-0.4.6.dist-info/RECORD
Normal file
@ -0,0 +1,31 @@
|
||||
colorama-0.4.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
colorama-0.4.6.dist-info/METADATA,sha256=e67SnrUMOym9sz_4TjF3vxvAV4T3aF7NyqRHHH3YEMw,17158
|
||||
colorama-0.4.6.dist-info/RECORD,,
|
||||
colorama-0.4.6.dist-info/WHEEL,sha256=cdcF4Fbd0FPtw2EMIOwH-3rSOTUdTCeOSXRMD1iLUb8,105
|
||||
colorama-0.4.6.dist-info/licenses/LICENSE.txt,sha256=ysNcAmhuXQSlpxQL-zs25zrtSWZW6JEQLkKIhteTAxg,1491
|
||||
colorama/__init__.py,sha256=wePQA4U20tKgYARySLEC047ucNX-g8pRLpYBuiHlLb8,266
|
||||
colorama/__pycache__/__init__.cpython-39.pyc,,
|
||||
colorama/__pycache__/ansi.cpython-39.pyc,,
|
||||
colorama/__pycache__/ansitowin32.cpython-39.pyc,,
|
||||
colorama/__pycache__/initialise.cpython-39.pyc,,
|
||||
colorama/__pycache__/win32.cpython-39.pyc,,
|
||||
colorama/__pycache__/winterm.cpython-39.pyc,,
|
||||
colorama/ansi.py,sha256=Top4EeEuaQdBWdteKMEcGOTeKeF19Q-Wo_6_Cj5kOzQ,2522
|
||||
colorama/ansitowin32.py,sha256=vPNYa3OZbxjbuFyaVo0Tmhmy1FZ1lKMWCnT7odXpItk,11128
|
||||
colorama/initialise.py,sha256=-hIny86ClXo39ixh5iSCfUIa2f_h_bgKRDW7gqs-KLU,3325
|
||||
colorama/tests/__init__.py,sha256=MkgPAEzGQd-Rq0w0PZXSX2LadRWhUECcisJY8lSrm4Q,75
|
||||
colorama/tests/__pycache__/__init__.cpython-39.pyc,,
|
||||
colorama/tests/__pycache__/ansi_test.cpython-39.pyc,,
|
||||
colorama/tests/__pycache__/ansitowin32_test.cpython-39.pyc,,
|
||||
colorama/tests/__pycache__/initialise_test.cpython-39.pyc,,
|
||||
colorama/tests/__pycache__/isatty_test.cpython-39.pyc,,
|
||||
colorama/tests/__pycache__/utils.cpython-39.pyc,,
|
||||
colorama/tests/__pycache__/winterm_test.cpython-39.pyc,,
|
||||
colorama/tests/ansi_test.py,sha256=FeViDrUINIZcr505PAxvU4AjXz1asEiALs9GXMhwRaE,2839
|
||||
colorama/tests/ansitowin32_test.py,sha256=RN7AIhMJ5EqDsYaCjVo-o4u8JzDD4ukJbmevWKS70rY,10678
|
||||
colorama/tests/initialise_test.py,sha256=BbPy-XfyHwJ6zKozuQOvNvQZzsx9vdb_0bYXn7hsBTc,6741
|
||||
colorama/tests/isatty_test.py,sha256=Pg26LRpv0yQDB5Ac-sxgVXG7hsA1NYvapFgApZfYzZg,1866
|
||||
colorama/tests/utils.py,sha256=1IIRylG39z5-dzq09R_ngufxyPZxgldNbrxKxUGwGKE,1079
|
||||
colorama/tests/winterm_test.py,sha256=qoWFPEjym5gm2RuMwpf3pOis3a5r_PJZFCzK254JL8A,3709
|
||||
colorama/win32.py,sha256=YQOKwMTwtGBbsY4dL5HYTvwTeP9wIQra5MvPNddpxZs,6181
|
||||
colorama/winterm.py,sha256=XCQFDHjPi6AHYNdZwy0tA02H-Jh48Jp-HvCjeLeLp3U,7134
|
@ -1,5 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.41.2)
|
||||
Generator: hatchling 1.11.1
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
27
site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt
Normal file
27
site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2010 Jonathan Hartley
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holders, nor those of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
7
site-packages/colorama/__init__.py
Normal file
7
site-packages/colorama/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
from .initialise import init, deinit, reinit, colorama_text, just_fix_windows_console
|
||||
from .ansi import Fore, Back, Style, Cursor
|
||||
from .ansitowin32 import AnsiToWin32
|
||||
|
||||
__version__ = '0.4.6'
|
||||
|
102
site-packages/colorama/ansi.py
Normal file
102
site-packages/colorama/ansi.py
Normal file
@ -0,0 +1,102 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
'''
|
||||
This module generates ANSI character codes to printing colors to terminals.
|
||||
See: http://en.wikipedia.org/wiki/ANSI_escape_code
|
||||
'''
|
||||
|
||||
CSI = '\033['
|
||||
OSC = '\033]'
|
||||
BEL = '\a'
|
||||
|
||||
|
||||
def code_to_chars(code):
|
||||
return CSI + str(code) + 'm'
|
||||
|
||||
def set_title(title):
|
||||
return OSC + '2;' + title + BEL
|
||||
|
||||
def clear_screen(mode=2):
|
||||
return CSI + str(mode) + 'J'
|
||||
|
||||
def clear_line(mode=2):
|
||||
return CSI + str(mode) + 'K'
|
||||
|
||||
|
||||
class AnsiCodes(object):
|
||||
def __init__(self):
|
||||
# the subclasses declare class attributes which are numbers.
|
||||
# Upon instantiation we define instance attributes, which are the same
|
||||
# as the class attributes but wrapped with the ANSI escape sequence
|
||||
for name in dir(self):
|
||||
if not name.startswith('_'):
|
||||
value = getattr(self, name)
|
||||
setattr(self, name, code_to_chars(value))
|
||||
|
||||
|
||||
class AnsiCursor(object):
|
||||
def UP(self, n=1):
|
||||
return CSI + str(n) + 'A'
|
||||
def DOWN(self, n=1):
|
||||
return CSI + str(n) + 'B'
|
||||
def FORWARD(self, n=1):
|
||||
return CSI + str(n) + 'C'
|
||||
def BACK(self, n=1):
|
||||
return CSI + str(n) + 'D'
|
||||
def POS(self, x=1, y=1):
|
||||
return CSI + str(y) + ';' + str(x) + 'H'
|
||||
|
||||
|
||||
class AnsiFore(AnsiCodes):
|
||||
BLACK = 30
|
||||
RED = 31
|
||||
GREEN = 32
|
||||
YELLOW = 33
|
||||
BLUE = 34
|
||||
MAGENTA = 35
|
||||
CYAN = 36
|
||||
WHITE = 37
|
||||
RESET = 39
|
||||
|
||||
# These are fairly well supported, but not part of the standard.
|
||||
LIGHTBLACK_EX = 90
|
||||
LIGHTRED_EX = 91
|
||||
LIGHTGREEN_EX = 92
|
||||
LIGHTYELLOW_EX = 93
|
||||
LIGHTBLUE_EX = 94
|
||||
LIGHTMAGENTA_EX = 95
|
||||
LIGHTCYAN_EX = 96
|
||||
LIGHTWHITE_EX = 97
|
||||
|
||||
|
||||
class AnsiBack(AnsiCodes):
|
||||
BLACK = 40
|
||||
RED = 41
|
||||
GREEN = 42
|
||||
YELLOW = 43
|
||||
BLUE = 44
|
||||
MAGENTA = 45
|
||||
CYAN = 46
|
||||
WHITE = 47
|
||||
RESET = 49
|
||||
|
||||
# These are fairly well supported, but not part of the standard.
|
||||
LIGHTBLACK_EX = 100
|
||||
LIGHTRED_EX = 101
|
||||
LIGHTGREEN_EX = 102
|
||||
LIGHTYELLOW_EX = 103
|
||||
LIGHTBLUE_EX = 104
|
||||
LIGHTMAGENTA_EX = 105
|
||||
LIGHTCYAN_EX = 106
|
||||
LIGHTWHITE_EX = 107
|
||||
|
||||
|
||||
class AnsiStyle(AnsiCodes):
|
||||
BRIGHT = 1
|
||||
DIM = 2
|
||||
NORMAL = 22
|
||||
RESET_ALL = 0
|
||||
|
||||
Fore = AnsiFore()
|
||||
Back = AnsiBack()
|
||||
Style = AnsiStyle()
|
||||
Cursor = AnsiCursor()
|
277
site-packages/colorama/ansitowin32.py
Normal file
277
site-packages/colorama/ansitowin32.py
Normal file
@ -0,0 +1,277 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
|
||||
from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style, BEL
|
||||
from .winterm import enable_vt_processing, WinTerm, WinColor, WinStyle
|
||||
from .win32 import windll, winapi_test
|
||||
|
||||
|
||||
winterm = None
|
||||
if windll is not None:
|
||||
winterm = WinTerm()
|
||||
|
||||
|
||||
class StreamWrapper(object):
|
||||
'''
|
||||
Wraps a stream (such as stdout), acting as a transparent proxy for all
|
||||
attribute access apart from method 'write()', which is delegated to our
|
||||
Converter instance.
|
||||
'''
|
||||
def __init__(self, wrapped, converter):
|
||||
# double-underscore everything to prevent clashes with names of
|
||||
# attributes on the wrapped stream object.
|
||||
self.__wrapped = wrapped
|
||||
self.__convertor = converter
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.__wrapped, name)
|
||||
|
||||
def __enter__(self, *args, **kwargs):
|
||||
# special method lookup bypasses __getattr__/__getattribute__, see
|
||||
# https://stackoverflow.com/questions/12632894/why-doesnt-getattr-work-with-exit
|
||||
# thus, contextlib magic methods are not proxied via __getattr__
|
||||
return self.__wrapped.__enter__(*args, **kwargs)
|
||||
|
||||
def __exit__(self, *args, **kwargs):
|
||||
return self.__wrapped.__exit__(*args, **kwargs)
|
||||
|
||||
def __setstate__(self, state):
|
||||
self.__dict__ = state
|
||||
|
||||
def __getstate__(self):
|
||||
return self.__dict__
|
||||
|
||||
def write(self, text):
|
||||
self.__convertor.write(text)
|
||||
|
||||
def isatty(self):
|
||||
stream = self.__wrapped
|
||||
if 'PYCHARM_HOSTED' in os.environ:
|
||||
if stream is not None and (stream is sys.__stdout__ or stream is sys.__stderr__):
|
||||
return True
|
||||
try:
|
||||
stream_isatty = stream.isatty
|
||||
except AttributeError:
|
||||
return False
|
||||
else:
|
||||
return stream_isatty()
|
||||
|
||||
@property
|
||||
def closed(self):
|
||||
stream = self.__wrapped
|
||||
try:
|
||||
return stream.closed
|
||||
# AttributeError in the case that the stream doesn't support being closed
|
||||
# ValueError for the case that the stream has already been detached when atexit runs
|
||||
except (AttributeError, ValueError):
|
||||
return True
|
||||
|
||||
|
||||
class AnsiToWin32(object):
|
||||
'''
|
||||
Implements a 'write()' method which, on Windows, will strip ANSI character
|
||||
sequences from the text, and if outputting to a tty, will convert them into
|
||||
win32 function calls.
|
||||
'''
|
||||
ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer
|
||||
ANSI_OSC_RE = re.compile('\001?\033\\]([^\a]*)(\a)\002?') # Operating System Command
|
||||
|
||||
def __init__(self, wrapped, convert=None, strip=None, autoreset=False):
|
||||
# The wrapped stream (normally sys.stdout or sys.stderr)
|
||||
self.wrapped = wrapped
|
||||
|
||||
# should we reset colors to defaults after every .write()
|
||||
self.autoreset = autoreset
|
||||
|
||||
# create the proxy wrapping our output stream
|
||||
self.stream = StreamWrapper(wrapped, self)
|
||||
|
||||
on_windows = os.name == 'nt'
|
||||
# We test if the WinAPI works, because even if we are on Windows
|
||||
# we may be using a terminal that doesn't support the WinAPI
|
||||
# (e.g. Cygwin Terminal). In this case it's up to the terminal
|
||||
# to support the ANSI codes.
|
||||
conversion_supported = on_windows and winapi_test()
|
||||
try:
|
||||
fd = wrapped.fileno()
|
||||
except Exception:
|
||||
fd = -1
|
||||
system_has_native_ansi = not on_windows or enable_vt_processing(fd)
|
||||
have_tty = not self.stream.closed and self.stream.isatty()
|
||||
need_conversion = conversion_supported and not system_has_native_ansi
|
||||
|
||||
# should we strip ANSI sequences from our output?
|
||||
if strip is None:
|
||||
strip = need_conversion or not have_tty
|
||||
self.strip = strip
|
||||
|
||||
# should we should convert ANSI sequences into win32 calls?
|
||||
if convert is None:
|
||||
convert = need_conversion and have_tty
|
||||
self.convert = convert
|
||||
|
||||
# dict of ansi codes to win32 functions and parameters
|
||||
self.win32_calls = self.get_win32_calls()
|
||||
|
||||
# are we wrapping stderr?
|
||||
self.on_stderr = self.wrapped is sys.stderr
|
||||
|
||||
def should_wrap(self):
|
||||
'''
|
||||
True if this class is actually needed. If false, then the output
|
||||
stream will not be affected, nor will win32 calls be issued, so
|
||||
wrapping stdout is not actually required. This will generally be
|
||||
False on non-Windows platforms, unless optional functionality like
|
||||
autoreset has been requested using kwargs to init()
|
||||
'''
|
||||
return self.convert or self.strip or self.autoreset
|
||||
|
||||
def get_win32_calls(self):
|
||||
if self.convert and winterm:
|
||||
return {
|
||||
AnsiStyle.RESET_ALL: (winterm.reset_all, ),
|
||||
AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT),
|
||||
AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL),
|
||||
AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL),
|
||||
AnsiFore.BLACK: (winterm.fore, WinColor.BLACK),
|
||||
AnsiFore.RED: (winterm.fore, WinColor.RED),
|
||||
AnsiFore.GREEN: (winterm.fore, WinColor.GREEN),
|
||||
AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW),
|
||||
AnsiFore.BLUE: (winterm.fore, WinColor.BLUE),
|
||||
AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA),
|
||||
AnsiFore.CYAN: (winterm.fore, WinColor.CYAN),
|
||||
AnsiFore.WHITE: (winterm.fore, WinColor.GREY),
|
||||
AnsiFore.RESET: (winterm.fore, ),
|
||||
AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True),
|
||||
AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True),
|
||||
AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True),
|
||||
AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True),
|
||||
AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True),
|
||||
AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True),
|
||||
AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True),
|
||||
AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True),
|
||||
AnsiBack.BLACK: (winterm.back, WinColor.BLACK),
|
||||
AnsiBack.RED: (winterm.back, WinColor.RED),
|
||||
AnsiBack.GREEN: (winterm.back, WinColor.GREEN),
|
||||
AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW),
|
||||
AnsiBack.BLUE: (winterm.back, WinColor.BLUE),
|
||||
AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA),
|
||||
AnsiBack.CYAN: (winterm.back, WinColor.CYAN),
|
||||
AnsiBack.WHITE: (winterm.back, WinColor.GREY),
|
||||
AnsiBack.RESET: (winterm.back, ),
|
||||
AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True),
|
||||
AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True),
|
||||
AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True),
|
||||
AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True),
|
||||
AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True),
|
||||
AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True),
|
||||
AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True),
|
||||
AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True),
|
||||
}
|
||||
return dict()
|
||||
|
||||
def write(self, text):
|
||||
if self.strip or self.convert:
|
||||
self.write_and_convert(text)
|
||||
else:
|
||||
self.wrapped.write(text)
|
||||
self.wrapped.flush()
|
||||
if self.autoreset:
|
||||
self.reset_all()
|
||||
|
||||
|
||||
def reset_all(self):
|
||||
if self.convert:
|
||||
self.call_win32('m', (0,))
|
||||
elif not self.strip and not self.stream.closed:
|
||||
self.wrapped.write(Style.RESET_ALL)
|
||||
|
||||
|
||||
def write_and_convert(self, text):
|
||||
'''
|
||||
Write the given text to our wrapped stream, stripping any ANSI
|
||||
sequences from the text, and optionally converting them into win32
|
||||
calls.
|
||||
'''
|
||||
cursor = 0
|
||||
text = self.convert_osc(text)
|
||||
for match in self.ANSI_CSI_RE.finditer(text):
|
||||
start, end = match.span()
|
||||
self.write_plain_text(text, cursor, start)
|
||||
self.convert_ansi(*match.groups())
|
||||
cursor = end
|
||||
self.write_plain_text(text, cursor, len(text))
|
||||
|
||||
|
||||
def write_plain_text(self, text, start, end):
|
||||
if start < end:
|
||||
self.wrapped.write(text[start:end])
|
||||
self.wrapped.flush()
|
||||
|
||||
|
||||
def convert_ansi(self, paramstring, command):
|
||||
if self.convert:
|
||||
params = self.extract_params(command, paramstring)
|
||||
self.call_win32(command, params)
|
||||
|
||||
|
||||
def extract_params(self, command, paramstring):
|
||||
if command in 'Hf':
|
||||
params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';'))
|
||||
while len(params) < 2:
|
||||
# defaults:
|
||||
params = params + (1,)
|
||||
else:
|
||||
params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0)
|
||||
if len(params) == 0:
|
||||
# defaults:
|
||||
if command in 'JKm':
|
||||
params = (0,)
|
||||
elif command in 'ABCD':
|
||||
params = (1,)
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def call_win32(self, command, params):
|
||||
if command == 'm':
|
||||
for param in params:
|
||||
if param in self.win32_calls:
|
||||
func_args = self.win32_calls[param]
|
||||
func = func_args[0]
|
||||
args = func_args[1:]
|
||||
kwargs = dict(on_stderr=self.on_stderr)
|
||||
func(*args, **kwargs)
|
||||
elif command in 'J':
|
||||
winterm.erase_screen(params[0], on_stderr=self.on_stderr)
|
||||
elif command in 'K':
|
||||
winterm.erase_line(params[0], on_stderr=self.on_stderr)
|
||||
elif command in 'Hf': # cursor position - absolute
|
||||
winterm.set_cursor_position(params, on_stderr=self.on_stderr)
|
||||
elif command in 'ABCD': # cursor position - relative
|
||||
n = params[0]
|
||||
# A - up, B - down, C - forward, D - back
|
||||
x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command]
|
||||
winterm.cursor_adjust(x, y, on_stderr=self.on_stderr)
|
||||
|
||||
|
||||
def convert_osc(self, text):
|
||||
for match in self.ANSI_OSC_RE.finditer(text):
|
||||
start, end = match.span()
|
||||
text = text[:start] + text[end:]
|
||||
paramstring, command = match.groups()
|
||||
if command == BEL:
|
||||
if paramstring.count(";") == 1:
|
||||
params = paramstring.split(";")
|
||||
# 0 - change title and icon (we will only change title)
|
||||
# 1 - change icon (we don't support this)
|
||||
# 2 - change title
|
||||
if params[0] in '02':
|
||||
winterm.set_title(params[1])
|
||||
return text
|
||||
|
||||
|
||||
def flush(self):
|
||||
self.wrapped.flush()
|
121
site-packages/colorama/initialise.py
Normal file
121
site-packages/colorama/initialise.py
Normal file
@ -0,0 +1,121 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
import atexit
|
||||
import contextlib
|
||||
import sys
|
||||
|
||||
from .ansitowin32 import AnsiToWin32
|
||||
|
||||
|
||||
def _wipe_internal_state_for_tests():
|
||||
global orig_stdout, orig_stderr
|
||||
orig_stdout = None
|
||||
orig_stderr = None
|
||||
|
||||
global wrapped_stdout, wrapped_stderr
|
||||
wrapped_stdout = None
|
||||
wrapped_stderr = None
|
||||
|
||||
global atexit_done
|
||||
atexit_done = False
|
||||
|
||||
global fixed_windows_console
|
||||
fixed_windows_console = False
|
||||
|
||||
try:
|
||||
# no-op if it wasn't registered
|
||||
atexit.unregister(reset_all)
|
||||
except AttributeError:
|
||||
# python 2: no atexit.unregister. Oh well, we did our best.
|
||||
pass
|
||||
|
||||
|
||||
def reset_all():
|
||||
if AnsiToWin32 is not None: # Issue #74: objects might become None at exit
|
||||
AnsiToWin32(orig_stdout).reset_all()
|
||||
|
||||
|
||||
def init(autoreset=False, convert=None, strip=None, wrap=True):
|
||||
|
||||
if not wrap and any([autoreset, convert, strip]):
|
||||
raise ValueError('wrap=False conflicts with any other arg=True')
|
||||
|
||||
global wrapped_stdout, wrapped_stderr
|
||||
global orig_stdout, orig_stderr
|
||||
|
||||
orig_stdout = sys.stdout
|
||||
orig_stderr = sys.stderr
|
||||
|
||||
if sys.stdout is None:
|
||||
wrapped_stdout = None
|
||||
else:
|
||||
sys.stdout = wrapped_stdout = \
|
||||
wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
|
||||
if sys.stderr is None:
|
||||
wrapped_stderr = None
|
||||
else:
|
||||
sys.stderr = wrapped_stderr = \
|
||||
wrap_stream(orig_stderr, convert, strip, autoreset, wrap)
|
||||
|
||||
global atexit_done
|
||||
if not atexit_done:
|
||||
atexit.register(reset_all)
|
||||
atexit_done = True
|
||||
|
||||
|
||||
def deinit():
|
||||
if orig_stdout is not None:
|
||||
sys.stdout = orig_stdout
|
||||
if orig_stderr is not None:
|
||||
sys.stderr = orig_stderr
|
||||
|
||||
|
||||
def just_fix_windows_console():
|
||||
global fixed_windows_console
|
||||
|
||||
if sys.platform != "win32":
|
||||
return
|
||||
if fixed_windows_console:
|
||||
return
|
||||
if wrapped_stdout is not None or wrapped_stderr is not None:
|
||||
# Someone already ran init() and it did stuff, so we won't second-guess them
|
||||
return
|
||||
|
||||
# On newer versions of Windows, AnsiToWin32.__init__ will implicitly enable the
|
||||
# native ANSI support in the console as a side-effect. We only need to actually
|
||||
# replace sys.stdout/stderr if we're in the old-style conversion mode.
|
||||
new_stdout = AnsiToWin32(sys.stdout, convert=None, strip=None, autoreset=False)
|
||||
if new_stdout.convert:
|
||||
sys.stdout = new_stdout
|
||||
new_stderr = AnsiToWin32(sys.stderr, convert=None, strip=None, autoreset=False)
|
||||
if new_stderr.convert:
|
||||
sys.stderr = new_stderr
|
||||
|
||||
fixed_windows_console = True
|
||||
|
||||
@contextlib.contextmanager
|
||||
def colorama_text(*args, **kwargs):
|
||||
init(*args, **kwargs)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
deinit()
|
||||
|
||||
|
||||
def reinit():
|
||||
if wrapped_stdout is not None:
|
||||
sys.stdout = wrapped_stdout
|
||||
if wrapped_stderr is not None:
|
||||
sys.stderr = wrapped_stderr
|
||||
|
||||
|
||||
def wrap_stream(stream, convert, strip, autoreset, wrap):
|
||||
if wrap:
|
||||
wrapper = AnsiToWin32(stream,
|
||||
convert=convert, strip=strip, autoreset=autoreset)
|
||||
if wrapper.should_wrap():
|
||||
stream = wrapper.stream
|
||||
return stream
|
||||
|
||||
|
||||
# Use this for initial setup as well, to reduce code duplication
|
||||
_wipe_internal_state_for_tests()
|
1
site-packages/colorama/tests/__init__.py
Normal file
1
site-packages/colorama/tests/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
76
site-packages/colorama/tests/ansi_test.py
Normal file
76
site-packages/colorama/tests/ansi_test.py
Normal file
@ -0,0 +1,76 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
import sys
|
||||
from unittest import TestCase, main
|
||||
|
||||
from ..ansi import Back, Fore, Style
|
||||
from ..ansitowin32 import AnsiToWin32
|
||||
|
||||
stdout_orig = sys.stdout
|
||||
stderr_orig = sys.stderr
|
||||
|
||||
|
||||
class AnsiTest(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
# sanity check: stdout should be a file or StringIO object.
|
||||
# It will only be AnsiToWin32 if init() has previously wrapped it
|
||||
self.assertNotEqual(type(sys.stdout), AnsiToWin32)
|
||||
self.assertNotEqual(type(sys.stderr), AnsiToWin32)
|
||||
|
||||
def tearDown(self):
|
||||
sys.stdout = stdout_orig
|
||||
sys.stderr = stderr_orig
|
||||
|
||||
|
||||
def testForeAttributes(self):
|
||||
self.assertEqual(Fore.BLACK, '\033[30m')
|
||||
self.assertEqual(Fore.RED, '\033[31m')
|
||||
self.assertEqual(Fore.GREEN, '\033[32m')
|
||||
self.assertEqual(Fore.YELLOW, '\033[33m')
|
||||
self.assertEqual(Fore.BLUE, '\033[34m')
|
||||
self.assertEqual(Fore.MAGENTA, '\033[35m')
|
||||
self.assertEqual(Fore.CYAN, '\033[36m')
|
||||
self.assertEqual(Fore.WHITE, '\033[37m')
|
||||
self.assertEqual(Fore.RESET, '\033[39m')
|
||||
|
||||
# Check the light, extended versions.
|
||||
self.assertEqual(Fore.LIGHTBLACK_EX, '\033[90m')
|
||||
self.assertEqual(Fore.LIGHTRED_EX, '\033[91m')
|
||||
self.assertEqual(Fore.LIGHTGREEN_EX, '\033[92m')
|
||||
self.assertEqual(Fore.LIGHTYELLOW_EX, '\033[93m')
|
||||
self.assertEqual(Fore.LIGHTBLUE_EX, '\033[94m')
|
||||
self.assertEqual(Fore.LIGHTMAGENTA_EX, '\033[95m')
|
||||
self.assertEqual(Fore.LIGHTCYAN_EX, '\033[96m')
|
||||
self.assertEqual(Fore.LIGHTWHITE_EX, '\033[97m')
|
||||
|
||||
|
||||
def testBackAttributes(self):
|
||||
self.assertEqual(Back.BLACK, '\033[40m')
|
||||
self.assertEqual(Back.RED, '\033[41m')
|
||||
self.assertEqual(Back.GREEN, '\033[42m')
|
||||
self.assertEqual(Back.YELLOW, '\033[43m')
|
||||
self.assertEqual(Back.BLUE, '\033[44m')
|
||||
self.assertEqual(Back.MAGENTA, '\033[45m')
|
||||
self.assertEqual(Back.CYAN, '\033[46m')
|
||||
self.assertEqual(Back.WHITE, '\033[47m')
|
||||
self.assertEqual(Back.RESET, '\033[49m')
|
||||
|
||||
# Check the light, extended versions.
|
||||
self.assertEqual(Back.LIGHTBLACK_EX, '\033[100m')
|
||||
self.assertEqual(Back.LIGHTRED_EX, '\033[101m')
|
||||
self.assertEqual(Back.LIGHTGREEN_EX, '\033[102m')
|
||||
self.assertEqual(Back.LIGHTYELLOW_EX, '\033[103m')
|
||||
self.assertEqual(Back.LIGHTBLUE_EX, '\033[104m')
|
||||
self.assertEqual(Back.LIGHTMAGENTA_EX, '\033[105m')
|
||||
self.assertEqual(Back.LIGHTCYAN_EX, '\033[106m')
|
||||
self.assertEqual(Back.LIGHTWHITE_EX, '\033[107m')
|
||||
|
||||
|
||||
def testStyleAttributes(self):
|
||||
self.assertEqual(Style.DIM, '\033[2m')
|
||||
self.assertEqual(Style.NORMAL, '\033[22m')
|
||||
self.assertEqual(Style.BRIGHT, '\033[1m')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
294
site-packages/colorama/tests/ansitowin32_test.py
Normal file
294
site-packages/colorama/tests/ansitowin32_test.py
Normal file
@ -0,0 +1,294 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
from io import StringIO, TextIOWrapper
|
||||
from unittest import TestCase, main
|
||||
try:
|
||||
from contextlib import ExitStack
|
||||
except ImportError:
|
||||
# python 2
|
||||
from contextlib2 import ExitStack
|
||||
|
||||
try:
|
||||
from unittest.mock import MagicMock, Mock, patch
|
||||
except ImportError:
|
||||
from mock import MagicMock, Mock, patch
|
||||
|
||||
from ..ansitowin32 import AnsiToWin32, StreamWrapper
|
||||
from ..win32 import ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
from .utils import osname
|
||||
|
||||
|
||||
class StreamWrapperTest(TestCase):
|
||||
|
||||
def testIsAProxy(self):
|
||||
mockStream = Mock()
|
||||
wrapper = StreamWrapper(mockStream, None)
|
||||
self.assertTrue( wrapper.random_attr is mockStream.random_attr )
|
||||
|
||||
def testDelegatesWrite(self):
|
||||
mockStream = Mock()
|
||||
mockConverter = Mock()
|
||||
wrapper = StreamWrapper(mockStream, mockConverter)
|
||||
wrapper.write('hello')
|
||||
self.assertTrue(mockConverter.write.call_args, (('hello',), {}))
|
||||
|
||||
def testDelegatesContext(self):
|
||||
mockConverter = Mock()
|
||||
s = StringIO()
|
||||
with StreamWrapper(s, mockConverter) as fp:
|
||||
fp.write(u'hello')
|
||||
self.assertTrue(s.closed)
|
||||
|
||||
def testProxyNoContextManager(self):
|
||||
mockStream = MagicMock()
|
||||
mockStream.__enter__.side_effect = AttributeError()
|
||||
mockConverter = Mock()
|
||||
with self.assertRaises(AttributeError) as excinfo:
|
||||
with StreamWrapper(mockStream, mockConverter) as wrapper:
|
||||
wrapper.write('hello')
|
||||
|
||||
def test_closed_shouldnt_raise_on_closed_stream(self):
|
||||
stream = StringIO()
|
||||
stream.close()
|
||||
wrapper = StreamWrapper(stream, None)
|
||||
self.assertEqual(wrapper.closed, True)
|
||||
|
||||
def test_closed_shouldnt_raise_on_detached_stream(self):
|
||||
stream = TextIOWrapper(StringIO())
|
||||
stream.detach()
|
||||
wrapper = StreamWrapper(stream, None)
|
||||
self.assertEqual(wrapper.closed, True)
|
||||
|
||||
class AnsiToWin32Test(TestCase):
|
||||
|
||||
def testInit(self):
|
||||
mockStdout = Mock()
|
||||
auto = Mock()
|
||||
stream = AnsiToWin32(mockStdout, autoreset=auto)
|
||||
self.assertEqual(stream.wrapped, mockStdout)
|
||||
self.assertEqual(stream.autoreset, auto)
|
||||
|
||||
@patch('colorama.ansitowin32.winterm', None)
|
||||
@patch('colorama.ansitowin32.winapi_test', lambda *_: True)
|
||||
def testStripIsTrueOnWindows(self):
|
||||
with osname('nt'):
|
||||
mockStdout = Mock()
|
||||
stream = AnsiToWin32(mockStdout)
|
||||
self.assertTrue(stream.strip)
|
||||
|
||||
def testStripIsFalseOffWindows(self):
|
||||
with osname('posix'):
|
||||
mockStdout = Mock(closed=False)
|
||||
stream = AnsiToWin32(mockStdout)
|
||||
self.assertFalse(stream.strip)
|
||||
|
||||
def testWriteStripsAnsi(self):
|
||||
mockStdout = Mock()
|
||||
stream = AnsiToWin32(mockStdout)
|
||||
stream.wrapped = Mock()
|
||||
stream.write_and_convert = Mock()
|
||||
stream.strip = True
|
||||
|
||||
stream.write('abc')
|
||||
|
||||
self.assertFalse(stream.wrapped.write.called)
|
||||
self.assertEqual(stream.write_and_convert.call_args, (('abc',), {}))
|
||||
|
||||
def testWriteDoesNotStripAnsi(self):
|
||||
mockStdout = Mock()
|
||||
stream = AnsiToWin32(mockStdout)
|
||||
stream.wrapped = Mock()
|
||||
stream.write_and_convert = Mock()
|
||||
stream.strip = False
|
||||
stream.convert = False
|
||||
|
||||
stream.write('abc')
|
||||
|
||||
self.assertFalse(stream.write_and_convert.called)
|
||||
self.assertEqual(stream.wrapped.write.call_args, (('abc',), {}))
|
||||
|
||||
def assert_autoresets(self, convert, autoreset=True):
|
||||
stream = AnsiToWin32(Mock())
|
||||
stream.convert = convert
|
||||
stream.reset_all = Mock()
|
||||
stream.autoreset = autoreset
|
||||
stream.winterm = Mock()
|
||||
|
||||
stream.write('abc')
|
||||
|
||||
self.assertEqual(stream.reset_all.called, autoreset)
|
||||
|
||||
def testWriteAutoresets(self):
|
||||
self.assert_autoresets(convert=True)
|
||||
self.assert_autoresets(convert=False)
|
||||
self.assert_autoresets(convert=True, autoreset=False)
|
||||
self.assert_autoresets(convert=False, autoreset=False)
|
||||
|
||||
def testWriteAndConvertWritesPlainText(self):
|
||||
stream = AnsiToWin32(Mock())
|
||||
stream.write_and_convert( 'abc' )
|
||||
self.assertEqual( stream.wrapped.write.call_args, (('abc',), {}) )
|
||||
|
||||
def testWriteAndConvertStripsAllValidAnsi(self):
|
||||
stream = AnsiToWin32(Mock())
|
||||
stream.call_win32 = Mock()
|
||||
data = [
|
||||
'abc\033[mdef',
|
||||
'abc\033[0mdef',
|
||||
'abc\033[2mdef',
|
||||
'abc\033[02mdef',
|
||||
'abc\033[002mdef',
|
||||
'abc\033[40mdef',
|
||||
'abc\033[040mdef',
|
||||
'abc\033[0;1mdef',
|
||||
'abc\033[40;50mdef',
|
||||
'abc\033[50;30;40mdef',
|
||||
'abc\033[Adef',
|
||||
'abc\033[0Gdef',
|
||||
'abc\033[1;20;128Hdef',
|
||||
]
|
||||
for datum in data:
|
||||
stream.wrapped.write.reset_mock()
|
||||
stream.write_and_convert( datum )
|
||||
self.assertEqual(
|
||||
[args[0] for args in stream.wrapped.write.call_args_list],
|
||||
[ ('abc',), ('def',) ]
|
||||
)
|
||||
|
||||
def testWriteAndConvertSkipsEmptySnippets(self):
|
||||
stream = AnsiToWin32(Mock())
|
||||
stream.call_win32 = Mock()
|
||||
stream.write_and_convert( '\033[40m\033[41m' )
|
||||
self.assertFalse( stream.wrapped.write.called )
|
||||
|
||||
def testWriteAndConvertCallsWin32WithParamsAndCommand(self):
|
||||
stream = AnsiToWin32(Mock())
|
||||
stream.convert = True
|
||||
stream.call_win32 = Mock()
|
||||
stream.extract_params = Mock(return_value='params')
|
||||
data = {
|
||||
'abc\033[adef': ('a', 'params'),
|
||||
'abc\033[;;bdef': ('b', 'params'),
|
||||
'abc\033[0cdef': ('c', 'params'),
|
||||
'abc\033[;;0;;Gdef': ('G', 'params'),
|
||||
'abc\033[1;20;128Hdef': ('H', 'params'),
|
||||
}
|
||||
for datum, expected in data.items():
|
||||
stream.call_win32.reset_mock()
|
||||
stream.write_and_convert( datum )
|
||||
self.assertEqual( stream.call_win32.call_args[0], expected )
|
||||
|
||||
def test_reset_all_shouldnt_raise_on_closed_orig_stdout(self):
|
||||
stream = StringIO()
|
||||
converter = AnsiToWin32(stream)
|
||||
stream.close()
|
||||
|
||||
converter.reset_all()
|
||||
|
||||
def test_wrap_shouldnt_raise_on_closed_orig_stdout(self):
|
||||
stream = StringIO()
|
||||
stream.close()
|
||||
with \
|
||||
patch("colorama.ansitowin32.os.name", "nt"), \
|
||||
patch("colorama.ansitowin32.winapi_test", lambda: True):
|
||||
converter = AnsiToWin32(stream)
|
||||
self.assertTrue(converter.strip)
|
||||
self.assertFalse(converter.convert)
|
||||
|
||||
def test_wrap_shouldnt_raise_on_missing_closed_attr(self):
|
||||
with \
|
||||
patch("colorama.ansitowin32.os.name", "nt"), \
|
||||
patch("colorama.ansitowin32.winapi_test", lambda: True):
|
||||
converter = AnsiToWin32(object())
|
||||
self.assertTrue(converter.strip)
|
||||
self.assertFalse(converter.convert)
|
||||
|
||||
def testExtractParams(self):
|
||||
stream = AnsiToWin32(Mock())
|
||||
data = {
|
||||
'': (0,),
|
||||
';;': (0,),
|
||||
'2': (2,),
|
||||
';;002;;': (2,),
|
||||
'0;1': (0, 1),
|
||||
';;003;;456;;': (3, 456),
|
||||
'11;22;33;44;55': (11, 22, 33, 44, 55),
|
||||
}
|
||||
for datum, expected in data.items():
|
||||
self.assertEqual(stream.extract_params('m', datum), expected)
|
||||
|
||||
def testCallWin32UsesLookup(self):
|
||||
listener = Mock()
|
||||
stream = AnsiToWin32(listener)
|
||||
stream.win32_calls = {
|
||||
1: (lambda *_, **__: listener(11),),
|
||||
2: (lambda *_, **__: listener(22),),
|
||||
3: (lambda *_, **__: listener(33),),
|
||||
}
|
||||
stream.call_win32('m', (3, 1, 99, 2))
|
||||
self.assertEqual(
|
||||
[a[0][0] for a in listener.call_args_list],
|
||||
[33, 11, 22] )
|
||||
|
||||
def test_osc_codes(self):
|
||||
mockStdout = Mock()
|
||||
stream = AnsiToWin32(mockStdout, convert=True)
|
||||
with patch('colorama.ansitowin32.winterm') as winterm:
|
||||
data = [
|
||||
'\033]0\x07', # missing arguments
|
||||
'\033]0;foo\x08', # wrong OSC command
|
||||
'\033]0;colorama_test_title\x07', # should work
|
||||
'\033]1;colorama_test_title\x07', # wrong set command
|
||||
'\033]2;colorama_test_title\x07', # should work
|
||||
'\033]' + ';' * 64 + '\x08', # see issue #247
|
||||
]
|
||||
for code in data:
|
||||
stream.write(code)
|
||||
self.assertEqual(winterm.set_title.call_count, 2)
|
||||
|
||||
def test_native_windows_ansi(self):
|
||||
with ExitStack() as stack:
|
||||
def p(a, b):
|
||||
stack.enter_context(patch(a, b, create=True))
|
||||
# Pretend to be on Windows
|
||||
p("colorama.ansitowin32.os.name", "nt")
|
||||
p("colorama.ansitowin32.winapi_test", lambda: True)
|
||||
p("colorama.win32.winapi_test", lambda: True)
|
||||
p("colorama.winterm.win32.windll", "non-None")
|
||||
p("colorama.winterm.get_osfhandle", lambda _: 1234)
|
||||
|
||||
# Pretend that our mock stream has native ANSI support
|
||||
p(
|
||||
"colorama.winterm.win32.GetConsoleMode",
|
||||
lambda _: ENABLE_VIRTUAL_TERMINAL_PROCESSING,
|
||||
)
|
||||
SetConsoleMode = Mock()
|
||||
p("colorama.winterm.win32.SetConsoleMode", SetConsoleMode)
|
||||
|
||||
stdout = Mock()
|
||||
stdout.closed = False
|
||||
stdout.isatty.return_value = True
|
||||
stdout.fileno.return_value = 1
|
||||
|
||||
# Our fake console says it has native vt support, so AnsiToWin32 should
|
||||
# enable that support and do nothing else.
|
||||
stream = AnsiToWin32(stdout)
|
||||
SetConsoleMode.assert_called_with(1234, ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
self.assertFalse(stream.strip)
|
||||
self.assertFalse(stream.convert)
|
||||
self.assertFalse(stream.should_wrap())
|
||||
|
||||
# Now let's pretend we're on an old Windows console, that doesn't have
|
||||
# native ANSI support.
|
||||
p("colorama.winterm.win32.GetConsoleMode", lambda _: 0)
|
||||
SetConsoleMode = Mock()
|
||||
p("colorama.winterm.win32.SetConsoleMode", SetConsoleMode)
|
||||
|
||||
stream = AnsiToWin32(stdout)
|
||||
SetConsoleMode.assert_called_with(1234, ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
self.assertTrue(stream.strip)
|
||||
self.assertTrue(stream.convert)
|
||||
self.assertTrue(stream.should_wrap())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
189
site-packages/colorama/tests/initialise_test.py
Normal file
189
site-packages/colorama/tests/initialise_test.py
Normal file
@ -0,0 +1,189 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
import sys
|
||||
from unittest import TestCase, main, skipUnless
|
||||
|
||||
try:
|
||||
from unittest.mock import patch, Mock
|
||||
except ImportError:
|
||||
from mock import patch, Mock
|
||||
|
||||
from ..ansitowin32 import StreamWrapper
|
||||
from ..initialise import init, just_fix_windows_console, _wipe_internal_state_for_tests
|
||||
from .utils import osname, replace_by
|
||||
|
||||
orig_stdout = sys.stdout
|
||||
orig_stderr = sys.stderr
|
||||
|
||||
|
||||
class InitTest(TestCase):
|
||||
|
||||
@skipUnless(sys.stdout.isatty(), "sys.stdout is not a tty")
|
||||
def setUp(self):
|
||||
# sanity check
|
||||
self.assertNotWrapped()
|
||||
|
||||
def tearDown(self):
|
||||
_wipe_internal_state_for_tests()
|
||||
sys.stdout = orig_stdout
|
||||
sys.stderr = orig_stderr
|
||||
|
||||
def assertWrapped(self):
|
||||
self.assertIsNot(sys.stdout, orig_stdout, 'stdout should be wrapped')
|
||||
self.assertIsNot(sys.stderr, orig_stderr, 'stderr should be wrapped')
|
||||
self.assertTrue(isinstance(sys.stdout, StreamWrapper),
|
||||
'bad stdout wrapper')
|
||||
self.assertTrue(isinstance(sys.stderr, StreamWrapper),
|
||||
'bad stderr wrapper')
|
||||
|
||||
def assertNotWrapped(self):
|
||||
self.assertIs(sys.stdout, orig_stdout, 'stdout should not be wrapped')
|
||||
self.assertIs(sys.stderr, orig_stderr, 'stderr should not be wrapped')
|
||||
|
||||
@patch('colorama.initialise.reset_all')
|
||||
@patch('colorama.ansitowin32.winapi_test', lambda *_: True)
|
||||
@patch('colorama.ansitowin32.enable_vt_processing', lambda *_: False)
|
||||
def testInitWrapsOnWindows(self, _):
|
||||
with osname("nt"):
|
||||
init()
|
||||
self.assertWrapped()
|
||||
|
||||
@patch('colorama.initialise.reset_all')
|
||||
@patch('colorama.ansitowin32.winapi_test', lambda *_: False)
|
||||
def testInitDoesntWrapOnEmulatedWindows(self, _):
|
||||
with osname("nt"):
|
||||
init()
|
||||
self.assertNotWrapped()
|
||||
|
||||
def testInitDoesntWrapOnNonWindows(self):
|
||||
with osname("posix"):
|
||||
init()
|
||||
self.assertNotWrapped()
|
||||
|
||||
def testInitDoesntWrapIfNone(self):
|
||||
with replace_by(None):
|
||||
init()
|
||||
# We can't use assertNotWrapped here because replace_by(None)
|
||||
# changes stdout/stderr already.
|
||||
self.assertIsNone(sys.stdout)
|
||||
self.assertIsNone(sys.stderr)
|
||||
|
||||
def testInitAutoresetOnWrapsOnAllPlatforms(self):
|
||||
with osname("posix"):
|
||||
init(autoreset=True)
|
||||
self.assertWrapped()
|
||||
|
||||
def testInitWrapOffDoesntWrapOnWindows(self):
|
||||
with osname("nt"):
|
||||
init(wrap=False)
|
||||
self.assertNotWrapped()
|
||||
|
||||
def testInitWrapOffIncompatibleWithAutoresetOn(self):
|
||||
self.assertRaises(ValueError, lambda: init(autoreset=True, wrap=False))
|
||||
|
||||
@patch('colorama.win32.SetConsoleTextAttribute')
|
||||
@patch('colorama.initialise.AnsiToWin32')
|
||||
def testAutoResetPassedOn(self, mockATW32, _):
|
||||
with osname("nt"):
|
||||
init(autoreset=True)
|
||||
self.assertEqual(len(mockATW32.call_args_list), 2)
|
||||
self.assertEqual(mockATW32.call_args_list[1][1]['autoreset'], True)
|
||||
self.assertEqual(mockATW32.call_args_list[0][1]['autoreset'], True)
|
||||
|
||||
@patch('colorama.initialise.AnsiToWin32')
|
||||
def testAutoResetChangeable(self, mockATW32):
|
||||
with osname("nt"):
|
||||
init()
|
||||
|
||||
init(autoreset=True)
|
||||
self.assertEqual(len(mockATW32.call_args_list), 4)
|
||||
self.assertEqual(mockATW32.call_args_list[2][1]['autoreset'], True)
|
||||
self.assertEqual(mockATW32.call_args_list[3][1]['autoreset'], True)
|
||||
|
||||
init()
|
||||
self.assertEqual(len(mockATW32.call_args_list), 6)
|
||||
self.assertEqual(
|
||||
mockATW32.call_args_list[4][1]['autoreset'], False)
|
||||
self.assertEqual(
|
||||
mockATW32.call_args_list[5][1]['autoreset'], False)
|
||||
|
||||
|
||||
@patch('colorama.initialise.atexit.register')
|
||||
def testAtexitRegisteredOnlyOnce(self, mockRegister):
|
||||
init()
|
||||
self.assertTrue(mockRegister.called)
|
||||
mockRegister.reset_mock()
|
||||
init()
|
||||
self.assertFalse(mockRegister.called)
|
||||
|
||||
|
||||
class JustFixWindowsConsoleTest(TestCase):
|
||||
def _reset(self):
|
||||
_wipe_internal_state_for_tests()
|
||||
sys.stdout = orig_stdout
|
||||
sys.stderr = orig_stderr
|
||||
|
||||
def tearDown(self):
|
||||
self._reset()
|
||||
|
||||
@patch("colorama.ansitowin32.winapi_test", lambda: True)
|
||||
def testJustFixWindowsConsole(self):
|
||||
if sys.platform != "win32":
|
||||
# just_fix_windows_console should be a no-op
|
||||
just_fix_windows_console()
|
||||
self.assertIs(sys.stdout, orig_stdout)
|
||||
self.assertIs(sys.stderr, orig_stderr)
|
||||
else:
|
||||
def fake_std():
|
||||
# Emulate stdout=not a tty, stderr=tty
|
||||
# to check that we handle both cases correctly
|
||||
stdout = Mock()
|
||||
stdout.closed = False
|
||||
stdout.isatty.return_value = False
|
||||
stdout.fileno.return_value = 1
|
||||
sys.stdout = stdout
|
||||
|
||||
stderr = Mock()
|
||||
stderr.closed = False
|
||||
stderr.isatty.return_value = True
|
||||
stderr.fileno.return_value = 2
|
||||
sys.stderr = stderr
|
||||
|
||||
for native_ansi in [False, True]:
|
||||
with patch(
|
||||
'colorama.ansitowin32.enable_vt_processing',
|
||||
lambda *_: native_ansi
|
||||
):
|
||||
self._reset()
|
||||
fake_std()
|
||||
|
||||
# Regular single-call test
|
||||
prev_stdout = sys.stdout
|
||||
prev_stderr = sys.stderr
|
||||
just_fix_windows_console()
|
||||
self.assertIs(sys.stdout, prev_stdout)
|
||||
if native_ansi:
|
||||
self.assertIs(sys.stderr, prev_stderr)
|
||||
else:
|
||||
self.assertIsNot(sys.stderr, prev_stderr)
|
||||
|
||||
# second call without resetting is always a no-op
|
||||
prev_stdout = sys.stdout
|
||||
prev_stderr = sys.stderr
|
||||
just_fix_windows_console()
|
||||
self.assertIs(sys.stdout, prev_stdout)
|
||||
self.assertIs(sys.stderr, prev_stderr)
|
||||
|
||||
self._reset()
|
||||
fake_std()
|
||||
|
||||
# If init() runs first, just_fix_windows_console should be a no-op
|
||||
init()
|
||||
prev_stdout = sys.stdout
|
||||
prev_stderr = sys.stderr
|
||||
just_fix_windows_console()
|
||||
self.assertIs(prev_stdout, sys.stdout)
|
||||
self.assertIs(prev_stderr, sys.stderr)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
57
site-packages/colorama/tests/isatty_test.py
Normal file
57
site-packages/colorama/tests/isatty_test.py
Normal file
@ -0,0 +1,57 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
import sys
|
||||
from unittest import TestCase, main
|
||||
|
||||
from ..ansitowin32 import StreamWrapper, AnsiToWin32
|
||||
from .utils import pycharm, replace_by, replace_original_by, StreamTTY, StreamNonTTY
|
||||
|
||||
|
||||
def is_a_tty(stream):
|
||||
return StreamWrapper(stream, None).isatty()
|
||||
|
||||
class IsattyTest(TestCase):
|
||||
|
||||
def test_TTY(self):
|
||||
tty = StreamTTY()
|
||||
self.assertTrue(is_a_tty(tty))
|
||||
with pycharm():
|
||||
self.assertTrue(is_a_tty(tty))
|
||||
|
||||
def test_nonTTY(self):
|
||||
non_tty = StreamNonTTY()
|
||||
self.assertFalse(is_a_tty(non_tty))
|
||||
with pycharm():
|
||||
self.assertFalse(is_a_tty(non_tty))
|
||||
|
||||
def test_withPycharm(self):
|
||||
with pycharm():
|
||||
self.assertTrue(is_a_tty(sys.stderr))
|
||||
self.assertTrue(is_a_tty(sys.stdout))
|
||||
|
||||
def test_withPycharmTTYOverride(self):
|
||||
tty = StreamTTY()
|
||||
with pycharm(), replace_by(tty):
|
||||
self.assertTrue(is_a_tty(tty))
|
||||
|
||||
def test_withPycharmNonTTYOverride(self):
|
||||
non_tty = StreamNonTTY()
|
||||
with pycharm(), replace_by(non_tty):
|
||||
self.assertFalse(is_a_tty(non_tty))
|
||||
|
||||
def test_withPycharmNoneOverride(self):
|
||||
with pycharm():
|
||||
with replace_by(None), replace_original_by(None):
|
||||
self.assertFalse(is_a_tty(None))
|
||||
self.assertFalse(is_a_tty(StreamNonTTY()))
|
||||
self.assertTrue(is_a_tty(StreamTTY()))
|
||||
|
||||
def test_withPycharmStreamWrapped(self):
|
||||
with pycharm():
|
||||
self.assertTrue(AnsiToWin32(StreamTTY()).stream.isatty())
|
||||
self.assertFalse(AnsiToWin32(StreamNonTTY()).stream.isatty())
|
||||
self.assertTrue(AnsiToWin32(sys.stdout).stream.isatty())
|
||||
self.assertTrue(AnsiToWin32(sys.stderr).stream.isatty())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
49
site-packages/colorama/tests/utils.py
Normal file
49
site-packages/colorama/tests/utils.py
Normal file
@ -0,0 +1,49 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
from contextlib import contextmanager
|
||||
from io import StringIO
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
class StreamTTY(StringIO):
|
||||
def isatty(self):
|
||||
return True
|
||||
|
||||
class StreamNonTTY(StringIO):
|
||||
def isatty(self):
|
||||
return False
|
||||
|
||||
@contextmanager
|
||||
def osname(name):
|
||||
orig = os.name
|
||||
os.name = name
|
||||
yield
|
||||
os.name = orig
|
||||
|
||||
@contextmanager
|
||||
def replace_by(stream):
|
||||
orig_stdout = sys.stdout
|
||||
orig_stderr = sys.stderr
|
||||
sys.stdout = stream
|
||||
sys.stderr = stream
|
||||
yield
|
||||
sys.stdout = orig_stdout
|
||||
sys.stderr = orig_stderr
|
||||
|
||||
@contextmanager
|
||||
def replace_original_by(stream):
|
||||
orig_stdout = sys.__stdout__
|
||||
orig_stderr = sys.__stderr__
|
||||
sys.__stdout__ = stream
|
||||
sys.__stderr__ = stream
|
||||
yield
|
||||
sys.__stdout__ = orig_stdout
|
||||
sys.__stderr__ = orig_stderr
|
||||
|
||||
@contextmanager
|
||||
def pycharm():
|
||||
os.environ["PYCHARM_HOSTED"] = "1"
|
||||
non_tty = StreamNonTTY()
|
||||
with replace_by(non_tty), replace_original_by(non_tty):
|
||||
yield
|
||||
del os.environ["PYCHARM_HOSTED"]
|
131
site-packages/colorama/tests/winterm_test.py
Normal file
131
site-packages/colorama/tests/winterm_test.py
Normal file
@ -0,0 +1,131 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
import sys
|
||||
from unittest import TestCase, main, skipUnless
|
||||
|
||||
try:
|
||||
from unittest.mock import Mock, patch
|
||||
except ImportError:
|
||||
from mock import Mock, patch
|
||||
|
||||
from ..winterm import WinColor, WinStyle, WinTerm
|
||||
|
||||
|
||||
class WinTermTest(TestCase):
|
||||
|
||||
@patch('colorama.winterm.win32')
|
||||
def testInit(self, mockWin32):
|
||||
mockAttr = Mock()
|
||||
mockAttr.wAttributes = 7 + 6 * 16 + 8
|
||||
mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr
|
||||
term = WinTerm()
|
||||
self.assertEqual(term._fore, 7)
|
||||
self.assertEqual(term._back, 6)
|
||||
self.assertEqual(term._style, 8)
|
||||
|
||||
@skipUnless(sys.platform.startswith("win"), "requires Windows")
|
||||
def testGetAttrs(self):
|
||||
term = WinTerm()
|
||||
|
||||
term._fore = 0
|
||||
term._back = 0
|
||||
term._style = 0
|
||||
self.assertEqual(term.get_attrs(), 0)
|
||||
|
||||
term._fore = WinColor.YELLOW
|
||||
self.assertEqual(term.get_attrs(), WinColor.YELLOW)
|
||||
|
||||
term._back = WinColor.MAGENTA
|
||||
self.assertEqual(
|
||||
term.get_attrs(),
|
||||
WinColor.YELLOW + WinColor.MAGENTA * 16)
|
||||
|
||||
term._style = WinStyle.BRIGHT
|
||||
self.assertEqual(
|
||||
term.get_attrs(),
|
||||
WinColor.YELLOW + WinColor.MAGENTA * 16 + WinStyle.BRIGHT)
|
||||
|
||||
@patch('colorama.winterm.win32')
|
||||
def testResetAll(self, mockWin32):
|
||||
mockAttr = Mock()
|
||||
mockAttr.wAttributes = 1 + 2 * 16 + 8
|
||||
mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr
|
||||
term = WinTerm()
|
||||
|
||||
term.set_console = Mock()
|
||||
term._fore = -1
|
||||
term._back = -1
|
||||
term._style = -1
|
||||
|
||||
term.reset_all()
|
||||
|
||||
self.assertEqual(term._fore, 1)
|
||||
self.assertEqual(term._back, 2)
|
||||
self.assertEqual(term._style, 8)
|
||||
self.assertEqual(term.set_console.called, True)
|
||||
|
||||
@skipUnless(sys.platform.startswith("win"), "requires Windows")
|
||||
def testFore(self):
|
||||
term = WinTerm()
|
||||
term.set_console = Mock()
|
||||
term._fore = 0
|
||||
|
||||
term.fore(5)
|
||||
|
||||
self.assertEqual(term._fore, 5)
|
||||
self.assertEqual(term.set_console.called, True)
|
||||
|
||||
@skipUnless(sys.platform.startswith("win"), "requires Windows")
|
||||
def testBack(self):
|
||||
term = WinTerm()
|
||||
term.set_console = Mock()
|
||||
term._back = 0
|
||||
|
||||
term.back(5)
|
||||
|
||||
self.assertEqual(term._back, 5)
|
||||
self.assertEqual(term.set_console.called, True)
|
||||
|
||||
@skipUnless(sys.platform.startswith("win"), "requires Windows")
|
||||
def testStyle(self):
|
||||
term = WinTerm()
|
||||
term.set_console = Mock()
|
||||
term._style = 0
|
||||
|
||||
term.style(22)
|
||||
|
||||
self.assertEqual(term._style, 22)
|
||||
self.assertEqual(term.set_console.called, True)
|
||||
|
||||
@patch('colorama.winterm.win32')
|
||||
def testSetConsole(self, mockWin32):
|
||||
mockAttr = Mock()
|
||||
mockAttr.wAttributes = 0
|
||||
mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr
|
||||
term = WinTerm()
|
||||
term.windll = Mock()
|
||||
|
||||
term.set_console()
|
||||
|
||||
self.assertEqual(
|
||||
mockWin32.SetConsoleTextAttribute.call_args,
|
||||
((mockWin32.STDOUT, term.get_attrs()), {})
|
||||
)
|
||||
|
||||
@patch('colorama.winterm.win32')
|
||||
def testSetConsoleOnStderr(self, mockWin32):
|
||||
mockAttr = Mock()
|
||||
mockAttr.wAttributes = 0
|
||||
mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr
|
||||
term = WinTerm()
|
||||
term.windll = Mock()
|
||||
|
||||
term.set_console(on_stderr=True)
|
||||
|
||||
self.assertEqual(
|
||||
mockWin32.SetConsoleTextAttribute.call_args,
|
||||
((mockWin32.STDERR, term.get_attrs()), {})
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
180
site-packages/colorama/win32.py
Normal file
180
site-packages/colorama/win32.py
Normal file
@ -0,0 +1,180 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
|
||||
# from winbase.h
|
||||
STDOUT = -11
|
||||
STDERR = -12
|
||||
|
||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
|
||||
|
||||
try:
|
||||
import ctypes
|
||||
from ctypes import LibraryLoader
|
||||
windll = LibraryLoader(ctypes.WinDLL)
|
||||
from ctypes import wintypes
|
||||
except (AttributeError, ImportError):
|
||||
windll = None
|
||||
SetConsoleTextAttribute = lambda *_: None
|
||||
winapi_test = lambda *_: None
|
||||
else:
|
||||
from ctypes import byref, Structure, c_char, POINTER
|
||||
|
||||
COORD = wintypes._COORD
|
||||
|
||||
class CONSOLE_SCREEN_BUFFER_INFO(Structure):
|
||||
"""struct in wincon.h."""
|
||||
_fields_ = [
|
||||
("dwSize", COORD),
|
||||
("dwCursorPosition", COORD),
|
||||
("wAttributes", wintypes.WORD),
|
||||
("srWindow", wintypes.SMALL_RECT),
|
||||
("dwMaximumWindowSize", COORD),
|
||||
]
|
||||
def __str__(self):
|
||||
return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % (
|
||||
self.dwSize.Y, self.dwSize.X
|
||||
, self.dwCursorPosition.Y, self.dwCursorPosition.X
|
||||
, self.wAttributes
|
||||
, self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right
|
||||
, self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X
|
||||
)
|
||||
|
||||
_GetStdHandle = windll.kernel32.GetStdHandle
|
||||
_GetStdHandle.argtypes = [
|
||||
wintypes.DWORD,
|
||||
]
|
||||
_GetStdHandle.restype = wintypes.HANDLE
|
||||
|
||||
_GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
|
||||
_GetConsoleScreenBufferInfo.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
POINTER(CONSOLE_SCREEN_BUFFER_INFO),
|
||||
]
|
||||
_GetConsoleScreenBufferInfo.restype = wintypes.BOOL
|
||||
|
||||
_SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
|
||||
_SetConsoleTextAttribute.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.WORD,
|
||||
]
|
||||
_SetConsoleTextAttribute.restype = wintypes.BOOL
|
||||
|
||||
_SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition
|
||||
_SetConsoleCursorPosition.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
COORD,
|
||||
]
|
||||
_SetConsoleCursorPosition.restype = wintypes.BOOL
|
||||
|
||||
_FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA
|
||||
_FillConsoleOutputCharacterA.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
c_char,
|
||||
wintypes.DWORD,
|
||||
COORD,
|
||||
POINTER(wintypes.DWORD),
|
||||
]
|
||||
_FillConsoleOutputCharacterA.restype = wintypes.BOOL
|
||||
|
||||
_FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute
|
||||
_FillConsoleOutputAttribute.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.WORD,
|
||||
wintypes.DWORD,
|
||||
COORD,
|
||||
POINTER(wintypes.DWORD),
|
||||
]
|
||||
_FillConsoleOutputAttribute.restype = wintypes.BOOL
|
||||
|
||||
_SetConsoleTitleW = windll.kernel32.SetConsoleTitleW
|
||||
_SetConsoleTitleW.argtypes = [
|
||||
wintypes.LPCWSTR
|
||||
]
|
||||
_SetConsoleTitleW.restype = wintypes.BOOL
|
||||
|
||||
_GetConsoleMode = windll.kernel32.GetConsoleMode
|
||||
_GetConsoleMode.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
POINTER(wintypes.DWORD)
|
||||
]
|
||||
_GetConsoleMode.restype = wintypes.BOOL
|
||||
|
||||
_SetConsoleMode = windll.kernel32.SetConsoleMode
|
||||
_SetConsoleMode.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.DWORD
|
||||
]
|
||||
_SetConsoleMode.restype = wintypes.BOOL
|
||||
|
||||
def _winapi_test(handle):
|
||||
csbi = CONSOLE_SCREEN_BUFFER_INFO()
|
||||
success = _GetConsoleScreenBufferInfo(
|
||||
handle, byref(csbi))
|
||||
return bool(success)
|
||||
|
||||
def winapi_test():
|
||||
return any(_winapi_test(h) for h in
|
||||
(_GetStdHandle(STDOUT), _GetStdHandle(STDERR)))
|
||||
|
||||
def GetConsoleScreenBufferInfo(stream_id=STDOUT):
|
||||
handle = _GetStdHandle(stream_id)
|
||||
csbi = CONSOLE_SCREEN_BUFFER_INFO()
|
||||
success = _GetConsoleScreenBufferInfo(
|
||||
handle, byref(csbi))
|
||||
return csbi
|
||||
|
||||
def SetConsoleTextAttribute(stream_id, attrs):
|
||||
handle = _GetStdHandle(stream_id)
|
||||
return _SetConsoleTextAttribute(handle, attrs)
|
||||
|
||||
def SetConsoleCursorPosition(stream_id, position, adjust=True):
|
||||
position = COORD(*position)
|
||||
# If the position is out of range, do nothing.
|
||||
if position.Y <= 0 or position.X <= 0:
|
||||
return
|
||||
# Adjust for Windows' SetConsoleCursorPosition:
|
||||
# 1. being 0-based, while ANSI is 1-based.
|
||||
# 2. expecting (x,y), while ANSI uses (y,x).
|
||||
adjusted_position = COORD(position.Y - 1, position.X - 1)
|
||||
if adjust:
|
||||
# Adjust for viewport's scroll position
|
||||
sr = GetConsoleScreenBufferInfo(STDOUT).srWindow
|
||||
adjusted_position.Y += sr.Top
|
||||
adjusted_position.X += sr.Left
|
||||
# Resume normal processing
|
||||
handle = _GetStdHandle(stream_id)
|
||||
return _SetConsoleCursorPosition(handle, adjusted_position)
|
||||
|
||||
def FillConsoleOutputCharacter(stream_id, char, length, start):
|
||||
handle = _GetStdHandle(stream_id)
|
||||
char = c_char(char.encode())
|
||||
length = wintypes.DWORD(length)
|
||||
num_written = wintypes.DWORD(0)
|
||||
# Note that this is hard-coded for ANSI (vs wide) bytes.
|
||||
success = _FillConsoleOutputCharacterA(
|
||||
handle, char, length, start, byref(num_written))
|
||||
return num_written.value
|
||||
|
||||
def FillConsoleOutputAttribute(stream_id, attr, length, start):
|
||||
''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )'''
|
||||
handle = _GetStdHandle(stream_id)
|
||||
attribute = wintypes.WORD(attr)
|
||||
length = wintypes.DWORD(length)
|
||||
num_written = wintypes.DWORD(0)
|
||||
# Note that this is hard-coded for ANSI (vs wide) bytes.
|
||||
return _FillConsoleOutputAttribute(
|
||||
handle, attribute, length, start, byref(num_written))
|
||||
|
||||
def SetConsoleTitle(title):
|
||||
return _SetConsoleTitleW(title)
|
||||
|
||||
def GetConsoleMode(handle):
|
||||
mode = wintypes.DWORD()
|
||||
success = _GetConsoleMode(handle, byref(mode))
|
||||
if not success:
|
||||
raise ctypes.WinError()
|
||||
return mode.value
|
||||
|
||||
def SetConsoleMode(handle, mode):
|
||||
success = _SetConsoleMode(handle, mode)
|
||||
if not success:
|
||||
raise ctypes.WinError()
|
195
site-packages/colorama/winterm.py
Normal file
195
site-packages/colorama/winterm.py
Normal file
@ -0,0 +1,195 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
try:
|
||||
from msvcrt import get_osfhandle
|
||||
except ImportError:
|
||||
def get_osfhandle(_):
|
||||
raise OSError("This isn't windows!")
|
||||
|
||||
|
||||
from . import win32
|
||||
|
||||
# from wincon.h
|
||||
class WinColor(object):
|
||||
BLACK = 0
|
||||
BLUE = 1
|
||||
GREEN = 2
|
||||
CYAN = 3
|
||||
RED = 4
|
||||
MAGENTA = 5
|
||||
YELLOW = 6
|
||||
GREY = 7
|
||||
|
||||
# from wincon.h
|
||||
class WinStyle(object):
|
||||
NORMAL = 0x00 # dim text, dim background
|
||||
BRIGHT = 0x08 # bright text, dim background
|
||||
BRIGHT_BACKGROUND = 0x80 # dim text, bright background
|
||||
|
||||
class WinTerm(object):
|
||||
|
||||
def __init__(self):
|
||||
self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes
|
||||
self.set_attrs(self._default)
|
||||
self._default_fore = self._fore
|
||||
self._default_back = self._back
|
||||
self._default_style = self._style
|
||||
# In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style.
|
||||
# So that LIGHT_EX colors and BRIGHT style do not clobber each other,
|
||||
# we track them separately, since LIGHT_EX is overwritten by Fore/Back
|
||||
# and BRIGHT is overwritten by Style codes.
|
||||
self._light = 0
|
||||
|
||||
def get_attrs(self):
|
||||
return self._fore + self._back * 16 + (self._style | self._light)
|
||||
|
||||
def set_attrs(self, value):
|
||||
self._fore = value & 7
|
||||
self._back = (value >> 4) & 7
|
||||
self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND)
|
||||
|
||||
def reset_all(self, on_stderr=None):
|
||||
self.set_attrs(self._default)
|
||||
self.set_console(attrs=self._default)
|
||||
self._light = 0
|
||||
|
||||
def fore(self, fore=None, light=False, on_stderr=False):
|
||||
if fore is None:
|
||||
fore = self._default_fore
|
||||
self._fore = fore
|
||||
# Emulate LIGHT_EX with BRIGHT Style
|
||||
if light:
|
||||
self._light |= WinStyle.BRIGHT
|
||||
else:
|
||||
self._light &= ~WinStyle.BRIGHT
|
||||
self.set_console(on_stderr=on_stderr)
|
||||
|
||||
def back(self, back=None, light=False, on_stderr=False):
|
||||
if back is None:
|
||||
back = self._default_back
|
||||
self._back = back
|
||||
# Emulate LIGHT_EX with BRIGHT_BACKGROUND Style
|
||||
if light:
|
||||
self._light |= WinStyle.BRIGHT_BACKGROUND
|
||||
else:
|
||||
self._light &= ~WinStyle.BRIGHT_BACKGROUND
|
||||
self.set_console(on_stderr=on_stderr)
|
||||
|
||||
def style(self, style=None, on_stderr=False):
|
||||
if style is None:
|
||||
style = self._default_style
|
||||
self._style = style
|
||||
self.set_console(on_stderr=on_stderr)
|
||||
|
||||
def set_console(self, attrs=None, on_stderr=False):
|
||||
if attrs is None:
|
||||
attrs = self.get_attrs()
|
||||
handle = win32.STDOUT
|
||||
if on_stderr:
|
||||
handle = win32.STDERR
|
||||
win32.SetConsoleTextAttribute(handle, attrs)
|
||||
|
||||
def get_position(self, handle):
|
||||
position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition
|
||||
# Because Windows coordinates are 0-based,
|
||||
# and win32.SetConsoleCursorPosition expects 1-based.
|
||||
position.X += 1
|
||||
position.Y += 1
|
||||
return position
|
||||
|
||||
def set_cursor_position(self, position=None, on_stderr=False):
|
||||
if position is None:
|
||||
# I'm not currently tracking the position, so there is no default.
|
||||
# position = self.get_position()
|
||||
return
|
||||
handle = win32.STDOUT
|
||||
if on_stderr:
|
||||
handle = win32.STDERR
|
||||
win32.SetConsoleCursorPosition(handle, position)
|
||||
|
||||
def cursor_adjust(self, x, y, on_stderr=False):
|
||||
handle = win32.STDOUT
|
||||
if on_stderr:
|
||||
handle = win32.STDERR
|
||||
position = self.get_position(handle)
|
||||
adjusted_position = (position.Y + y, position.X + x)
|
||||
win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False)
|
||||
|
||||
def erase_screen(self, mode=0, on_stderr=False):
|
||||
# 0 should clear from the cursor to the end of the screen.
|
||||
# 1 should clear from the cursor to the beginning of the screen.
|
||||
# 2 should clear the entire screen, and move cursor to (1,1)
|
||||
handle = win32.STDOUT
|
||||
if on_stderr:
|
||||
handle = win32.STDERR
|
||||
csbi = win32.GetConsoleScreenBufferInfo(handle)
|
||||
# get the number of character cells in the current buffer
|
||||
cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y
|
||||
# get number of character cells before current cursor position
|
||||
cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X
|
||||
if mode == 0:
|
||||
from_coord = csbi.dwCursorPosition
|
||||
cells_to_erase = cells_in_screen - cells_before_cursor
|
||||
elif mode == 1:
|
||||
from_coord = win32.COORD(0, 0)
|
||||
cells_to_erase = cells_before_cursor
|
||||
elif mode == 2:
|
||||
from_coord = win32.COORD(0, 0)
|
||||
cells_to_erase = cells_in_screen
|
||||
else:
|
||||
# invalid mode
|
||||
return
|
||||
# fill the entire screen with blanks
|
||||
win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord)
|
||||
# now set the buffer's attributes accordingly
|
||||
win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord)
|
||||
if mode == 2:
|
||||
# put the cursor where needed
|
||||
win32.SetConsoleCursorPosition(handle, (1, 1))
|
||||
|
||||
def erase_line(self, mode=0, on_stderr=False):
|
||||
# 0 should clear from the cursor to the end of the line.
|
||||
# 1 should clear from the cursor to the beginning of the line.
|
||||
# 2 should clear the entire line.
|
||||
handle = win32.STDOUT
|
||||
if on_stderr:
|
||||
handle = win32.STDERR
|
||||
csbi = win32.GetConsoleScreenBufferInfo(handle)
|
||||
if mode == 0:
|
||||
from_coord = csbi.dwCursorPosition
|
||||
cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X
|
||||
elif mode == 1:
|
||||
from_coord = win32.COORD(0, csbi.dwCursorPosition.Y)
|
||||
cells_to_erase = csbi.dwCursorPosition.X
|
||||
elif mode == 2:
|
||||
from_coord = win32.COORD(0, csbi.dwCursorPosition.Y)
|
||||
cells_to_erase = csbi.dwSize.X
|
||||
else:
|
||||
# invalid mode
|
||||
return
|
||||
# fill the entire screen with blanks
|
||||
win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord)
|
||||
# now set the buffer's attributes accordingly
|
||||
win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord)
|
||||
|
||||
def set_title(self, title):
|
||||
win32.SetConsoleTitle(title)
|
||||
|
||||
|
||||
def enable_vt_processing(fd):
|
||||
if win32.windll is None or not win32.winapi_test():
|
||||
return False
|
||||
|
||||
try:
|
||||
handle = get_osfhandle(fd)
|
||||
mode = win32.GetConsoleMode(handle)
|
||||
win32.SetConsoleMode(
|
||||
handle,
|
||||
mode | win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING,
|
||||
)
|
||||
|
||||
mode = win32.GetConsoleMode(handle)
|
||||
if mode & win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING:
|
||||
return True
|
||||
# Can get TypeError in testsuite where 'fd' is a Mock()
|
||||
except (OSError, TypeError):
|
||||
return False
|
@ -1,6 +1,6 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: devchat
|
||||
Version: 0.2.9
|
||||
Version: 0.2.10
|
||||
Summary: DevChat is an open-source tool that helps developers write prompts to generate code and documentation.
|
||||
Home-page: https://github.com/devchat-ai/devchat
|
||||
License: Apache-2.0
|
||||
@ -20,12 +20,13 @@ Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
||||
Classifier: Topic :: Software Development
|
||||
Requires-Dist: colorama (>=0.4.6,<0.5.0)
|
||||
Requires-Dist: gitpython (>=3.1.32,<4.0.0)
|
||||
Requires-Dist: importlib-metadata (>=6.8.0,<7.0.0)
|
||||
Requires-Dist: networkx (>=3.1,<4.0)
|
||||
Requires-Dist: openai (>=1.0rc,<2.0)
|
||||
Requires-Dist: oyaml (>=1.0,<2.0)
|
||||
Requires-Dist: pydantic (>=1.10.7,<2.0.0)
|
||||
Requires-Dist: pydantic (==1.10.13)
|
||||
Requires-Dist: rich_click (>=1.6.1,<2.0.0)
|
||||
Requires-Dist: tiktoken (>=0.4.0,<0.5.0)
|
||||
Requires-Dist: tinydb (>=4.7.1,<5.0.0)
|
@ -1,14 +1,14 @@
|
||||
../../../bin/devchat,sha256=vIdrM1HVCLtIIPguIbzu4QV0CKMZvbRJqEBeLF9xyXE,247
|
||||
devchat-0.2.9.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
devchat-0.2.9.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
||||
devchat-0.2.9.dist-info/METADATA,sha256=WJiWT9Wr22Ze88H5U3Y_QtXhoveDeXuhlYNdB86-iT0,9739
|
||||
devchat-0.2.9.dist-info/RECORD,,
|
||||
devchat-0.2.9.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
devchat-0.2.9.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
||||
devchat-0.2.9.dist-info/direct_url.json,sha256=zd3JCXQPIQyScA8lV44s-V6X6GM2woo8TWVYFvT3e9Y,59
|
||||
devchat-0.2.9.dist-info/entry_points.txt,sha256=Glu9CHUNBjYbZXTQc3YW2rZFr2S_3AvqKu50gj3aWT4,50
|
||||
../../../bin/devchat,sha256=suM8Tlq7_32mdUbhBivdAeg9W---BD14D3E7bhy9LOc,247
|
||||
devchat-0.2.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
devchat-0.2.10.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
||||
devchat-0.2.10.dist-info/METADATA,sha256=NxGPR5qcRawRtREwinMGazaQIaefdeOOui9A60ynYo0,9775
|
||||
devchat-0.2.10.dist-info/RECORD,,
|
||||
devchat-0.2.10.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
devchat-0.2.10.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
||||
devchat-0.2.10.dist-info/direct_url.json,sha256=zd3JCXQPIQyScA8lV44s-V6X6GM2woo8TWVYFvT3e9Y,59
|
||||
devchat-0.2.10.dist-info/entry_points.txt,sha256=Glu9CHUNBjYbZXTQc3YW2rZFr2S_3AvqKu50gj3aWT4,50
|
||||
devchat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
devchat/__main__.py,sha256=KOQA2JI9HBmG32X3K8Uisa_tmkIn_gT9z1QPSnxzAOs,109
|
||||
devchat/__main__.py,sha256=RY7_u5N5S0Ye2YtBWeYkk9n8zia_z9oe3DnS1SHRxZA,110
|
||||
devchat/__pycache__/__init__.cpython-39.pyc,,
|
||||
devchat/__pycache__/__main__.cpython-39.pyc,,
|
||||
devchat/__pycache__/assistant.cpython-39.pyc,,
|
||||
@ -29,14 +29,14 @@ devchat/_cli/__pycache__/utils.cpython-39.pyc,,
|
||||
devchat/_cli/log.py,sha256=GAYVrNPprDQEB6G2Z1J97jjDU-EbYlJBHnz-Lz6nzvo,3106
|
||||
devchat/_cli/main.py,sha256=_uJ6KOiV19kATA0CYUtJZ1gGX9IGcX_8pjQyZ9J8wSU,659
|
||||
devchat/_cli/prompt.py,sha256=uvug9x7zclL0P1xbT_xjFsSCx2PjjLtmGUf0O8Sx1Ek,3923
|
||||
devchat/_cli/run.py,sha256=52eABhjkUuNgd44CaGyoHRfgAdO9tr6MZBSFikqts_g,4129
|
||||
devchat/_cli/run.py,sha256=nCCqNV7IuTxp7XrroHShR772qKWDXGmx8vM388QjPW8,4849
|
||||
devchat/_cli/topic.py,sha256=CLE8y2Vox_5igtoSfsnFgaCa7YtJE-rcDtoNhnnedyQ,1455
|
||||
devchat/_cli/utils.py,sha256=MQUpQ4JYB9nhlgKwBLUNnpsMZfGiJ2xLST2RgZUKWOU,4993
|
||||
devchat/_cli/utils.py,sha256=u43D4lqihdil1BEenaryzP-NUp5CQo4jTmtq640gTLY,5975
|
||||
devchat/anthropic/__init__.py,sha256=xaFR1uXxn0sVHBhCJdJKuWKVVgPnSLw3mlaCFFivD_8,97
|
||||
devchat/anthropic/__pycache__/__init__.cpython-39.pyc,,
|
||||
devchat/anthropic/__pycache__/anthropic_chat.cpython-39.pyc,,
|
||||
devchat/anthropic/anthropic_chat.py,sha256=OujoXOQywPQf4gjLhdZBYTwKoRDs8hujktss3hN-BNk,423
|
||||
devchat/assistant.py,sha256=VOpfvX6Tbq57EYqoOo2V-HJ91D02-s2URc2ZdM7wRlM,6077
|
||||
devchat/assistant.py,sha256=qOU8u0nrRbruTmH0FS7Ax2H8aOws5uLOnVC8v-WzFoU,6033
|
||||
devchat/chat.py,sha256=TEO8OndmL4hpJ1D-QAFKO-JB_7w1kTeUC3VVwL9FSUQ,1676
|
||||
devchat/config.py,sha256=3lvhi-YRbCOM2Ye28GJF14n10mEYczD3sllhz_ZwZS8,6348
|
||||
devchat/engine/__init__.py,sha256=sXaM_4kQtG-VV7NxMDj7a7v4rbNg7dJHEMF8BOz9NtI,262
|
||||
@ -53,9 +53,9 @@ devchat/openai/__pycache__/__init__.cpython-39.pyc,,
|
||||
devchat/openai/__pycache__/openai_chat.cpython-39.pyc,,
|
||||
devchat/openai/__pycache__/openai_message.cpython-39.pyc,,
|
||||
devchat/openai/__pycache__/openai_prompt.cpython-39.pyc,,
|
||||
devchat/openai/openai_chat.py,sha256=ELEa31w-138cyZ08eHqG9FGtwNzsBCy1UfSXhtdnOT0,3684
|
||||
devchat/openai/openai_chat.py,sha256=aME5qfzvZsnoUKJ344uaUJ27okTk9if46nF3T9DeMK0,3826
|
||||
devchat/openai/openai_message.py,sha256=xTmglsj5Iyvcytn3pUYhwkuiyJSx932N88fS4OCJ7Qk,3293
|
||||
devchat/openai/openai_prompt.py,sha256=Jikny5lkjt_u3LaKxlzXgUdR8ttZrUMzIVghr63VlYk,10848
|
||||
devchat/openai/openai_prompt.py,sha256=M9NIBP5W9DwzFJyMO0L9DYM470383wQOZJwZv4KvQfs,10856
|
||||
devchat/prompt.py,sha256=WAHa6LmVU1xvBp6AGalQ1TzQuVwt1lsdBd70OazVoW0,9523
|
||||
devchat/store.py,sha256=pdZ3TjzNcAyPcvyD9Roc12SY5znYMh3waM0z9yF9o2w,9845
|
||||
devchat/utils.py,sha256=rUQc-iy7d7DL8xBNj_1C1W1cag9jD8xeaqdnDaFnZ9U,7509
|
||||
devchat/store.py,sha256=PI2HvMyZmIV1XyyjIr5rPayagBQWJUWsEdpUCBZ7xLU,9879
|
||||
devchat/utils.py,sha256=_-FUAC-4ZKoF0q7eg6xWz6hrj0rKJKLHenK4S_uZvkE,7643
|
BIN
site-packages/devchat/.DS_Store
vendored
BIN
site-packages/devchat/.DS_Store
vendored
Binary file not shown.
@ -4,7 +4,10 @@ import shutil
|
||||
import sys
|
||||
from typing import List
|
||||
import rich_click as click
|
||||
from git import Repo, GitCommandError
|
||||
try:
|
||||
from git import Repo, GitCommandError
|
||||
except Exception:
|
||||
pass
|
||||
from devchat._cli.utils import init_dir, handle_errors, valid_git_repo, clone_git_repo
|
||||
from devchat._cli.utils import download_and_extract_workflow
|
||||
from devchat.engine import Namespace, CommandParser, RecursivePrompter
|
||||
@ -89,8 +92,8 @@ def _clone_or_pull_git_repo(target_dir: str, repo_urls: List[str], zip_urls: Lis
|
||||
try:
|
||||
download_and_extract_workflow(url, target_dir)
|
||||
break
|
||||
except Exception as e:
|
||||
logger.exception("Failed to download and extract workflow: %s", e)
|
||||
except Exception as err:
|
||||
logger.exception("Failed to download and extract workflow: %s", err)
|
||||
return
|
||||
|
||||
if os.path.exists(target_dir):
|
||||
|
@ -3,11 +3,13 @@ import os
|
||||
import sys
|
||||
import json
|
||||
import shutil
|
||||
import requests
|
||||
import zipfile
|
||||
from urllib.parse import urlparse
|
||||
from typing import Tuple, List, Optional, Any
|
||||
from git import Repo, InvalidGitRepositoryError, GitCommandError
|
||||
import zipfile
|
||||
import requests
|
||||
try:
|
||||
from git import Repo, InvalidGitRepositoryError, GitCommandError
|
||||
except Exception:
|
||||
pass
|
||||
import rich_click as click
|
||||
from devchat.config import ConfigManager, OpenAIModelConfig
|
||||
from devchat.utils import find_root_dir, add_gitignore, setup_logger, get_logger
|
||||
@ -22,20 +24,20 @@ def download_and_extract_workflow(workflow_url, target_dir):
|
||||
# Downaload file to temp dir
|
||||
os.makedirs(target_dir, exist_ok=True)
|
||||
zip_path = os.path.join(target_dir, 'workflow.zip')
|
||||
with open(zip_path, 'wb') as f:
|
||||
with open(zip_path, 'wb') as file_handle:
|
||||
for chunk in response.iter_content(chunk_size=8192):
|
||||
if chunk:
|
||||
f.write(chunk)
|
||||
file_handle.write(chunk)
|
||||
|
||||
# Extract the zip file
|
||||
parent_dir = os.path.dirname(target_dir)
|
||||
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
|
||||
zip_ref.extractall(parent_dir)
|
||||
|
||||
|
||||
# Delete target directory if exists
|
||||
if os.path.exists(target_dir):
|
||||
shutil.rmtree(target_dir)
|
||||
|
||||
|
||||
# Rename extracted directory to target directory
|
||||
extracted_dir = os.path.join(parent_dir, 'workflows-main')
|
||||
os.rename(extracted_dir, target_dir)
|
||||
|
@ -214,9 +214,9 @@ class OpenAIPrompt(Prompt):
|
||||
self.responses[index].stream_from_dict(delta)
|
||||
|
||||
if 'function_call' in delta:
|
||||
if 'name' in delta['function_call']:
|
||||
if 'name' in delta['function_call'] and \
|
||||
self.responses[index].function_call.get('name', '') == '':
|
||||
self.responses[index].function_call['name'] = \
|
||||
self.responses[index].function_call.get('name', '') + \
|
||||
delta['function_call']['name']
|
||||
if 'arguments' in delta['function_call']:
|
||||
self.responses[index].function_call['arguments'] = \
|
||||
|
@ -131,7 +131,11 @@ def get_user_info() -> Tuple[str, str]:
|
||||
cmd = ['git', 'config', 'user.name']
|
||||
user_name = subprocess.check_output(cmd, encoding='utf-8').strip()
|
||||
except Exception:
|
||||
user_name = getpass.getuser()
|
||||
try:
|
||||
user_name = getpass.getuser()
|
||||
except Exception:
|
||||
user_dir = os.path.expanduser("~")
|
||||
user_name = user_dir.split(os.sep)[-1]
|
||||
|
||||
try:
|
||||
cmd = ['git', 'config', 'user.email']
|
||||
|
@ -1,4 +1,4 @@
|
||||
../../../bin/distro,sha256=dnDD1oUCxitRiZYscod_zaN_Jx9vaObsAqxc7z0ISzY,243
|
||||
../../../bin/distro,sha256=MvzdEoL8w1_5cIA9f0DnTWI5Nedce0jHhqtxkt8PE_4,243
|
||||
distro-1.8.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
distro-1.8.0.dist-info/LICENSE,sha256=y16Ofl9KOYjhBjwULGDcLfdWBfTEZRXnduOspt-XbhQ,11325
|
||||
distro-1.8.0.dist-info/METADATA,sha256=NhYw94UPXb78_Z3_VtLxTJ1zQgUUKoTndg10uKJX800,6915
|
||||
|
BIN
site-packages/distro/.DS_Store
vendored
BIN
site-packages/distro/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/exceptiongroup/.DS_Store
vendored
BIN
site-packages/exceptiongroup/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/git/.DS_Store
vendored
BIN
site-packages/git/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/git/index/.DS_Store
vendored
BIN
site-packages/git/index/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/git/objects/.DS_Store
vendored
BIN
site-packages/git/objects/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/git/objects/submodule/.DS_Store
vendored
BIN
site-packages/git/objects/submodule/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/git/refs/.DS_Store
vendored
BIN
site-packages/git/refs/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/git/repo/.DS_Store
vendored
BIN
site-packages/git/repo/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/gitdb/.DS_Store
vendored
BIN
site-packages/gitdb/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/gitdb/db/.DS_Store
vendored
BIN
site-packages/gitdb/db/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/gitdb/test/.DS_Store
vendored
BIN
site-packages/gitdb/test/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/gitdb/utils/.DS_Store
vendored
BIN
site-packages/gitdb/utils/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/h11/.DS_Store
vendored
BIN
site-packages/h11/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/h11/tests/.DS_Store
vendored
BIN
site-packages/h11/tests/.DS_Store
vendored
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: httpcore
|
||||
Version: 0.18.0
|
||||
Version: 1.0.2
|
||||
Summary: A minimal low-level HTTP client.
|
||||
Project-URL: Documentation, https://www.encode.io/httpcore
|
||||
Project-URL: Homepage, https://www.encode.io/httpcore/
|
||||
@ -21,16 +21,19 @@ Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Topic :: Internet :: WWW/HTTP
|
||||
Requires-Python: >=3.8
|
||||
Requires-Dist: anyio<5.0,>=3.0
|
||||
Requires-Dist: certifi
|
||||
Requires-Dist: h11<0.15,>=0.13
|
||||
Requires-Dist: sniffio==1.*
|
||||
Provides-Extra: asyncio
|
||||
Requires-Dist: anyio<5.0,>=4.0; extra == 'asyncio'
|
||||
Provides-Extra: http2
|
||||
Requires-Dist: h2<5,>=3; extra == 'http2'
|
||||
Provides-Extra: socks
|
||||
Requires-Dist: socksio==1.*; extra == 'socks'
|
||||
Provides-Extra: trio
|
||||
Requires-Dist: trio<0.23.0,>=0.22.0; extra == 'trio'
|
||||
Description-Content-Type: text/markdown
|
||||
|
||||
# HTTP Core
|
||||
@ -70,16 +73,10 @@ For HTTP/1.1 only support, install with:
|
||||
$ pip install httpcore
|
||||
```
|
||||
|
||||
For HTTP/1.1 and HTTP/2 support, install with:
|
||||
There are also a number of optional extras available...
|
||||
|
||||
```shell
|
||||
$ pip install httpcore[http2]
|
||||
```
|
||||
|
||||
For SOCKS proxy support, install with:
|
||||
|
||||
```shell
|
||||
$ pip install httpcore[socks]
|
||||
$ pip install httpcore['asyncio,trio,http2,socks']
|
||||
```
|
||||
|
||||
# Sending requests
|
||||
@ -124,12 +121,59 @@ The motivation for `httpcore` is:
|
||||
* To provide a reusable low-level client library, that other packages can then build on top of.
|
||||
* To provide a *really clear interface split* between the networking code and client logic,
|
||||
so that each is easier to understand and reason about in isolation.
|
||||
|
||||
## Dependencies
|
||||
|
||||
The `httpcore` package has the following dependencies...
|
||||
|
||||
* `h11`
|
||||
* `certifi`
|
||||
|
||||
And the following optional extras...
|
||||
|
||||
* `anyio` - Required by `pip install httpcore['asyncio']`.
|
||||
* `trio` - Required by `pip install httpcore['trio']`.
|
||||
* `h2` - Required by `pip install httpcore['http2']`.
|
||||
* `socksio` - Required by `pip install httpcore['socks']`.
|
||||
|
||||
## Versioning
|
||||
|
||||
We use [SEMVER for our versioning policy](https://semver.org/).
|
||||
|
||||
For changes between package versions please see our [project changelog](CHANGELOG.md).
|
||||
|
||||
We recommend pinning your requirements either the most current major version, or a more specific version range:
|
||||
|
||||
```python
|
||||
pip install 'httpcore==1.*'
|
||||
```
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## 1.0.2 (November 10th, 2023)
|
||||
|
||||
- Fix `float("inf")` timeouts in `Event.wait` function. (#846)
|
||||
|
||||
## 1.0.1 (November 3rd, 2023)
|
||||
|
||||
- Fix pool timeout to account for the total time spent retrying. (#823)
|
||||
- Raise a neater RuntimeError when the correct async deps are not installed. (#826)
|
||||
- Add support for synchronous TLS-in-TLS streams. (#840)
|
||||
|
||||
## 1.0.0 (October 6th, 2023)
|
||||
|
||||
From version 1.0 our async support is now optional, as the package has minimal dependencies by default.
|
||||
|
||||
For async support use either `pip install 'httpcore[asyncio]'` or `pip install 'httpcore[trio]'`.
|
||||
|
||||
The project versioning policy is now explicitly governed by SEMVER. See https://semver.org/.
|
||||
|
||||
- Async support becomes fully optional. (#809)
|
||||
- Add support for Python 3.12. (#807)
|
||||
|
||||
## 0.18.0 (September 8th, 2023)
|
||||
|
||||
- Add support for HTTPS proxies. (#745, #786)
|
@ -1,9 +1,9 @@
|
||||
httpcore-0.18.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
httpcore-0.18.0.dist-info/METADATA,sha256=HYLl3BBm0kYpuqAPEqFCT0ErYv1rHgvxkY4-EuwPlEY,18914
|
||||
httpcore-0.18.0.dist-info/RECORD,,
|
||||
httpcore-0.18.0.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
|
||||
httpcore-0.18.0.dist-info/licenses/LICENSE.md,sha256=_ctZFUx0y6uhahEkL3dAvqnyPW_rVUeRfYxflKgDkqU,1518
|
||||
httpcore/__init__.py,sha256=VfaTITS2e1pevgXk6fF0cZSH3f4YUt_iXqGYSsbyyY0,3338
|
||||
httpcore-1.0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
httpcore-1.0.2.dist-info/METADATA,sha256=APYVcc50lK6LWlbwft616GXXpg3gRxKY1Srm-g0xEHM,20442
|
||||
httpcore-1.0.2.dist-info/RECORD,,
|
||||
httpcore-1.0.2.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
|
||||
httpcore-1.0.2.dist-info/licenses/LICENSE.md,sha256=_ctZFUx0y6uhahEkL3dAvqnyPW_rVUeRfYxflKgDkqU,1518
|
||||
httpcore/__init__.py,sha256=_nBsHMRwZbRGG3ci9bZPcyBwL5z3_SM1EEEafTw37EA,3337
|
||||
httpcore/__pycache__/__init__.cpython-39.pyc,,
|
||||
httpcore/__pycache__/_api.cpython-39.pyc,,
|
||||
httpcore/__pycache__/_exceptions.cpython-39.pyc,,
|
||||
@ -23,7 +23,7 @@ httpcore/_async/__pycache__/http_proxy.cpython-39.pyc,,
|
||||
httpcore/_async/__pycache__/interfaces.cpython-39.pyc,,
|
||||
httpcore/_async/__pycache__/socks_proxy.cpython-39.pyc,,
|
||||
httpcore/_async/connection.py,sha256=klHOqiHVo4TUC_X9IsKEnfMHKQcH-WajYAkszBuLXOA,8619
|
||||
httpcore/_async/connection_pool.py,sha256=hj1viqcWZivNmoRu-QZjyuOvAFx3-Ae2rMpuK6OZhEM,14305
|
||||
httpcore/_async/connection_pool.py,sha256=k9pkv4w_tntmxzDtkHuM54nJmHT3aabxf_7ou5b-9L4,14767
|
||||
httpcore/_async/http11.py,sha256=t7I91I77Zh06UVopMfqvrGskFdpwnQLo5kt04qTCI7U,12441
|
||||
httpcore/_async/http2.py,sha256=KXwWZxZ-43vxIWzr1aTLErhaCodDzFr-XAvzc4fUb10,23879
|
||||
httpcore/_async/http_proxy.py,sha256=hl4t-PahlAuCGtKNYRx4LSgjx1ZuspE9oDBaL6BOess,14851
|
||||
@ -38,10 +38,10 @@ httpcore/_backends/__pycache__/mock.cpython-39.pyc,,
|
||||
httpcore/_backends/__pycache__/sync.cpython-39.pyc,,
|
||||
httpcore/_backends/__pycache__/trio.cpython-39.pyc,,
|
||||
httpcore/_backends/anyio.py,sha256=mU8gtunBSLxESGkU0Iy1ZMgumDlAeMkwBjFE3kZiCnc,5208
|
||||
httpcore/_backends/auto.py,sha256=8r0ipGxSwXoCb_xKQAyRwL1UzfXVbO4Ee2y8vYQv3Ic,1654
|
||||
httpcore/_backends/auto.py,sha256=Q_iQjNuwJseqBxeYJYtiaGzFs08_LGI3K_egYrixEqE,1683
|
||||
httpcore/_backends/base.py,sha256=Qsb8b_PSiVP1ldHHGXHxQzJ1Qlzj2r8KR9KQeANkSbE,3218
|
||||
httpcore/_backends/mock.py,sha256=S4IADhC6kE22ge_jR_WHlEUkD6QAsXnwz26DSWZLcG4,4179
|
||||
httpcore/_backends/sync.py,sha256=z4emZ__8qOAWewBtpkkl3gkpR210RN1l3J8Nud0kZc8,8347
|
||||
httpcore/_backends/sync.py,sha256=LAomvc-MAlot5-S9CCFxnr561aDp9yhyfs_65WeCkZ4,8086
|
||||
httpcore/_backends/trio.py,sha256=INOeHEkA8pO6AsSqjColWcayM0FQSyGi1hpaQghjrCs,6078
|
||||
httpcore/_exceptions.py,sha256=7zb3KNiG0qmfUNIdFgdaUSbn2Pu3oztghi6Vg7i-LJU,1185
|
||||
httpcore/_models.py,sha256=GTqsbLHxsd_lx0cvtgUBf7OltodKHjIrNKs-DbSc67k,16370
|
||||
@ -56,13 +56,13 @@ httpcore/_sync/__pycache__/http_proxy.cpython-39.pyc,,
|
||||
httpcore/_sync/__pycache__/interfaces.cpython-39.pyc,,
|
||||
httpcore/_sync/__pycache__/socks_proxy.cpython-39.pyc,,
|
||||
httpcore/_sync/connection.py,sha256=luocU3Tv3jlvOCaro33xrHZAwBkpn991LWdL7BC8Bkg,8408
|
||||
httpcore/_sync/connection_pool.py,sha256=1iwYLdiq3pi9LBvpMZ8O8gWdb56qqPlm6rp35zeORBQ,13928
|
||||
httpcore/_sync/connection_pool.py,sha256=JUt-Rpg2l_17JbckVMk2TCs-EbBeUf1swH3EYC5AZVU,14384
|
||||
httpcore/_sync/http11.py,sha256=1VRRlpqQgIKjxt9xQAeUbDH1Mq3280pC1AU_gwu19VQ,12102
|
||||
httpcore/_sync/http2.py,sha256=lkpHesGkrwzIA4oHLyClJf5IAwRLcaAFMnmffAahAK4,23343
|
||||
httpcore/_sync/http_proxy.py,sha256=82oin8vjt2a7YmmVvz7sXEZSBuajK-mHDF-EwnR_pJ0,14613
|
||||
httpcore/_sync/interfaces.py,sha256=EM4PTf-rgkclzisFcrTyx1G8FwraoffE8rbckOznX_o,4365
|
||||
httpcore/_sync/socks_proxy.py,sha256=T13QSceeEAg1PM9Yh7Nk-DoqI28TIUqDS-9O3OSC9Uc,13707
|
||||
httpcore/_synchronization.py,sha256=_d_vHqylvzm1Jh58_0G7i-1VwCg3Gu39Cgd4nWASvP0,8751
|
||||
httpcore/_synchronization.py,sha256=ABAtHNAESvZqu43FP_lTKpuJ84bavUbAZoN2q8E0W3o,8054
|
||||
httpcore/_trace.py,sha256=akf5PsWVq3rZjqmXniomU59OY37K7JHoeNDCQ4GU84E,3954
|
||||
httpcore/_utils.py,sha256=9QPh5ib4JilWX4dBCC_XO6wdBY4b0kbUGgfV3QfBANc,1525
|
||||
httpcore/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
BIN
site-packages/httpcore/.DS_Store
vendored
BIN
site-packages/httpcore/.DS_Store
vendored
Binary file not shown.
@ -130,7 +130,7 @@ __all__ = [
|
||||
"WriteError",
|
||||
]
|
||||
|
||||
__version__ = "0.18.0"
|
||||
__version__ = "1.0.2"
|
||||
|
||||
|
||||
__locals = locals()
|
||||
|
BIN
site-packages/httpcore/_async/.DS_Store
vendored
BIN
site-packages/httpcore/_async/.DS_Store
vendored
Binary file not shown.
@ -1,11 +1,12 @@
|
||||
import ssl
|
||||
import sys
|
||||
import time
|
||||
from types import TracebackType
|
||||
from typing import AsyncIterable, AsyncIterator, Iterable, List, Optional, Type
|
||||
|
||||
from .._backends.auto import AutoBackend
|
||||
from .._backends.base import SOCKET_OPTION, AsyncNetworkBackend
|
||||
from .._exceptions import ConnectionNotAvailable, UnsupportedProtocol
|
||||
from .._exceptions import ConnectionNotAvailable, PoolTimeout, UnsupportedProtocol
|
||||
from .._models import Origin, Request, Response
|
||||
from .._synchronization import AsyncEvent, AsyncLock, AsyncShieldCancellation
|
||||
from .connection import AsyncHTTPConnection
|
||||
@ -220,6 +221,13 @@ class AsyncConnectionPool(AsyncRequestInterface):
|
||||
)
|
||||
|
||||
status = RequestStatus(request)
|
||||
timeouts = request.extensions.get("timeout", {})
|
||||
timeout = timeouts.get("pool", None)
|
||||
|
||||
if timeout is not None:
|
||||
deadline = time.monotonic() + timeout
|
||||
else:
|
||||
deadline = float("inf")
|
||||
|
||||
async with self._pool_lock:
|
||||
self._requests.append(status)
|
||||
@ -227,8 +235,6 @@ class AsyncConnectionPool(AsyncRequestInterface):
|
||||
await self._attempt_to_acquire_connection(status)
|
||||
|
||||
while True:
|
||||
timeouts = request.extensions.get("timeout", {})
|
||||
timeout = timeouts.get("pool", None)
|
||||
try:
|
||||
connection = await status.wait_for_connection(timeout=timeout)
|
||||
except BaseException as exc:
|
||||
@ -263,6 +269,10 @@ class AsyncConnectionPool(AsyncRequestInterface):
|
||||
else:
|
||||
break
|
||||
|
||||
timeout = deadline - time.monotonic()
|
||||
if timeout < 0:
|
||||
raise PoolTimeout # pragma: nocover
|
||||
|
||||
# When we return the response, we wrap the stream in a special class
|
||||
# that handles notifying the connection pool once the response
|
||||
# has been released.
|
||||
@ -316,6 +326,10 @@ class AsyncConnectionPool(AsyncRequestInterface):
|
||||
self._requests = []
|
||||
|
||||
async def __aenter__(self) -> "AsyncConnectionPool":
|
||||
# Acquiring the pool lock here ensures that we have the
|
||||
# correct dependencies installed as early as possible.
|
||||
async with self._pool_lock:
|
||||
pass
|
||||
return self
|
||||
|
||||
async def __aexit__(
|
||||
|
BIN
site-packages/httpcore/_backends/.DS_Store
vendored
BIN
site-packages/httpcore/_backends/.DS_Store
vendored
Binary file not shown.
@ -1,15 +1,14 @@
|
||||
import typing
|
||||
from typing import Optional
|
||||
|
||||
import sniffio
|
||||
|
||||
from .._synchronization import current_async_library
|
||||
from .base import SOCKET_OPTION, AsyncNetworkBackend, AsyncNetworkStream
|
||||
|
||||
|
||||
class AutoBackend(AsyncNetworkBackend):
|
||||
async def _init_backend(self) -> None:
|
||||
if not (hasattr(self, "_backend")):
|
||||
backend = sniffio.current_async_library()
|
||||
backend = current_async_library()
|
||||
if backend == "trio":
|
||||
from .trio import TrioBackend
|
||||
|
||||
|
@ -145,12 +145,6 @@ class SyncStream(NetworkStream):
|
||||
server_hostname: typing.Optional[str] = None,
|
||||
timeout: typing.Optional[float] = None,
|
||||
) -> NetworkStream:
|
||||
if isinstance(self._sock, ssl.SSLSocket): # pragma: no cover
|
||||
raise RuntimeError(
|
||||
"Attempted to add a TLS layer on top of the existing "
|
||||
"TLS stream, which is not supported by httpcore package"
|
||||
)
|
||||
|
||||
exc_map: ExceptionMapping = {
|
||||
socket.timeout: ConnectTimeout,
|
||||
OSError: ConnectError,
|
||||
|
BIN
site-packages/httpcore/_sync/.DS_Store
vendored
BIN
site-packages/httpcore/_sync/.DS_Store
vendored
Binary file not shown.
@ -1,11 +1,12 @@
|
||||
import ssl
|
||||
import sys
|
||||
import time
|
||||
from types import TracebackType
|
||||
from typing import Iterable, Iterator, Iterable, List, Optional, Type
|
||||
|
||||
from .._backends.sync import SyncBackend
|
||||
from .._backends.base import SOCKET_OPTION, NetworkBackend
|
||||
from .._exceptions import ConnectionNotAvailable, UnsupportedProtocol
|
||||
from .._exceptions import ConnectionNotAvailable, PoolTimeout, UnsupportedProtocol
|
||||
from .._models import Origin, Request, Response
|
||||
from .._synchronization import Event, Lock, ShieldCancellation
|
||||
from .connection import HTTPConnection
|
||||
@ -220,6 +221,13 @@ class ConnectionPool(RequestInterface):
|
||||
)
|
||||
|
||||
status = RequestStatus(request)
|
||||
timeouts = request.extensions.get("timeout", {})
|
||||
timeout = timeouts.get("pool", None)
|
||||
|
||||
if timeout is not None:
|
||||
deadline = time.monotonic() + timeout
|
||||
else:
|
||||
deadline = float("inf")
|
||||
|
||||
with self._pool_lock:
|
||||
self._requests.append(status)
|
||||
@ -227,8 +235,6 @@ class ConnectionPool(RequestInterface):
|
||||
self._attempt_to_acquire_connection(status)
|
||||
|
||||
while True:
|
||||
timeouts = request.extensions.get("timeout", {})
|
||||
timeout = timeouts.get("pool", None)
|
||||
try:
|
||||
connection = status.wait_for_connection(timeout=timeout)
|
||||
except BaseException as exc:
|
||||
@ -263,6 +269,10 @@ class ConnectionPool(RequestInterface):
|
||||
else:
|
||||
break
|
||||
|
||||
timeout = deadline - time.monotonic()
|
||||
if timeout < 0:
|
||||
raise PoolTimeout # pragma: nocover
|
||||
|
||||
# When we return the response, we wrap the stream in a special class
|
||||
# that handles notifying the connection pool once the response
|
||||
# has been released.
|
||||
@ -316,6 +326,10 @@ class ConnectionPool(RequestInterface):
|
||||
self._requests = []
|
||||
|
||||
def __enter__(self) -> "ConnectionPool":
|
||||
# Acquiring the pool lock here ensures that we have the
|
||||
# correct dependencies installed as early as possible.
|
||||
with self._pool_lock:
|
||||
pass
|
||||
return self
|
||||
|
||||
def __exit__(
|
||||
|
@ -2,8 +2,6 @@ import threading
|
||||
from types import TracebackType
|
||||
from typing import Optional, Type
|
||||
|
||||
import sniffio
|
||||
|
||||
from ._exceptions import ExceptionMapping, PoolTimeout, map_exceptions
|
||||
|
||||
# Our async synchronization primatives use either 'anyio' or 'trio' depending
|
||||
@ -20,6 +18,32 @@ except ImportError: # pragma: nocover
|
||||
anyio = None # type: ignore
|
||||
|
||||
|
||||
def current_async_library() -> str:
|
||||
# Determine if we're running under trio or asyncio.
|
||||
# See https://sniffio.readthedocs.io/en/latest/
|
||||
try:
|
||||
import sniffio
|
||||
except ImportError: # pragma: nocover
|
||||
environment = "asyncio"
|
||||
else:
|
||||
environment = sniffio.current_async_library()
|
||||
|
||||
if environment not in ("asyncio", "trio"): # pragma: nocover
|
||||
raise RuntimeError("Running under an unsupported async environment.")
|
||||
|
||||
if environment == "asyncio" and anyio is None: # pragma: nocover
|
||||
raise RuntimeError(
|
||||
"Running with asyncio requires installation of 'httpcore[asyncio]'."
|
||||
)
|
||||
|
||||
if environment == "trio" and trio is None: # pragma: nocover
|
||||
raise RuntimeError(
|
||||
"Running with trio requires installation of 'httpcore[trio]'."
|
||||
)
|
||||
|
||||
return environment
|
||||
|
||||
|
||||
class AsyncLock:
|
||||
def __init__(self) -> None:
|
||||
self._backend = ""
|
||||
@ -29,18 +53,10 @@ class AsyncLock:
|
||||
Detect if we're running under 'asyncio' or 'trio' and create
|
||||
a lock with the correct implementation.
|
||||
"""
|
||||
self._backend = sniffio.current_async_library()
|
||||
self._backend = current_async_library()
|
||||
if self._backend == "trio":
|
||||
if trio is None: # pragma: nocover
|
||||
raise RuntimeError(
|
||||
"Running under trio, requires the 'trio' package to be installed."
|
||||
)
|
||||
self._trio_lock = trio.Lock()
|
||||
else:
|
||||
if anyio is None: # pragma: nocover
|
||||
raise RuntimeError(
|
||||
"Running under asyncio requires the 'anyio' package to be installed."
|
||||
)
|
||||
elif self._backend == "asyncio":
|
||||
self._anyio_lock = anyio.Lock()
|
||||
|
||||
async def __aenter__(self) -> "AsyncLock":
|
||||
@ -49,7 +65,7 @@ class AsyncLock:
|
||||
|
||||
if self._backend == "trio":
|
||||
await self._trio_lock.acquire()
|
||||
else:
|
||||
elif self._backend == "asyncio":
|
||||
await self._anyio_lock.acquire()
|
||||
|
||||
return self
|
||||
@ -62,7 +78,7 @@ class AsyncLock:
|
||||
) -> None:
|
||||
if self._backend == "trio":
|
||||
self._trio_lock.release()
|
||||
else:
|
||||
elif self._backend == "asyncio":
|
||||
self._anyio_lock.release()
|
||||
|
||||
|
||||
@ -75,18 +91,10 @@ class AsyncEvent:
|
||||
Detect if we're running under 'asyncio' or 'trio' and create
|
||||
a lock with the correct implementation.
|
||||
"""
|
||||
self._backend = sniffio.current_async_library()
|
||||
self._backend = current_async_library()
|
||||
if self._backend == "trio":
|
||||
if trio is None: # pragma: nocover
|
||||
raise RuntimeError(
|
||||
"Running under trio requires the 'trio' package to be installed."
|
||||
)
|
||||
self._trio_event = trio.Event()
|
||||
else:
|
||||
if anyio is None: # pragma: nocover
|
||||
raise RuntimeError(
|
||||
"Running under asyncio requires the 'anyio' package to be installed."
|
||||
)
|
||||
elif self._backend == "asyncio":
|
||||
self._anyio_event = anyio.Event()
|
||||
|
||||
def set(self) -> None:
|
||||
@ -95,7 +103,7 @@ class AsyncEvent:
|
||||
|
||||
if self._backend == "trio":
|
||||
self._trio_event.set()
|
||||
else:
|
||||
elif self._backend == "asyncio":
|
||||
self._anyio_event.set()
|
||||
|
||||
async def wait(self, timeout: Optional[float] = None) -> None:
|
||||
@ -103,22 +111,12 @@ class AsyncEvent:
|
||||
self.setup()
|
||||
|
||||
if self._backend == "trio":
|
||||
if trio is None: # pragma: nocover
|
||||
raise RuntimeError(
|
||||
"Running under trio requires the 'trio' package to be installed."
|
||||
)
|
||||
|
||||
trio_exc_map: ExceptionMapping = {trio.TooSlowError: PoolTimeout}
|
||||
timeout_or_inf = float("inf") if timeout is None else timeout
|
||||
with map_exceptions(trio_exc_map):
|
||||
with trio.fail_after(timeout_or_inf):
|
||||
await self._trio_event.wait()
|
||||
else:
|
||||
if anyio is None: # pragma: nocover
|
||||
raise RuntimeError(
|
||||
"Running under asyncio requires the 'anyio' package to be installed."
|
||||
)
|
||||
|
||||
elif self._backend == "asyncio":
|
||||
anyio_exc_map: ExceptionMapping = {TimeoutError: PoolTimeout}
|
||||
with map_exceptions(anyio_exc_map):
|
||||
with anyio.fail_after(timeout):
|
||||
@ -135,22 +133,12 @@ class AsyncSemaphore:
|
||||
Detect if we're running under 'asyncio' or 'trio' and create
|
||||
a semaphore with the correct implementation.
|
||||
"""
|
||||
self._backend = sniffio.current_async_library()
|
||||
self._backend = current_async_library()
|
||||
if self._backend == "trio":
|
||||
if trio is None: # pragma: nocover
|
||||
raise RuntimeError(
|
||||
"Running under trio requires the 'trio' package to be installed."
|
||||
)
|
||||
|
||||
self._trio_semaphore = trio.Semaphore(
|
||||
initial_value=self._bound, max_value=self._bound
|
||||
)
|
||||
else:
|
||||
if anyio is None: # pragma: nocover
|
||||
raise RuntimeError(
|
||||
"Running under asyncio requires the 'anyio' package to be installed."
|
||||
)
|
||||
|
||||
elif self._backend == "asyncio":
|
||||
self._anyio_semaphore = anyio.Semaphore(
|
||||
initial_value=self._bound, max_value=self._bound
|
||||
)
|
||||
@ -161,13 +149,13 @@ class AsyncSemaphore:
|
||||
|
||||
if self._backend == "trio":
|
||||
await self._trio_semaphore.acquire()
|
||||
else:
|
||||
elif self._backend == "asyncio":
|
||||
await self._anyio_semaphore.acquire()
|
||||
|
||||
async def release(self) -> None:
|
||||
if self._backend == "trio":
|
||||
self._trio_semaphore.release()
|
||||
else:
|
||||
elif self._backend == "asyncio":
|
||||
self._anyio_semaphore.release()
|
||||
|
||||
|
||||
@ -184,27 +172,17 @@ class AsyncShieldCancellation:
|
||||
Detect if we're running under 'asyncio' or 'trio' and create
|
||||
a shielded scope with the correct implementation.
|
||||
"""
|
||||
self._backend = sniffio.current_async_library()
|
||||
self._backend = current_async_library()
|
||||
|
||||
if self._backend == "trio":
|
||||
if trio is None: # pragma: nocover
|
||||
raise RuntimeError(
|
||||
"Running under trio requires the 'trio' package to be installed."
|
||||
)
|
||||
|
||||
self._trio_shield = trio.CancelScope(shield=True)
|
||||
else:
|
||||
if anyio is None: # pragma: nocover
|
||||
raise RuntimeError(
|
||||
"Running under asyncio requires the 'anyio' package to be installed."
|
||||
)
|
||||
|
||||
elif self._backend == "asyncio":
|
||||
self._anyio_shield = anyio.CancelScope(shield=True)
|
||||
|
||||
def __enter__(self) -> "AsyncShieldCancellation":
|
||||
if self._backend == "trio":
|
||||
self._trio_shield.__enter__()
|
||||
else:
|
||||
elif self._backend == "asyncio":
|
||||
self._anyio_shield.__enter__()
|
||||
return self
|
||||
|
||||
@ -216,7 +194,7 @@ class AsyncShieldCancellation:
|
||||
) -> None:
|
||||
if self._backend == "trio":
|
||||
self._trio_shield.__exit__(exc_type, exc_value, traceback)
|
||||
else:
|
||||
elif self._backend == "asyncio":
|
||||
self._anyio_shield.__exit__(exc_type, exc_value, traceback)
|
||||
|
||||
|
||||
@ -248,6 +226,8 @@ class Event:
|
||||
self._event.set()
|
||||
|
||||
def wait(self, timeout: Optional[float] = None) -> None:
|
||||
if timeout == float("inf"): # pragma: no cover
|
||||
timeout = None
|
||||
if not self._event.wait(timeout=timeout):
|
||||
raise PoolTimeout() # pragma: nocover
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: httpx
|
||||
Version: 0.25.0
|
||||
Version: 0.25.1
|
||||
Summary: The next generation HTTP client.
|
||||
Project-URL: Changelog, https://github.com/encode/httpx/blob/master/CHANGELOG.md
|
||||
Project-URL: Documentation, https://www.python-httpx.org
|
||||
@ -22,10 +22,12 @@ Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Topic :: Internet :: WWW/HTTP
|
||||
Requires-Python: >=3.8
|
||||
Requires-Dist: anyio
|
||||
Requires-Dist: certifi
|
||||
Requires-Dist: httpcore<0.19.0,>=0.18.0
|
||||
Requires-Dist: httpcore
|
||||
Requires-Dist: idna
|
||||
Requires-Dist: sniffio
|
||||
Provides-Extra: brotli
|
||||
@ -192,23 +194,14 @@ inspiration around the lower-level networking details.
|
||||
|
||||
## Release Information
|
||||
|
||||
### Removed
|
||||
### 0.25.1 (3rd November, 2023)
|
||||
|
||||
* Drop support for Python 3.7. (#2813)
|
||||
|
||||
### Added
|
||||
|
||||
* Support HTTPS proxies. (#2845)
|
||||
* Change the type of `Extensions` from `Mapping[Str, Any]` to `MutableMapping[Str, Any]`. (#2803)
|
||||
* Add `socket_options` argument to `httpx.HTTPTransport` and `httpx.AsyncHTTPTransport` classes. (#2716)
|
||||
* The `Response.raise_for_status()` method now returns the response instance. For example: `data = httpx.get('...').raise_for_status().json()`. (#2776)
|
||||
* Add support for Python 3.12. (#2854)
|
||||
* Add support for httpcore 1.0 (#2885)
|
||||
|
||||
### Fixed
|
||||
|
||||
* Return `500` error response instead of exceptions when `raise_app_exceptions=False` is set on `ASGITransport`. (#2669)
|
||||
* Ensure all `WSGITransport` environs have a `SERVER_PROTOCOL`. (#2708)
|
||||
* Always encode forward slashes as `%2F` in query parameters (#2723)
|
||||
* Use Mozilla documentation instead of `httpstatuses.com` for HTTP error reference (#2768)
|
||||
* Raise `ValueError` on `Response.encoding` being set after `Response.text` has been accessed. (#2852)
|
||||
|
||||
|
||||
---
|
@ -1,10 +1,10 @@
|
||||
../../../bin/httpx,sha256=KIP6KGLZF0RAHfVjqe3qTPD8GRYex0qWFBxARqKqu94,235
|
||||
httpx-0.25.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
httpx-0.25.0.dist-info/METADATA,sha256=8ZnffZ9BAo4gzHpfUFlvx2tQYM3-Z3FRwOh4BsgKgLk,7630
|
||||
httpx-0.25.0.dist-info/RECORD,,
|
||||
httpx-0.25.0.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
|
||||
httpx-0.25.0.dist-info/entry_points.txt,sha256=2lVkdQmxLA1pNMgSN2eV89o90HCZezhmNwsy6ryKDSA,37
|
||||
httpx-0.25.0.dist-info/licenses/LICENSE.md,sha256=TsWdVE8StfU5o6cW_TIaxYzNgDC0ZSIfLIgCAM3yjY0,1508
|
||||
../../../bin/httpx,sha256=Ug7WqeS1tnOXHYhEuY-5dLJW9cLyfsYkhpAZ_-JlYc0,235
|
||||
httpx-0.25.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
httpx-0.25.1.dist-info/METADATA,sha256=F-1gg84Cs1LReAfx4NmiNXp-qE9DqJKD3pHD1B64y5A,7095
|
||||
httpx-0.25.1.dist-info/RECORD,,
|
||||
httpx-0.25.1.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
|
||||
httpx-0.25.1.dist-info/entry_points.txt,sha256=2lVkdQmxLA1pNMgSN2eV89o90HCZezhmNwsy6ryKDSA,37
|
||||
httpx-0.25.1.dist-info/licenses/LICENSE.md,sha256=TsWdVE8StfU5o6cW_TIaxYzNgDC0ZSIfLIgCAM3yjY0,1508
|
||||
httpx/__init__.py,sha256=oCxVAsePEy5DE9eLhGAAq9H3RBGZUDaUROtGEyzbBRo,3210
|
||||
httpx/__pycache__/__init__.cpython-39.pyc,,
|
||||
httpx/__pycache__/__version__.cpython-39.pyc,,
|
||||
@ -24,18 +24,18 @@ httpx/__pycache__/_types.cpython-39.pyc,,
|
||||
httpx/__pycache__/_urlparse.cpython-39.pyc,,
|
||||
httpx/__pycache__/_urls.cpython-39.pyc,,
|
||||
httpx/__pycache__/_utils.cpython-39.pyc,,
|
||||
httpx/__version__.py,sha256=hVLEi3Fe6ziNKrXxfBIkYicKi_9NvZZvMQJMGUkSjIU,108
|
||||
httpx/__version__.py,sha256=Qdj8HFntcoM-E84xA8Y05EMH5ocBUPDZX722C_2Tvi0,108
|
||||
httpx/_api.py,sha256=cVU9ErzaXve5rqoPoSHr9yJbovHtICrcxR7yBoNSeOw,13011
|
||||
httpx/_auth.py,sha256=58FA-xqqp-XgLZ7Emd4-et-XXuTRaa5buiBYB2MzyvE,11773
|
||||
httpx/_auth.py,sha256=4ZLi3wfSttjqxOQFxys7hZ55b-8xq3ZKypa-sEz3d-Q,12013
|
||||
httpx/_client.py,sha256=A9MPP_d1ZlqcO5CeGLgyzVwdHgCpROYSdjoAUA6rpYE,68131
|
||||
httpx/_compat.py,sha256=S4sL2QocE1gj0qn6F7egl7dYhY809rXE5P9YD3e_zDg,1602
|
||||
httpx/_config.py,sha256=3AKbxOVuh2UeZi95UqALtoO1thrmHUhTxvcFAyspKPw,12491
|
||||
httpx/_compat.py,sha256=rJERfjHkRvvHFVfltbHyCVcAboNsfEeN6j_00Z2C4k8,1563
|
||||
httpx/_config.py,sha256=_NFrJwZr0yFysMaTt3rCnJqHvV5vQQG3yUg1kxSomjs,12334
|
||||
httpx/_content.py,sha256=olbWqawdWWweXeW6gDYHPiEGjip5lqFZKv9OmVd-zIg,8092
|
||||
httpx/_decoders.py,sha256=dd8GSkEAe45BzRUF47zH_lg3-BcwXtxzPBSGP5Y4F90,9739
|
||||
httpx/_exceptions.py,sha256=xKw-U6vW7zmdReUAGYHMegYWZuDAuE5039L087SHe4Q,7880
|
||||
httpx/_main.py,sha256=m9C4RuqjOB6UqL3FFHMjmC45f4SDSO-iOREFLdw4IdM,15784
|
||||
httpx/_models.py,sha256=gfrZvx3B0R2U7bLT7JfNKt4DMnUoT8leHOiij6Te13A,42791
|
||||
httpx/_multipart.py,sha256=qzt35jAgapaRPwdq-lTKSA5YY6ayrfDIsZLdr3t4NWc,8972
|
||||
httpx/_models.py,sha256=6lIr7avUeJo2qp0vN4HSOgI96TPzbq1HtGSHNRwO-gg,42896
|
||||
httpx/_multipart.py,sha256=yTaczu2EcFX5GcOmDW8_2x2w2d1j4_8qFcsUCyYLSUI,8960
|
||||
httpx/_status_codes.py,sha256=XKArMrSoo8oKBQCHdFGA-wsM2PcSTaHE8svDYOUcwWk,5584
|
||||
httpx/_transports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
httpx/_transports/__pycache__/__init__.cpython-39.pyc,,
|
||||
@ -46,11 +46,11 @@ httpx/_transports/__pycache__/mock.cpython-39.pyc,,
|
||||
httpx/_transports/__pycache__/wsgi.cpython-39.pyc,,
|
||||
httpx/_transports/asgi.py,sha256=ZoIHy1-Wu09vZRkjzVzXJFgw9sh0Dq5cG8zfgtqK-SA,5469
|
||||
httpx/_transports/base.py,sha256=0BM8yZZEkdFT4tXXSm0h0dK0cSYA4hLgInj_BljGEGw,2510
|
||||
httpx/_transports/default.py,sha256=u99Nctd3mDNHfOc-S_ldaEwSvlp8NGLwIW2rjY0VgP4,13192
|
||||
httpx/_transports/default.py,sha256=Kn-RztYMwpHT3rBna3UVYE39W67ipEXnUr1FJTc0-9s,13175
|
||||
httpx/_transports/mock.py,sha256=sDt3BDXbz8-W94kC8OXtGzF1PWH0y73h1De7Q-XkVtg,1179
|
||||
httpx/_transports/wsgi.py,sha256=Zt3EhTagyF3o-HC2oPMp-hTy3M3kQThL1ECJRc8eXEM,4797
|
||||
httpx/_types.py,sha256=W_lOq_3FnHmZGQuXaGm5JDykFoC0WoqhnfH92nRDNGQ,3367
|
||||
httpx/_urlparse.py,sha256=UQbI0l39smQh5UplxFAtLYfuxSx1cC_JPivhBPBSWgk,16774
|
||||
httpx/_urlparse.py,sha256=Vpz_ydrcGCy5ReNqrU9lhuqsZJLER3hE-Wq5crYCb48,16777
|
||||
httpx/_urls.py,sha256=JAONd-2reXpB_WuQ7WuvhUcLuebiQeYJQPyszADmCow,21840
|
||||
httpx/_utils.py,sha256=I_m2rFyEpoU2j8lS0GwdWcUTBTQ8cjvFnZ8ROmnCpR8,15403
|
||||
httpx/_utils.py,sha256=ugUzRBmO4i_wDXSmyaGhOiQ6w4WAXCopG-uxrdn16dk,14109
|
||||
httpx/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
BIN
site-packages/httpx/.DS_Store
vendored
BIN
site-packages/httpx/.DS_Store
vendored
Binary file not shown.
@ -1,3 +1,3 @@
|
||||
__title__ = "httpx"
|
||||
__description__ = "A next generation HTTP client, for Python 3."
|
||||
__version__ = "0.25.0"
|
||||
__version__ = "0.25.1"
|
||||
|
@ -1,5 +1,4 @@
|
||||
import hashlib
|
||||
import netrc
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
@ -8,7 +7,7 @@ from base64 import b64encode
|
||||
from urllib.request import parse_http_list
|
||||
|
||||
from ._exceptions import ProtocolError
|
||||
from ._models import Request, Response
|
||||
from ._models import Cookies, Request, Response
|
||||
from ._utils import to_bytes, to_str, unquote
|
||||
|
||||
if typing.TYPE_CHECKING: # pragma: no cover
|
||||
@ -148,6 +147,10 @@ class NetRCAuth(Auth):
|
||||
"""
|
||||
|
||||
def __init__(self, file: typing.Optional[str] = None):
|
||||
# Lazily import 'netrc'.
|
||||
# There's no need for us to load this module unless 'NetRCAuth' is being used.
|
||||
import netrc
|
||||
|
||||
self._netrc_info = netrc.netrc(file)
|
||||
|
||||
def auth_flow(self, request: Request) -> typing.Generator[Request, Response, None]:
|
||||
@ -217,6 +220,8 @@ class DigestAuth(Auth):
|
||||
request.headers["Authorization"] = self._build_auth_header(
|
||||
request, self._last_challenge
|
||||
)
|
||||
if response.cookies:
|
||||
Cookies(response.cookies).set_cookie_header(request=request)
|
||||
yield request
|
||||
|
||||
def _parse_challenge(
|
||||
|
@ -16,9 +16,7 @@ except ImportError: # pragma: no cover
|
||||
except ImportError:
|
||||
brotli = None
|
||||
|
||||
if sys.version_info >= (3, 10) or (
|
||||
sys.version_info >= (3, 8) and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0, 7)
|
||||
):
|
||||
if sys.version_info >= (3, 10) or ssl.OPENSSL_VERSION_INFO >= (1, 1, 0, 7):
|
||||
|
||||
def set_minimum_tls_version_1_2(context: ssl.SSLContext) -> None:
|
||||
# The OP_NO_SSL* and OP_NO_TLS* become deprecated in favor of
|
||||
|
@ -1,7 +1,6 @@
|
||||
import logging
|
||||
import os
|
||||
import ssl
|
||||
import sys
|
||||
import typing
|
||||
from pathlib import Path
|
||||
|
||||
@ -128,11 +127,10 @@ class SSLConfig:
|
||||
|
||||
# Signal to server support for PHA in TLS 1.3. Raises an
|
||||
# AttributeError if only read-only access is implemented.
|
||||
if sys.version_info >= (3, 8): # pragma: no cover
|
||||
try:
|
||||
context.post_handshake_auth = True
|
||||
except AttributeError: # pragma: no cover
|
||||
pass
|
||||
try:
|
||||
context.post_handshake_auth = True
|
||||
except AttributeError: # pragma: no cover
|
||||
pass
|
||||
|
||||
# Disable using 'commonName' for SSLContext.check_hostname
|
||||
# when the 'subjectAltName' extension isn't available.
|
||||
@ -168,10 +166,9 @@ class SSLConfig:
|
||||
alpn_idents = ["http/1.1", "h2"] if self.http2 else ["http/1.1"]
|
||||
context.set_alpn_protocols(alpn_idents)
|
||||
|
||||
if sys.version_info >= (3, 8): # pragma: no cover
|
||||
keylogfile = os.environ.get("SSLKEYLOGFILE")
|
||||
if keylogfile and self.trust_env:
|
||||
context.keylog_filename = keylogfile
|
||||
keylogfile = os.environ.get("SSLKEYLOGFILE")
|
||||
if keylogfile and self.trust_env:
|
||||
context.keylog_filename = keylogfile
|
||||
|
||||
return context
|
||||
|
||||
|
@ -43,7 +43,6 @@ from ._types import (
|
||||
)
|
||||
from ._urls import URL
|
||||
from ._utils import (
|
||||
guess_json_utf,
|
||||
is_known_encoding,
|
||||
normalize_header_key,
|
||||
normalize_header_value,
|
||||
@ -603,6 +602,16 @@ class Response:
|
||||
|
||||
@encoding.setter
|
||||
def encoding(self, value: str) -> None:
|
||||
"""
|
||||
Set the encoding to use for decoding the byte content into text.
|
||||
|
||||
If the `text` attribute has been accessed, attempting to set the
|
||||
encoding will throw a ValueError.
|
||||
"""
|
||||
if hasattr(self, "_text"):
|
||||
raise ValueError(
|
||||
"Setting encoding after `text` has been accessed is not allowed."
|
||||
)
|
||||
self._encoding = value
|
||||
|
||||
@property
|
||||
@ -749,11 +758,7 @@ class Response:
|
||||
raise HTTPStatusError(message, request=request, response=self)
|
||||
|
||||
def json(self, **kwargs: typing.Any) -> typing.Any:
|
||||
if self.charset_encoding is None and self.content and len(self.content) > 3:
|
||||
encoding = guess_json_utf(self.content)
|
||||
if encoding is not None:
|
||||
return jsonlib.loads(self.content.decode(encoding), **kwargs)
|
||||
return jsonlib.loads(self.text, **kwargs)
|
||||
return jsonlib.loads(self.content, **kwargs)
|
||||
|
||||
@property
|
||||
def cookies(self) -> "Cookies":
|
||||
|
@ -1,4 +1,3 @@
|
||||
import binascii
|
||||
import io
|
||||
import os
|
||||
import typing
|
||||
@ -200,7 +199,7 @@ class MultipartStream(SyncByteStream, AsyncByteStream):
|
||||
boundary: typing.Optional[bytes] = None,
|
||||
) -> None:
|
||||
if boundary is None:
|
||||
boundary = binascii.hexlify(os.urandom(16))
|
||||
boundary = os.urandom(16).hex().encode("ascii")
|
||||
|
||||
self.boundary = boundary
|
||||
self.content_type = "multipart/form-data; boundary=%s" % boundary.decode(
|
||||
|
BIN
site-packages/httpx/_transports/.DS_Store
vendored
BIN
site-packages/httpx/_transports/.DS_Store
vendored
Binary file not shown.
@ -64,7 +64,7 @@ SOCKET_OPTION = typing.Union[
|
||||
def map_httpcore_exceptions() -> typing.Iterator[None]:
|
||||
try:
|
||||
yield
|
||||
except Exception as exc: # noqa: PIE-786
|
||||
except Exception as exc:
|
||||
mapped_exc = None
|
||||
|
||||
for from_exc, to_exc in HTTPCORE_EXC_MAP.items():
|
||||
|
@ -87,7 +87,7 @@ COMPONENT_REGEX = {
|
||||
|
||||
# We use these simple regexs as a first pass before handing off to
|
||||
# the stdlib 'ipaddress' module for IP address validation.
|
||||
IPv4_STYLE_HOSTNAME = re.compile(r"^[0-9]+.[0-9]+.[0-9]+.[0-9]+$")
|
||||
IPv4_STYLE_HOSTNAME = re.compile(r"^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$")
|
||||
IPv6_STYLE_HOSTNAME = re.compile(r"^\[.*\]$")
|
||||
|
||||
|
||||
|
@ -91,41 +91,6 @@ def format_form_param(name: str, value: str) -> bytes:
|
||||
return f'{name}="{value}"'.encode()
|
||||
|
||||
|
||||
# Null bytes; no need to recreate these on each call to guess_json_utf
|
||||
_null = b"\x00"
|
||||
_null2 = _null * 2
|
||||
_null3 = _null * 3
|
||||
|
||||
|
||||
def guess_json_utf(data: bytes) -> typing.Optional[str]:
|
||||
# JSON always starts with two ASCII characters, so detection is as
|
||||
# easy as counting the nulls and from their location and count
|
||||
# determine the encoding. Also detect a BOM, if present.
|
||||
sample = data[:4]
|
||||
if sample in (codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE):
|
||||
return "utf-32" # BOM included
|
||||
if sample[:3] == codecs.BOM_UTF8:
|
||||
return "utf-8-sig" # BOM included, MS style (discouraged)
|
||||
if sample[:2] in (codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE):
|
||||
return "utf-16" # BOM included
|
||||
nullcount = sample.count(_null)
|
||||
if nullcount == 0:
|
||||
return "utf-8"
|
||||
if nullcount == 2:
|
||||
if sample[::2] == _null2: # 1st and 3rd are null
|
||||
return "utf-16-be"
|
||||
if sample[1::2] == _null2: # 2nd and 4th are null
|
||||
return "utf-16-le"
|
||||
# Did not detect 2 valid UTF-16 ascii-range characters
|
||||
if nullcount == 3:
|
||||
if sample[:3] == _null3:
|
||||
return "utf-32-be"
|
||||
if sample[1:] == _null3:
|
||||
return "utf-32-le"
|
||||
# Did not detect a valid UTF-32 ascii-range character
|
||||
return None
|
||||
|
||||
|
||||
def get_ca_bundle_from_env() -> typing.Optional[str]:
|
||||
if "SSL_CERT_FILE" in os.environ:
|
||||
ssl_file = Path(os.environ["SSL_CERT_FILE"])
|
||||
|
BIN
site-packages/idna/.DS_Store
vendored
BIN
site-packages/idna/.DS_Store
vendored
Binary file not shown.
BIN
site-packages/importlib_metadata/.DS_Store
vendored
BIN
site-packages/importlib_metadata/.DS_Store
vendored
Binary file not shown.
@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -1,104 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: importlib-resources
|
||||
Version: 6.1.0
|
||||
Summary: Read resources from Python packages
|
||||
Home-page: https://github.com/python/importlib_resources
|
||||
Author: Barry Warsaw
|
||||
Author-email: barry@python.org
|
||||
Project-URL: Documentation, https://importlib-resources.readthedocs.io/
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: Apache Software License
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3 :: Only
|
||||
Requires-Python: >=3.8
|
||||
License-File: LICENSE
|
||||
Requires-Dist: zipp >=3.1.0 ; python_version < "3.10"
|
||||
Provides-Extra: docs
|
||||
Requires-Dist: sphinx >=3.5 ; extra == 'docs'
|
||||
Requires-Dist: sphinx <7.2.5 ; extra == 'docs'
|
||||
Requires-Dist: jaraco.packaging >=9.3 ; extra == 'docs'
|
||||
Requires-Dist: rst.linker >=1.9 ; extra == 'docs'
|
||||
Requires-Dist: furo ; extra == 'docs'
|
||||
Requires-Dist: sphinx-lint ; extra == 'docs'
|
||||
Requires-Dist: jaraco.tidelift >=1.4 ; extra == 'docs'
|
||||
Provides-Extra: testing
|
||||
Requires-Dist: pytest >=6 ; extra == 'testing'
|
||||
Requires-Dist: pytest-checkdocs >=2.4 ; extra == 'testing'
|
||||
Requires-Dist: pytest-cov ; extra == 'testing'
|
||||
Requires-Dist: pytest-enabler >=2.2 ; extra == 'testing'
|
||||
Requires-Dist: pytest-ruff ; extra == 'testing'
|
||||
Requires-Dist: zipp >=3.17 ; extra == 'testing'
|
||||
Requires-Dist: pytest-black >=0.3.7 ; (platform_python_implementation != "PyPy") and extra == 'testing'
|
||||
Requires-Dist: pytest-mypy >=0.9.1 ; (platform_python_implementation != "PyPy") and extra == 'testing'
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/importlib_resources.svg
|
||||
:target: https://pypi.org/project/importlib_resources
|
||||
|
||||
.. image:: https://img.shields.io/pypi/pyversions/importlib_resources.svg
|
||||
|
||||
.. image:: https://github.com/python/importlib_resources/workflows/tests/badge.svg
|
||||
:target: https://github.com/python/importlib_resources/actions?query=workflow%3A%22tests%22
|
||||
:alt: tests
|
||||
|
||||
.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
|
||||
:target: https://github.com/astral-sh/ruff
|
||||
:alt: Ruff
|
||||
|
||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||
:target: https://github.com/psf/black
|
||||
:alt: Code style: Black
|
||||
|
||||
.. image:: https://readthedocs.org/projects/importlib-resources/badge/?version=latest
|
||||
:target: https://importlib-resources.readthedocs.io/en/latest/?badge=latest
|
||||
|
||||
.. image:: https://img.shields.io/badge/skeleton-2023-informational
|
||||
:target: https://blog.jaraco.com/skeleton
|
||||
|
||||
.. image:: https://tidelift.com/badges/package/pypi/importlib-resources
|
||||
:target: https://tidelift.com/subscription/pkg/pypi-importlib-resources?utm_source=pypi-importlib-resources&utm_medium=readme
|
||||
|
||||
``importlib_resources`` is a backport of Python standard library
|
||||
`importlib.resources
|
||||
<https://docs.python.org/3/library/importlib.html#module-importlib.resources>`_
|
||||
module for older Pythons.
|
||||
|
||||
The key goal of this module is to replace parts of `pkg_resources
|
||||
<https://setuptools.readthedocs.io/en/latest/pkg_resources.html>`_ with a
|
||||
solution in Python's stdlib that relies on well-defined APIs. This makes
|
||||
reading resources included in packages easier, with more stable and consistent
|
||||
semantics.
|
||||
|
||||
Compatibility
|
||||
=============
|
||||
|
||||
New features are introduced in this third-party library and later merged
|
||||
into CPython. The following table indicates which versions of this library
|
||||
were contributed to different versions in the standard library:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - importlib_resources
|
||||
- stdlib
|
||||
* - 6.0
|
||||
- 3.13
|
||||
* - 5.12
|
||||
- 3.12
|
||||
* - 5.7
|
||||
- 3.11
|
||||
* - 5.0
|
||||
- 3.10
|
||||
* - 1.3
|
||||
- 3.9
|
||||
* - 0.5 (?)
|
||||
- 3.7
|
||||
|
||||
For Enterprise
|
||||
==============
|
||||
|
||||
Available as part of the Tidelift Subscription.
|
||||
|
||||
This project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.
|
||||
|
||||
`Learn more <https://tidelift.com/subscription/pkg/pypi-importlib-resources?utm_source=pypi-importlib-resources&utm_medium=referral&utm_campaign=github>`_.
|
@ -1,72 +0,0 @@
|
||||
importlib_resources-6.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
importlib_resources-6.1.0.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
||||
importlib_resources-6.1.0.dist-info/METADATA,sha256=sv8t8W7Di2p_H14Lu2B9GY_dPyup1R-xqDOCMR--jHI,4122
|
||||
importlib_resources-6.1.0.dist-info/RECORD,,
|
||||
importlib_resources-6.1.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources-6.1.0.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
||||
importlib_resources-6.1.0.dist-info/top_level.txt,sha256=fHIjHU1GZwAjvcydpmUnUrTnbvdiWjG4OEVZK8by0TQ,20
|
||||
importlib_resources/__init__.py,sha256=t3v1sx-q_TzszzsOs3dqNOjqBQVbSB_KY-BjCvf65qQ,226
|
||||
importlib_resources/__pycache__/__init__.cpython-39.pyc,,
|
||||
importlib_resources/__pycache__/_adapters.cpython-39.pyc,,
|
||||
importlib_resources/__pycache__/_common.cpython-39.pyc,,
|
||||
importlib_resources/__pycache__/_compat.cpython-39.pyc,,
|
||||
importlib_resources/__pycache__/_itertools.cpython-39.pyc,,
|
||||
importlib_resources/__pycache__/abc.cpython-39.pyc,,
|
||||
importlib_resources/__pycache__/readers.cpython-39.pyc,,
|
||||
importlib_resources/__pycache__/simple.cpython-39.pyc,,
|
||||
importlib_resources/_adapters.py,sha256=vprJGbUeHbajX6XCuMP6J3lMrqCi-P_MTlziJUR7jfk,4482
|
||||
importlib_resources/_common.py,sha256=jSC4xfLdcMNbtbWHtpzbFkNa0W7kvf__nsYn14C_AEU,5457
|
||||
importlib_resources/_compat.py,sha256=6MduVulDb7YTwL5f1KAzJUYdYUs12ZAnew_nnCqq0_8,3304
|
||||
importlib_resources/_itertools.py,sha256=eDisV6RqiNZOogLSXf6LOGHOYc79FGgPrKNLzFLmCrU,1277
|
||||
importlib_resources/abc.py,sha256=Icr2IJ2QtH7vvAB9vC5WRJ9KBoaDyJa7KUs8McuROzo,5140
|
||||
importlib_resources/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/readers.py,sha256=ytBi6cqzs_viuvwhEOh0rTI9b8-QLnMaxW7E_LQI1Pc,5409
|
||||
importlib_resources/simple.py,sha256=0__2TQBTQoqkajYmNPt1HxERcReAT6boVKJA328pr04,2576
|
||||
importlib_resources/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/__pycache__/__init__.cpython-39.pyc,,
|
||||
importlib_resources/tests/__pycache__/_compat.cpython-39.pyc,,
|
||||
importlib_resources/tests/__pycache__/_path.cpython-39.pyc,,
|
||||
importlib_resources/tests/__pycache__/test_compatibilty_files.cpython-39.pyc,,
|
||||
importlib_resources/tests/__pycache__/test_contents.cpython-39.pyc,,
|
||||
importlib_resources/tests/__pycache__/test_custom.cpython-39.pyc,,
|
||||
importlib_resources/tests/__pycache__/test_files.cpython-39.pyc,,
|
||||
importlib_resources/tests/__pycache__/test_open.cpython-39.pyc,,
|
||||
importlib_resources/tests/__pycache__/test_path.cpython-39.pyc,,
|
||||
importlib_resources/tests/__pycache__/test_read.cpython-39.pyc,,
|
||||
importlib_resources/tests/__pycache__/test_reader.cpython-39.pyc,,
|
||||
importlib_resources/tests/__pycache__/test_resource.cpython-39.pyc,,
|
||||
importlib_resources/tests/__pycache__/util.cpython-39.pyc,,
|
||||
importlib_resources/tests/__pycache__/zip.cpython-39.pyc,,
|
||||
importlib_resources/tests/_compat.py,sha256=YTSB0U1R9oADnh6GrQcOCgojxcF_N6H1LklymEWf9SQ,708
|
||||
importlib_resources/tests/_path.py,sha256=nkv3ek7D1U898v921rYbldDCtKri2oyYOi3EJqGjEGU,1289
|
||||
importlib_resources/tests/data01/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data01/__pycache__/__init__.cpython-39.pyc,,
|
||||
importlib_resources/tests/data01/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4
|
||||
importlib_resources/tests/data01/subdirectory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data01/subdirectory/__pycache__/__init__.cpython-39.pyc,,
|
||||
importlib_resources/tests/data01/subdirectory/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4
|
||||
importlib_resources/tests/data01/utf-16.file,sha256=t5q9qhxX0rYqItBOM8D3ylwG-RHrnOYteTLtQr6sF7g,44
|
||||
importlib_resources/tests/data01/utf-8.file,sha256=kwWgYG4yQ-ZF2X_WA66EjYPmxJRn-w8aSOiS9e8tKYY,20
|
||||
importlib_resources/tests/data02/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data02/__pycache__/__init__.cpython-39.pyc,,
|
||||
importlib_resources/tests/data02/one/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data02/one/__pycache__/__init__.cpython-39.pyc,,
|
||||
importlib_resources/tests/data02/one/resource1.txt,sha256=10flKac7c-XXFzJ3t-AB5MJjlBy__dSZvPE_dOm2q6U,13
|
||||
importlib_resources/tests/data02/subdirectory/subsubdir/resource.txt,sha256=jnrBBztxYrtQck7cmVnc4xQVO4-agzAZDGSFkAWtlFw,10
|
||||
importlib_resources/tests/data02/two/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data02/two/__pycache__/__init__.cpython-39.pyc,,
|
||||
importlib_resources/tests/data02/two/resource2.txt,sha256=lt2jbN3TMn9QiFKM832X39bU_62UptDdUkoYzkvEbl0,13
|
||||
importlib_resources/tests/namespacedata01/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4
|
||||
importlib_resources/tests/namespacedata01/utf-16.file,sha256=t5q9qhxX0rYqItBOM8D3ylwG-RHrnOYteTLtQr6sF7g,44
|
||||
importlib_resources/tests/namespacedata01/utf-8.file,sha256=kwWgYG4yQ-ZF2X_WA66EjYPmxJRn-w8aSOiS9e8tKYY,20
|
||||
importlib_resources/tests/test_compatibilty_files.py,sha256=95N_R7aik8cvnE6sBJpsxmP0K5plOWRIJDgbalD-Hpw,3314
|
||||
importlib_resources/tests/test_contents.py,sha256=V1Xfk3lqTDdvUsZuV18Kndf0CT_tkM2oEIwk9Vv0rhg,968
|
||||
importlib_resources/tests/test_custom.py,sha256=jVYg9idEVdUN6idHUfDDlZ-zDWl56qYNbj5QrcZO76Y,1124
|
||||
importlib_resources/tests/test_files.py,sha256=W5XoBWSTr84Ke15UtjqWLet2iUDUyJfQxbST4PDlj2w,3283
|
||||
importlib_resources/tests/test_open.py,sha256=9qvdC6Eu2Kn3mh3xDR5HUEQoePSKIecTxU4vnH9veO8,2671
|
||||
importlib_resources/tests/test_path.py,sha256=XR5RI7_zndI_Nqw9eHU1tDmSGIo29N1GP8INodPc584,2142
|
||||
importlib_resources/tests/test_read.py,sha256=ZEUosdzSMHxF6s7u9sWI9M-LbIJXyFtR34tpA6eGzrs,2476
|
||||
importlib_resources/tests/test_reader.py,sha256=WHlZKJBa3MOHnWQG2CB02l8LQ4QjQ0kG_KdcVqZSZ4o,4945
|
||||
importlib_resources/tests/test_resource.py,sha256=3rY9zrUKAlOwSuHmgrVw-tGPpQ9HxRDeGwcFYwbtKHc,7188
|
||||
importlib_resources/tests/util.py,sha256=ZJ9ouR8UOZRbgQ6_ZeXxXBvcjOlSVae4ckIMqzhyAZg,4784
|
||||
importlib_resources/tests/zip.py,sha256=2MKmF8-osXBJSnqcUTuAUek_-tSB3iKmIT9qPhcsOsM,783
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user