[Python-checkins] cpython: Issue #20141: Improved Argument Clinic's support for the PyArg_Parse "O!"
larry.hastings
python-checkins at python.org
Tue Jan 7 21:13:46 CET 2014
http://hg.python.org/cpython/rev/ddb5cd3e0860
changeset: 88342:ddb5cd3e0860
user: Larry Hastings <larry at hastings.org>
date: Tue Jan 07 12:13:13 2014 -0800
summary:
Issue #20141: Improved Argument Clinic's support for the PyArg_Parse "O!"
format unit.
files:
Doc/howto/clinic.rst | 27 +-
Misc/NEWS | 3 +
Modules/unicodedata.c | 10 +-
Python/importlib.h | 8709 +++++++++++++--------------
Tools/clinic/clinic.py | 28 +-
5 files changed, 4384 insertions(+), 4393 deletions(-)
diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst
--- a/Doc/howto/clinic.rst
+++ b/Doc/howto/clinic.rst
@@ -640,7 +640,7 @@
``'K'`` ``unsigned_PY_LONG_LONG``
``'L'`` ``PY_LONG_LONG``
``'n'`` ``Py_ssize_t``
-``'O!'`` ``object(type='name_of_Python_type')``
+``'O!'`` ``object(subclass_of='&PySomething_Type')``
``'O&'`` ``object(converter='name_of_c_function')``
``'O'`` ``object``
``'p'`` ``bool``
@@ -693,20 +693,22 @@
(But "legacy converters" don't support arguments. That's why we
skipped them for your first function.) The argument you specified
to the format unit is now an argument to the converter; this
-argument is either ``converter`` (for ``O&``), ``type`` (for ``O!``),
+argument is either ``converter`` (for ``O&``), ``subclass_of`` (for ``O!``),
or ``encoding`` (for all the format units that start with ``e``).
-Note that ``object()`` must explicitly support each Python type you specify
-for the ``type`` argument. Currently it only supports ``str``. It should be
-easy to add more, just edit ``Tools/clinic/clinic.py``, search for ``O!`` in
-the text, and add more entries to the dict mapping types to strings just above it.
+When using ``subclass_of``, you may also want to use the other
+custom argument for ``object()``: ``type``, which lets you set the type
+actually used for the parameter. For example, if you want to ensure
+that the object is a subclass of ``PyUnicode_Type``, you probably want
+to use the converter ``object(type='PyUnicodeObject *', subclass_of='&PyUnicode_Type')``.
-Note also that this approach takes away some possible flexibility for the format
-units starting with ``e``. It used to be possible to decide at runtime what
+One possible problem with using Argument Clinic: it takes away some possible
+flexibility for the format units starting with ``e``. When writing a
+``PyArg_Parse`` call by hand, you could theoretically decide at runtime what
encoding string to pass in to :c:func:`PyArg_ParseTuple`. But now this string must
-be hard-coded at compile-time. This limitation is deliberate; it made supporting
-this format unit much easier, and may allow for future compile-time optimizations.
-This restriction does not seem unreasonable; CPython itself always passes in static
+be hard-coded at Argument-Clinic-preprocessing-time. This limitation is deliberate;
+it made supporting this format unit much easier, and may allow for future optimizations.
+This restriction doesn't seem unreasonable; CPython itself always passes in static
hard-coded encoding strings for parameters whose format units start with ``e``.
@@ -796,7 +798,8 @@
``self_converter`` or a subclass thereof.
What's the point? This lets you automatically cast ``self``
-from ``PyObject *`` to a custom type.
+from ``PyObject *`` to a custom type, just like ``object()``
+does with its ``type`` parameter.
How do you specify the custom type you want to cast ``self`` to?
If you only have one or two functions with the same type for ``self``,
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -21,6 +21,9 @@
Tools/Demos
-----------
+- Issue #20141: Improved Argument Clinic's support for the PyArg_Parse "O!"
+ format unit.
+
- Issue #20144: Argument Clinic now supports simple symbolic constants
as parameter default values.
diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c
--- a/Modules/unicodedata.c
+++ b/Modules/unicodedata.c
@@ -117,7 +117,7 @@
unicodedata.UCD.decimal
- unichr: object(type='str')
+ unichr: object(type='PyUnicodeObject *', subclass_of='&PyUnicode_Type')
default: object=NULL
/
@@ -140,13 +140,13 @@
{"decimal", (PyCFunction)unicodedata_UCD_decimal, METH_VARARGS, unicodedata_UCD_decimal__doc__},
static PyObject *
-unicodedata_UCD_decimal_impl(PyObject *self, PyObject *unichr, PyObject *default_value);
+unicodedata_UCD_decimal_impl(PyObject *self, PyUnicodeObject *unichr, PyObject *default_value);
static PyObject *
unicodedata_UCD_decimal(PyObject *self, PyObject *args)
{
PyObject *return_value = NULL;
- PyObject *unichr;
+ PyUnicodeObject *unichr;
PyObject *default_value = NULL;
if (!PyArg_ParseTuple(args,
@@ -160,8 +160,8 @@
}
static PyObject *
-unicodedata_UCD_decimal_impl(PyObject *self, PyObject *unichr, PyObject *default_value)
-/*[clinic checksum: 9576fa55f4ea0be82968af39dc9d0283e634beeb]*/
+unicodedata_UCD_decimal_impl(PyObject *self, PyUnicodeObject *unichr, PyObject *default_value)
+/*[clinic checksum: 73edde0e9cd5913ea174c4fa81504369761b7426]*/
{
PyUnicodeObject *v = (PyUnicodeObject *)unichr;
int have_old = 0;
diff --git a/Python/importlib.h b/Python/importlib.h
--- a/Python/importlib.h
+++ b/Python/importlib.h
[stripped]
diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -1358,6 +1358,12 @@
# by format units starting with 'e'.
encoding = None
+ # Should this object be required to be a subclass of a specific type?
+ # If not None, should be a string representing a pointer to a
+ # PyTypeObject (e.g. "&PyUnicode_Type").
+ # Only used by the 'O!' format unit (and the "object" converter).
+ subclass_of = None
+
# Do we want an adjacent '_length' variable for this variable?
# Only used by format units ending with '#'.
length = False
@@ -1446,7 +1452,9 @@
list.append(self.converter)
if self.encoding:
- list.append(self.encoding)
+ list.append(c_repr(self.encoding))
+ elif self.subclass_of:
+ list.append(self.subclass_of)
legal_name = ensure_legal_c_identifier(self.name)
s = ("&" if self.parse_by_reference else "") + legal_name
@@ -1627,20 +1635,12 @@
type = 'PyObject *'
format_unit = 'O'
- def converter_init(self, *, type=None):
- if type:
- assert isinstance(type, str)
- assert type.isidentifier()
- try:
- type = eval(type)
- # need more of these!
- type = {
- str: '&PyUnicode_Type',
- }[type]
- except NameError:
- type = type
+ def converter_init(self, *, type=None, subclass_of=None):
+ if subclass_of:
self.format_unit = 'O!'
- self.encoding = type
+ self.subclass_of = subclass_of
+ if type is not None:
+ self.type = type
@add_legacy_c_converter('s#', length=True)
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list