Custom format() proposal redux

The original proposal was well-received but it didn't make provisions to handle str.format(). Here is the revised proposal. Only the last paragraph is new. Raymond ------------------------------------------------------------------- Mark Dickinson's decimal test code suggested a good, extensible approach to the problem. Here's the idea in a nutshell: format(value, format_spec='', conventions=None) 'calls value.__format__(format_spec, conventions)' Where conventions is an optional dictionary with formatting control values. Any value object can accept custom controls, but the names for standard ones would be taken from the standards provided by localeconv(): { 'decimal_point': '.', 'grouping': [3, 0], 'negative_sign': '-', 'positive_sign': '', 'thousands_sep': ','} The would let you store several locales using localeconv() and use them at will, thus solving the global variable and threading problems with locale: import locale loc = locale.getlocale() # get current locale locale.setlocale(locale.LC_ALL, 'de_DE') DE = locale.localeconv() locale.setlocale(locale.LC_ALL, 'en_US') US = locale.localeconv() locale.setlocale(locale.LC_ALL, loc) # restore saved locale . . . format(x, '8,.f', DE) format(y, '8,d', US) It also lets you write your own conventions on the fly: DEBUG = dict(thousands_sep='_') # style for debugging EXTERN = dict(thousands_sep=',') # style for external display . . . format(x, '8.1f', DEBUG) format(y, '8d', EXTERN) The dictionaries can be registered for use with the mini-formatting language: locale.setlocale(locale.LC_ALL, 'en_US') str.format.register(US=locale.localeconv()) str.format.register(HY=dict(thousands_sep='-')) . . . 'Nigerian President will forward {0:,d!US} to your account'.format(10000000) format(y, ',d!HY') format(z, ',d!US')

My general thought is that I like the mechanism Mark uses to get the parameters into the __format__ function (the conventions dict). I'm just not sure where it needs to be specified in order to get the data into __format__.
I'm not sure you want to use the word "register", as we might want to register other things in the future. Maybe "register_convention"? I realize it's a little long. Also, I don't like the **kwargs functionality here, why not specify it as 2 parameters? str.format.register_convention('HY', dict(thousands_sep='-'))
What happens if both a "conventions" parameter and a "!<registered-convention>" specifier are present? An error? Does one win? Are they merged? What happens if you specify a convention that's not registered? I'm not sure I like using the "!<registered-convention>" syntax. I think it means you couldn't have both a "!s" or "!r" and a "!<convention>" in the same format string, unless we allow "!s!HY". OTOH, "!s" and "!r" always yield strings, and I can't see how strings would need a convention, since they don't really do much formatting. But I haven't given that part much thought, and I don't have a counter-proposal. Using "!" also means we should probably require that conventions not be named "s" or "r", and we might want to reserve all single character lower case strings. A larger concern is libraries. If I'm a library author, there's no way I can know what conventions the application has registered. And even if I could inspect them, I'm not sure what I'd do with the knowledge. I either would have to register my own private conventions (like "libraryname.HY"), or we'd need to agree on conventions we're expecting to be available and what they mean. What are your thoughts on what a library author should do? Eric.

My general thought is that I like the mechanism Mark uses to get the parameters into the __format__ function (the conventions dict). I'm just not sure where it needs to be specified in order to get the data into __format__.
I'm not sure you want to use the word "register", as we might want to register other things in the future. Maybe "register_convention"? I realize it's a little long. Also, I don't like the **kwargs functionality here, why not specify it as 2 parameters? str.format.register_convention('HY', dict(thousands_sep='-'))
What happens if both a "conventions" parameter and a "!<registered-convention>" specifier are present? An error? Does one win? Are they merged? What happens if you specify a convention that's not registered? I'm not sure I like using the "!<registered-convention>" syntax. I think it means you couldn't have both a "!s" or "!r" and a "!<convention>" in the same format string, unless we allow "!s!HY". OTOH, "!s" and "!r" always yield strings, and I can't see how strings would need a convention, since they don't really do much formatting. But I haven't given that part much thought, and I don't have a counter-proposal. Using "!" also means we should probably require that conventions not be named "s" or "r", and we might want to reserve all single character lower case strings. A larger concern is libraries. If I'm a library author, there's no way I can know what conventions the application has registered. And even if I could inspect them, I'm not sure what I'd do with the knowledge. I either would have to register my own private conventions (like "libraryname.HY"), or we'd need to agree on conventions we're expecting to be available and what they mean. What are your thoughts on what a library author should do? Eric.
participants (2)
-
Eric Smith
-
Raymond Hettinger