We try to do the same thing in various libraries. We've settled on using 
existing python and end up with syntax like:

class MyForm(Form):
        field = Field()

or in your case

class Colors(TokenContainer):
        red = Token()
        green = Token()
        blue = Token()

(this is using tri.token).

The discussion on creating namespaces seem to match this type of usage more 
than what you've suggested here.

> On 20 Oct 2019, at 07:57, Steve Jorgensen <ste...@stevej.name> wrote:
> 
> Several requests for a specific use case. This is something I have been 
> working on just to practice getting a deeper understanding of Python 
> metaprogramming, so whether this is something that someone should be trying 
> to do is, of course, a matter of opinion.
> 
> The idea is to use a class as a singleton collection of choices where every 
> choice appears both as an attribute of the class/singleton and as a 
> value/label pair when treating it as a sequence.
> 
> Usage example:
> 
>    class Colors(Choices):
>        with choices():
>            RED
>            GREEN
>            BLUE
> 
>    Colors.RED -> 'Red'
>    Colors.GREEN -> 'Green'
>    Colors.BLUE -> 'Blue'
> 
>    tuple(Colors) -> (('RED', 'Red'), ('GREEN', 'Green'), ('BLUE', 'Blue'))
> 
> This can be implemented using a mapping object (classdict) returned from the 
> metaclass' `__prepare__` class method. The classdict is checked prior to 
> checking the surrounding context and takes priority unless its `__getitem__` 
> method raises `KeyError`.
> 
> The problem in this case is that the classdict generates results dynamically, 
> and it has no way of knowing whether a variable reference would have been 
> resolved in the surrounding context or not. Therefore, it will ALWAYS take 
> precedence, even masking builtins like `print`, `range`, etc. This is 
> surprising behavior and generally undesirable.
> 
> As I mentioned already, it is possible to work around the problem for 
> builtins by having the classdict object specifically test for those, but that 
> doesn't solve the problem of masking other variables from the surrounding 
> context. Masking those is also surprising behavior.
> 
> Steve Jorgensen wrote:
>> When using a custom classdict to implement a DSL or use in the body of a 
>> class
>> definition, from what I can tell by experiment, the classdict takes 
>> priority, and the
>> surrounding context is only referenced if trying to get an item from the 
>> classdict raises
>> KeyError.
>> There is at least one case in which I would like to do the reverse, and have 
>> the
>> classdict be secondary to (masked by) any variables defined in the context 
>> surrounding the
>> execution of the class body.
>> I have been able to at least unmask builtins by having the classdict object 
>> first try
>> to get a result from __builtins__ and then fall back to itself. Also, in the
>> actual class body, declaring a variable as global seems to be a workaround
>> for global variables, but that has to be done explicitly in the body of any 
>> subclass that
>> needs it. Also, that does not handle non-globals in its surrounding context.
>> I'm not sure what the best way to deal with this would be, but my first 
>> thought is to
>> maybe have a property that can be set on the metaclass type such as
>> `metacls.reluctant_classdict = True` [typo corrected from original post].
> _______________________________________________
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at 
> https://mail.python.org/archives/list/python-ideas@python.org/message/HATKS2TRWGA2XLDKEGMBSEO7FLLTLQKJ/
> Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/THU7JPWX5L7FEZPRDKSZJZGZJSKEKXVP/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to