Skip to content

Commit ba7584d

Browse files
authored
Merge pull request #6118 from pypa/spring-2024-vendoring
Spring 2024 vendoring
2 parents 7188a59 + 52ee957 commit ba7584d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1272
-681
lines changed

news/6118.vendor.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Spring 2024 Vendoring includes:
2+
* ``click-didyoumean==0.3.1``
3+
* ``expect==4.9.0``
4+
* ``pipdeptree==2.16.2``
5+
* ``python-dotenv==1.0.1``
6+
* ``ruamel.yaml==0.18.6``
7+
* ``shellingham==1.5.4``
8+
* ``tomlkit==0.12.4``

pipenv/vendor/dotenv/main.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import io
22
import logging
33
import os
4+
import pathlib
45
import shutil
56
import sys
67
import tempfile
@@ -131,17 +132,21 @@ def rewrite(
131132
path: StrPath,
132133
encoding: Optional[str],
133134
) -> Iterator[Tuple[IO[str], IO[str]]]:
134-
if not os.path.isfile(path):
135-
with open(path, mode="w", encoding=encoding) as source:
136-
source.write("")
135+
pathlib.Path(path).touch()
136+
137137
with tempfile.NamedTemporaryFile(mode="w", encoding=encoding, delete=False) as dest:
138+
error = None
138139
try:
139140
with open(path, encoding=encoding) as source:
140141
yield (source, dest)
141-
except BaseException:
142-
os.unlink(dest.name)
143-
raise
144-
shutil.move(dest.name, path)
142+
except BaseException as err:
143+
error = err
144+
145+
if error is None:
146+
shutil.move(dest.name, path)
147+
else:
148+
os.unlink(dest.name)
149+
raise error from None
145150

146151

