Author: Ronan Lamy <[email protected]>
Branch: apptest-file
Changeset: r96297:73c5a033c44d
Date: 2019-03-12 18:18 +0000
http://bitbucket.org/pypy/pypy/changeset/73c5a033c44d/
Log: hg merge default
diff too long, truncating to 2000 out of 229297 lines
diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -4,8 +4,10 @@
*~
.*.swp
.idea
+.mypy_cache
.project
.pydevproject
+.vscode
__pycache__
.cache/
diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -58,3 +58,12 @@
3f6eaa010fce78cc7973bdc1dfdb95970f08fed2 release-pypy3.5-v5.10.1
ab0b9caf307db6592905a80b8faffd69b39005b8 release-pypy2.7-v6.0.0
fdd60ed87e941677e8ea11acf9f1819466521bf2 release-pypy3.5-v6.0.0
+9112c8071614108b1042bfef0713915107004d62 release-pypy2.7-v7.0.0
+1f86f25937b6ae6c8b25236c35228fac587678bf release-pypy3.5-v7.0.0
+dab365a465140aa79a5f3ba4db784c4af4d5c195 release-pypy3.6-v7.0.0
+9112c8071614108b1042bfef0713915107004d62 release-pypy2.7-v7.0.0
+c8805ee6d7846ca2722b106eeaa2f128c699aba3 release-pypy2.7-v7.0.0
+1f86f25937b6ae6c8b25236c35228fac587678bf release-pypy3.5-v7.0.0
+928a4f70d3de7d17449456946154c5da6e600162 release-pypy3.5-v7.0.0
+dab365a465140aa79a5f3ba4db784c4af4d5c195 release-pypy3.6-v7.0.0
+fb40f7a5524c77b80e6c468e087d621610137261 release-pypy3.6-v7.0.0
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -123,7 +123,9 @@
Wenzhu Man
Konstantin Lopuhin
John Witulski
+ Stefan Beyer
Jeremy Thurgood
+ Andrew Lawrence
Greg Price
Ivan Sichmann Freitas
Dario Bertini
@@ -134,7 +136,6 @@
Jean-Philippe St. Pierre
Guido van Rossum
Pavel Vinogradov
- Stefan Beyer
William Leslie
Paweł Piotr Przeradowski
marky1991
@@ -152,6 +153,7 @@
Wanja Saatkamp
Mike Blume
Gerald Klix
+ Julian Berman
Oscar Nierstrasz
Rami Chowdhury
Stefan H. Muller
@@ -174,6 +176,7 @@
Anton Gulenko
Sergey Matyunin
Andrew Chambers
+ Łukasz Langa
Nicolas Chauvat
Andrew Durdin
Ben Young
@@ -296,7 +299,6 @@
Bobby Impollonia
Roberto De Ioris
Jeong YunWon
- andrewjlawrence
Christopher Armstrong
Aaron Tubbs
Vasantha Ganesh K
@@ -328,7 +330,6 @@
Ben Darnell
Juan Francisco Cantero Hurtado
Godefroid Chappelle
- Julian Berman
Stephan Busemann
Dan Colish
timo
diff --git a/TODO b/TODO
new file mode 100644
--- /dev/null
+++ b/TODO
@@ -0,0 +1,4 @@
+* find a better way to run "find" without creating the index storage,
+ if one is not already readily available (understand cost now, improve after
merge)
+* improve performance of splitlines
+* think about cost of utf8 list strategy (Armin and CF)
diff --git a/extra_tests/cffi_tests/cffi0/test_ownlib.py
b/extra_tests/cffi_tests/cffi0/test_ownlib.py
--- a/extra_tests/cffi_tests/cffi0/test_ownlib.py
+++ b/extra_tests/cffi_tests/cffi0/test_ownlib.py
@@ -352,6 +352,8 @@
def test_modify_struct_value(self):
if self.module is None:
py.test.skip("fix the auto-generation of the tiny test lib")
+ if self.Backend is CTypesBackend:
+ py.test.skip("fails with the ctypes backend on some architectures")
ffi = FFI(backend=self.Backend())
ffi.cdef("""
typedef struct {
diff --git a/extra_tests/cffi_tests/cffi1/test_pkgconfig.py
b/extra_tests/cffi_tests/cffi1/test_pkgconfig.py
new file mode 100644
--- /dev/null
+++ b/extra_tests/cffi_tests/cffi1/test_pkgconfig.py
@@ -0,0 +1,95 @@
+# Generated by pypy/tool/import_cffi.py
+import sys
+import subprocess
+import py
+import cffi.pkgconfig as pkgconfig
+from cffi import PkgConfigError
+
+
+def mock_call(libname, flag):
+ assert libname=="foobarbaz"
+ flags = {
+ "--cflags": "-I/usr/include/python3.6m -DABCD -DCFFI_TEST=1 -O42\n",
+ "--libs": "-L/usr/lib64 -lpython3.6 -shared\n",
+ }
+ return flags[flag]
+
+
+def test_merge_flags():
+ d1 = {"ham": [1, 2, 3], "spam" : ["a", "b", "c"], "foo" : []}
+ d2 = {"spam" : ["spam", "spam", "spam"], "bar" : ["b", "a", "z"]}
+
+ pkgconfig.merge_flags(d1, d2)
+ assert d1 == {
+ "ham": [1, 2, 3],
+ "spam" : ["a", "b", "c", "spam", "spam", "spam"],
+ "bar" : ["b", "a", "z"],
+ "foo" : []}
+
+
+def test_pkgconfig():
+ assert pkgconfig.flags_from_pkgconfig([]) == {}
+
+ saved = pkgconfig.call
+ try:
+ pkgconfig.call = mock_call
+ flags = pkgconfig.flags_from_pkgconfig(["foobarbaz"])
+ finally:
+ pkgconfig.call = saved
+ assert flags == {
+ 'include_dirs': ['/usr/include/python3.6m'],
+ 'library_dirs': ['/usr/lib64'],
+ 'libraries': ['python3.6'],
+ 'define_macros': [('ABCD', None), ('CFFI_TEST', '1')],
+ 'extra_compile_args': ['-O42'],
+ 'extra_link_args': ['-shared']
+ }
+
+class mock_subprocess:
+ PIPE = Ellipsis
+ class Popen:
+ def __init__(self, cmd, stdout, stderr):
+ if mock_subprocess.RESULT is None:
+ raise OSError("oops can't run")
+ assert cmd == ['pkg-config', '--print-errors', '--cflags',
'libfoo']
+ def communicate(self):
+ bout, berr, rc = mock_subprocess.RESULT
+ self.returncode = rc
+ return bout, berr
+
+def test_call():
+ saved = pkgconfig.subprocess
+ try:
+ pkgconfig.subprocess = mock_subprocess
+
+ mock_subprocess.RESULT = None
+ e = py.test.raises(PkgConfigError, pkgconfig.call, "libfoo",
"--cflags")
+ assert str(e.value) == "cannot run pkg-config: oops can't run"
+
+ mock_subprocess.RESULT = b"", "Foo error!\n", 1
+ e = py.test.raises(PkgConfigError, pkgconfig.call, "libfoo",
"--cflags")
+ assert str(e.value) == "Foo error!"
+
+ mock_subprocess.RESULT = b"abc\\def\n", "", 0
+ e = py.test.raises(PkgConfigError, pkgconfig.call, "libfoo",
"--cflags")
+ assert str(e.value).startswith("pkg-config --cflags libfoo returned an
"
+ "unsupported backslash-escaped output:")
+
+ mock_subprocess.RESULT = b"abc def\n", "", 0
+ result = pkgconfig.call("libfoo", "--cflags")
+ assert result == "abc def\n"
+
+ mock_subprocess.RESULT = b"abc def\n", "", 0
+ result = pkgconfig.call("libfoo", "--cflags")
+ assert result == "abc def\n"
+
+ if sys.version_info >= (3,):
+ mock_subprocess.RESULT = b"\xff\n", "", 0
+ e = py.test.raises(PkgConfigError, pkgconfig.call,
+ "libfoo", "--cflags", encoding="utf-8")
+ assert str(e.value) == (
+ "pkg-config --cflags libfoo returned bytes that cannot be "
+ "decoded with encoding 'utf-8':\nb'\\xff\\n'")
+
+ finally:
+ pkgconfig.subprocess = saved
diff --git a/extra_tests/cffi_tests/embedding/thread3-test.c
b/extra_tests/cffi_tests/embedding/thread3-test.c
--- a/extra_tests/cffi_tests/embedding/thread3-test.c
+++ b/extra_tests/cffi_tests/embedding/thread3-test.c
@@ -52,5 +52,6 @@
assert(status == 0);
}
printf("done\n");
+ fflush(stdout); /* this is occasionally needed on Windows */
return 0;
}
diff --git a/extra_tests/ctypes_tests/test_structures.py
b/extra_tests/ctypes_tests/test_structures.py
--- a/extra_tests/ctypes_tests/test_structures.py
+++ b/extra_tests/ctypes_tests/test_structures.py
@@ -124,12 +124,15 @@
ms.n = 0xff00
return repr(ba[:])
+ nstruct = dostruct(Native)
if sys.byteorder == 'little':
- assert dostruct(Native) == dostruct(Little)
- assert dostruct(Native) != dostruct(Big)
+ assert nstruct == dostruct(Little)
+ assert nstruct != dostruct(Big)
+ assert Big._fields_[0][1] is not i
else:
- assert dostruct(Native) == dostruct(Big)
- assert dostruct(Native) != dostruct(Little)
+ assert nstruct == dostruct(Big)
+ assert nstruct != dostruct(Little)
+ assert Little._fields_[0][1] is not i
def test_from_buffer_copy():
from array import array
@@ -190,3 +193,20 @@
assert sizeof(s) == 3 * sizeof(c_int)
assert s.a == 4 # 256 + 4
assert s.b == -123
+
+def test_memoryview():
+ class S(Structure):
+ _fields_ = [('a', c_int16),
+ ('b', c_int16),
+ ]
+
+ S3 = S * 3
+ c_array = (2 * S3)(
+ S3(S(a=0, b=1), S(a=2, b=3), S(a=4, b=5)),
+ S3(S(a=6, b=7), S(a=8, b=9), S(a=10, b=11)),
+ )
+
+ mv = memoryview(c_array)
+ assert mv.format == 'T{<h:a:<h:b:}'
+ assert mv.shape == (2, 3)
+ assert mv.itemsize == 4
diff --git a/extra_tests/requirements.txt b/extra_tests/requirements.txt
--- a/extra_tests/requirements.txt
+++ b/extra_tests/requirements.txt
@@ -1,3 +1,3 @@
-pytest
+pytest<=4.0
hypothesis
vmprof
diff --git a/lib-python/2.7/test/test_memoryio.py
b/lib-python/2.7/test/test_memoryio.py
--- a/lib-python/2.7/test/test_memoryio.py
+++ b/lib-python/2.7/test/test_memoryio.py
@@ -712,6 +712,7 @@
# XXX: For the Python version of io.StringIO, this is highly
# dependent on the encoding used for the underlying buffer.
+ @support.cpython_only
def test_widechar(self):
buf = self.buftype("\U0002030a\U00020347")
memio = self.ioclass(buf)
diff --git a/lib_pypy/_csv.py b/lib_pypy/_csv.py
deleted file mode 100644
--- a/lib_pypy/_csv.py
+++ /dev/null
@@ -1,573 +0,0 @@
-"""CSV parsing and writing.
-
-This module provides classes that assist in the reading and writing
-of Comma Separated Value (CSV) files, and implements the interface
-described by PEP 305. Although many CSV files are simple to parse,
-the format is not formally defined by a stable specification and
-is subtle enough that parsing lines of a CSV file with something
-like line.split(\",\") is bound to fail. The module supports three
-basic APIs: reading, writing, and registration of dialects.
-
-
-DIALECT REGISTRATION:
-
-Readers and writers support a dialect argument, which is a convenient
-handle on a group of settings. When the dialect argument is a string,
-it identifies one of the dialects previously registered with the module.
-If it is a class or instance, the attributes of the argument are used as
-the settings for the reader or writer:
-
- class excel:
- delimiter = ','
- quotechar = '\"'
- escapechar = None
- doublequote = True
- skipinitialspace = False
- lineterminator = '\\r\\n'
- quoting = QUOTE_MINIMAL
-
-SETTINGS:
-
- * quotechar - specifies a one-character string to use as the
- quoting character. It defaults to '\"'.
- * delimiter - specifies a one-character string to use as the
- field separator. It defaults to ','.
- * skipinitialspace - specifies how to interpret whitespace which
- immediately follows a delimiter. It defaults to False, which
- means that whitespace immediately following a delimiter is part
- of the following field.
- * lineterminator - specifies the character sequence which should
- terminate rows.
- * quoting - controls when quotes should be generated by the writer.
- It can take on any of the following module constants:
-
- csv.QUOTE_MINIMAL means only when required, for example, when a
- field contains either the quotechar or the delimiter
- csv.QUOTE_ALL means that quotes are always placed around fields.
- csv.QUOTE_NONNUMERIC means that quotes are always placed around
- fields which do not parse as integers or floating point
- numbers.
- csv.QUOTE_NONE means that quotes are never placed around fields.
- * escapechar - specifies a one-character string used to escape
- the delimiter when quoting is set to QUOTE_NONE.
- * doublequote - controls the handling of quotes inside fields. When
- True, two consecutive quotes are interpreted as one during read,
- and when writing, each quote character embedded in the data is
- written as two quotes.
-"""
-
-__version__ = "1.0"
-
-QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE = range(4)
-_dialects = {}
-_field_limit = 128 * 1024 # max parsed field size
-
-class Error(Exception):
- pass
-
-class Dialect(object):
- """CSV dialect
-
- The Dialect type records CSV parsing and generation options."""
-
- __slots__ = ["_delimiter", "_doublequote", "_escapechar",
- "_lineterminator", "_quotechar", "_quoting",
- "_skipinitialspace", "_strict"]
-
- def __new__(cls, dialect, **kwargs):
-
- for name in kwargs:
- if '_' + name not in Dialect.__slots__:
- raise TypeError("unexpected keyword argument '%s'" %
- (name,))
-
- if dialect is not None:
- if isinstance(dialect, basestring):
- dialect = get_dialect(dialect)
-
- # Can we reuse this instance?
- if (isinstance(dialect, Dialect)
- and all(value is None for value in kwargs.itervalues())):
- return dialect
-
- self = object.__new__(cls)
-
-
- def set_char(x):
- if x is None:
- return None
- if isinstance(x, str) and len(x) <= 1:
- return x
- raise TypeError("%r must be a 1-character string" % (name,))
- def set_str(x):
- if isinstance(x, str):
- return x
- raise TypeError("%r must be a string" % (name,))
- def set_quoting(x):
- if x in range(4):
- return x
- raise TypeError("bad 'quoting' value")
-
- attributes = {"delimiter": (',', set_char),
- "doublequote": (True, bool),
- "escapechar": (None, set_char),
- "lineterminator": ("\r\n", set_str),
- "quotechar": ('"', set_char),
- "quoting": (QUOTE_MINIMAL, set_quoting),
- "skipinitialspace": (False, bool),
- "strict": (False, bool),
- }
-
- # Copy attributes
- notset = object()
- for name in Dialect.__slots__:
- name = name[1:]
- value = notset
- if name in kwargs:
- value = kwargs[name]
- elif dialect is not None:
- value = getattr(dialect, name, notset)
-
- # mapping by name: (default, converter)
- if value is notset:
- value = attributes[name][0]
- if name == 'quoting' and not self.quotechar:
- value = QUOTE_NONE
- else:
- converter = attributes[name][1]
- if converter:
- value = converter(value)
-
- setattr(self, '_' + name, value)
-
- if not self.delimiter:
- raise TypeError("delimiter must be set")
-
- if self.quoting != QUOTE_NONE and not self.quotechar:
- raise TypeError("quotechar must be set if quoting enabled")
-
- if not self.lineterminator:
- raise TypeError("lineterminator must be set")
-
- return self
-
- delimiter = property(lambda self: self._delimiter)
- doublequote = property(lambda self: self._doublequote)
- escapechar = property(lambda self: self._escapechar)
- lineterminator = property(lambda self: self._lineterminator)
- quotechar = property(lambda self: self._quotechar)
- quoting = property(lambda self: self._quoting)
- skipinitialspace = property(lambda self: self._skipinitialspace)
- strict = property(lambda self: self._strict)
-
-
-def _call_dialect(dialect_inst, kwargs):
- return Dialect(dialect_inst, **kwargs)
-
-def register_dialect(name, dialect=None, **kwargs):
- """Create a mapping from a string name to a dialect class.
- dialect = csv.register_dialect(name, dialect)"""
- if not isinstance(name, basestring):
- raise TypeError("dialect name must be a string or unicode")
-
- dialect = _call_dialect(dialect, kwargs)
- _dialects[name] = dialect
-
-def unregister_dialect(name):
- """Delete the name/dialect mapping associated with a string name.\n
- csv.unregister_dialect(name)"""
- try:
- del _dialects[name]
- except KeyError:
- raise Error("unknown dialect")
-
-def get_dialect(name):
- """Return the dialect instance associated with name.
- dialect = csv.get_dialect(name)"""
- try:
- return _dialects[name]
- except KeyError:
- raise Error("unknown dialect")
-
-def list_dialects():
- """Return a list of all know dialect names
- names = csv.list_dialects()"""
- return list(_dialects)
-
-class Reader(object):
- """CSV reader
-
- Reader objects are responsible for reading and parsing tabular data
- in CSV format."""
-
-
- (START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD,
- IN_QUOTED_FIELD, ESCAPE_IN_QUOTED_FIELD, QUOTE_IN_QUOTED_FIELD,
- EAT_CRNL) = range(8)
-
- def __init__(self, iterator, dialect=None, **kwargs):
- self.dialect = _call_dialect(dialect, kwargs)
- self.input_iter = iter(iterator)
- self.line_num = 0
-
- self._parse_reset()
-
- def _parse_reset(self):
- self.field = ''
- self.fields = []
- self.state = self.START_RECORD
- self.numeric_field = False
-
- def __iter__(self):
- return self
-
- def next(self):
- self._parse_reset()
- while True:
- try:
- line = next(self.input_iter)
- except StopIteration:
- # End of input OR exception
- if len(self.field) > 0:
- raise Error("newline inside string")
- raise
-
- self.line_num += 1
-
- if '\0' in line:
- raise Error("line contains NULL byte")
- pos = 0
- while pos < len(line):
- pos = self._parse_process_char(line, pos)
- self._parse_eol()
-
- if self.state == self.START_RECORD:
- break
-
- fields = self.fields
- self.fields = []
- return fields
-
- def _parse_process_char(self, line, pos):
- c = line[pos]
- if self.state == self.IN_FIELD:
- # in unquoted field
- pos2 = pos
- while True:
- if c in '\n\r':
- # end of line - return [fields]
- if pos2 > pos:
- self._parse_add_char(line[pos:pos2])
- pos = pos2
- self._parse_save_field()
- self.state = self.EAT_CRNL
- elif c == self.dialect.escapechar:
- # possible escaped character
- pos2 -= 1
- self.state = self.ESCAPED_CHAR
- elif c == self.dialect.delimiter:
- # save field - wait for new field
- if pos2 > pos:
- self._parse_add_char(line[pos:pos2])
- pos = pos2
- self._parse_save_field()
- self.state = self.START_FIELD
- else:
- # normal character - save in field
- pos2 += 1
- if pos2 < len(line):
- c = line[pos2]
- continue
- break
- if pos2 > pos:
- self._parse_add_char(line[pos:pos2])
- pos = pos2 - 1
-
- elif self.state == self.START_RECORD:
- if c in '\n\r':
- self.state = self.EAT_CRNL
- else:
- self.state = self.START_FIELD
- # restart process
- self._parse_process_char(line, pos)
-
- elif self.state == self.START_FIELD:
- if c in '\n\r':
- # save empty field - return [fields]
- self._parse_save_field()
- self.state = self.EAT_CRNL
- elif (c == self.dialect.quotechar
- and self.dialect.quoting != QUOTE_NONE):
- # start quoted field
- self.state = self.IN_QUOTED_FIELD
- elif c == self.dialect.escapechar:
- # possible escaped character
- self.state = self.ESCAPED_CHAR
- elif c == ' ' and self.dialect.skipinitialspace:
- # ignore space at start of field
- pass
- elif c == self.dialect.delimiter:
- # save empty field
- self._parse_save_field()
- else:
- # begin new unquoted field
- if self.dialect.quoting == QUOTE_NONNUMERIC:
- self.numeric_field = True
- self._parse_add_char(c)
- self.state = self.IN_FIELD
-
- elif self.state == self.ESCAPED_CHAR:
- self._parse_add_char(c)
- self.state = self.IN_FIELD
-
- elif self.state == self.IN_QUOTED_FIELD:
- if c == self.dialect.escapechar:
- # possible escape character
- self.state = self.ESCAPE_IN_QUOTED_FIELD
- elif (c == self.dialect.quotechar
- and self.dialect.quoting != QUOTE_NONE):
- if self.dialect.doublequote:
- # doublequote; " represented by ""
- self.state = self.QUOTE_IN_QUOTED_FIELD
- else:
- #end of quote part of field
- self.state = self.IN_FIELD
- else:
- # normal character - save in field
- self._parse_add_char(c)
-
- elif self.state == self.ESCAPE_IN_QUOTED_FIELD:
- self._parse_add_char(c)
- self.state = self.IN_QUOTED_FIELD
-
- elif self.state == self.QUOTE_IN_QUOTED_FIELD:
- # doublequote - seen a quote in a quoted field
- if (c == self.dialect.quotechar
- and self.dialect.quoting != QUOTE_NONE):
- # save "" as "
- self._parse_add_char(c)
- self.state = self.IN_QUOTED_FIELD
- elif c == self.dialect.delimiter:
- # save field - wait for new field
- self._parse_save_field()
- self.state = self.START_FIELD
- elif c in '\r\n':
- # end of line - return [fields]
- self._parse_save_field()
- self.state = self.EAT_CRNL
- elif not self.dialect.strict:
- self._parse_add_char(c)
- self.state = self.IN_FIELD
- else:
- raise Error("'%c' expected after '%c'" %
- (self.dialect.delimiter, self.dialect.quotechar))
-
- elif self.state == self.EAT_CRNL:
- if c not in '\r\n':
- raise Error("new-line character seen in unquoted field - "
- "do you need to open the file "
- "in universal-newline mode?")
-
- else:
- raise RuntimeError("unknown state: %r" % (self.state,))
-
- return pos + 1
-
- def _parse_eol(self):
- if self.state == self.EAT_CRNL:
- self.state = self.START_RECORD
- elif self.state == self.START_RECORD:
- # empty line - return []
- pass
- elif self.state == self.IN_FIELD:
- # in unquoted field
- # end of line - return [fields]
- self._parse_save_field()
- self.state = self.START_RECORD
- elif self.state == self.START_FIELD:
- # save empty field - return [fields]
- self._parse_save_field()
- self.state = self.START_RECORD
- elif self.state == self.ESCAPED_CHAR:
- self._parse_add_char('\n')
- self.state = self.IN_FIELD
- elif self.state == self.IN_QUOTED_FIELD:
- pass
- elif self.state == self.ESCAPE_IN_QUOTED_FIELD:
- self._parse_add_char('\n')
- self.state = self.IN_QUOTED_FIELD
- elif self.state == self.QUOTE_IN_QUOTED_FIELD:
- # end of line - return [fields]
- self._parse_save_field()
- self.state = self.START_RECORD
- else:
- raise RuntimeError("unknown state: %r" % (self.state,))
-
- def _parse_save_field(self):
- field, self.field = self.field, ''
- if self.numeric_field:
- self.numeric_field = False
- field = float(field)
- self.fields.append(field)
-
- def _parse_add_char(self, c):
- if len(self.field) + len(c) > _field_limit:
- raise Error("field larger than field limit (%d)" % (_field_limit))
- self.field += c
-
-
-class Writer(object):
- """CSV writer
-
- Writer objects are responsible for generating tabular data
- in CSV format from sequence input."""
-
- def __init__(self, file, dialect=None, **kwargs):
- if not (hasattr(file, 'write') and callable(file.write)):
- raise TypeError("argument 1 must have a 'write' method")
- self.writeline = file.write
- self.dialect = _call_dialect(dialect, kwargs)
-
- def _join_reset(self):
- self.rec = []
- self.num_fields = 0
-
- def _join_append(self, field, quoted, quote_empty):
- dialect = self.dialect
- # If this is not the first field we need a field separator
- if self.num_fields > 0:
- self.rec.append(dialect.delimiter)
-
- if dialect.quoting == QUOTE_NONE:
- need_escape = tuple(dialect.lineterminator) + (
- dialect.escapechar, # escapechar always first
- dialect.delimiter, dialect.quotechar)
-
- else:
- for c in tuple(dialect.lineterminator) + (
- dialect.delimiter, dialect.escapechar):
- if c and c in field:
- quoted = True
-
- need_escape = ()
- if dialect.quotechar in field:
- if dialect.doublequote:
- field = field.replace(dialect.quotechar,
- dialect.quotechar * 2)
- quoted = True
- else:
- need_escape = (dialect.quotechar,)
-
-
- for c in need_escape:
- if c and c in field:
- if not dialect.escapechar:
- raise Error("need to escape, but no escapechar set")
- field = field.replace(c, dialect.escapechar + c)
-
- # If field is empty check if it needs to be quoted
- if field == '' and quote_empty:
- if dialect.quoting == QUOTE_NONE:
- raise Error("single empty field record must be quoted")
- quoted = 1
-
- if quoted:
- field = dialect.quotechar + field + dialect.quotechar
-
- self.rec.append(field)
- self.num_fields += 1
-
-
-
- def writerow(self, row):
- dialect = self.dialect
- try:
- rowlen = len(row)
- except TypeError:
- raise Error("sequence expected")
-
- # join all fields in internal buffer
- self._join_reset()
-
- for field in row:
- quoted = False
- if dialect.quoting == QUOTE_NONNUMERIC:
- try:
- float(field)
- except:
- quoted = True
- # This changed since 2.5:
- # quoted = not isinstance(field, (int, long, float))
- elif dialect.quoting == QUOTE_ALL:
- quoted = True
-
- if field is None:
- value = ""
- elif isinstance(field, float):
- value = repr(field)
- else:
- value = str(field)
- self._join_append(value, quoted, rowlen == 1)
-
- # add line terminator
- self.rec.append(dialect.lineterminator)
-
- self.writeline(''.join(self.rec))
-
- def writerows(self, rows):
- for row in rows:
- self.writerow(row)
-
-def reader(*args, **kwargs):
- """
- csv_reader = reader(iterable [, dialect='excel']
- [optional keyword args])
- for row in csv_reader:
- process(row)
-
- The "iterable" argument can be any object that returns a line
- of input for each iteration, such as a file object or a list. The
- optional \"dialect\" parameter is discussed below. The function
- also accepts optional keyword arguments which override settings
- provided by the dialect.
-
- The returned object is an iterator. Each iteration returns a row
- of the CSV file (which can span multiple input lines)"""
-
- return Reader(*args, **kwargs)
-
-def writer(*args, **kwargs):
- """
- csv_writer = csv.writer(fileobj [, dialect='excel']
- [optional keyword args])
- for row in sequence:
- csv_writer.writerow(row)
-
- [or]
-
- csv_writer = csv.writer(fileobj [, dialect='excel']
- [optional keyword args])
- csv_writer.writerows(rows)
-
- The \"fileobj\" argument can be any object that supports the file API."""
- return Writer(*args, **kwargs)
-
-
-undefined = object()
-def field_size_limit(limit=undefined):
- """Sets an upper limit on parsed fields.
- csv.field_size_limit([limit])
-
- Returns old limit. If limit is not given, no new limit is set and
- the old limit is returned"""
-
- global _field_limit
- old_limit = _field_limit
-
- if limit is not undefined:
- if not isinstance(limit, (int, long)):
- raise TypeError("int expected, got %s" %
- (limit.__class__.__name__,))
- _field_limit = limit
-
- return old_limit
diff --git a/lib_pypy/_ctypes/array.py b/lib_pypy/_ctypes/array.py
--- a/lib_pypy/_ctypes/array.py
+++ b/lib_pypy/_ctypes/array.py
@@ -4,6 +4,7 @@
from _ctypes.basics import _CData, cdata_from_address, _CDataMeta, sizeof
from _ctypes.basics import keepalive_key, store_reference, ensure_objects
from _ctypes.basics import CArgObject, as_ffi_pointer
+import sys, __pypy__, struct
class ArrayMeta(_CDataMeta):
def __new__(self, name, cls, typedict):
@@ -241,6 +242,24 @@
def _as_ffi_pointer_(self, ffitype):
return as_ffi_pointer(self, ffitype)
+ def __buffer__(self, flags):
+ shape = []
+ obj = self
+ while 1:
+ shape.append(obj._length_)
+ try:
+ obj[0]._length_
+ except (AttributeError, IndexError):
+ break
+ obj = obj[0]
+
+ fmt = get_format_str(obj._type_)
+ try:
+ itemsize = struct.calcsize(fmt[1:])
+ except:
+ itemsize = sizeof(obj[0])
+ return __pypy__.newmemoryview(memoryview(self._buffer), itemsize, fmt,
shape)
+
ARRAY_CACHE = {}
def create_array_type(base, length):
@@ -260,3 +279,31 @@
cls = ArrayMeta(name, (Array,), tpdict)
ARRAY_CACHE[key] = cls
return cls
+
+byteorder = {'little': '<', 'big': '>'}
+swappedorder = {'little': '>', 'big': '<'}
+
+def get_format_str(typ):
+ if hasattr(typ, '_fields_'):
+ if hasattr(typ, '_swappedbytes_'):
+ bo = swappedorder[sys.byteorder]
+ else:
+ bo = byteorder[sys.byteorder]
+ flds = []
+ for name, obj in typ._fields_:
+ # Trim off the leading '<' or '>'
+ ch = get_format_str(obj)[1:]
+ if (ch) == 'B':
+ flds.append(byteorder[sys.byteorder])
+ else:
+ flds.append(bo)
+ flds.append(ch)
+ flds.append(':')
+ flds.append(name)
+ flds.append(':')
+ return 'T{' + ''.join(flds) + '}'
+ elif hasattr(typ, '_type_'):
+ ch = typ._type_
+ return byteorder[sys.byteorder] + ch
+ else:
+ raise ValueError('cannot get format string for %r' % typ)
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -2,8 +2,15 @@
from _rawffi import alt as _ffi
import sys
-try: from __pypy__ import builtinify
-except ImportError: builtinify = lambda f: f
+try:
+ from __pypy__ import builtinify
+except ImportError:
+ builtinify = lambda f: f
+
+try:
+ from __pypy__.bufferable import bufferable
+except ImportError:
+ bufferable = object
keepalive_key = str # XXX fix this when provided with test
@@ -64,7 +71,7 @@
'resbuffer' is a _rawffi array of length 1 containing the value,
and this returns a general Python object that corresponds.
"""
- res = object.__new__(self)
+ res = bufferable.__new__(self)
res.__class__ = self
res.__dict__['_buffer'] = resbuffer
if base is not None:
@@ -158,7 +165,7 @@
def __ne__(self, other):
return self._obj != other
-class _CData(object):
+class _CData(bufferable):
""" The most basic object for all ctypes types
"""
__metaclass__ = _CDataMeta
diff --git a/lib_pypy/_ctypes/pointer.py b/lib_pypy/_ctypes/pointer.py
--- a/lib_pypy/_ctypes/pointer.py
+++ b/lib_pypy/_ctypes/pointer.py
@@ -7,8 +7,7 @@
from _ctypes.array import Array, array_get_slice_params, array_slice_getitem,\
array_slice_setitem
-try: from __pypy__ import builtinify
-except ImportError: builtinify = lambda f: f
+from __pypy__ import builtinify, newmemoryview
# This cache maps types to pointers to them.
_pointer_type_cache = {}
@@ -135,6 +134,9 @@
def _as_ffi_pointer_(self, ffitype):
return as_ffi_pointer(self, ffitype)
+ def __buffer__(self, flags):
+ mv = memoryview(self.getcontents())
+ return newmemoryview(mv, mv.itemsize, '&' + mv.format, mv.shape)
def _cast_addr(obj, _, tp):
if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()):
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -2,9 +2,9 @@
import _rawffi
from _ctypes.basics import _CData, _CDataMeta, keepalive_key,\
store_reference, ensure_objects, CArgObject
-from _ctypes.array import Array
+from _ctypes.array import Array, get_format_str
from _ctypes.pointer import _Pointer
-import inspect
+import inspect, __pypy__
def names_and_fields(self, _fields_, superclass, anonymous_fields=None):
@@ -176,6 +176,11 @@
class StructOrUnionMeta(_CDataMeta):
def __new__(self, name, cls, typedict):
res = type.__new__(self, name, cls, typedict)
+ if hasattr(res, '_swappedbytes_') and '_fields_' in typedict:
+ # Activate the stdlib ctypes._swapped_meta.__setattr__ to convert
fields
+ tmp = res._fields_
+ delattr(res, '_fields_')
+ setattr(res, '_fields_', tmp)
if "_abstract_" in typedict:
return res
cls = cls or (object,)
@@ -254,17 +259,7 @@
or cls is union.Union):
raise TypeError("abstract class")
if hasattr(cls, '_swappedbytes_'):
- fields = [None] * len(cls._fields_)
- for i in range(len(cls._fields_)):
- if cls._fields_[i][1] ==
cls._fields_[i][1].__dict__.get('__ctype_be__', None):
- swapped = cls._fields_[i][1].__dict__.get('__ctype_le__',
cls._fields_[i][1])
- else:
- swapped = cls._fields_[i][1].__dict__.get('__ctype_be__',
cls._fields_[i][1])
- if len(cls._fields_[i]) < 3:
- fields[i] = (cls._fields_[i][0], swapped)
- else:
- fields[i] = (cls._fields_[i][0], swapped,
cls._fields_[i][2])
- names_and_fields(cls, fields, _CData,
cls.__dict__.get('_anonymous_', None))
+ names_and_fields(cls, cls._fields_, _CData,
cls.__dict__.get('_anonymous_', None))
self = super(_CData, cls).__new__(cls)
if hasattr(cls, '_ffistruct_'):
self.__dict__['_buffer'] = self._ffistruct_(autofree=True)
@@ -304,6 +299,10 @@
def _to_ffi_param(self):
return self._buffer
+ def __buffer__(self, flags):
+ fmt = get_format_str(self)
+ itemsize = type(self)._sizeofinstances()
+ return __pypy__.newmemoryview(memoryview(self._buffer), itemsize, fmt)
class StructureMeta(StructOrUnionMeta):
_is_union = False
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: cffi
-Version: 1.12.0
+Version: 1.12.2
Summary: Foreign Function Interface for Python calling C code.
Home-page: http://cffi.readthedocs.org
Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -3,9 +3,10 @@
from .api import FFI
from .error import CDefError, FFIError, VerificationError, VerificationMissing
+from .error import PkgConfigError
-__version__ = "1.12.0"
-__version_info__ = (1, 12, 0)
+__version__ = "1.12.2"
+__version_info__ = (1, 12, 2)
# The verifier module file names are based on the CRC32 of a string that
# contains the following version number. It may be older than __version__
diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h
--- a/lib_pypy/cffi/_cffi_include.h
+++ b/lib_pypy/cffi/_cffi_include.h
@@ -8,43 +8,20 @@
the same works for the other two macros. Py_DEBUG implies them,
but not the other way around.
- The implementation is messy (issue #350): on Windows, with _MSC_VER,
- we have to define Py_LIMITED_API even before including pyconfig.h.
- In that case, we guess what pyconfig.h will do to the macros above,
- and check our guess after the #include.
-
- Note that on Windows, with CPython 3.x, you need virtualenv version
- >= 16.0.0. Older versions don't copy PYTHON3.DLL. As a workaround
- you can remove the definition of Py_LIMITED_API here.
-
- See also 'py_limited_api' in cffi/setuptools_ext.py.
+ Issue #350 is still open: on Windows, the code here causes it to link
+ with PYTHON36.DLL (for example) instead of PYTHON3.DLL. A fix was
+ attempted in 164e526a5515 and 14ce6985e1c3, but reverted: virtualenv
+ does not make PYTHON3.DLL available, and so the "correctly" compiled
+ version would not run inside a virtualenv. We will re-apply the fix
+ after virtualenv has been fixed for some time. For explanation, see
+ issue #355. For a workaround if you want PYTHON3.DLL and don't worry
+ about virtualenv, see issue #350. See also 'py_limited_api' in
+ setuptools_ext.py.
*/
#if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API)
-# ifdef _MSC_VER
-# if !defined(_DEBUG) && !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) &&
!defined(Py_REF_DEBUG)
-# define Py_LIMITED_API
-# endif
-# include <pyconfig.h>
- /* sanity-check: Py_LIMITED_API will cause crashes if any of these
- are also defined. Normally, the Python file PC/pyconfig.h does not
- cause any of these to be defined, with the exception that _DEBUG
- causes Py_DEBUG. Double-check that. */
-# ifdef Py_LIMITED_API
-# if defined(Py_DEBUG)
-# error "pyconfig.h unexpectedly defines Py_DEBUG, but Py_LIMITED_API
is set"
-# endif
-# if defined(Py_TRACE_REFS)
-# error "pyconfig.h unexpectedly defines Py_TRACE_REFS, but
Py_LIMITED_API is set"
-# endif
-# if defined(Py_REF_DEBUG)
-# error "pyconfig.h unexpectedly defines Py_REF_DEBUG, but
Py_LIMITED_API is set"
-# endif
-# endif
-# else
-# include <pyconfig.h>
-# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
-# define Py_LIMITED_API
-# endif
+# include <pyconfig.h>
+# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
+# define Py_LIMITED_API
# endif
#endif
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -221,7 +221,7 @@
if (f != NULL && f != Py_None) {
PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
- "\ncompiled with cffi version: 1.12.0"
+ "\ncompiled with cffi version: 1.12.2"
"\n_cffi_backend module: ", f);
modules = PyImport_GetModuleDict();
mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -592,7 +592,7 @@
if sys.platform == "win32":
# we need 'libpypy-c.lib'. Current distributions of
# pypy (>= 4.1) contain it as 'libs/python27.lib'.
- pythonlib = "python27"
+ pythonlib = "python{0[0]}{0[1]}".format(sys.version_info)
if hasattr(sys, 'prefix'):
ensure('library_dirs', os.path.join(sys.prefix, 'libs'))
else:
@@ -643,6 +643,16 @@
self._assigned_source = (str(module_name), source,
source_extension, kwds)
+ def set_source_pkgconfig(self, module_name, pkgconfig_libs, source,
+ source_extension='.c', **kwds):
+ from . import pkgconfig
+ if not isinstance(pkgconfig_libs, list):
+ raise TypeError("the pkgconfig_libs argument must be a list "
+ "of package names")
+ kwds2 = pkgconfig.flags_from_pkgconfig(pkgconfig_libs)
+ pkgconfig.merge_flags(kwds, kwds2)
+ self.set_source(module_name, source, source_extension, **kwds)
+
def distutils_extension(self, tmpdir='build', verbose=True):
from distutils.dir_util import mkpath
from .recompiler import recompile
diff --git a/lib_pypy/cffi/error.py b/lib_pypy/cffi/error.py
--- a/lib_pypy/cffi/error.py
+++ b/lib_pypy/cffi/error.py
@@ -1,8 +1,9 @@
class FFIError(Exception):
- pass
+ __module__ = 'cffi'
class CDefError(Exception):
+ __module__ = 'cffi'
def __str__(self):
try:
current_decl = self.args[1]
@@ -16,8 +17,15 @@
class VerificationError(Exception):
""" An error raised when verification fails
"""
+ __module__ = 'cffi'
class VerificationMissing(Exception):
""" An error raised when incomplete structures are passed into
cdef, but no verification has been done
"""
+ __module__ = 'cffi'
+
+class PkgConfigError(Exception):
+ """ An error raised for missing modules in pkg-config
+ """
+ __module__ = 'cffi'
diff --git a/lib_pypy/cffi/pkgconfig.py b/lib_pypy/cffi/pkgconfig.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/cffi/pkgconfig.py
@@ -0,0 +1,121 @@
+# pkg-config, https://www.freedesktop.org/wiki/Software/pkg-config/
integration for cffi
+import sys, os, subprocess
+
+from .error import PkgConfigError
+
+
+def merge_flags(cfg1, cfg2):
+ """Merge values from cffi config flags cfg2 to cf1
+
+ Example:
+ merge_flags({"libraries": ["one"]}, {"libraries": ["two"]})
+ {"libraries": ["one", "two"]}
+ """
+ for key, value in cfg2.items():
+ if key not in cfg1:
+ cfg1[key] = value
+ else:
+ if not isinstance(cfg1[key], list):
+ raise TypeError("cfg1[%r] should be a list of strings" %
(key,))
+ if not isinstance(value, list):
+ raise TypeError("cfg2[%r] should be a list of strings" %
(key,))
+ cfg1[key].extend(value)
+ return cfg1
+
+
+def call(libname, flag, encoding=sys.getfilesystemencoding()):
+ """Calls pkg-config and returns the output if found
+ """
+ a = ["pkg-config", "--print-errors"]
+ a.append(flag)
+ a.append(libname)
+ try:
+ pc = subprocess.Popen(a, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
+ except EnvironmentError as e:
+ raise PkgConfigError("cannot run pkg-config: %s" % (str(e).strip(),))
+
+ bout, berr = pc.communicate()
+ if pc.returncode != 0:
+ try:
+ berr = berr.decode(encoding)
+ except Exception:
+ pass
+ raise PkgConfigError(berr.strip())
+
+ if sys.version_info >= (3,) and not isinstance(bout, str): # Python 3.x
+ try:
+ bout = bout.decode(encoding)
+ except UnicodeDecodeError:
+ raise PkgConfigError("pkg-config %s %s returned bytes that cannot "
+ "be decoded with encoding %r:\n%r" %
+ (flag, libname, encoding, bout))
+
+ if os.altsep != '\\' and '\\' in bout:
+ raise PkgConfigError("pkg-config %s %s returned an unsupported "
+ "backslash-escaped output:\n%r" %
+ (flag, libname, bout))
+ return bout
+
+
+def flags_from_pkgconfig(libs):
+ r"""Return compiler line flags for FFI.set_source based on pkg-config
output
+
+ Usage
+ ...
+ ffibuilder.set_source("_foo", pkgconfig = ["libfoo", "libbar >=
1.8.3"])
+
+ If pkg-config is installed on build machine, then arguments include_dirs,
+ library_dirs, libraries, define_macros, extra_compile_args and
+ extra_link_args are extended with an output of pkg-config for libfoo and
+ libbar.
+
+ Raises PkgConfigError in case the pkg-config call fails.
+ """
+
+ def get_include_dirs(string):
+ return [x[2:] for x in string.split() if x.startswith("-I")]
+
+ def get_library_dirs(string):
+ return [x[2:] for x in string.split() if x.startswith("-L")]
+
+ def get_libraries(string):
+ return [x[2:] for x in string.split() if x.startswith("-l")]
+
+ # convert -Dfoo=bar to list of tuples [("foo", "bar")] expected by
distutils
+ def get_macros(string):
+ def _macro(x):
+ x = x[2:] # drop "-D"
+ if '=' in x:
+ return tuple(x.split("=", 1)) # "-Dfoo=bar" => ("foo", "bar")
+ else:
+ return (x, None) # "-Dfoo" => ("foo", None)
+ return [_macro(x) for x in string.split() if x.startswith("-D")]
+
+ def get_other_cflags(string):
+ return [x for x in string.split() if not x.startswith("-I") and
+ not x.startswith("-D")]
+
+ def get_other_libs(string):
+ return [x for x in string.split() if not x.startswith("-L") and
+ not x.startswith("-l")]
+
+ # return kwargs for given libname
+ def kwargs(libname):
+ fse = sys.getfilesystemencoding()
+ all_cflags = call(libname, "--cflags")
+ all_libs = call(libname, "--libs")
+ return {
+ "include_dirs": get_include_dirs(all_cflags),
+ "library_dirs": get_library_dirs(all_libs),
+ "libraries": get_libraries(all_libs),
+ "define_macros": get_macros(all_cflags),
+ "extra_compile_args": get_other_cflags(all_cflags),
+ "extra_link_args": get_other_libs(all_libs),
+ }
+
+ # merge all arguments together
+ ret = {}
+ for libname in libs:
+ lib_flags = kwargs(libname)
+ merge_flags(ret, lib_flags)
+ return ret
diff --git a/lib_pypy/cffi/setuptools_ext.py b/lib_pypy/cffi/setuptools_ext.py
--- a/lib_pypy/cffi/setuptools_ext.py
+++ b/lib_pypy/cffi/setuptools_ext.py
@@ -81,8 +81,14 @@
it doesn't so far, creating troubles. That's why we check
for "not hasattr(sys, 'gettotalrefcount')" (the 2.7 compatible equivalent
of 'd' not in sys.abiflags). (http://bugs.python.org/issue28401)
+
+ On Windows, with CPython <= 3.4, it's better not to use py_limited_api
+ because virtualenv *still* doesn't copy PYTHON3.DLL on these versions.
+ For now we'll skip py_limited_api on all Windows versions to avoid an
+ inconsistent mess.
"""
- if 'py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount'):
+ if ('py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount')
+ and sys.platform != 'win32'):
import setuptools
try:
setuptools_major_version =
int(setuptools.__version__.partition('.')[0])
diff --git a/lib_pypy/pwd.py b/lib_pypy/pwd.py
deleted file mode 100644
--- a/lib_pypy/pwd.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# indirectly based on ctypes implementation: Victor Stinner, 2008-05-08
-"""
-This module provides access to the Unix password database.
-It is available on all Unix versions.
-
-Password database entries are reported as 7-tuples containing the following
-items from the password database (see `<pwd.h>'), in order:
-pw_name, pw_passwd, pw_uid, pw_gid, pw_gecos, pw_dir, pw_shell.
-The uid and gid items are integers, all others are strings. An
-exception is raised if the entry asked for cannot be found.
-"""
-
-from _pwdgrp_cffi import ffi, lib
-import _structseq
-import thread
-_lock = thread.allocate_lock()
-
-try: from __pypy__ import builtinify
-except ImportError: builtinify = lambda f: f
-
-
-class struct_passwd:
- """
- pwd.struct_passwd: Results from getpw*() routines.
-
- This object may be accessed either as a tuple of
- (pw_name,pw_passwd,pw_uid,pw_gid,pw_gecos,pw_dir,pw_shell)
- or via the object attributes as named in the above tuple.
- """
- __metaclass__ = _structseq.structseqtype
- name = "pwd.struct_passwd"
-
- pw_name = _structseq.structseqfield(0)
- pw_passwd = _structseq.structseqfield(1)
- pw_uid = _structseq.structseqfield(2)
- pw_gid = _structseq.structseqfield(3)
- pw_gecos = _structseq.structseqfield(4)
- pw_dir = _structseq.structseqfield(5)
- pw_shell = _structseq.structseqfield(6)
-
-
-def _mkpwent(pw):
- return struct_passwd([
- ffi.string(pw.pw_name),
- ffi.string(pw.pw_passwd),
- pw.pw_uid,
- pw.pw_gid,
- ffi.string(pw.pw_gecos),
- ffi.string(pw.pw_dir),
- ffi.string(pw.pw_shell)])
-
-@builtinify
-def getpwuid(uid):
- """
- getpwuid(uid) -> (pw_name,pw_passwd,pw_uid,
- pw_gid,pw_gecos,pw_dir,pw_shell)
- Return the password database entry for the given numeric user ID.
- See pwd.__doc__ for more on password database entries.
- """
- with _lock:
- pw = lib.getpwuid(uid)
- if not pw:
- raise KeyError("getpwuid(): uid not found: %s" % uid)
- return _mkpwent(pw)
-
-@builtinify
-def getpwnam(name):
- """
- getpwnam(name) -> (pw_name,pw_passwd,pw_uid,
- pw_gid,pw_gecos,pw_dir,pw_shell)
- Return the password database entry for the given user name.
- See pwd.__doc__ for more on password database entries.
- """
- if not isinstance(name, basestring):
- raise TypeError("expected string")
- name = str(name)
- with _lock:
- pw = lib.getpwnam(name)
- if not pw:
- raise KeyError("getpwname(): name not found: %s" % name)
- return _mkpwent(pw)
-
-@builtinify
-def getpwall():
- """
- getpwall() -> list_of_entries
- Return a list of all available password database entries, in arbitrary
order.
- See pwd.__doc__ for more on password database entries.
- """
- users = []
- with _lock:
- lib.setpwent()
- while True:
- pw = lib.getpwent()
- if not pw:
- break
- users.append(_mkpwent(pw))
- lib.endpwent()
- return users
-
-__all__ = ('struct_passwd', 'getpwuid', 'getpwnam', 'getpwall')
-
-if __name__ == "__main__":
-# Uncomment next line to test CPython implementation
-# from pwd import getpwuid, getpwnam, getpwall
- from os import getuid
- uid = getuid()
- pw = getpwuid(uid)
- print("uid %s: %s" % (pw.pw_uid, pw))
- name = pw.pw_name
- print("name %r: %s" % (name, getpwnam(name)))
- print("All:")
- for pw in getpwall():
- print(pw)
diff --git a/pypy/conftest.py b/pypy/conftest.py
--- a/pypy/conftest.py
+++ b/pypy/conftest.py
@@ -12,11 +12,12 @@
except ImportError:
pass
else:
- if __version__[:2] < '3.6':
- s = settings(deadline=None)
- settings.register_profile('default', s)
- else:
+ try:
settings.register_profile('default', deadline=None)
+ except Exception:
+ import warnings
+ warnings.warn("Version of hypothesis too old, "
+ "cannot set the deadline to None")
settings.load_profile('default')
# PyPy's command line extra options (these are added
diff --git a/pypy/doc/__pypy__-module.rst b/pypy/doc/__pypy__-module.rst
--- a/pypy/doc/__pypy__-module.rst
+++ b/pypy/doc/__pypy__-module.rst
@@ -1,26 +1,186 @@
-.. comment: this document is very incomplete, should we generate
- it automatically?
+.. comment: this document may get out of synch with the code, but to generate
+ it automatically we would need to use pypy to run sphinx-build
The ``__pypy__`` module
=======================
The ``__pypy__`` module is the main entry point to special features provided
-by PyPy's standard interpreter. Its content depends on :doc:`configuration
options <config/index>`
-which may add new functionality and functions whose existence or non-existence
-indicates the presence of such features.
-
+by PyPy's standard interpreter. Its content depends on :doc:`configuration
+options <config/index>` which may add new functionality and functions whose
+existence or non-existence indicates the presence of such features. These are
+generally used for compatibility when writing pure python modules that in
+CPython are written in C. Not available in CPython, and so must be used inside
a
+``if platform.python_implementation == 'PyPy'`` block or otherwise hidden from
+the CPython interpreter.
Generally available functionality
---------------------------------
- - ``internal_repr(obj)``: return the interpreter-level representation of an
- object.
- - ``bytebuffer(length)``: return a new read-write buffer of the given length.
- It works like a simplified array of characters (actually, depending on the
- configuration the ``array`` module internally uses this).
- - ``attach_gdb()``: start a GDB at the interpreter-level (or a PDB before
translation).
+ - ``internal_repr(obj)``: return the interpreter-level representation of an
+ object.
+ - ``bytebuffer(length)``: return a new read-write buffer of the given length.
+ It works like a simplified array of characters (actually, depending on the
+ configuration the ``array`` module internally uses this).
+ - ``attach_gdb()``: start a GDB at the interpreter-level (or a PDB before
translation).
+ - ``newmemoryview(buffer, itemsize, format, shape=None, strides=None)``:
+ create a `memoryview` instance with the data from ``buffer`` and the
+ specified itemsize, format, and optional shape and strides.
+
+ - ``bufferable``: a base class that provides a ``__buffer__(self, flags)``
+ method for subclasses to override. This method should return a memoryview
+ instance of the class instance. It is called by the C-API's ``tp_as_buffer.
+ bf_getbuffer``.
+
+ - ``builtinify(func)``: To implement at app-level modules that are, in
CPython,
+ implemented in C: this decorator protects a function from being ever bound
+ like a method. Useful because some tests do things like put a "built-in"
+ function on a class and access it via the instance.
+
+ - ``hidden_applevel(func)``: Decorator that hides a function's frame from
+ app-level
+
+ - ``get_hidden_tb()``: Return the traceback of the current exception being
+ handled by a frame hidden from applevel.
+
+ - ``lookup_special(obj, meth)``: Lookup up a special method on an object.
+ - ``do_what_I_mean``
+
+ - ``resizelist_hint(...)``: Reallocate the underlying storage of the argument
+ list to sizehint
+
+ - ``newlist_hint(...)``: Create a new empty list that has an underlying
+ storage of length sizehint
+
+ - ``add_memory_pressure(bytes)``: Add memory pressure of estimate bytes.
+ Useful when calling a C function that internally allocates a big chunk of
+ memory. This instructs the GC to garbage collect sooner than it would
+ otherwise.
+
+ - ``newdict(type)``: Create a normal dict with a special implementation
+ strategy. ``type`` is a string and can be:
+
+ * ``"module"`` - equivalent to ``some_module.__dict__``
+
+ * ``"instance"`` - equivalent to an instance dict with a not-changing-much
+ set of keys
+
+ * ``"kwargs"`` - keyword args dict equivalent of what you get from
+ ``**kwargs`` in a function, optimized for passing around
+
+ * ``"strdict"`` - string-key only dict. This one should be chosen
+ automatically
+
+ - ``reversed_dict``: Enumerate the keys in a dictionary object in reversed
+ order. This is a ``__pypy__`` function instead of being simply done by
+ calling reversed(), for CPython compatibility: dictionaries are ordered in
+ PyPY but not in Cpython2.7. You should use the collections.OrderedDict
+ class for cases where ordering is important. That class implements
+ ``__reversed__`` by calling __pypy__.reversed_dict()
+
+ - ``dict_popitem_first``: Interp-level implementation of
+ ``OrderedDict.popitem(last=False)``.
+
+ - ``delitem_if_value_is`` Atomic equivalent to: ``if dict.get(key) is value:
+ del dict[key]``.
+
+ SPECIAL USE CASES ONLY! Avoid using on dicts which are specialized,
+ e.g. to ``int`` or ``str`` keys, because it switches to the object
+ strategy. Also, the ``is`` operation is really pointer equality, so avoid
+ using it if ``value`` is an immutable object like ``int`` or ``str``.
+
+ - ``move_to_end``: Move the key in a dictionary object into the first or last
+ position. This is used in Python 3.x to implement
``OrderedDict.move_to_end()``.
+
+ - ``strategy(dict or list or set)``: Return the underlying strategy currently
+ used by the object
+
+ - ``specialized_zip_2_lists``
+ - ``locals_to_fast``
+ - ``set_code_callback``
+ - ``save_module_content_for_future_reload``
+ - ``decode_long``
+ - ``side_effects_ok``: For use with the reverse-debugger: this function
+ normally returns True, but will return False if we are evaluating a
+ debugging command like a watchpoint. You are responsible for not doing any
+ side effect at all (including no caching) when evaluating watchpoints. This
+ function is meant to help a bit---you can write::
+
+ if not __pypy__.side_effects_ok():
+ skip the caching logic
+
+ inside getter methods or properties, to make them usable from
+ watchpoints. Note that you need to re-run ``REVDB=.. pypy``
+ after changing the Python code.
+
+ - ``stack_almost_full``: Return True if the stack is more than 15/16th full.
+ - ``pyos_inputhook``: Call PyOS_InputHook() from the CPython C API
+ - ``os.real_getenv(...)`` gets OS environment variables skipping python code
+ - ``_pypydatetime`` provides base classes with correct C API interactions for
+ the pure-python ``datetime`` stdlib module
+
+Fast String Concatenation
+-------------------------
+Rather than in-place concatenation ``+=``, use these to enable fast, minimal
+copy, string building.
+
+ - ``builders.StringBuilder``
+ - ``builders.UnicodeBuilder``
+
+Interacting with the PyPy debug log
+------------------------------------
+
+The following functions can be used to write your own content to the
+:ref:`PYPYLOG <pypylog>`.
+
+ - ``debug_start(category, timestamp=False)``: open a new section; if
+ ``timestamp`` is ``True``, also return the timestamp which was written to
+ the log.
+
+ - ``debug_stop(category, timestamp=False)``: close a section opened by
+ ``debug_start``.
+
+ - ``debug_print(...)``: print arbitrary text to the log.
+
+ - ``debug_print_once(category, ...)``: equivalent to ``debug_start`` +
+ ``debug_print`` + ``debug_stop``.
+
+ - ``debug_flush``: flush the log.
+
+ - ``debug_read_timestamp()``: read the timestamp from the same timer used by
+ the log.
+
+ - ``debug_get_timestamp_unit()``: get the unit of the value returned by
+ ``debug_read_timestamp()``.
+
+
+Depending on the architecture and operating system, PyPy uses different ways
+to read timestamps, so the timestamps used in the log file are expressed in
+varying units. It is possible to know which by calling
+``debug_get_timestamp_unit()``, which can be one of the following values:
+
+``tsc``
+ The default on ``x86`` machines: timestamps are expressed in CPU ticks, as
+ read by the `Time Stamp Counter`_.
+
+``ns``
+ Timestamps are expressed in nanoseconds.
+
+``QueryPerformanceCounter``
+ On Windows, in case for some reason ``tsc`` is not available: timestamps
+ are read using the win API ``QueryPerformanceCounter()``.
+
+
+Unfortunately, there does not seem to be a reliable standard way for
+converting ``tsc`` ticks into nanoseconds, although in practice on modern CPUs
+it is enough to divide the ticks by the maximum nominal frequency of the CPU.
+For this reason, PyPy gives the raw value, and leaves the job of doing the
+conversion to external libraries.
+
+.. _`Time Stamp Counter`: https://en.wikipedia.org/wiki/Time_Stamp_Counter
+
+
Transparent Proxy Functionality
-------------------------------
@@ -34,6 +194,30 @@
its controller. Otherwise return None.
+Additional Clocks for Timing
+----------------------------
+The ``time`` submodule exposes the platform-dependent clock types such as
+``CLOCK_BOOTTIME``, ``CLOCK_MONOTONIC``, ``CLOCK_MONOTONIC_COARSE``,
+``CLOCK_MONOTONIC_RAW`` and two functions:
+
+ - ``clock_gettime(m)`` which returns the clock type time in seconds and
+ - ``clock_getres(m)`` which returns the clock resolution in seconds.
+
+Extended Signal Handling
+------------------------
+``thread.signals_enbaled`` is a context manager to use in non-main threads.
+ enables receiving signals in a "with" statement. More precisely, if a
+ signal is received by the process, then the signal handler might be
+ called either in the main thread (as usual) or within another thread
+ that is within a "with signals_enabled:". This other thread should be
+ ready to handle unexpected exceptions that the signal handler might
+ raise --- notably KeyboardInterrupt.
+
+Integer Operations with Overflow
+--------------------------------
+ - ``intop`` provides a module with integer operations that have
+ two-complement overflow behaviour instead of overflowing to longs
+
Functionality available on py.py (not after translation)
--------------------------------------------------------
diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst
--- a/pypy/doc/build.rst
+++ b/pypy/doc/build.rst
@@ -220,11 +220,12 @@
Making a debug build of PyPy
----------------------------
-If the Makefile is rerun with the lldebug or lldebug0 target, appropriate
-compilation flags are added to add debug info and reduce compiler optimizations
-to ``-O0`` respectively. If you stop in a debugger, you will see the
-very wordy machine-generated C code from the rpython translation step, which
-takes a little bit of reading to relate back to the rpython code.
+Rerun the ``Makefile`` with the ``make lldebug`` or ``make lldebug0`` target,
+which will build in a way that running under a debugger makes sense.
+Appropriate compilation flags are added to add debug info, and for ``lldebug0``
+compiler optimizations are fully disabled. If you stop in a debugger, you will
+see the very wordy machine-generated C code from the rpython translation step,
+which takes a little bit of reading to relate back to the rpython code.
Build cffi import libraries for the stdlib
------------------------------------------
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -71,9 +71,9 @@
# module/cpyext/include/patchlevel.h
#
# The short X.Y version.
-version = '7.1'
+version = '7.2'
# The full version, including alpha/beta/rc tags.
-release = '7.1.0'
+release = '7.2.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/pypy/doc/contributor.rst b/pypy/doc/contributor.rst
--- a/pypy/doc/contributor.rst
+++ b/pypy/doc/contributor.rst
@@ -90,7 +90,9 @@
Wenzhu Man
Konstantin Lopuhin
John Witulski
+ Stefan Beyer
Jeremy Thurgood
+ Andrew Lawrence
Greg Price
Ivan Sichmann Freitas
Dario Bertini
@@ -101,7 +103,6 @@
Jean-Philippe St. Pierre
Guido van Rossum
Pavel Vinogradov
- Stefan Beyer
William Leslie
Paweł Piotr Przeradowski
marky1991
@@ -119,6 +120,7 @@
Wanja Saatkamp
Mike Blume
Gerald Klix
+ Julian Berman
Oscar Nierstrasz
Rami Chowdhury
Stefan H. Muller
@@ -141,6 +143,7 @@
Anton Gulenko
Sergey Matyunin
Andrew Chambers
+ Łukasz Langa
Nicolas Chauvat
Andrew Durdin
Ben Young
@@ -263,7 +266,6 @@
Bobby Impollonia
Roberto De Ioris
Jeong YunWon
- andrewjlawrence
Christopher Armstrong
Aaron Tubbs
Vasantha Ganesh K
@@ -295,7 +297,6 @@
Ben Darnell
Juan Francisco Cantero Hurtado
Godefroid Chappelle
- Julian Berman
Stephan Busemann
Dan Colish
timo
diff --git a/pypy/doc/extending.rst b/pypy/doc/extending.rst
--- a/pypy/doc/extending.rst
+++ b/pypy/doc/extending.rst
@@ -45,16 +45,13 @@
with the `CPython ctypes`_ version. It works for large examples, such
as pyglet. PyPy's implementation is not strictly 100% compatible with
CPython, but close enough for most cases.
-
-We also used to provide ``ctypes-configure`` for some API-level access.
-This is now viewed as a precursor of CFFI, which you should use instead.
More (but older) information is available :doc:`here
<discussion/ctypes-implementation>`.
Also, ctypes' performance is not as good as CFFI's.
.. _CPython ctypes: http://docs.python.org/library/ctypes.html
PyPy implements ctypes as pure Python code around two built-in modules
-called ``_ffi`` and ``_rawffi``, which give a very low-level binding to
+called ``_rawffi`` and ``_rawffi.alt``, which give a very low-level binding to
the C library libffi_. Nowadays it is not recommended to use directly
these two modules.
diff --git a/pypy/doc/gc_info.rst b/pypy/doc/gc_info.rst
--- a/pypy/doc/gc_info.rst
+++ b/pypy/doc/gc_info.rst
@@ -203,7 +203,7 @@
``duration``
The total time spent inside minor collections since the last hook
- call. See below for more information on the unit.
+ call, in seconds.
``duration_min``
The duration of the fastest minor collection since the last hook call.
@@ -265,30 +265,6 @@
``gc-collect-done`` is used only to give additional stats, but doesn't do any
actual work.
-A note about the ``duration`` field: depending on the architecture and
-operating system, PyPy uses different ways to read timestamps, so ``duration``
-is expressed in varying units. It is possible to know which by calling
-``__pypy__.debug_get_timestamp_unit()``, which can be one of the following
-values:
-
-``tsc``
- The default on ``x86`` machines: timestamps are expressed in CPU ticks, as
- read by the `Time Stamp Counter`_.
-
-``ns``
- Timestamps are expressed in nanoseconds.
-
-``QueryPerformanceCounter``
- On Windows, in case for some reason ``tsc`` is not available: timestamps
- are read using the win API ``QueryPerformanceCounter()``.
-
-
-Unfortunately, there does not seem to be a reliable standard way for
-converting ``tsc`` ticks into nanoseconds, although in practice on modern CPUs
-it is enough to divide the ticks by the maximum nominal frequency of the CPU.
-For this reason, PyPy gives the raw value, and leaves the job of doing the
-conversion to external libraries.
-
Here is an example of GC hooks in use::
import sys
@@ -321,8 +297,6 @@
lst = [lst, 1, 2, 3]
-.. _`Time Stamp Counter`: https://en.wikipedia.org/wiki/Time_Stamp_Counter
-
.. _minimark-environment-variables:
Environment variables
diff --git a/pypy/doc/index-of-release-notes.rst
b/pypy/doc/index-of-release-notes.rst
--- a/pypy/doc/index-of-release-notes.rst
+++ b/pypy/doc/index-of-release-notes.rst
@@ -1,11 +1,12 @@
Historical release notes
========================
-CPython 2.7 compatible versions
--------------------------------
+Combined releases
+-----------------
.. toctree::
+ release-v7.1.0.rst
release-v7.0.0.rst
release-v6.0.0.rst
release-v5.10.1.rst
@@ -14,6 +15,12 @@
release-v5.8.0.rst
release-v5.7.1.rst
release-v5.7.0.rst
+
+CPython 2.7 compatible versions
+-------------------------------
+
+.. toctree::
+
release-pypy2.7-v5.6.0.rst
release-pypy2.7-v5.4.1.rst
release-pypy2.7-v5.4.0.rst
@@ -61,15 +68,6 @@
release-0.7.0.rst
release-0.6
-CPython 3.5 compatible versions
--------------------------------
-
-.. toctree::
-
- release-v5.8.0.rst
- release-v5.7.1.rst
- release-v5.7.0.rst
-
CPython 3.3 compatible versions
-------------------------------
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -103,7 +103,7 @@
the `development mailing list`_.
.. _#pypy on irc.freenode.net: irc://irc.freenode.net/pypy
-.. _here: https://botbot.me/freenode/pypy/
+.. _here: https://quodlibet.duckdns.org/irc/pypy/latest.log.html#irc-end
.. _Development mailing list: http://mail.python.org/mailman/listinfo/pypy-dev
.. _Commit mailing list: http://mail.python.org/mailman/listinfo/pypy-commit
.. _Development bug/feature tracker: https://bitbucket.org/pypy/pypy/issues
diff --git a/pypy/doc/man/pypy.1.rst b/pypy/doc/man/pypy.1.rst
--- a/pypy/doc/man/pypy.1.rst
+++ b/pypy/doc/man/pypy.1.rst
@@ -99,6 +99,8 @@
If set, equivalent to the ``-W`` option (warning control).
The value should be a comma-separated list of ``-W`` parameters.
+.. _pypylog:
+
``PYPYLOG``
If set to a non-empty value, enable logging, the format is:
diff --git a/pypy/doc/release-v7.0.0.rst b/pypy/doc/release-v7.0.0.rst
--- a/pypy/doc/release-v7.0.0.rst
+++ b/pypy/doc/release-v7.0.0.rst
@@ -19,10 +19,12 @@
Until we can work with downstream providers to distribute builds with PyPy, we
have made packages for some common packages `available as wheels`_.
-The GC now has `hooks`_ to gain more insights into its performance, and it is
-now possible to manually manage the GC by using a combination of
-``gc.disable`` and ``gc.collect_step``. See the `GC blog post`_.
+The `GC hooks`_ , which can be used to gain more insights into its
+performance, has been improved and it is now possible to manually manage the
+GC by using a combination of ``gc.disable`` and ``gc.collect_step``. See the
+`GC blog post`_.
+.. _`GC hooks`:
http://doc.pypy.org/en/latest/gc_info.html#semi-manual-gc-management
We updated the `cffi`_ module included in PyPy to version 1.12, and the
`cppyy`_ backend to 1.4. Please use these to wrap your C and C++ code,
@@ -38,7 +40,7 @@
The utf8 branch that changes internal representation of unicode to utf8 did not
make it into the release, so there is still more goodness coming.
-You can download the v6.0 releases here:
+You can download the v7.0 releases here:
http://pypy.org/download.html
@@ -48,7 +50,7 @@
We would also like to thank our contributors and encourage new people to join
the project. PyPy has many layers and we need help with all of them: `PyPy`_
-and `RPython`_ documentation improvements, tweaking popular `modules`_ to run
+and `RPython`_ documentation improvements, tweaking popular modules to run
on pypy, or general `help`_ with making RPython's JIT even better.
.. _`PyPy`: index.html
diff --git a/pypy/doc/release-v7.1.0.rst b/pypy/doc/release-v7.1.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-v7.1.0.rst
@@ -0,0 +1,84 @@
+=========================================
+PyPy v7.1.0: release of 2.7, and 3.6-beta
+=========================================
+
+The PyPy team is proud to release the version 7.1.0 of PyPy, which includes
+two different interpreters:
+
+ - PyPy2.7, which is an interpreter supporting the syntax and the features of
+ Python 2.7
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit