[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

AltStyle によって変換されたページ (->オリジナル) /