Skip to content

Commit 4dbf187

Browse files
authored
Merge branch 'main' into pybyteswriter_bytes_format
2 parents aee6552 + 8b5ce31 commit 4dbf187

39 files changed

Lines changed: 416 additions & 360 deletions

Doc/faq/python-video-icon.png

-2.82 KB
Binary file not shown.
-42.9 KB
Loading
-25 KB
Loading

Doc/using/win_installer.png

-4.56 KB
Loading

Include/internal/pycore_code.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ extern void _PyLineTable_InitAddressRange(
274274
/** API for traversing the line number table. */
275275
extern int _PyLineTable_NextAddressRange(PyCodeAddressRange *range);
276276
extern int _PyLineTable_PreviousAddressRange(PyCodeAddressRange *range);
277+
// This is used in dump_frame() in traceback.c without an attached tstate.
278+
extern int _PyCode_Addr2LineNoTstate(PyCodeObject *co, int addr);
277279

278280
/** API for executors */
279281
extern void _PyCode_Clear_Executors(PyCodeObject *code);

Lib/idlelib/Icons/idle_256.png

-7.8 KB
Loading

Lib/pathlib/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
from pathlib._os import (
3030
PathInfo, DirEntryInfo,
31-
magic_open, vfspath,
31+
vfsopen, vfspath,
3232
ensure_different_files, ensure_distinct_paths,
3333
copyfile2, copyfileobj, copy_info,
3434
)
@@ -1129,7 +1129,7 @@ def _copy_from(self, source, follow_symlinks=True, preserve_metadata=False):
11291129

11301130
def _copy_from_file(self, source, preserve_metadata=False):
11311131
ensure_different_files(source, self)
1132-
with magic_open(source, 'rb') as source_f:
1132+
with vfsopen(source, 'rb') as source_f:
11331133
with open(self, 'wb') as target_f:
11341134
copyfileobj(source_f, target_f)
11351135
if preserve_metadata:

Lib/pathlib/_os.py

Lines changed: 66 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -166,48 +166,86 @@ def copyfileobj(source_f, target_f):
166166
write_target(buf)
167167

168168

169-
def magic_open(path, mode='r', buffering=-1, encoding=None, errors=None,
170-
newline=None):
169+
def _open_reader(obj):
170+
cls = type(obj)
171+
try:
172+
open_reader = cls.__open_reader__
173+
except AttributeError:
174+
cls_name = cls.__name__
175+
raise TypeError(f"{cls_name} can't be opened for reading") from None
176+
else:
177+
return open_reader(obj)
178+
179+
180+
def _open_writer(obj, mode):
181+
cls = type(obj)
182+
try:
183+
open_writer = cls.__open_writer__
184+
except AttributeError:
185+
cls_name = cls.__name__
186+
raise TypeError(f"{cls_name} can't be opened for writing") from None
187+
else:
188+
return open_writer(obj, mode)
189+
190+
191+
def _open_updater(obj, mode):
192+
cls = type(obj)
193+
try:
194+
open_updater = cls.__open_updater__
195+
except AttributeError:
196+
cls_name = cls.__name__
197+
raise TypeError(f"{cls_name} can't be opened for updating") from None
198+
else:
199+
return open_updater(obj, mode)
200+
201+
202+
def vfsopen(obj, mode='r', buffering=-1, encoding=None, errors=None,
203+
newline=None):
171204
"""
172205
Open the file pointed to by this path and return a file object, as
173206
the built-in open() function does.
207+
208+
Unlike the built-in open() function, this function additionally accepts
209+
'openable' objects, which are objects with any of these special methods:
210+
211+
__open_reader__()
212+
__open_writer__(mode)
213+
__open_updater__(mode)
214+
215+
'__open_reader__' is called for 'r' mode; '__open_writer__' for 'a', 'w'
216+
and 'x' modes; and '__open_updater__' for 'r+' and 'w+' modes. If text
217+
mode is requested, the result is wrapped in an io.TextIOWrapper object.
174218
"""
219+
if buffering != -1:
220+
raise ValueError("buffer size can't be customized")
175221
text = 'b' not in mode
176222
if text:
177223
# Call io.text_encoding() here to ensure any warning is raised at an
178224
# appropriate stack level.
179225
encoding = text_encoding(encoding)
180226
try:
181-
return open(path, mode, buffering, encoding, errors, newline)
227+
return open(obj, mode, buffering, encoding, errors, newline)
182228
except TypeError:
183229
pass
184-
cls = type(path)
230+
if not text:
231+
if encoding is not None:
232+
raise ValueError("binary mode doesn't take an encoding argument")
233+
if errors is not None:
234+
raise ValueError("binary mode doesn't take an errors argument")
235+
if newline is not None:
236+
raise ValueError("binary mode doesn't take a newline argument")
185237
mode = ''.join(sorted(c for c in mode if c not in 'bt'))
186-
if text:
187-
try:
188-
attr = getattr(cls, f'__open_{mode}__')
189-
except AttributeError:
190-
pass
191-
else:
192-
return attr(path, buffering, encoding, errors, newline)
193-
elif encoding is not None:
194-
raise ValueError("binary mode doesn't take an encoding argument")
195-
elif errors is not None:
196-
raise ValueError("binary mode doesn't take an errors argument")
197-
elif newline is not None:
198-
raise ValueError("binary mode doesn't take a newline argument")
199-
200-
try:
201-
attr = getattr(cls, f'__open_{mode}b__')
202-
except AttributeError:
203-
pass
238+
if mode == 'r':
239+
stream = _open_reader(obj)
240+
elif mode in ('a', 'w', 'x'):
241+
stream = _open_writer(obj, mode)
242+
elif mode in ('+r', '+w'):
243+
stream = _open_updater(obj, mode[1])
204244
else:
205-
stream = attr(path, buffering)
206-
if text:
207-
stream = TextIOWrapper(stream, encoding, errors, newline)
208-
return stream
209-
210-
raise TypeError(f"{cls.__name__} can't be opened with mode {mode!r}")
245+
raise ValueError(f'invalid mode: {mode}')
246+
if text:
247+
stream = TextIOWrapper(stream, encoding, errors, newline)
248+
return stream
211249

212250

213251
def vfspath(obj):

Lib/pathlib/types.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from abc import ABC, abstractmethod
1414
from glob import _GlobberBase
1515
from io import text_encoding
16-
from pathlib._os import (magic_open, vfspath, ensure_distinct_paths,
16+
from pathlib._os import (vfsopen, vfspath, ensure_distinct_paths,
1717
ensure_different_files, copyfileobj)
1818
from pathlib import PurePath, Path
1919
from typing import Optional, Protocol, runtime_checkable
@@ -264,18 +264,18 @@ def info(self):
264264
raise NotImplementedError
265265

266266
@abstractmethod
267-
def __open_rb__(self, buffering=-1):
267+
def __open_reader__(self):
268268
"""
269269
Open the file pointed to by this path for reading in binary mode and
270-
return a file object, like open(mode='rb').
270+
return a file object.
271271
"""
272272
raise NotImplementedError
273273

274274
def read_bytes(self):
275275
"""
276276
Open the file in bytes mode, read it, and close the file.
277277
"""
278-
with magic_open(self, mode='rb', buffering=0) as f:
278+
with vfsopen(self, mode='rb') as f:
279279
return f.read()
280280

281281
def read_text(self, encoding=None, errors=None, newline=None):
@@ -285,7 +285,7 @@ def read_text(self, encoding=None, errors=None, newline=None):
285285
# Call io.text_encoding() here to ensure any warning is raised at an
286286
# appropriate stack level.
287287
encoding = text_encoding(encoding)
288-
with magic_open(self, mode='r', encoding=encoding, errors=errors, newline=newline) as f:
288+
with vfsopen(self, mode='r', encoding=encoding, errors=errors, newline=newline) as f:
289289
return f.read()
290290

291291
@abstractmethod
@@ -394,10 +394,10 @@ def mkdir(self):
394394
raise NotImplementedError
395395

396396
@abstractmethod
397-
def __open_wb__(self, buffering=-1):
397+
def __open_writer__(self, mode):
398398
"""
399399
Open the file pointed to by this path for writing in binary mode and
400-
return a file object, like open(mode='wb').
400+
return a file object.
401401
"""
402402
raise NotImplementedError
403403

@@ -407,7 +407,7 @@ def write_bytes(self, data):
407407
"""
408408
# type-check for the buffer interface before truncating the file
409409
view = memoryview(data)
410-
with magic_open(self, mode='wb') as f:
410+
with vfsopen(self, mode='wb') as f:
411411
return f.write(view)
412412

413413
def write_text(self, data, encoding=None, errors=None, newline=None):
@@ -420,7 +420,7 @@ def write_text(self, data, encoding=None, errors=None, newline=None):
420420
if not isinstance(data, str):
421421
raise TypeError('data must be str, not %s' %
422422
data.__class__.__name__)
423-
with magic_open(self, mode='w', encoding=encoding, errors=errors, newline=newline) as f:
423+
with vfsopen(self, mode='w', encoding=encoding, errors=errors, newline=newline) as f:
424424
return f.write(data)
425425

426426
def _copy_from(self, source, follow_symlinks=True):
@@ -439,8 +439,8 @@ def _copy_from(self, source, follow_symlinks=True):
439439
stack.append((child, dst.joinpath(child.name)))
440440
else:
441441
ensure_different_files(src, dst)
442-
with magic_open(src, 'rb') as source_f:
443-
with magic_open(dst, 'wb') as target_f:
442+
with vfsopen(src, 'rb') as source_f:
443+
with vfsopen(dst, 'wb') as target_f:
444444
copyfileobj(source_f, target_f)
445445

446446

-7.73 KB
Loading

0 commit comments

Comments
 (0)