147152
def set_key(
@@ -280,7 +285,10 @@ def find_dotenv(
280285

281286
def _is_interactive():
282287
""" Decide whether this is running in a REPL or IPython notebook """
283-
main = __import__('__main__', None, None, fromlist=['__file__'])
288+
try:
289+
main = __import__('__main__', None, None, fromlist=['__file__'])
290+
except ModuleNotFoundError:
291+
return False
284292
return not hasattr(main, '__file__')
285293

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

294-
while frame.f_code.co_filename == current_file:
302+
while frame.f_code.co_filename == current_file or not os.path.exists(
303+
frame.f_code.co_filename
304+
):
295305
assert frame.f_back is not None
296306
frame = frame.f_back
297307
frame_filename = frame.f_code.co_filename

pipenv/vendor/dotenv/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.0.0"
1+
__version__ = "1.0.1"

pipenv/vendor/pexpect/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'''Pexpect is a Python module for spawning child applications and controlling
22
them automatically. Pexpect can be used for automating interactive applications
3-
such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
3+
such as ssh, ftp, passwd, telnet, etc. It can be used to automate setup
44
scripts for duplicating software package installations on different servers. It
55
can be used for automated software testing. Pexpect is in the spirit of Don
66
Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python
@@ -29,6 +29,12 @@
2929
child.expect('Password:')
3030
child.sendline(mypassword)
3131
32+
Context manager can be used for the spawn() function::
33+
34+
with pexpect.spawn('scp foo user@example.com:.') as child:
35+
child.expect('Password:')
36+
child.sendline(mypassword)
37+
3238
This works even for commands that ask for passwords or other input outside of
3339
the normal stdio streams. For example, ssh reads input directly from the TTY
3440
device which bypasses stdin.
@@ -75,7 +81,7 @@
7581
from .pty_spawn import spawn, spawnu
7682
from .run import run, runu
7783

78-
__version__ = '4.8.0'
84+
__version__ = '4.9.0'
7985
__revision__ = ''
8086
__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnu', 'run', 'runu',
8187
'which', 'split_command_line', '__version__', '__revision__']

pipenv/vendor/pexpect/_async.py

Lines changed: 28 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,28 @@
1-
import asyncio
2-
import errno
3-
import signal
4-
5-
from pipenv.vendor.pexpect import EOF
6-
7-
@asyncio.coroutine
8-
def expect_async(expecter, timeout=None):
9-
# First process data that was previously read - if it maches, we don't need
10-
# async stuff.
11-
idx = expecter.existing_data()
12-
if idx is not None:
13-
return idx
14-
if not expecter.spawn.async_pw_transport:
15-
pw = PatternWaiter()
16-
pw.set_expecter(expecter)
17-
transport, pw = yield from asyncio.get_event_loop()\
18-
.connect_read_pipe(lambda: pw, expecter.spawn)
19-
expecter.spawn.async_pw_transport = pw, transport
20-
else:
21-
pw, transport = expecter.spawn.async_pw_transport
22-
pw.set_expecter(expecter)
23-
transport.resume_reading()
24-
try:
25-
return (yield from asyncio.wait_for(pw.fut, timeout))
26-
except asyncio.TimeoutError as e:
27-
transport.pause_reading()
28-
return expecter.timeout(e)
29-
30-
@asyncio.coroutine
31-
def repl_run_command_async(repl, cmdlines, timeout=-1):
32-
res = []
33-
repl.child.sendline(cmdlines[0])
34-
for line in cmdlines[1:]:
35-
yield from repl._expect_prompt(timeout=timeout, async_=True)
36-
res.append(repl.child.before)
37-
repl.child.sendline(line)
38-
39-
# Command was fully submitted, now wait for the next prompt
40-
prompt_idx = yield from repl._expect_prompt(timeout=timeout, async_=True)
41-
if prompt_idx == 1:
42-
# We got the continuation prompt - command was incomplete
43-
repl.child.kill(signal.SIGINT)
44-
yield from repl._expect_prompt(timeout=1, async_=True)
45-
raise ValueError("Continuation prompt found - input was incomplete:")
46-
return u''.join(res + [repl.child.before])
47-
48-
class PatternWaiter(asyncio.Protocol):
49-
transport = None
50-
51-
def set_expecter(self, expecter):
52-
self.expecter = expecter
53-
self.fut = asyncio.Future()
54-
55-
def found(self, result):
56-
if not self.fut.done():
57-
self.fut.set_result(result)
58-
self.transport.pause_reading()
59-
60-
def error(self, exc):
61-
if not self.fut.done():
62-
self.fut.set_exception(exc)
63-
self.transport.pause_reading()
64-
65-
def connection_made(self, transport):
66-
self.transport = transport
67-
68-
def data_received(self, data):
69-
spawn = self.expecter.spawn
70-
s = spawn._decoder.decode(data)
71-
spawn._log(s, 'read')
72-
73-
if self.fut.done():
74-
spawn._before.write(s)
75-
spawn._buffer.write(s)
76-
return
77-
78-
try:
79-
index = self.expecter.new_data(s)
80-
if index is not None:
81-
# Found a match
82-
self.found(index)
83-
except Exception as e:
84-
self.expecter.errored()
85-
self.error(e)
86-
87-
def eof_received(self):
88-
# N.B. If this gets called, async will close the pipe (the spawn object)
89-
# for us
90-
try:
91-
self.expecter.spawn.flag_eof = True
92-
index = self.expecter.eof()
93-
except EOF as e:
94-
self.error(e)
95-
else:
96-
self.found(index)
97-
98-
def connection_lost(self, exc):
99-
if isinstance(exc, OSError) and exc.errno == errno.EIO:
100-
# We may get here without eof_received being called, e.g on Linux
101-
self.eof_received()
102-
elif exc is not None:
103-
self.error(exc)
1+
"""Facade that provides coroutines implementation pertinent to running Py version.
2+
3+
Python 3.5 introduced the async def/await syntax keyword.
4+
With later versions coroutines and methods to get the running asyncio loop are
5+
being deprecated, not supported anymore.
6+
7+
For Python versions later than 3.6, coroutines and objects that are defined via
8+
``async def``/``await`` keywords are imported.
9+
10+
Here the code is just imported, to provide the same interface to older code.
11+
"""
12+
# pylint: disable=unused-import
13+
# flake8: noqa: F401
14+
from sys import version_info as py_version_info
15+
16+
# this assumes async def/await are more stable
17+
if py_version_info >= (3, 6):
18+
from pipenv.vendor.pexpect._async_w_await import (
19+
PatternWaiter,
20+
expect_async,
21+
repl_run_command_async,
22+
)
23+
else:
24+
from pipenv.vendor.pexpect._async_pre_await import (
25+
PatternWaiter,
26+
expect_async,
27+
repl_run_command_async,
28+
)
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
"""Implementation of coroutines without using ``async def``/``await`` keywords.
2+
3+
``@asyncio.coroutine`` and ``yield from`` are used here instead.
4+
"""
5+
import asyncio
6+
import errno
7+
import signal
8+
9+
from pipenv.vendor.pexpect import EOF
10+
11+
12+
@asyncio.coroutine
13+
def expect_async(expecter, timeout=None):
14+
# First process data that was previously read - if it maches, we don't need
15+
# async stuff.
16+
idx = expecter.existing_data()
17+
if idx is not None:
18+
return idx
19+
if not expecter.spawn.async_pw_transport:
20+
pw = PatternWaiter()
21+
pw.set_expecter(expecter)
22+
transport, pw = yield from asyncio.get_event_loop().connect_read_pipe(
23+
lambda: pw, expecter.spawn
24+
)
25+
expecter.spawn.async_pw_transport = pw, transport
26+
else:
27+
pw, transport = expecter.spawn.async_pw_transport
28+
pw.set_expecter(expecter)
29+
transport.resume_reading()
30+
try:
31+
return (yield from asyncio.wait_for(pw.fut, timeout))
32+
except asyncio.TimeoutError as e:
33+
transport.pause_reading()
34+
return expecter.timeout(e)
35+
36+
37+
@asyncio.coroutine
38+
def repl_run_command_async(repl, cmdlines, timeout=-1):
39+
res = []
40+
repl.child.sendline(cmdlines[0])
41+
for line in cmdlines[1:]:
42+
yield from repl._expect_prompt(timeout=timeout, async_=True)
43+
res.append(repl.child.before)
44+
repl.child.sendline(line)
45+
46+
# Command was fully submitted, now wait for the next prompt
47+
prompt_idx = yield from repl._expect_prompt(timeout=timeout, async_=True)
48+
if prompt_idx == 1:
49+
# We got the continuation prompt - command was incomplete
50+
repl.child.kill(signal.SIGINT)
51+
yield from repl._expect_prompt(timeout=1, async_=True)
52+
raise ValueError("Continuation prompt found - input was incomplete:")
53+
return "".join(res + [repl.child.before])
54+
55+
56+
class PatternWaiter(asyncio.Protocol):
57+
transport = None
58+
59+
def set_expecter(self, expecter):
60+
self.expecter = expecter
61+
self.fut = asyncio.Future()
62+
63+
def found(self, result):
64+
if not self.fut.done():
65+
self.fut.set_result(result)
66+
self.transport.pause_reading()
67+
68+
def error(self, exc):
69+
if not self.fut.done():
70+
self.fut.set_exception(exc)
71+
self.transport.pause_reading()
72+
73+
def connection_made(self, transport):
74+
self.transport = transport
75+
76+
def data_received(self, data):
77+
spawn = self.expecter.spawn
78+
s = spawn._decoder.decode(data)
79+
spawn._log(s, "read")
80+
81+
if self.fut.done():
82+
spawn._before.write(s)
83+
spawn._buffer.write(s)
84+
return
85+
86+
try:
87+
index = self.expecter.new_data(s)
88+
if index is not None:
89+
# Found a match
90+
self.found(index)
91+
except Exception as e:
92+
self.expecter.errored()
93+
self.error(e)
94+
95+
def eof_received(self):
96+
# N.B. If this gets called, async will close the pipe (the spawn object)
97+
# for us
98+
try:
99+
self.expecter.spawn.flag_eof = True
100+
index = self.expecter.eof()
101+
except EOF as e:
102+
self.error(e)
103+
else:
104+
self.found(index)
105+
106+
def connection_lost(self, exc):
107+
if isinstance(exc, OSError) and exc.errno == errno.EIO:
108+
# We may get here without eof_received being called, e.g on Linux
109+
self.eof_received()
110+
elif exc is not None:
111+
self.error(exc)

0 commit comments

Comments
 (0)