Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spring 2024 vendoring #6118

Merged
merged 6 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 [email protected]:.') 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
Loading