Skip to content

Commit

Permalink
Merge pull request pypa#6118 from pypa/spring-2024-vendoring
Browse files Browse the repository at this point in the history
Spring 2024 vendoring
  • Loading branch information
matteius authored Apr 16, 2024
2 parents 7188a59 + 52ee957 commit ba7584d
Show file tree
Hide file tree
Showing 68 changed files with 1,272 additions and 681 deletions.
8 changes: 8 additions & 0 deletions news/6118.vendor.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Spring 2024 Vendoring includes:
* ``click-didyoumean==0.3.1``
* ``expect==4.9.0``
* ``pipdeptree==2.16.2``
* ``python-dotenv==1.0.1``
* ``ruamel.yaml==0.18.6``
* ``shellingham==1.5.4``
* ``tomlkit==0.12.4``
28 changes: 19 additions & 9 deletions pipenv/vendor/dotenv/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import io
import logging
import os
import pathlib
import shutil
import sys
import tempfile
Expand Down Expand Up @@ -131,17 +132,21 @@ def rewrite(
path: StrPath,
encoding: Optional[str],
) -> Iterator[Tuple[IO[str], IO[str]]]:
if not os.path.isfile(path):
with open(path, mode="w", encoding=encoding) as source:
source.write("")
pathlib.Path(path).touch()

with tempfile.NamedTemporaryFile(mode="w", encoding=encoding, delete=False) as dest:
error = None
try:
with open(path, encoding=encoding) as source:
yield (source, dest)
except BaseException:
os.unlink(dest.name)
raise
shutil.move(dest.name, path)
except BaseException as err:
error = err

if error is None:
shutil.move(dest.name, path)
else:
os.unlink(dest.name)
raise error from None


