Guido van Rossum wrote: > > Paul, thanks for submitting a warnings framework. I'd like to give > some feedback, comparing it to my own proposal. Please also give > explicit feedback on mine! Okay, but I'm a little bit worried about getting into a science project -- in terms of my time to work on it. I'm perfectly happy with the two requirements you mentioned but I haven't thought enough about filters to be able to whip off ideas about them quickly. > What's missing here is a set of requirements. Comparing your proposal > to my requirements, I find that you are not addressing two > requirements that are important in my mind: a convenient and efficient > C API, and a mechanism that prints a warning message only the first > time that the warning is issued. I agree that these are both important things and I will add them to my proposal. Also, I like your requirement that the target for warnings should be easily customizable. > Warnings are more a human engineering issue than a technical issue! > That's also why I am emphasizing a C API -- I want to make it real > easy to ussue quality warnings in the runtime. It's also why I > specify a rich (probably too rich!) filtering mechanism. Let me put out the strawman proposal that "grep" is a nicely orthogonal filtering mechanism. <duck!> I guess my thinking is that you turn off warnings at the source. If you get a warning about __del__ exceptions then you put in a try/except. If you get a warning about an unused variable then you assign it to itself. If you get a warning about integer division then you should pass in a float and so forth. > > Syntax > > > > assert >> cls, test[[[, arg], arg]...] > > I have several problems with this. First of all, using "assert" means > that in "optimizing" mode (python -O) you won't get *any* warnings. I > think that the decision to disable all warnings should be independent > from the decision to "optimize". Arguable. I see it as "release" and "debug" configurations. python and python_d. > Second, you're hypergeneralizing the > extended print syntax. Just because I think it's okay to add >>file > to the print syntax doesn't mean that it's now okay to add >>object > syntax to all statements! Well getting new syntax into Python is really, really hard so we've got to squeeze out as much value out of what we have as possible. But anyhow, assertions are not allowed to You and I agree that there is an important sociological dimension to this. We can't require: import warnings warnings.warn("foo", "bar") I prefer: warn Foo, "Bar" just like: raise Foo, "Bar" > I also don't see what warnings have to do with assertions. Assertions > are a mechanism to check for error conditions. What happens if the > error is detected is of less importance -- it could raise an exception > (Python), issue a fatal error (C), or do nothing (in -O mode). Warnings are issued when an error or dubious construct is detected. Assertions are "fatal warnings". You agree that it is appropriate for some "warnings" to kill the app in some circumstances. Isn't it just a hop-skip-and-a-jump to say that warnings and errors are just points on the spectrum: Report Once Report Always Report and Die Python trained me to think of function calls and object constructions as being basically the same thing -- and keyword arguments and variable names being basically the same thing. etc. > With warnings I believe the issue is not so much the detection of the > condition (for which a regular 'if' statement does just fine) but the > reporting. Again, this is motivated by the fact that I expect that > flexible filtering is essential for a successful warning mechanism. I don't see why assertions need special syntax but warnings do not! I would have been happy for a "warn" keyword with assert-like syntax but I don't think I'll see that in my lifetime. > This is just a matter of exposition, but when I first read your PEP I > had a hard time figuring out the purpose of the cls object. It wasn't > until I got to the very end where I saw your example classes that I > realized what it is: it represents a specific warning condition or a > group of related warning conditions. It sort of evolved into an exception-like mechanism in that the class is instantiated with arguments just as exception classes are. > > if action=="error": > > *** existing assertion code *** > > That's just > > raise AssertionError, message > > Right? Well I'd like the traceback to emanate from the caller's position not the warning handler's position. Python doesn't really have a way to say that simply. This may well be implemented in C so it might not matter. > Suggestion: have separate warning and error handlers, so that if I > want to override these branches of the if statement I don't have to > repeat the entire handler. Good idea. > I see no definition of sys.disabled_warnings. Instead of > sys.disabled_warnings you meant sys.suppress, right? Right. > > return "suppress" > > for base in cls.__bases__: > > rc = self.get_user_request(base) > > if rc: > > return rc > > else: > > return None > > This approach (searching for the class name or the name of one of its > base classes in a list) doesn't look very object-oriented. It would > make more sense to store the desired return value as a class or > instance attribute. The default warning action could be stored on the > base class. The way I came to this odd structure is I wanted most subclasses to be just no-ops as many exceptions are: class ActiveStateLintWarning(Warning): pass class CodeLooksLikePerl(ActiveStateLintWarning): pass class TooMuchOnOneLine(CodeLooksLikePerl): pass So what __init__ could I write that would look up -wTooMuchOnOneLine and then if it failed that, look up -wCodeLooksLikePerl and so forth? It gets pretty mind-bending because you sort of want one method to call another and yet you want it to be the *same* inherited method (i.e. don't have to code it each time). E.g. you want to run the *same method* at each level of the hierarchy. So I just do that directly. > > -w XXX => sys.warnings.append("XXX") > > -e XXX => sys.errors.append("XXX") > > -no-w XXX => sys.suppress.append("XXX") > > -wall => sys.default_warning_action => "warn" > > -eall => sys.default_warning_action => "error" > > -no-wall => sys.default_warning_action => "suppress" > > Python doesn't support long options (I don't *like* long options so I > doubt that this is a good occasion to start lobbying for them :-). We > can come up with different options though. Are these long options? Or just overloaded behavior on -w, -e, -n . Think of "all" as the base class for warnings or something. > > As per the code above, errors take precedence over warnings and > > warnings over suppressions unless a particular assertion class > > specifies otherwise. > > I would use a different precedence scheme: a more specific filter > takes precedence over a more general filter. So -eall -wdubious would > mean that "dubious" class warnings are warnings but all others are > errors, and -wall -edubious would mean the opposite. Good idea. I think the code may work that way already. :) Paul Prescod
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4