PEP 501: add logging examples, other tweaks

This commit is contained in:
Nick Coghlan 2015-08-22 21:17:31 +10:00
parent e91d95900e
commit d377d6216a
1 changed files with 47 additions and 10 deletions

View File

@ -83,11 +83,13 @@ Rationale
=========
PEP 498 makes interpolating values into strings with full access to Python's
lexical namespace semantics simpler, but it does so at the cost of introducing
yet another string interpolation syntax, and also creates a situation where
interpolating values into sensitive targets like SQL queries, shell commands
and HTML templates will enjoy a much cleaner syntax when handled without
regard for code injection attacks than when they are handled correctly.
lexical namespace semantics simpler, but it does so at the cost of creating a
situation where interpolating values into sensitive targets like SQL queries,
shell commands and HTML templates will enjoy a much cleaner syntax when handled
without regard for code injection attacks than when they are handled correctly.
It also has the effect of introducing yet another syntax for substitution
expressions into Python, when we already have 3 (``str.format``,
``bytes.__mod__`` and ``string.Template``)
This PEP proposes to handle the latter issue by always specifying an explicit
interpolator for interpolation operations, and the former by adopting the
@ -112,8 +114,8 @@ exactly as defined in PEP 498.
The specific proposal in this PEP is also deliberately close in both syntax
and semantics to the general purpose interpolation syntax introduced to
JavaScript in ES6, as we can reasonably expect a great many Python to be
regularly switching back and forth between user interface code written in
JavaScript in ES6, as we can reasonably expect a great many Python developers
to be regularly switching back and forth between user interface code written in
JavaScript and core application code written in Python.
@ -190,7 +192,7 @@ the parsed fields tuple would be::
('$jkl', None, None, None, None)
)
While the field values tupe would be::
While the field values tuple would be::
(expr1, expr2, expr3, ident)
@ -337,8 +339,8 @@ would delegate interpolation calls to ``string.Template``::
@interpolator
def i18n(template, fields, values):
translated = gettext.gettext(template)
values = _build_interpolation_map(fields, values)
return string.Template(translated).safe_substitute(values)
value_map = _build_interpolation_map(fields, values)
return string.Template(translated).safe_substitute(value_map)
def _build_interpolation_map(fields, values):
field_values = {}
@ -372,6 +374,24 @@ while preserving all of the expected braces::
interpolated = "{{{{ ${user} }}}} is running {{{{ appname }}}}"
Possible integration with the logging module
============================================
One of the challenges with the logging module has been that previously been
unable to devise a reasonable migration strategy away from the use of
printf-style formatting. The runtime parsing and interpolation overhead for
logging messages also poses a problem for extensive logging of runtime events
for monitoring purposes.
While beyond the scope of this initial PEP, the proposal described here could
potentially be applied to the logging module's event reporting APIs, permitting
relevant details to be captured using forms like::
!logging.debug "Event: $event; Details: $data"
!logging.critical "Error: $error; Details: $data"
Discussion
==========
@ -415,6 +435,23 @@ worth fixing it in for the customer interpolator API, since the tuple already
has other differences (like including both the field position number *and* the
text of the expression).
Using call syntax to support keyword-only parameters
----------------------------------------------------
The logging examples could potentially be better written as::
!logging.debug("Event: $event; Details: $data")
!logging.critical("Error: $error; Details: $data")
The key benefit this would provide is access to keyword arguments, so you
could write:
!logging.critical("Error: $error; Details: $data", exc_info=True)
In this version, an interpolation expression would largely be syntactically
equivalent to a normal function call, except that it would be restricted to
accepting a single string literal as its sole position argument.
References
==========