diff --git a/pep-0501.txt b/pep-0501.txt index e5df21539..9d94d0640 100644 --- a/pep-0501.txt +++ b/pep-0501.txt @@ -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 ==========