diff --git a/pep-0230.txt b/pep-0230.txt index 7417e0d32b4..c528011e5bb 100644 --- a/pep-0230.txt +++ b/pep-0230.txt @@ -5,399 +5,413 @@ Last-Modified: $Date$ Author: guido@python.org (Guido van Rossum) Status: Final Type: Standards Track +Content-Type: text/x-rst Created: Python-Version: 2.1 Post-History: 05-Nov-2000 Abstract +======== - This PEP proposes a C and Python level API, as well as command - line flags, to issue warning messages and control what happens to - them. This is mostly based on GvR's proposal posted to python-dev - on 05-Nov-2000, with some ideas (such as using classes to - categorize warnings) merged in from Paul Prescod's - counter-proposal posted on the same date. Also, an attempt to - implement the proposal caused several small tweaks. +This PEP proposes a C and Python level API, as well as command +line flags, to issue warning messages and control what happens to +them. This is mostly based on GvR's proposal posted to python-dev +on 05-Nov-2000, with some ideas (such as using classes to +categorize warnings) merged in from Paul Prescod's +counter-proposal posted on the same date. Also, an attempt to +implement the proposal caused several small tweaks. Motivation +========== - With Python 3000 looming, it is necessary to start issuing - warnings about the use of obsolete or deprecated features, in - addition to errors. There are also lots of other reasons to be - able to issue warnings, both from C and from Python code, both at - compile time and at run time. +With Python 3000 looming, it is necessary to start issuing +warnings about the use of obsolete or deprecated features, in +addition to errors. There are also lots of other reasons to be +able to issue warnings, both from C and from Python code, both at +compile time and at run time. - Warnings aren't fatal, and thus it's possible that a program - triggers the same warning many times during a single execution. - It would be annoying if a program emitted an endless stream of - identical warnings. Therefore, a mechanism is needed that - suppresses multiple identical warnings. +Warnings aren't fatal, and thus it's possible that a program +triggers the same warning many times during a single execution. +It would be annoying if a program emitted an endless stream of +identical warnings. Therefore, a mechanism is needed that +suppresses multiple identical warnings. - It is also desirable to have user control over which warnings are - printed. While in general it is useful to see all warnings all - the time, there may be times where it is impractical to fix the - code right away in a production program. In this case, there - should be a way to suppress warnings. +It is also desirable to have user control over which warnings are +printed. While in general it is useful to see all warnings all +the time, there may be times where it is impractical to fix the +code right away in a production program. In this case, there +should be a way to suppress warnings. - It is also useful to be able to suppress specific warnings during - program development, e.g. when a warning is generated by a piece - of 3rd party code that cannot be fixed right away, or when there - is no way to fix the code (possibly a warning message is generated - for a perfectly fine piece of code). It would be unwise to offer - to suppress all warnings in such cases: the developer would miss - warnings about the rest of the code. +It is also useful to be able to suppress specific warnings during +program development, e.g. when a warning is generated by a piece +of 3rd party code that cannot be fixed right away, or when there +is no way to fix the code (possibly a warning message is generated +for a perfectly fine piece of code). It would be unwise to offer +to suppress all warnings in such cases: the developer would miss +warnings about the rest of the code. - On the other hand, there are also situations conceivable where - some or all warnings are better treated as errors. For example, - it may be a local coding standard that a particular deprecated - feature should not be used. In order to enforce this, it is - useful to be able to turn the warning about this particular - feature into an error, raising an exception (without necessarily - turning all warnings into errors). +On the other hand, there are also situations conceivable where +some or all warnings are better treated as errors. For example, +it may be a local coding standard that a particular deprecated +feature should not be used. In order to enforce this, it is +useful to be able to turn the warning about this particular +feature into an error, raising an exception (without necessarily +turning all warnings into errors). - Therefore, I propose to introduce a flexible "warning filter" - which can filter out warnings or change them into exceptions, - based on: +Therefore, I propose to introduce a flexible "warning filter" +which can filter out warnings or change them into exceptions, +based on: - - Where in the code they are generated (per package, module, or - function) +- Where in the code they are generated (per package, module, or + function) - - The warning category (warning categories are discussed below) +- The warning category (warning categories are discussed below) - - A specific warning message +- A specific warning message - The warning filter must be controllable both from the command line - and from Python code. +The warning filter must be controllable both from the command line +and from Python code. APIs For Issuing Warnings +========================= - - To issue a warning from Python: +- To issue a warning from Python:: - import warnings - warnings.warn(message[, category[, stacklevel]]) + import warnings + warnings.warn(message[, category[, stacklevel]]) - The category argument, if given, must be a warning category - class (see below); it defaults to warnings.UserWarning. This - may raise an exception if the particular warning issued is - changed into an error by the warnings filter. The stacklevel - can be used by wrapper functions written in Python, like this: + The category argument, if given, must be a warning category + class (see below); it defaults to warnings.UserWarning. This + may raise an exception if the particular warning issued is + changed into an error by the warnings filter. The stacklevel + can be used by wrapper functions written in Python, like this:: def deprecation(message): warn(message, DeprecationWarning, level=2) - This makes the warning refer to the deprecation()'s caller, - rather than to the source of deprecation() itself (since the - latter would defeat the purpose of the warning message). + This makes the warning refer to the deprecation()'s caller, + rather than to the source of deprecation() itself (since the + latter would defeat the purpose of the warning message). - - To issue a warning from C: +- To issue a warning from C:: - int PyErr_Warn(PyObject *category, char *message); + int PyErr_Warn(PyObject *category, char *message); - Return 0 normally, 1 if an exception is raised (either because - the warning was transformed into an exception, or because of a - malfunction in the implementation, such as running out of - memory). The category argument must be a warning category class - (see below) or NULL, in which case it defaults to - PyExc_RuntimeWarning. When PyErr_Warn() function returns 1, the - caller should do normal exception handling. + Return 0 normally, 1 if an exception is raised (either because + the warning was transformed into an exception, or because of a + malfunction in the implementation, such as running out of + memory). The category argument must be a warning category class + (see below) or ``NULL``, in which case it defaults to + ``PyExc_RuntimeWarning``. When ``PyErr_Warn()`` function returns 1, the + caller should do normal exception handling. - The current C implementation of PyErr_Warn() imports the - warnings module (implemented in Python) and calls its warn() - function. This minimizes the amount of C code that needs to be - added to implement the warning feature. + The current C implementation of ``PyErr_Warn()`` imports the + warnings module (implemented in Python) and calls its ``warn()`` + function. This minimizes the amount of C code that needs to be + added to implement the warning feature. - [XXX Open Issue: what about issuing warnings during lexing or - parsing, which don't have the exception machinery available?] + [XXX Open Issue: what about issuing warnings during lexing or + parsing, which don't have the exception machinery available?] Warnings Categories +=================== - There are a number of built-in exceptions that represent warning - categories. This categorization is useful to be able to filter - out groups of warnings. The following warnings category classes - are currently defined: +There are a number of built-in exceptions that represent warning +categories. This categorization is useful to be able to filter +out groups of warnings. The following warnings category classes +are currently defined: - - Warning -- this is the base class of all warning category - classes and it itself a subclass of Exception +- ``Warning`` -- this is the base class of all warning category + classes and it itself a subclass of Exception - - UserWarning -- the default category for warnings.warn() +- ``UserWarning`` -- the default category for ``warnings.warn()`` - - DeprecationWarning -- base category for warnings about deprecated - features +- ``DeprecationWarning`` -- base category for warnings about deprecated + features - - SyntaxWarning -- base category for warnings about dubious - syntactic features +- ``SyntaxWarning`` -- base category for warnings about dubious + syntactic features - - RuntimeWarning -- base category for warnings about dubious - runtime features +- ``RuntimeWarning`` -- base category for warnings about dubious + runtime features - [XXX: Other warning categories may be proposed during the review - period for this PEP.] +[XXX: Other warning categories may be proposed during the review +period for this PEP.] - These standard warning categories are available from C as - PyExc_Warning, PyExc_UserWarning, etc. From Python, they are - available in the __builtin__ module, so no import is necessary. +These standard warning categories are available from C as +``PyExc_Warning``, ``PyExc_UserWarning``, etc. From Python, they are +available in the ``__builtin__`` module, so no import is necessary. - User code can define additional warning categories by subclassing - one of the standard warning categories. A warning category must - always be a subclass of the Warning class. +User code can define additional warning categories by subclassing +one of the standard warning categories. A warning category must +always be a subclass of the Warning class. The Warnings Filter +=================== - The warnings filter control whether warnings are ignored, - displayed, or turned into errors (raising an exception). +The warnings filter control whether warnings are ignored, +displayed, or turned into errors (raising an exception). - There are three sides to the warnings filter: +There are three sides to the warnings filter: - - The data structures used to efficiently determine the - disposition of a particular warnings.warn() or PyErr_Warn() - call. +- The data structures used to efficiently determine the + disposition of a particular ``warnings.warn()`` or ``PyErr_Warn()`` + call. - - The API to control the filter from Python source code. +- The API to control the filter from Python source code. - - The command line switches to control the filter. +- The command line switches to control the filter. - The warnings filter works in several stages. It is optimized for - the (expected to be common) case where the same warning is issued - from the same place in the code over and over. +The warnings filter works in several stages. It is optimized for +the (expected to be common) case where the same warning is issued +from the same place in the code over and over. - First, the warning filter collects the module and line number - where the warning is issued; this information is readily available - through sys._getframe(). +First, the warning filter collects the module and line number +where the warning is issued; this information is readily available +through ``sys._getframe()``. - Conceptually, the warnings filter maintains an ordered list of - filter specifications; any specific warning is matched against - each filter specification in the list in turn until a match is - found; the match determines the disposition of the match. Each - entry is a tuple as follows: +Conceptually, the warnings filter maintains an ordered list of +filter specifications; any specific warning is matched against +each filter specification in the list in turn until a match is +found; the match determines the disposition of the match. Each +entry is a tuple as follows:: - (category, message, module, lineno, action) + (category, message, module, lineno, action) - - category is a class (a subclass of warnings.Warning) of which - the warning category must be a subclass in order to match +- category is a class (a subclass of ``warnings.Warning``) of which + the warning category must be a subclass in order to match - - message is a compiled regular expression that the warning - message must match (the match is case-insensitive) +- message is a compiled regular expression that the warning + message must match (the match is case-insensitive) - - module is a compiled regular expression that the module name - must match +- module is a compiled regular expression that the module name + must match - - lineno is an integer that the line number where the warning - occurred must match, or 0 to match all line numbers +- lineno is an integer that the line number where the warning + occurred must match, or 0 to match all line numbers - - action is one of the following strings: +- action is one of the following strings: - - "error" -- turn matching warnings into exceptions + - "error" -- turn matching warnings into exceptions - - "ignore" -- never print matching warnings + - "ignore" -- never print matching warnings - - "always" -- always print matching warnings + - "always" -- always print matching warnings - - "default" -- print the first occurrence of matching warnings - for each location where the warning is issued + - "default" -- print the first occurrence of matching warnings + for each location where the warning is issued - - "module" -- print the first occurrence of matching warnings - for each module where the warning is issued + - "module" -- print the first occurrence of matching warnings + for each module where the warning is issued - - "once" -- print only the first occurrence of matching - warnings + - "once" -- print only the first occurrence of matching + warnings - Since the Warning class is derived from the built-in Exception - class, to turn a warning into an error we simply raise - category(message). +Since the ``Warning`` class is derived from the built-in ``Exception`` +class, to turn a warning into an error we simply raise +``category(message)``. Warnings Output And Formatting Hooks +==================================== - When the warnings filter decides to issue a warning (but not when - it decides to raise an exception), it passes the information about - the function warnings.showwarning(message, category, filename, lineno). - The default implementation of this function writes the warning text - to sys.stderr, and shows the source line of the filename. It has - an optional 5th argument which can be used to specify a different - file than sys.stderr. +When the warnings filter decides to issue a warning (but not when +it decides to raise an exception), it passes the information about +the function ``warnings.showwarning(message, category, filename, lineno)``. +The default implementation of this function writes the warning text +to ``sys.stderr``, and shows the source line of the filename. It has +an optional 5th argument which can be used to specify a different +file than ``sys.stderr``. - The formatting of warnings is done by a separate function, - warnings.formatwarning(message, category, filename, lineno). This - returns a string (that may contain newlines and ends in a newline) - that can be printed to get the identical effect of the - showwarning() function. +The formatting of warnings is done by a separate function, +``warnings.formatwarning(message, category, filename, lineno)``. This +returns a string (that may contain newlines and ends in a newline) +that can be printed to get the identical effect of the +``showwarning()`` function. API For Manipulating Warning Filters +==================================== +:: - warnings.filterwarnings(message, category, module, lineno, action) + warnings.filterwarnings(message, category, module, lineno, action) - This checks the types of the arguments, compiles the message and - module regular expressions, and inserts them as a tuple in front - of the warnings filter. +This checks the types of the arguments, compiles the message and +module regular expressions, and inserts them as a tuple in front +of the warnings filter. - warnings.resetwarnings() +:: - Reset the warnings filter to empty. + warnings.resetwarnings() + +Reset the warnings filter to empty. Command Line Syntax +=================== - There should be command line options to specify the most common - filtering actions, which I expect to include at least: +There should be command line options to specify the most common +filtering actions, which I expect to include at least: - - suppress all warnings +- suppress all warnings - - suppress a particular warning message everywhere +- suppress a particular warning message everywhere - - suppress all warnings in a particular module +- suppress all warnings in a particular module - - turn all warnings into exceptions +- turn all warnings into exceptions - I propose the following command line option syntax: +I propose the following command line option syntax:: -Waction[:message[:category[:module[:lineno]]]] - Where: +Where: - - 'action' is an abbreviation of one of the allowed actions - ("error", "default", "ignore", "always", "once", or "module") +- 'action' is an abbreviation of one of the allowed actions + ("error", "default", "ignore", "always", "once", or "module") - - 'message' is a message string; matches warnings whose message - text is an initial substring of 'message' (matching is - case-insensitive) +- 'message' is a message string; matches warnings whose message + text is an initial substring of 'message' (matching is + case-insensitive) - - 'category' is an abbreviation of a standard warning category - class name *or* a fully-qualified name for a user-defined - warning category class of the form [package.]module.classname +- 'category' is an abbreviation of a standard warning category + class name **or** a fully-qualified name for a user-defined + warning category class of the form [package.]module.classname - - 'module' is a module name (possibly package.module) +- 'module' is a module name (possibly package.module) - - 'lineno' is an integral line number +- 'lineno' is an integral line number - All parts except 'action' may be omitted, where an empty value - after stripping whitespace is the same as an omitted value. +All parts except 'action' may be omitted, where an empty value +after stripping whitespace is the same as an omitted value. - The C code that parses the Python command line saves the body of - all -W options in a list of strings, which is made available to - the warnings module as sys.warnoptions. The warnings module - parses these when it is first imported. Errors detected during - the parsing of sys.warnoptions are not fatal; a message is written - to sys.stderr and processing continues with the option. +The C code that parses the Python command line saves the body of +all -W options in a list of strings, which is made available to +the warnings module as sys.warnoptions. The warnings module +parses these when it is first imported. Errors detected during +the parsing of sys.warnoptions are not fatal; a message is written +to sys.stderr and processing continues with the option. - Examples: +Examples: - -Werror - Turn all warnings into errors +``-Werror`` + Turn all warnings into errors - -Wall - Show all warnings +``-Wall`` + Show all warnings - -Wignore - Ignore all warnings +``-Wignore`` + Ignore all warnings - -Wi:hello - Ignore warnings whose message text starts with "hello" +``-Wi:hello`` + Ignore warnings whose message text starts with "hello" - -We::Deprecation - Turn deprecation warnings into errors +``-We::Deprecation`` + Turn deprecation warnings into errors - -Wi:::spam:10 - Ignore all warnings on line 10 of module spam +``-Wi:::spam:10`` + Ignore all warnings on line 10 of module spam - -Wi:::spam -Wd:::spam:10 - Ignore all warnings in module spam except on line 10 +``-Wi:::spam -Wd:::spam:10`` + Ignore all warnings in module spam except on line 10 - -We::Deprecation -Wd::Deprecation:spam - Turn deprecation warnings into errors except in module spam +``-We::Deprecation -Wd::Deprecation:spam`` + Turn deprecation warnings into errors except in module spam Open Issues +=========== - Some open issues off the top of my head: +Some open issues off the top of my head: - - What about issuing warnings during lexing or parsing, which - don't have the exception machinery available? +- What about issuing warnings during lexing or parsing, which + don't have the exception machinery available? - - The proposed command line syntax is a bit ugly (although the - simple cases aren't so bad: -Werror, -Wignore, etc.). Anybody - got a better idea? +- The proposed command line syntax is a bit ugly (although the + simple cases aren't so bad: ``-Werror``, ``-Wignore``, etc.). Anybody + got a better idea? - - I'm a bit worried that the filter specifications are too - complex. Perhaps filtering only on category and module (not on - message text and line number) would be enough? +- I'm a bit worried that the filter specifications are too + complex. Perhaps filtering only on category and module (not on + message text and line number) would be enough? - - There's a bit of confusion between module names and file names. - The reporting uses file names, but the filter specification uses - module names. Maybe it should allow filenames as well? +- There's a bit of confusion between module names and file names. + The reporting uses file names, but the filter specification uses + module names. Maybe it should allow filenames as well? - - I'm not at all convinced that packages are handled right. +- I'm not at all convinced that packages are handled right. - - Do we need more standard warning categories? Fewer? +- Do we need more standard warning categories? Fewer? - - In order to minimize the start-up overhead, the warnings module - is imported by the first call to PyErr_Warn(). It does the - command line parsing for -W options upon import. Therefore, it - is possible that warning-free programs will not complain about - invalid -W options. +- In order to minimize the start-up overhead, the warnings module + is imported by the first call to ``PyErr_Warn()``. It does the + command line parsing for ``-W`` options upon import. Therefore, it + is possible that warning-free programs will not complain about + invalid ``-W`` options. Rejected Concerns +================= - Paul Prescod, Barry Warsaw and Fred Drake have brought up several - additional concerns that I feel aren't critical. I address them - here (the concerns are paraphrased, not exactly their words): +Paul Prescod, Barry Warsaw and Fred Drake have brought up several +additional concerns that I feel aren't critical. I address them +here (the concerns are paraphrased, not exactly their words): - - Paul: warn() should be a built-in or a statement to make it easily - available. +- Paul: ``warn()`` should be a built-in or a statement to make it easily + available. - Response: "from warnings import warn" is easy enough. + Response: "from warnings import warn" is easy enough. - - Paul: What if I have a speed-critical module that triggers - warnings in an inner loop. It should be possible to disable the - overhead for detecting the warning (not just suppress the - warning). +- Paul: What if I have a speed-critical module that triggers + warnings in an inner loop. It should be possible to disable the + overhead for detecting the warning (not just suppress the + warning). - Response: rewrite the inner loop to avoid triggering the - warning. + Response: rewrite the inner loop to avoid triggering the + warning. - - Paul: What if I want to see the full context of a warning? +- Paul: What if I want to see the full context of a warning? - Response: use -Werror to turn it into an exception. + Response: use ``-Werror`` to turn it into an exception. - - Paul: I prefer ":*:*:" to ":::" for leaving parts of the warning - spec out. +- Paul: I prefer ":\*:\*:" to ":::" for leaving parts of the warning + spec out. - Response: I don't. + Response: I don't. - - Barry: It would be nice if lineno can be a range specification. +- Barry: It would be nice if lineno can be a range specification. - Response: Too much complexity already. + Response: Too much complexity already. - - Barry: I'd like to add my own warning action. Maybe if `action' - could be a callable as well as a string. Then in my IDE, I - could set that to "mygui.popupWarningsDialog". +- Barry: I'd like to add my own warning action. Maybe if 'action' + could be a callable as well as a string. Then in my IDE, I + could set that to "mygui.popupWarningsDialog". - Response: For that purpose you would override - warnings.showwarning(). + Response: For that purpose you would override + ``warnings.showwarning()``. - - Fred: why do the Warning category classes have to be in - __builtin__? +- Fred: why do the Warning category classes have to be in + ``__builtin__``? - Response: that's the simplest implementation, given that the - warning categories must be available in C before the first - PyErr_Warn() call, which imports the warnings module. I see no - problem with making them available as built-ins. + Response: that's the simplest implementation, given that the + warning categories must be available in C before the first + ``PyErr_Warn()`` call, which imports the warnings module. I see no + problem with making them available as built-ins. Implementation +============== - Here's a prototype implementation: - - http://sourceforge.net/patch/?func=detailpatch&patch_id=102715&group_id=5470 +Here's a prototype implementation: +http://sourceforge.net/patch/?func=detailpatch&patch_id=102715&group_id=5470 - -Local Variables: -mode: indented-text -indent-tabs-mode: nil -End: +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + End: