PEP 436: fix markup and make it consistent.
This commit is contained in:
parent
3f90114628
commit
298f064289
356
pep-0436.txt
356
pep-0436.txt
|
@ -49,62 +49,62 @@ But over the years the ``PyArg_Parse`` interface has been extended
|
||||||
in numerous ways. The modern API is complex, to the point that it
|
in numerous ways. The modern API is complex, to the point that it
|
||||||
is somewhat painful to use. Consider:
|
is somewhat painful to use. Consider:
|
||||||
|
|
||||||
* There are now forty different "format units"; a few are even three
|
* There are now forty different "format units"; a few are even three
|
||||||
characters long. This makes it difficult for the programmer to
|
characters long. This makes it difficult for the programmer to
|
||||||
understand what the format string says--or even perhaps to parse
|
understand what the format string says--or even perhaps to parse
|
||||||
it--without constantly cross-indexing it with the documentation.
|
it--without constantly cross-indexing it with the documentation.
|
||||||
* There are also six meta-format units that may be buried in the
|
* There are also six meta-format units that may be buried in the
|
||||||
format string. (They are: ``"()|$:;"``.)
|
format string. (They are: ``"()|$:;"``.)
|
||||||
* The more format units are added, the less likely it is the
|
* The more format units are added, the less likely it is the
|
||||||
implementer can pick an easy-to-use mnemonic for the format unit,
|
implementer can pick an easy-to-use mnemonic for the format unit,
|
||||||
because the character of choice is probably already in use. In
|
because the character of choice is probably already in use. In
|
||||||
other words, the more format units we have, the more obtuse the
|
other words, the more format units we have, the more obtuse the
|
||||||
format units become.
|
format units become.
|
||||||
* Several format units are nearly identical to others, having only
|
* Several format units are nearly identical to others, having only
|
||||||
subtle differences. This makes understanding the exact semantics
|
subtle differences. This makes understanding the exact semantics
|
||||||
of the format string even harder, and can make it difficult to
|
of the format string even harder, and can make it difficult to
|
||||||
figure out exactly which format unit you want.
|
figure out exactly which format unit you want.
|
||||||
* The docstring is specified as a static C string, making it mildly
|
* The docstring is specified as a static C string, making it mildly
|
||||||
bothersome to read and edit since it must obey C string quoting rules.
|
bothersome to read and edit since it must obey C string quoting rules.
|
||||||
* When adding a new parameter to a function using
|
* When adding a new parameter to a function using
|
||||||
``PyArg_ParseTupleAndKeywords()``, it's necessary to touch six
|
``PyArg_ParseTupleAndKeywords()``, it's necessary to touch six
|
||||||
different places in the code: [4]_
|
different places in the code: [4]_
|
||||||
|
|
||||||
* Declaring the variable to store the argument.
|
* Declaring the variable to store the argument.
|
||||||
* Passing in a pointer to that variable in the correct spot in
|
* Passing in a pointer to that variable in the correct spot in
|
||||||
``PyArg_ParseTupleAndKeywords()``, also passing in any
|
``PyArg_ParseTupleAndKeywords()``, also passing in any
|
||||||
"length" or "converter" arguments in the correct order.
|
"length" or "converter" arguments in the correct order.
|
||||||
* Adding the name of the argument in the correct spot of the
|
* Adding the name of the argument in the correct spot of the
|
||||||
"keywords" array passed in to
|
"keywords" array passed in to
|
||||||
``PyArg_ParseTupleAndKeywords()``.
|
``PyArg_ParseTupleAndKeywords()``.
|
||||||
* Adding the format unit to the correct spot in the format
|
* Adding the format unit to the correct spot in the format
|
||||||
string.
|
string.
|
||||||
* Adding the parameter to the prototype in the docstring.
|
* Adding the parameter to the prototype in the docstring.
|
||||||
* Documenting the parameter in the docstring.
|
* Documenting the parameter in the docstring.
|
||||||
|
|
||||||
* There is currently no mechanism for builtin functions to provide
|
* There is currently no mechanism for builtin functions to provide
|
||||||
their "signature" information (see ``inspect.getfullargspec`` and
|
their "signature" information (see ``inspect.getfullargspec`` and
|
||||||
``inspect.Signature``). Adding this information using a mechanism
|
``inspect.Signature``). Adding this information using a mechanism
|
||||||
similar to the existing ``PyArg_Parse`` functions would require
|
similar to the existing ``PyArg_Parse`` functions would require
|
||||||
repeating ourselves yet again.
|
repeating ourselves yet again.
|
||||||
|
|
||||||
The goal of Argument Clinic is to replace this API with a mechanism
|
The goal of Argument Clinic is to replace this API with a mechanism
|
||||||
inheriting none of these downsides:
|
inheriting none of these downsides:
|
||||||
|
|
||||||
* You need specify each parameter only once.
|
* You need specify each parameter only once.
|
||||||
* All information about a parameter is kept together in one place.
|
* All information about a parameter is kept together in one place.
|
||||||
* For each parameter, you specify a conversion function; Argument
|
* For each parameter, you specify a conversion function; Argument
|
||||||
Clinic handles the translation from Python value into C value for
|
Clinic handles the translation from Python value into C value for
|
||||||
you.
|
you.
|
||||||
* Argument Clinic also allows for fine-tuning of argument processing
|
* Argument Clinic also allows for fine-tuning of argument processing
|
||||||
behavior with parameterized conversion functions.
|
behavior with parameterized conversion functions.
|
||||||
* Docstrings are written in plain text. Function docstrings are
|
* Docstrings are written in plain text. Function docstrings are
|
||||||
required; per-parameter docstrings are encouraged.
|
required; per-parameter docstrings are encouraged.
|
||||||
* From this, Argument Clinic generates for you all the mundane,
|
* From this, Argument Clinic generates for you all the mundane,
|
||||||
repetitious code and data structures CPython needs internally.
|
repetitious code and data structures CPython needs internally.
|
||||||
Once you've specified the interface, the next step is simply to
|
Once you've specified the interface, the next step is simply to
|
||||||
write your implementation using native C types. Every detail of
|
write your implementation using native C types. Every detail of
|
||||||
argument parsing is handled for you.
|
argument parsing is handled for you.
|
||||||
|
|
||||||
Argument Clinic is implemented as a preprocessor. It draws inspiration
|
Argument Clinic is implemented as a preprocessor. It draws inspiration
|
||||||
for its workflow directly from [Cog]_ by Ned Batchelder. To use Clinic,
|
for its workflow directly from [Cog]_ by Ned Batchelder. To use Clinic,
|
||||||
|
@ -121,11 +121,11 @@ interpreter.
|
||||||
|
|
||||||
Future goals of Argument Clinic include:
|
Future goals of Argument Clinic include:
|
||||||
|
|
||||||
* providing signature information for builtins,
|
* providing signature information for builtins,
|
||||||
* enabling alternative implementations of Python to create
|
* enabling alternative implementations of Python to create
|
||||||
automated library compatibility tests, and
|
automated library compatibility tests, and
|
||||||
* speeding up argument parsing with improvements to the
|
* speeding up argument parsing with improvements to the
|
||||||
generated code.
|
generated code.
|
||||||
|
|
||||||
|
|
||||||
DSL Syntax Summary
|
DSL Syntax Summary
|
||||||
|
@ -141,117 +141,115 @@ statement, lending it some familiarity to Python core developers.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
+-----------------------+-----------------------------------------------------------------+
|
+-----------------------+-----------------------------------------------------------------+
|
||||||
| Section | Example |
|
| Section | Example |
|
||||||
+-----------------------+-----------------------------------------------------------------+
|
+-----------------------+-----------------------------------------------------------------+
|
||||||
| Clinic DSL start | /*[clinic] |
|
| Clinic DSL start | /*[clinic] |
|
||||||
| Module declaration | module module_name |
|
| Module declaration | module module_name |
|
||||||
| Class declaration | class module_name.class_name |
|
| Class declaration | class module_name.class_name |
|
||||||
| Function declaration | module_name.function_name -> return_annotation |
|
| Function declaration | module_name.function_name -> return_annotation |
|
||||||
| Parameter declaration | name : converter(param=value) |
|
| Parameter declaration | name : converter(param=value) |
|
||||||
| Parameter docstring | Lorem ipsum dolor sit amet, consectetur |
|
| Parameter docstring | Lorem ipsum dolor sit amet, consectetur |
|
||||||
| | adipisicing elit, sed do eiusmod tempor |
|
| | adipisicing elit, sed do eiusmod tempor |
|
||||||
| Function docstring | Lorem ipsum dolor sit amet, consectetur adipisicing |
|
| Function docstring | Lorem ipsum dolor sit amet, consectetur adipisicing |
|
||||||
| | elit, sed do eiusmod tempor incididunt ut labore et |
|
| | elit, sed do eiusmod tempor incididunt ut labore et |
|
||||||
| Clinic DSL end | [clinic]*/ |
|
| Clinic DSL end | [clinic]*/ |
|
||||||
| Clinic output | ... |
|
| Clinic output | ... |
|
||||||
| Clinic output end | /*[clinic end output:<checksum>]*/ |
|
| Clinic output end | /*[clinic end output:<checksum>]*/ |
|
||||||
+-----------------------+-----------------------------------------------------------------+
|
+-----------------------+-----------------------------------------------------------------+
|
||||||
|
|
||||||
To give some flavor of the proposed DSL syntax, here are some sample Clinic
|
To give some flavor of the proposed DSL syntax, here are some sample Clinic
|
||||||
code blocks. This first block reflects the normally preferred style, including
|
code blocks. This first block reflects the normally preferred style, including
|
||||||
blank lines between parameters and per-argument docstrings.
|
blank lines between parameters and per-argument docstrings.
|
||||||
It also includes a user-defined converter (``path_t``) created
|
It also includes a user-defined converter (``path_t``) created
|
||||||
locally
|
locally::
|
||||||
|
|
||||||
::
|
/*[clinic]
|
||||||
|
os.stat as os_stat_fn -> stat result
|
||||||
|
|
||||||
/*[clinic]
|
path: path_t(allow_fd=1)
|
||||||
os.stat as os_stat_fn -> stat result
|
Path to be examined; can be string, bytes, or open-file-descriptor int.
|
||||||
|
|
||||||
path: path_t(allow_fd=1)
|
*
|
||||||
Path to be examined; can be string, bytes, or open-file-descriptor int.
|
|
||||||
|
|
||||||
*
|
dir_fd: OS_STAT_DIR_FD_CONVERTER = DEFAULT_DIR_FD
|
||||||
|
If not None, it should be a file descriptor open to a directory,
|
||||||
|
and path should be a relative string; path will then be relative to
|
||||||
|
that directory.
|
||||||
|
|
||||||
dir_fd: OS_STAT_DIR_FD_CONVERTER = DEFAULT_DIR_FD
|
follow_symlinks: bool = True
|
||||||
If not None, it should be a file descriptor open to a directory,
|
If False, and the last element of the path is a symbolic link,
|
||||||
and path should be a relative string; path will then be relative to
|
stat will examine the symbolic link itself instead of the file
|
||||||
that directory.
|
the link points to.
|
||||||
|
|
||||||
follow_symlinks: bool = True
|
Perform a stat system call on the given path.
|
||||||
If False, and the last element of the path is a symbolic link,
|
|
||||||
stat will examine the symbolic link itself instead of the file
|
|
||||||
the link points to.
|
|
||||||
|
|
||||||
Perform a stat system call on the given path.
|
{parameters}
|
||||||
|
|
||||||
{parameters}
|
dir_fd and follow_symlinks may not be implemented
|
||||||
|
on your platform. If they are unavailable, using them will raise a
|
||||||
|
NotImplementedError.
|
||||||
|
|
||||||
dir_fd and follow_symlinks may not be implemented
|
It's an error to use dir_fd or follow_symlinks when specifying path as
|
||||||
on your platform. If they are unavailable, using them will raise a
|
an open file descriptor.
|
||||||
NotImplementedError.
|
|
||||||
|
|
||||||
It's an error to use dir_fd or follow_symlinks when specifying path as
|
[clinic]*/
|
||||||
an open file descriptor.
|
|
||||||
|
|
||||||
[clinic]*/
|
|
||||||
|
|
||||||
This second example shows a minimal Clinic code block, omitting all
|
This second example shows a minimal Clinic code block, omitting all
|
||||||
parameter docstrings and non-significant blank lines::
|
parameter docstrings and non-significant blank lines::
|
||||||
|
|
||||||
/*[clinic]
|
/*[clinic]
|
||||||
os.access
|
os.access
|
||||||
path: path
|
path: path
|
||||||
mode: int
|
mode: int
|
||||||
*
|
*
|
||||||
dir_fd: OS_ACCESS_DIR_FD_CONVERTER = 1
|
dir_fd: OS_ACCESS_DIR_FD_CONVERTER = 1
|
||||||
effective_ids: bool = False
|
effective_ids: bool = False
|
||||||
follow_symlinks: bool = True
|
follow_symlinks: bool = True
|
||||||
Use the real uid/gid to test for access to a path.
|
Use the real uid/gid to test for access to a path.
|
||||||
Returns True if granted, False otherwise.
|
Returns True if granted, False otherwise.
|
||||||
|
|
||||||
{parameters}
|
{parameters}
|
||||||
|
|
||||||
dir_fd, effective_ids, and follow_symlinks may not be implemented
|
dir_fd, effective_ids, and follow_symlinks may not be implemented
|
||||||
on your platform. If they are unavailable, using them will raise a
|
on your platform. If they are unavailable, using them will raise a
|
||||||
NotImplementedError.
|
NotImplementedError.
|
||||||
|
|
||||||
Note that most operations will use the effective uid/gid, therefore this
|
Note that most operations will use the effective uid/gid, therefore this
|
||||||
routine can be used in a suid/sgid environment to test if the invoking user
|
routine can be used in a suid/sgid environment to test if the invoking user
|
||||||
has the specified access to the path.
|
has the specified access to the path.
|
||||||
|
|
||||||
[clinic]*/
|
[clinic]*/
|
||||||
|
|
||||||
This final example shows a Clinic code block handling groups of
|
This final example shows a Clinic code block handling groups of
|
||||||
optional parameters, including parameters on the left::
|
optional parameters, including parameters on the left::
|
||||||
|
|
||||||
/*[clinic]
|
/*[clinic]
|
||||||
curses.window.addch
|
curses.window.addch
|
||||||
|
|
||||||
[
|
[
|
||||||
y: int
|
y: int
|
||||||
Y-coordinate.
|
Y-coordinate.
|
||||||
|
|
||||||
x: int
|
x: int
|
||||||
X-coordinate.
|
X-coordinate.
|
||||||
]
|
]
|
||||||
|
|
||||||
ch: char
|
ch: char
|
||||||
Character to add.
|
Character to add.
|
||||||
|
|
||||||
[
|
[
|
||||||
attr: long
|
attr: long
|
||||||
Attributes for the character.
|
Attributes for the character.
|
||||||
]
|
]
|
||||||
|
|
||||||
/
|
/
|
||||||
|
|
||||||
Paint character ch at (y, x) with attributes attr,
|
Paint character ch at (y, x) with attributes attr,
|
||||||
overwriting any character previously painter at that location.
|
overwriting any character previously painter at that location.
|
||||||
By default, the character position and attributes are the
|
By default, the character position and attributes are the
|
||||||
current settings for the window object.
|
current settings for the window object.
|
||||||
[clinic]*/
|
[clinic]*/
|
||||||
|
|
||||||
|
|
||||||
General Behavior Of the Argument Clinic DSL
|
General Behavior Of the Argument Clinic DSL
|
||||||
|
@ -275,17 +273,13 @@ Module and Class Declarations
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
When a C file implements a module or class, this should be declared to
|
When a C file implements a module or class, this should be declared to
|
||||||
Clinic. The syntax is simple:
|
Clinic. The syntax is simple::
|
||||||
|
|
||||||
::
|
module module_name
|
||||||
|
|
||||||
module module_name
|
or ::
|
||||||
|
|
||||||
or
|
class module_name.class_name
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
class module_name.class_name
|
|
||||||
|
|
||||||
(Note that these are not actually special syntax; they are implemented
|
(Note that these are not actually special syntax; they are implemented
|
||||||
as `Directives`_.)
|
as `Directives`_.)
|
||||||
|
@ -297,11 +291,9 @@ from the top-level module. Nested modules and classes are supported.
|
||||||
Function Declaration
|
Function Declaration
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
The full form of the function declaration is as follows:
|
The full form of the function declaration is as follows::
|
||||||
|
|
||||||
::
|
dotted.name [ as legal_c_id ] [ -> return_annotation ]
|
||||||
|
|
||||||
dotted.name [ as legal_c_id ] [ -> return_annotation ]
|
|
||||||
|
|
||||||
The dotted name should be the full name of the function, starting
|
The dotted name should be the full name of the function, starting
|
||||||
with the highest-level package (e.g. "os.stat" or "curses.window.addch").
|
with the highest-level package (e.g. "os.stat" or "curses.window.addch").
|
||||||
|
@ -323,11 +315,9 @@ a *return converter*.
|
||||||
Parameter Declaration
|
Parameter Declaration
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
The full form of the parameter declaration line as as follows:
|
The full form of the parameter declaration line as as follows::
|
||||||
|
|
||||||
::
|
name: converter [ (parameter=value [, parameter2=value2]) ] [ = default]
|
||||||
|
|
||||||
name: converter [ (parameter=value [, parameter2=value2]) ] [ = default]
|
|
||||||
|
|
||||||
The "name" must be a legal C identifier. Whitespace is permitted between
|
The "name" must be a legal C identifier. Whitespace is permitted between
|
||||||
the name and the colon (though this is not the preferred style). Whitespace
|
the name and the colon (though this is not the preferred style). Whitespace
|
||||||
|
@ -377,11 +367,9 @@ For convenience's sake in converting existing code to Argument Clinic,
|
||||||
Clinic provides a set of legacy converters that match ``PyArg_ParseTuple``
|
Clinic provides a set of legacy converters that match ``PyArg_ParseTuple``
|
||||||
format units. They are specified as a C string containing the format
|
format units. They are specified as a C string containing the format
|
||||||
unit. For example, to specify a parameter "foo" as taking a Python
|
unit. For example, to specify a parameter "foo" as taking a Python
|
||||||
"int" and emitting a C int, you could specify:
|
"int" and emitting a C int, you could specify::
|
||||||
|
|
||||||
::
|
foo : "i"
|
||||||
|
|
||||||
foo : "i"
|
|
||||||
|
|
||||||
(To more closely resemble a C string, these must always use double quotes.)
|
(To more closely resemble a C string, these must always use double quotes.)
|
||||||
|
|
||||||
|
@ -554,11 +542,9 @@ Argument Clinic also permits "directives" in Clinic code blocks.
|
||||||
Directives are similar to *pragmas* in C; they are statements
|
Directives are similar to *pragmas* in C; they are statements
|
||||||
that modify Argument Clinic's behavior.
|
that modify Argument Clinic's behavior.
|
||||||
|
|
||||||
The format of a directive is as follows:
|
The format of a directive is as follows::
|
||||||
|
|
||||||
::
|
directive_name [argument [second_argument [ ... ]]]
|
||||||
|
|
||||||
directive_name [argument [second_argument [ ... ]]]
|
|
||||||
|
|
||||||
Directives only take positional arguments.
|
Directives only take positional arguments.
|
||||||
|
|
||||||
|
@ -566,7 +552,7 @@ A Clinic code block must contain either one or more directives,
|
||||||
or a function declaration. It may contain both, in which
|
or a function declaration. It may contain both, in which
|
||||||
case all directives must come before the function declaration.
|
case all directives must come before the function declaration.
|
||||||
|
|
||||||
Internally directives map directly to Python callables.
|
Internally directives map directly to Python callables.
|
||||||
The directive's arguments are passed directly to the callable
|
The directive's arguments are passed directly to the callable
|
||||||
as positional arguments of type ``str()``.
|
as positional arguments of type ``str()``.
|
||||||
|
|
||||||
|
@ -581,18 +567,16 @@ Python Code
|
||||||
|
|
||||||
Argument Clinic also permits embedding Python code inside C files,
|
Argument Clinic also permits embedding Python code inside C files,
|
||||||
which is executed in-place when Argument Clinic processes the file.
|
which is executed in-place when Argument Clinic processes the file.
|
||||||
Embedded code looks like this:
|
Embedded code looks like this::
|
||||||
|
|
||||||
::
|
/*[python]
|
||||||
|
|
||||||
/*[python]
|
# this is python code!
|
||||||
|
print("/" + "* Hello world! *" + "/")
|
||||||
|
|
||||||
# this is python code!
|
[python]*/
|
||||||
print("/" + "* Hello world! *" + "/")
|
/* Hello world! */
|
||||||
|
/*[python end:da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
||||||
[python]*/
|
|
||||||
/* Hello world! */
|
|
||||||
/*[python end:da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
|
||||||
|
|
||||||
The ``"/* Hello world! */"`` line above was generated by running the Python
|
The ``"/* Hello world! */"`` line above was generated by running the Python
|
||||||
code in the preceding comment.
|
code in the preceding comment.
|
||||||
|
@ -610,14 +594,14 @@ after the section of Clinic code. For "python" sections, the output
|
||||||
is everything printed using ``builtins.print``. For "clinic"
|
is everything printed using ``builtins.print``. For "clinic"
|
||||||
sections, the output is valid C code, including:
|
sections, the output is valid C code, including:
|
||||||
|
|
||||||
* a ``#define`` providing the correct ``methoddef`` structure for the
|
* a ``#define`` providing the correct ``methoddef`` structure for the
|
||||||
function
|
function
|
||||||
* a prototype for the "impl" function -- this is what you'll write
|
* a prototype for the "impl" function -- this is what you'll write
|
||||||
to implement this function
|
to implement this function
|
||||||
* a function that handles all argument processing, which calls your
|
* a function that handles all argument processing, which calls your
|
||||||
"impl" function
|
"impl" function
|
||||||
* the definition line of the "impl" function
|
* the definition line of the "impl" function
|
||||||
* and a comment indicating the end of output.
|
* and a comment indicating the end of output.
|
||||||
|
|
||||||
The intention is that you write the body of your impl function immediately
|
The intention is that you write the body of your impl function immediately
|
||||||
after the output -- as in, you write a left-curly-brace immediately after
|
after the output -- as in, you write a left-curly-brace immediately after
|
||||||
|
@ -738,15 +722,15 @@ Notes / TBD
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
/*[clinic]
|
/*[clinic]
|
||||||
... prototype and parameters (including parameter docstrings) go here
|
... prototype and parameters (including parameter docstrings) go here
|
||||||
[clinic]*/
|
[clinic]*/
|
||||||
... some output ...
|
... some output ...
|
||||||
/*[clinic docstring start]*/
|
/*[clinic docstring start]*/
|
||||||
... hand-edited function docstring goes here <-- you edit this by hand!
|
... hand-edited function docstring goes here <-- you edit this by hand!
|
||||||
/*[clinic docstring end]*/
|
/*[clinic docstring end]*/
|
||||||
... more output
|
... more output
|
||||||
/*[clinic output end]*/
|
/*[clinic output end]*/
|
||||||
|
|
||||||
I tried it this way and don't like it -- I think it's clumsy. I
|
I tried it this way and don't like it -- I think it's clumsy. I
|
||||||
prefer that everything you write goes in one place, rather than
|
prefer that everything you write goes in one place, rather than
|
||||||
|
@ -756,7 +740,7 @@ Notes / TBD
|
||||||
* Argument Clinic does not support automatic tuple unpacking
|
* Argument Clinic does not support automatic tuple unpacking
|
||||||
(the "``(OOO)``" style format string for ``PyArg_ParseTuple()``.)
|
(the "``(OOO)``" style format string for ``PyArg_ParseTuple()``.)
|
||||||
|
|
||||||
* Argument Clinic removes some dynamism / flexibility. With
|
* Argument Clinic removes some dynamism / flexibility. With
|
||||||
``PyArg_ParseTuple()`` one could theoretically pass in different
|
``PyArg_ParseTuple()`` one could theoretically pass in different
|
||||||
encodings at runtime for the "``es``"/"``et``" format units.
|
encodings at runtime for the "``es``"/"``et``" format units.
|
||||||
AFAICT CPython doesn't do this itself, however it's possible
|
AFAICT CPython doesn't do this itself, however it's possible
|
||||||
|
@ -773,7 +757,7 @@ shamelessly rip off his clever design for Cog--"my favorite tool
|
||||||
that I've never gotten to use". Thanks also to everyone who provided
|
that I've never gotten to use". Thanks also to everyone who provided
|
||||||
feedback on the [bugtracker issue] and on python-dev. Special thanks
|
feedback on the [bugtracker issue] and on python-dev. Special thanks
|
||||||
to Nick Coglan and Guido van Rossum for a rousing two-hour in-person
|
to Nick Coglan and Guido van Rossum for a rousing two-hour in-person
|
||||||
deep dive on the topic at PyCon US 2013.
|
deep dive on the topic at PyCon US 2013.
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
|
|
Loading…
Reference in New Issue