def set_key(
Expand Down Expand Up @@ -280,7 +285,10 @@ def find_dotenv(

def _is_interactive():
""" Decide whether this is running in a REPL or IPython notebook """
main = __import__('__main__', None, None, fromlist=['__file__'])
try:
main = __import__('__main__', None, None, fromlist=['__file__'])
except ModuleNotFoundError:
return False
return not hasattr(main, '__file__')

if usecwd or _is_interactive() or getattr(sys, 'frozen', False):
Expand All @@ -291,7 +299,9 @@ def _is_interactive():
frame = sys._getframe()
current_file = __file__

while frame.f_code.co_filename == current_file:
while frame.f_code.co_filename == current_file or not os.path.exists(
frame.f_code.co_filename
):
assert frame.f_back is not None
frame = frame.f_back
frame_filename = frame.f_code.co_filename
Expand Down
2 changes: 1 addition & 1 deletion pipenv/vendor/dotenv/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.0.0"
__version__ = "1.0.1"
10 changes: 8 additions & 2 deletions pipenv/vendor/pexpect/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'''Pexpect is a Python module for spawning child applications and controlling
them automatically. Pexpect can be used for automating interactive applications
such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
such as ssh, ftp, passwd, telnet, etc. It can be used to automate setup
scripts for duplicating software package installations on different servers. It
can be used for automated software testing. Pexpect is in the spirit of Don
Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python
Expand Down Expand Up @@ -29,6 +29,12 @@
child.expect('Password:')
child.sendline(mypassword)
Context manager can be used for the spawn() function::
with pexpect.spawn('scp foo user@example.com:.') as child:
child.expect('Password:')
child.sendline(mypassword)
This works even for commands that ask for passwords or other input outside of
the normal stdio streams. For example, ssh reads input directly from the TTY
device which bypasses stdin.
Expand Down Expand Up @@ -75,7 +81,7 @@
from .pty_spawn import spawn, spawnu
from .run import run, runu

__version__ = '4.8.0'
__version__ = '4.9.0'
__revision__ = ''
__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnu', 'run', 'runu',
'which', 'split_command_line', '__version__', '__revision__']
Expand Down
131 changes: 28 additions & 103 deletions pipenv/vendor/pexpect/_async.py
Original file line number Diff line number Diff line change
@@ -1,103 +1,28 @@
import asyncio
import errno
import signal

from pipenv.vendor.pexpect import EOF

@asyncio.coroutine
def expect_async(expecter, timeout=None):
# First process data that was previously read - if it maches, we don't need
# async stuff.
idx = expecter.existing_data()
if idx is not None:
return idx
if not expecter.spawn.async_pw_transport:
pw = PatternWaiter()
pw.set_expecter(expecter)
transport, pw = yield from asyncio.get_event_loop()\
.connect_read_pipe(lambda: pw, expecter.spawn)
expecter.spawn.async_pw_transport = pw, transport
else:
pw, transport = expecter.spawn.async_pw_transport
pw.set_expecter(expecter)
transport.resume_reading()
try:
return (yield from asyncio.wait_for(pw.fut, timeout))
except asyncio.TimeoutError as e:
transport.pause_reading()
return expecter.timeout(e)

@asyncio.coroutine
def repl_run_command_async(repl, cmdlines, timeout=-1):
res = []
repl.child.sendline(cmdlines[0])
for line in cmdlines[1:]:
yield from repl._expect_prompt(timeout=timeout, async_=True)
res.append(repl.child.before)
repl.child.sendline(line)

# Command was fully submitted, now wait for the next prompt
prompt_idx = yield from repl._expect_prompt(timeout=timeout, async_=True)
if prompt_idx == 1:
# We got the continuation prompt - command was incomplete
repl.child.kill(signal.SIGINT)
yield from repl._expect_prompt(timeout=1, async_=True)
raise ValueError("Continuation prompt found - input was incomplete:")
return u''.join(res + [repl.child.before])

class PatternWaiter(asyncio.Protocol):
transport = None

def set_expecter(self, expecter):
self.expecter = expecter
self.fut = asyncio.Future()

def found(self, result):
if not self.fut.done():
self.fut.set_result(result)
self.transport.pause_reading()

def error(self, exc):
if not self.fut.done():
self.fut.set_exception(exc)
self.transport.pause_reading()

def connection_made(self, transport):
self.transport = transport

def data_received(self, data):
spawn = self.expecter.spawn
s = spawn._decoder.decode(data)
spawn._log(s, 'read')

if self.fut.done():
spawn._before.write(s)
spawn._buffer.write(s)
return

try:
index = self.expecter.new_data(s)
if index is not None:
# Found a match
self.found(index)
except Exception as e:
self.expecter.errored()
self.error(e)

def eof_received(self):
# N.B. If this gets called, async will close the pipe (the spawn object)
# for us
try:
self.expecter.spawn.flag_eof = True
index = self.expecter.eof()
except EOF as e:
self.error(e)
else:
self.found(index)

def connection_lost(self, exc):
if isinstance(exc, OSError) and exc.errno == errno.EIO:
# We may get here without eof_received being called, e.g on Linux
self.eof_received()
elif exc is not None:
self.error(exc)
"""Facade that provides coroutines implementation pertinent to running Py version.
Python 3.5 introduced the async def/await syntax keyword.
With later versions coroutines and methods to get the running asyncio loop are
being deprecated, not supported anymore.
For Python versions later than 3.6, coroutines and objects that are defined via
``async def``/``await`` keywords are imported.
Here the code is just imported, to provide the same interface to older code.
"""
# pylint: disable=unused-import
# flake8: noqa: F401
from sys import version_info as py_version_info

# this assumes async def/await are more stable
if py_version_info >= (3, 6):
from pipenv.vendor.pexpect._async_w_await import (
PatternWaiter,
expect_async,
repl_run_command_async,
)
else:
from pipenv.vendor.pexpect._async_pre_await import (
PatternWaiter,
expect_async,
repl_run_command_async,
)
111 changes: 111 additions & 0 deletions pipenv/vendor/pexpect/_async_pre_await.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
"""Implementation of coroutines without using ``async def``/``await`` keywords.
``@asyncio.coroutine`` and ``yield from`` are used here instead.
"""
import asyncio
import errno
import signal

from pipenv.vendor.pexpect import EOF


@asyncio.coroutine
def expect_async(expecter, timeout=None):
# First process data that was previously read - if it maches, we don't need
# async stuff.
idx = expecter.existing_data()
if idx is not None:
return idx
if not expecter.spawn.async_pw_transport:
pw = PatternWaiter()
pw.set_expecter(expecter)
transport, pw = yield from asyncio.get_event_loop().connect_read_pipe(
lambda: pw, expecter.spawn
)
expecter.spawn.async_pw_transport = pw, transport
else:
pw, transport = expecter.spawn.async_pw_transport
pw.set_expecter(expecter)
transport.resume_reading()
try:
return (yield from asyncio.wait_for(pw.fut, timeout))
except asyncio.TimeoutError as e:
transport.pause_reading()
return expecter.timeout(e)


@asyncio.coroutine
def repl_run_command_async(repl, cmdlines, timeout=-1):
res = []
repl.child.sendline(cmdlines[0])
for line in cmdlines[1:]:
yield from repl._expect_prompt(timeout=timeout, async_=True)
res.append(repl.child.before)
repl.child.sendline(line)

# Command was fully submitted, now wait for the next prompt
prompt_idx = yield from repl._expect_prompt(timeout=timeout, async_=True)
if prompt_idx == 1:
# We got the continuation prompt - command was incomplete
repl.child.kill(signal.SIGINT)
yield from repl._expect_prompt(timeout=1, async_=True)
raise ValueError("Continuation prompt found - input was incomplete:")
return "".join(res + [repl.child.before])


class PatternWaiter(asyncio.Protocol):
transport = None

def set_expecter(self, expecter):
self.expecter = expecter
self.fut = asyncio.Future()

def found(self, result):
if not self.fut.done():
self.fut.set_result(result)
self.transport.pause_reading()

def error(self, exc):
if not self.fut.done():
self.fut.set_exception(exc)
self.transport.pause_reading()

def connection_made(self, transport):
self.transport = transport

def data_received(self, data):
spawn = self.expecter.spawn
s = spawn._decoder.decode(data)
spawn._log(s, "read")

if self.fut.done():
spawn._before.write(s)
spawn._buffer.write(s)
return

try:
index = self.expecter.new_data(s)
if index is not None:
# Found a match
self.found(index)
except Exception as e:
self.expecter.errored()
self.error(e)

def eof_received(self):
# N.B. If this gets called, async will close the pipe (the spawn object)
# for us
try:
self.expecter.spawn.flag_eof = True
index = self.expecter.eof()
except EOF as e:
self.error(e)
else:
self.found(index)

def connection_lost(self, exc):
if isinstance(exc, OSError) and exc.errno == errno.EIO:
# We may get here without eof_received being called, e.g on Linux
self.eof_received()
elif exc is not None:
self.error(exc)
Loading

0 comments on commit ba7584d

Please sign in to comment.