diff options
-rw-r--r-- | Doc/library/ast.rst | 2 | ||||
-rw-r--r-- | Doc/library/cgi.rst | 2 | ||||
-rw-r--r-- | Doc/library/cmath.rst | 10 | ||||
-rw-r--r-- | Doc/library/decimal.rst | 5 | ||||
-rw-r--r-- | Doc/library/os.rst | 21 | ||||
-rw-r--r-- | Doc/library/stdtypes.rst | 5 | ||||
-rw-r--r-- | Doc/library/subprocess.rst | 6 | ||||
-rw-r--r-- | Lib/ast.py | 2 | ||||
-rwxr-xr-x | Lib/cgi.py | 11 | ||||
-rwxr-xr-x | Lib/fractions.py | 2 | ||||
-rw-r--r-- | Lib/test/test_cgi.py | 87 | ||||
-rw-r--r-- | Lib/test/test_fractions.py | 18 | ||||
-rw-r--r-- | Lib/test/test_posix.py | 39 | ||||
-rw-r--r-- | Modules/_sqlite/module.c | 64 | ||||
-rw-r--r-- | Modules/posixmodule.c | 29 | ||||
-rw-r--r-- | Objects/bytearrayobject.c | 2 |
16 files changed, 249 insertions, 56 deletions
diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index 3c2f8d2..b10b9cb 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -253,5 +253,5 @@ and classes for traversing abstract syntax trees: debugging purposes. The returned string will show the names and the values for fields. This makes the code impossible to evaluate, so if evaluation is wanted *annotate_fields* must be set to False. Attributes such as line - numbers and column offsets are dumped by default. If this is wanted, + numbers and column offsets are not dumped by default. If this is wanted, *include_attributes* can be set to ``True``. diff --git a/Doc/library/cgi.rst b/Doc/library/cgi.rst index a69e98d..4286703 100644 --- a/Doc/library/cgi.rst +++ b/Doc/library/cgi.rst @@ -162,6 +162,8 @@ data part of type :mimetype:`application/x-www-form-urlencoded`), the items will actually be instances of the class :class:`MiniFieldStorage`. In this case, the :attr:`list`, :attr:`file`, and :attr:`filename` attributes are always ``None``. +A form submitted via POST that also has a query string will contain both +:class:`FieldStorage` and :class:`MiniFieldStorage` items. Higher Level Interface ---------------------- diff --git a/Doc/library/cmath.rst b/Doc/library/cmath.rst index 83a220c..2d804c97 100644 --- a/Doc/library/cmath.rst +++ b/Doc/library/cmath.rst @@ -40,9 +40,9 @@ Definition:: In engineering the polar coordinate system is popular for complex numbers. In polar coordinates a complex number is defined by the radius *r* and the phase -angle *φ*. The radius *r* is the absolute value of the complex, which can be +angle *phi*. The radius *r* is the absolute value of the complex, which can be viewed as distance from (0, 0). The radius *r* is always 0 or a positive float. -The phase angle *φ* is the counter clockwise angle from the positive x axis, +The phase angle *phi* is the counter clockwise angle from the positive x axis, e.g. *1* has the angle *0*, *1j* has the angle *π/2* and *-1* the angle *-π*. .. note:: @@ -53,12 +53,12 @@ e.g. *1* has the angle *0*, *1j* has the angle *π/2* and *-1* the angle *-π*. Definition:: - z = r * exp(1j * φ) - z = r * cis(φ) + z = r * exp(1j * phi) + z = r * cis(phi) r := abs(z) := sqrt(real(z)**2 + imag(z)**2) phi := phase(z) := atan2(imag(z), real(z)) - cis(φ) := cos(φ) + 1j * sin(φ) + cis(phi) := cos(phi) + 1j * sin(phi) .. function:: phase(x) diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst index aea1c01..d24cddf 100644 --- a/Doc/library/decimal.rst +++ b/Doc/library/decimal.rst @@ -418,7 +418,7 @@ Decimal objects .. method:: conjugate() - Just returns itself, this method is only to comply with the Decimal + Just returns self, this method is only to comply with the Decimal Specification. .. method:: copy_abs() @@ -1192,9 +1192,10 @@ In addition to the three supplied contexts, new contexts can be created with the The sign of the result, if non-zero, is the same as that of the original dividend. + .. method:: remainder_near(x, y) - Returns `x - y * n`, where *n* is the integer nearest the exact value + Returns `x - y * n`, where *n* is the integer nearest the exact value of `x / y` (if the result is `0` then its sign will be the sign of *x*). diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 33d42da..86d9a89 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -337,21 +337,6 @@ These functions create new file objects. (See also :func:`open`.) does on most platforms). -.. function:: popen(command[, mode[, bufsize]]) - - Open a pipe to or from *command*. The return value is an open file object - connected to the pipe, which can be read or written depending on whether *mode* - is ``'r'`` (default) or ``'w'``. The *bufsize* argument has the same meaning as - the corresponding argument to the built-in :func:`open` function. The exit - status of the command (encoded in the format specified for :func:`wait`) is - available as the return value of the :meth:`close` method of the file object, - except that when the exit status is zero (termination without errors), ``None`` - is returned. Availability: Macintosh, Unix, Windows. - - .. deprecated:: 2.6 - This function is obsolete. Use the :mod:`subprocess` module. - - .. _os-fd-ops: File Descriptor Operations @@ -1449,7 +1434,8 @@ written in Python, such as a mail server's external command delivery program. (Note that the :mod:`subprocess` module provides more powerful facilities for spawning new processes and retrieving their results; using that module is - preferable to using these functions.) + preferable to using these functions. Check specially the *Replacing Older + Functions with the subprocess Module* section in that documentation page.) If *mode* is :const:`P_NOWAIT`, this function returns the process id of the new process; if *mode* is :const:`P_WAIT`, returns the process's exit code if it @@ -1571,7 +1557,8 @@ written in Python, such as a mail server's external command delivery program. The :mod:`subprocess` module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using - this function. + this function. Use the :mod:`subprocess` module. Check especially the + :ref:`subprocess-replacements` section. .. function:: times() diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 101f737..9107d03 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2145,6 +2145,11 @@ the particular object. the system default encoding for converting strings. +.. attribute:: file.errors + + The Unicode error handler used along with the encoding. + + .. attribute:: file.mode The I/O mode for the file. If the file was created using the :func:`open` diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index d85f5dc..ba2a5a1 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -289,6 +289,8 @@ The following attributes are also available: ``N`` (Unix only). +.. _subprocess-replacements: + Replacing Older Functions with the subprocess Module ---------------------------------------------------- @@ -386,13 +388,13 @@ Replacing os.popen\* :: - pipe = os.popen(cmd, mode='r', bufsize) + pipe = os.popen(cmd, 'r', bufsize) ==> pipe = Popen(cmd, shell=True, bufsize=bufsize, stdout=PIPE).stdout :: - pipe = os.popen(cmd, mode='w', bufsize) + pipe = os.popen(cmd, 'w', bufsize) ==> pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin @@ -73,7 +73,7 @@ def dump(node, annotate_fields=True, include_attributes=False): debugging purposes. The returned string will show the names and the values for fields. This makes the code impossible to evaluate, so if evaluation is wanted *annotate_fields* must be set to False. Attributes such as line - numbers and column offsets are dumped by default. If this is wanted, + numbers and column offsets are not dumped by default. If this is wanted, *include_attributes* can be set to True. """ def _format(node): @@ -449,6 +449,7 @@ class FieldStorage: self.strict_parsing = strict_parsing if 'REQUEST_METHOD' in environ: method = environ['REQUEST_METHOD'].upper() + self.qs_on_post = None if method == 'GET' or method == 'HEAD': if 'QUERY_STRING' in environ: qs = environ['QUERY_STRING'] @@ -467,6 +468,8 @@ class FieldStorage: headers['content-type'] = "application/x-www-form-urlencoded" if 'CONTENT_TYPE' in environ: headers['content-type'] = environ['CONTENT_TYPE'] + if 'QUERY_STRING' in environ: + self.qs_on_post = environ['QUERY_STRING'] if 'CONTENT_LENGTH' in environ: headers['content-length'] = environ['CONTENT_LENGTH'] self.fp = fp or sys.stdin @@ -618,6 +621,8 @@ class FieldStorage: def read_urlencoded(self): """Internal: read data in query string format.""" qs = self.fp.read(self.length) + if self.qs_on_post: + qs += '&' + self.qs_on_post self.list = list = [] for key, value in parse_qsl(qs, self.keep_blank_values, self.strict_parsing): @@ -632,6 +637,12 @@ class FieldStorage: if not valid_boundary(ib): raise ValueError('Invalid boundary in multipart form: %r' % (ib,)) self.list = [] + if self.qs_on_post: + for key, value in parse_qsl(self.qs_on_post, self.keep_blank_values, + self.strict_parsing): + self.list.append(MiniFieldStorage(key, value)) + FieldStorageClass = None + klass = self.FieldStorageClass or self.__class__ parser = email.parser.FeedParser() # Create bogus content-type header for proper multipart parsing diff --git a/Lib/fractions.py b/Lib/fractions.py index 670c8eb..d3fd920 100755 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -68,7 +68,7 @@ class Fraction(numbers.Rational): input = numerator m = _RATIONAL_FORMAT.match(input) if m is None: - raise ValueError('Invalid literal for Fraction: ' + input) + raise ValueError('Invalid literal for Fraction: %r' % input) numerator = m.group('num') decimal = m.group('decimal') if decimal: diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py index 0d9b227..9381a3c 100644 --- a/Lib/test/test_cgi.py +++ b/Lib/test/test_cgi.py @@ -126,6 +126,16 @@ def first_elts(list): def first_second_elts(list): return [(p[0], p[1][0]) for p in list] +def gen_result(data, environ): + fake_stdin = StringIO(data) + fake_stdin.seek(0) + form = cgi.FieldStorage(fp=fake_stdin, environ=environ) + + result = {} + for k, v in dict(form).items(): + result[k] = type(v) is list and form.getlist(k) or v.value + + return result class CgiTests(unittest.TestCase): @@ -241,6 +251,83 @@ Content-Disposition: form-data; name="submit" got = getattr(fs.list[x], k) self.assertEquals(got, exp) + _qs_result = { + 'key1': 'value1', + 'key2': ['value2x', 'value2y'], + 'key3': 'value3', + 'key4': 'value4' + } + def testQSAndUrlEncode(self): + data = "key2=value2x&key3=value3&key4=value4" + environ = { + 'CONTENT_LENGTH': str(len(data)), + 'CONTENT_TYPE': 'application/x-www-form-urlencoded', + 'QUERY_STRING': 'key1=value1&key2=value2y', + 'REQUEST_METHOD': 'POST', + } + v = gen_result(data, environ) + self.assertEqual(self._qs_result, v) + + def testQSAndFormData(self): + data = """ +---123 +Content-Disposition: form-data; name="key2" + +value2y +---123 +Content-Disposition: form-data; name="key3" + +value3 +---123 +Content-Disposition: form-data; name="key4" + +value4 +---123-- +""" + environ = { + 'CONTENT_LENGTH': str(len(data)), + 'CONTENT_TYPE': 'multipart/form-data; boundary=-123', + 'QUERY_STRING': 'key1=value1&key2=value2x', + 'REQUEST_METHOD': 'POST', + } + v = gen_result(data, environ) + self.assertEqual(self._qs_result, v) + + def testQSAndFormDataFile(self): + data = """ +---123 +Content-Disposition: form-data; name="key2" + +value2y +---123 +Content-Disposition: form-data; name="key3" + +value3 +---123 +Content-Disposition: form-data; name="key4" + +value4 +---123 +Content-Disposition: form-data; name="upload"; filename="fake.txt" +Content-Type: text/plain + +this is the content of the fake file + +---123-- +""" + environ = { + 'CONTENT_LENGTH': str(len(data)), + 'CONTENT_TYPE': 'multipart/form-data; boundary=-123', + 'QUERY_STRING': 'key1=value1&key2=value2x', + 'REQUEST_METHOD': 'POST', + } + result = self._qs_result.copy() + result.update({ + 'upload': 'this is the content of the fake file' + }) + v = gen_result(data, environ) + self.assertEqual(result, v) + def test_main(): run_unittest(CgiTests) diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py index d06c206..97e91ce 100644 --- a/Lib/test/test_fractions.py +++ b/Lib/test/test_fractions.py @@ -83,38 +83,38 @@ class FractionTest(unittest.TestCase): ZeroDivisionError, "Fraction(3, 0)", F, "3/0") self.assertRaisesMessage( - ValueError, "Invalid literal for Fraction: 3/", + ValueError, "Invalid literal for Fraction: '3/'", F, "3/") self.assertRaisesMessage( - ValueError, "Invalid literal for Fraction: 3 /2", + ValueError, "Invalid literal for Fraction: '3 /2'", F, "3 /2") self.assertRaisesMessage( # Denominators don't need a sign. - ValueError, "Invalid literal for Fraction: 3/+2", + ValueError, "Invalid literal for Fraction: '3/+2'", F, "3/+2") self.assertRaisesMessage( # Imitate float's parsing. - ValueError, "Invalid literal for Fraction: + 3/2", + ValueError, "Invalid literal for Fraction: '+ 3/2'", F, "+ 3/2") self.assertRaisesMessage( # Avoid treating '.' as a regex special character. - ValueError, "Invalid literal for Fraction: 3a2", + ValueError, "Invalid literal for Fraction: '3a2'", F, "3a2") self.assertRaisesMessage( # Only parse ordinary decimals, not scientific form. - ValueError, "Invalid literal for Fraction: 3.2e4", + ValueError, "Invalid literal for Fraction: '3.2e4'", F, "3.2e4") self.assertRaisesMessage( # Don't accept combinations of decimals and rationals. - ValueError, "Invalid literal for Fraction: 3/7.2", + ValueError, "Invalid literal for Fraction: '3/7.2'", F, "3/7.2") self.assertRaisesMessage( # Don't accept combinations of decimals and rationals. - ValueError, "Invalid literal for Fraction: 3.2/7", + ValueError, "Invalid literal for Fraction: '3.2/7'", F, "3.2/7") self.assertRaisesMessage( # Allow 3. and .3, but not . - ValueError, "Invalid literal for Fraction: .", + ValueError, "Invalid literal for Fraction: '.'", F, ".") def testImmutable(self): diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index f16abb2..b7ce71e 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -10,6 +10,7 @@ except ImportError: import time import os import pwd +import shutil import unittest import warnings warnings.filterwarnings('ignore', '.* potential security risk .*', @@ -225,6 +226,44 @@ class PosixTester(unittest.TestCase): self.assertEqual(type(k), str) self.assertEqual(type(v), str) + def test_getcwd_long_pathnames(self): + if hasattr(posix, 'getcwd'): + dirname = 'getcwd-test-directory-0123456789abcdef-01234567890abcdef' + curdir = os.getcwd() + base_path = os.path.abspath(support.TESTFN) + '.getcwd' + + try: + os.mkdir(base_path) + os.chdir(base_path) + except: +# Just returning nothing instead of the TestSkipped exception, +# because the test results in Error in that case. +# Is that ok? +# raise support.TestSkipped, "cannot create directory for testing" + return + + def _create_and_do_getcwd(dirname, current_path_length = 0): + try: + os.mkdir(dirname) + except: + raise support.TestSkipped("mkdir cannot create directory sufficiently deep for getcwd test") + + os.chdir(dirname) + try: + os.getcwd() + if current_path_length < 1027: + _create_and_do_getcwd(dirname, current_path_length + len(dirname) + 1) + finally: + os.chdir('..') + os.rmdir(dirname) + + _create_and_do_getcwd(dirname) + + finally: + shutil.rmtree(base_path) + os.chdir(curdir) + + def test_main(): support.run_unittest(PosixTester) diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 59d0d17..3f209eb 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -76,6 +76,13 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* return result; } +PyDoc_STRVAR(module_connect_doc, +"connect(database[, timeout, isolation_level, detect_types, factory])\n\ +\n\ +Opens a connection to the SQLite database file *database*. You can use\n\ +\":memory:\" to open a database connection to a database that resides in\n\ +RAM instead of on disk."); + static PyObject* module_complete(PyObject* self, PyObject* args, PyObject* kwargs) { @@ -100,6 +107,11 @@ static PyObject* module_complete(PyObject* self, PyObject* args, PyObject* return result; } +PyDoc_STRVAR(module_complete_doc, +"complete_statement(sql)\n\ +\n\ +Checks if a string contains a complete SQL statement. Non-standard."); + #ifdef HAVE_SHARED_CACHE static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyObject* kwargs) @@ -123,9 +135,15 @@ static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyOb return Py_None; } } + +PyDoc_STRVAR(module_enable_shared_cache_doc, +"enable_shared_cache(do_enable)\n\ +\n\ +Enable or disable shared cache mode for the calling thread.\n\ +Experimental/Non-standard."); #endif /* HAVE_SHARED_CACHE */ -static PyObject* module_register_adapter(PyObject* self, PyObject* args, PyObject* kwargs) +static PyObject* module_register_adapter(PyObject* self, PyObject* args) { PyTypeObject* type; PyObject* caster; @@ -147,7 +165,12 @@ static PyObject* module_register_adapter(PyObject* self, PyObject* args, PyObjec return Py_None; } -static PyObject* module_register_converter(PyObject* self, PyObject* args, PyObject* kwargs) +PyDoc_STRVAR(module_register_adapter_doc, +"register_adapter(type, callable)\n\ +\n\ +Registers an adapter with pysqlite's adapter registry. Non-standard."); + +static PyObject* module_register_converter(PyObject* self, PyObject* args) { PyObject* orig_name; PyObject* name = NULL; @@ -175,7 +198,12 @@ error: return retval; } -static PyObject* enable_callback_tracebacks(PyObject* self, PyObject* args, PyObject* kwargs) +PyDoc_STRVAR(module_register_converter_doc, +"register_converter(typename, callable)\n\ +\n\ +Registers a converter with pysqlite. Non-standard."); + +static PyObject* enable_callback_tracebacks(PyObject* self, PyObject* args) { if (!PyArg_ParseTuple(args, "i", &_enable_callback_tracebacks)) { return NULL; @@ -185,6 +213,11 @@ static PyObject* enable_callback_tracebacks(PyObject* self, PyObject* args, PyOb return Py_None; } +PyDoc_STRVAR(enable_callback_tracebacks_doc, +"enable_callback_tracebacks(flag)\n\ +\n\ +Enable or disable callback functions throwing errors to stderr."); + static void converters_init(PyObject* dict) { converters = PyDict_New(); @@ -196,15 +229,22 @@ static void converters_init(PyObject* dict) } static PyMethodDef module_methods[] = { - {"connect", (PyCFunction)module_connect, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Creates a connection.")}, - {"complete_statement", (PyCFunction)module_complete, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Checks if a string contains a complete SQL statement. Non-standard.")}, + {"connect", (PyCFunction)module_connect, + METH_VARARGS | METH_KEYWORDS, module_connect_doc}, + {"complete_statement", (PyCFunction)module_complete, + METH_VARARGS | METH_KEYWORDS, module_complete_doc}, #ifdef HAVE_SHARED_CACHE - {"enable_shared_cache", (PyCFunction)module_enable_shared_cache, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Enable or disable shared cache mode for the calling thread. Experimental/Non-standard.")}, + {"enable_shared_cache", (PyCFunction)module_enable_shared_cache, + METH_VARARGS | METH_KEYWORDS, module_enable_shared_cache_doc}, #endif - {"register_adapter", (PyCFunction)module_register_adapter, METH_VARARGS, PyDoc_STR("Registers an adapter with pysqlite's adapter registry. Non-standard.")}, - {"register_converter", (PyCFunction)module_register_converter, METH_VARARGS, PyDoc_STR("Registers a converter with pysqlite. Non-standard.")}, - {"adapt", (PyCFunction)psyco_microprotocols_adapt, METH_VARARGS, psyco_microprotocols_adapt_doc}, - {"enable_callback_tracebacks", (PyCFunction)enable_callback_tracebacks, METH_VARARGS, PyDoc_STR("Enable or disable callback functions throwing errors to stderr.")}, + {"register_adapter", (PyCFunction)module_register_adapter, + METH_VARARGS, module_register_adapter_doc}, + {"register_converter", (PyCFunction)module_register_converter, + METH_VARARGS, module_register_converter_doc}, + {"adapt", (PyCFunction)psyco_microprotocols_adapt, METH_VARARGS, + psyco_microprotocols_adapt_doc}, + {"enable_callback_tracebacks", (PyCFunction)enable_callback_tracebacks, + METH_VARARGS, enable_callback_tracebacks_doc}, {NULL, NULL} }; @@ -403,12 +443,12 @@ PyMODINIT_FUNC PyInit__sqlite3(void) pysqlite_BaseTypeAdapted = 0; - /* Original comment form _bsddb.c in the Python core. This is also still + /* Original comment from _bsddb.c in the Python core. This is also still * needed nowadays for Python 2.3/2.4. * * PyEval_InitThreads is called here due to a quirk in python 1.5 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>: - * The global interepreter lock is not initialized until the first + * The global interpreter lock is not initialized until the first * thread is created using thread.start_new_thread() or fork() is * called. that would cause the ALLOW_THREADS here to segfault due * to a null pointer reference if no threads or child processes diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 16aed52..8282134 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1981,19 +1981,38 @@ Return a string representing the current working directory."); static PyObject * posix_getcwd(PyObject *self, PyObject *noargs) { - char buf[1026]; - char *res; + int bufsize_incr = 1024; + int bufsize = 0; + char *tmpbuf = NULL; + char *res = NULL; + PyObject *dynamic_return; Py_BEGIN_ALLOW_THREADS + do { + bufsize = bufsize + bufsize_incr; + tmpbuf = malloc(bufsize); + if (tmpbuf == NULL) { + break; + } #if defined(PYOS_OS2) && defined(PYCC_GCC) - res = _getcwd2(buf, sizeof buf); + res = _getcwd2(tmpbuf, bufsize); #else - res = getcwd(buf, sizeof buf); + res = getcwd(tmpbuf, bufsize); #endif + + if (res == NULL) { + free(tmpbuf); + } + } while ((res == NULL) && (errno == ERANGE)); Py_END_ALLOW_THREADS + if (res == NULL) return posix_error(); - return PyUnicode_FromString(buf); + + dynamic_return = PyUnicode_FromString(tmpbuf); + free(tmpbuf); + + return dynamic_return; } PyDoc_STRVAR(posix_getcwdu__doc__, diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 70921c0..f97c467 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2648,7 +2648,7 @@ PyDoc_STRVAR(pop__doc__, "B.pop([index]) -> int\n\ \n\ Remove and return a single item from B. If no index\n\ -argument is give, will pop the last value."); +argument is given, will pop the last value."); static PyObject * bytes_pop(PyByteArrayObject *self, PyObject *args) { |