On 12/18/2013 10:02 AM, Peter Otten wrote:
spir wrote:
[...]
Like Steven I have no idea how you produced the mappingproxy. Are you trying
to use a class as a namespace (in Python 3.3)?

class A: pass
...
A.__dict__["foo"] = "bar"
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
TypeError: 'mappingproxy' object does not support item assignment

I have no idea neither, for me it's just a term in an error message. Here is a minimal reduction of the context, that produces similar outcome (py 3.3):
EDIT: you are right about class dicts, see below.

def set_var(scope, id, value):
    scope[id] = value

set_var(locals(), "foo", 'FOO')
assert(foo == 'FOO')            # OK

bar = 'bar'
set_var(globals(), "bar", 'BAR')
assert(bar == 'BAR')            # OK

class C:
    pass

set_var(C.__dict__, "baz", 'BAZ')
# ==> TypeError: 'mappingproxy' object does not support item assignment
assert(C.baz == 'BAZ')          # statement never reached

C.baz = "trial to define symbol first"
set_var(C.__dict__, "baz", 'BAZ')
# ==> TypeError: 'mappingproxy' object does not support item assignment
assert(C.baz == 'BAZ')          # statement never reached

It is effectively the case that I like to use classes as namespaces (to define grammars / parsers): they are highly practicle, one can even have computation in their def! They're kind of sub-modules, in fact; free scopes. So, it was actually so that the error happened in such a case; and thus "mappingproxy" seems to be an implementation term for a class's dict, or so.

This does explain why we cannot modify them (as we can do it in plain python code, but symbol names must be constant). But I have no solution for my issue: there is no way to write:
        c.id = value
with id beeing a variable. Or is there? As fat as I know I really need to do
        c.__dict__[id_var] = value

EDIT: works!!!

I tried
    C.__setattr__(C, "baz", "BAZ")
which fails, for any reason, with
    TypeError: can't apply this __setattr__ to type object

But the direct way works fine, for any reason:
    setattr(C, "baz", "BAZ")

Thus we can modify set_var like eg:

def set_var(scope, id, value):
    if isinstance(scope, type):
        setattr(scope, id, value)
    else:
        scope[id] = value

Which then enables:

class C:
    pass
set_var(C, "baz", 'BAZ')
assert(C.baz == 'BAZ')          # OK

=======================
For the record, here in (the code of) my final tool func:

    def name (scope):               # name all defined pattern in given scope
        # Note: if scope is a class, there is a distinction between the scope
        # and the actual dict we traverse (c.__dict__): for any reason, we
        # cannot set entries in a class's dict directly, but must use setattr.
        dic = scope.__dict__ if isinstance(scope, type) else scope

        # all patterns in scope (in dic, in fact):
        names_pats = ((name, pat) for (name, pat) in dic.items() \
            if isinstance(pat, Pattern))

        for (name, pat) in names_pats:
            # If the original pat is already named, leave it as is and
            # instead create a copy with the new name:
            if pat.name:
                new_pat = copy(pat)
                new_pat.name = name             # give it its name
                if isinstance(scope, type):     # case scope is a class
                    setattr(scope, name, new_pat)
                else:                   # case scope is module or local
                    scope[name] = new_pat
            # Else, this is a new pattern, which just demands a name:
            else:
                pat.name = name

            # Special case of recursive pattern,
            # also name its actual matching pattern:
            if isinstance(pat, Recurs):
                pat.pattern.name = name

Issue solved ;-). Thank you vey much,
Denis
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to