Guido van Rossum wrote: >>>>...but -- to answer your question -- the point here isn't really the >>>>'singleness' of the factory function, but the fact that it is >>>>type-independent, which (in principle) would allow it to be extended >>>>to handle arbitrary types by delegating some functionality to the >>>>types themselves. >>> >>>This is all a nice generalization, but I don't see that much use for >>>it. There's only a handful of types that are worth supporting here. So >>>the cost of the generalization isn't worth the benefits. >> >>I definitely disagree. A common case is a constrained type, where only >>a limited number of strings are allowed. Or an IP address, or domain >>name, or an internationalized boolean converter ("si" -> True), or a >>color specification, or a valid CSS class name, or... well, the list >>goes on forever. >> >>The advantage of putting this in the parser is that you could have >>better error messages when the values were malformed. If the parser >>doesn't do the conversion, you are likely to have lost the location >>information by the time you try to do the conversion. Good error >>messages are one of the primary visible features for people who use the >>configuration files. > > > Sure, I agree with all of that. But my original (optint, optstr, > optbool, optfloat) proposal can easily be extended the same way; in > fact it is in some sense easier than an API that expects a type > object. (Unless you have an adaptation framework in place; until we > have a general one, inventing one just for this purpose definitely > feels like overkill. OK. I guess you could subclass opt* to get a new type; I wasn't thinking of that. I shy away from subclassing, but it might be appropriate here. It makes it easier to hang different parameters onto the type as well, like not_empty (for strings), max, min, etc. It would even be easier to hang serialization onto it. I don't think adaptation fits well here, since adaptation seems to generally be context-insensitive, and this conversion process is done in the context of a specific type declaration. >>An additional complication, though; if you plan to make the >>configuration file writable, these types shouldn't just support >>converting from a string to a Python type, but the other direction -- so >>that ambiguous Python types (like a boolean; easily confused as an >>integer) can be converted in specific ways to a configuration string. I >>don't think __repr__ or __str__ of the value to be converted are >>necessarily appropriate. > > > Actually, repr() or str() probably *is* the right answer for this, > even if calling the constructor with a string argument isn't the > answer for parsing and validation. In my experience, this stops working as the types become more complex. For instance, consider a converter that takes a string that has comma-separated names and creates a list of strings; there is a specific way to convert back to that representation (','.join(value)), and both repr() and str() will be incorrect. Potentially you could create a list subclass that has the right repr(), but that seems prone to error. repr() only gives an estimated Python representation of an object -- it is neither reliable (since obj == eval(repr(obj)) isn't true for a large number of objects), nor is it appropriate, since we're trying to generate configuration expressions that are tightly bound to a context, not Python expressions. In the case of generating a config file, if the conversion isn't reliable or is ambiguous it should be an error (which doesn't happen with repr() or str()). -- Ian Bicking / ianb at colorstudy.com / http://blog.ianbicking.org
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