namespace/dictionary quandry

Peter Otten __peter__ at web.de
Wed Sep 22 20:48:13 CEST 2004


Jack Carter wrote:

>> class WeirdNamespace:
>>     def __init__(self, d): self.d = d
>>     def __getitem__(self, n): return self.d.get(n,repr(n))
> 
> So, how and or where does this fit in with my example?
> Does both the call to the function where I want to do
> the eval() and self.push(line) command have to be in the
> same namespace and or file for this to work?

I use a slight variation of Alex' suggestion:

class Locals(dict):
    def __getitem__(self, name):
        try:
            return dict.__getitem__(self, name)
        except KeyError:
            return name
 
class CLI(code.InteractiveConsole):
    """Simple test of a Python interpreter augmented with custom
commands."""

    commands = { \
        "attach" : "DoAttach"
        }

    def __init__(self, locals = None):

        # Call super-class initializer
        code.InteractiveConsole.__init__(self, locals, "<console>")
        self.locals = Locals(self.locals)

        # Compile regular expression for finding commmands
        self.regexp = re.compile('[a-z]*')

[The rest of the code is the same as in my previous post] 

Now try it:

>>> for name in "abc":
fed to the snake: for name in "abc":
...     attach name
fed to the snake:       myparse.DoAttach([name])
...     attach noname
fed to the snake:       myparse.DoAttach([noname])
...
fed to the snake:
DoAttach: ['a']
DoAttach: ['noname']
DoAttach: ['b']
DoAttach: ['noname']
DoAttach: ['c']
DoAttach: ['noname']

Unfortunately this will only work with Python 2.4.

Here's a solution that might work for 2.3:

[Does not require the above modifications]

    def process(self, line):
        indent = line.lstrip()
        # Attempt to match line against our command regular expression

        temp_line = string.lstrip(line)
        len_1 = len(line)
        len_2 = len(temp_line)

        white_spaces = len_1-len_2
        if white_spaces:
            front_padding = line[0:white_spaces]

        match = self.regexp.match(temp_line)
        if match is not None:

            #self.write("process 1\n")
            # Extract the command and argument strings
            cmd_string = match.group()
            arg_string = string.lstrip(temp_line[match.end():])

            # Find the function for this command in the command dictionary
            function = self.commands.get(cmd_string)

            if function is not None:

                args = parseArgs(arg_string)
                for arg in args:
                    if arg not in self.locals:
                        self.locals[arg] = arg
                line = makePythonCall("myparse." + function, args)
                if white_spaces:
                    line = front_padding + line
        print "fed to the snake:", line

        # Return the line to be processed by Python
        return line

I just ensure that all arguments not already in self.locals are added with
their name as their value. (I also renamed 'parent' to 'self' - I could not
stand it any longer :-)

Note that I don't particularly like both hacks and would rather use plain
old python functions with standard python syntax instead of your custom
language.


Peter







More information about the Python-list mailing list