<br><br><div class="gmail_quote">On Thu, Mar 19, 2009 at 6:52 PM, Austin Schutz <span dir="ltr"><<a href="mailto:tex@off.org">tex@off.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
I have a fairly simple bit of code, something like:<br>
<br>
# This should be importing the subclasses somehow, so that the factory<br>
# can make them.<br>
# import Parser.One<br>
# import Parser.Two<br>
# or.. from Parser import *?<br>
class Parser():<br>
   def parse:<br>
        'Implemented only in subclass'<br>
<br>
   def make_parser(which_parser):<br>
       if(which_parser = 'one'):<br>
         return One()<br>
       else:<br>
          return Two()<br>
<br>
# import Parser?<br>
class One(Parser):<br>
   def parse:<br>
       'one implementation'<br>
<br>
class Two(Parser):<br>
   def parse:<br>
       'another implementation'<br>
<br>
The problem I have is that I don't understand how to put this into<br>
actual files in actual directories and have the interpreter do<br>
something actually useful :-) . What I would like to do is something<br>
like:<br>
<br>
lib/<br>
  Parser.py<br>
  Parser/<br>
      __init__.py (maybe?)<br>
      One.py<br>
      Two.py<br>
<br>
But I'm not clear on how to structure the import statements. I'm a bit<br>
of a newb wrt python, and I get any number of different errors depending<br>
on how I arrange the import statements, everything from<br>
<br>
AttributeError: 'module' object has no attribute 'make_parser'<br>
to<br>
ImportError: cannot import name<br>
to<br>
TypeError: Error when calling the metaclass bases<br>
<br>
depending on how I use import. Nothing seems to be the correct<br>
combination. Any help would be much appreciated!<br>
<br>
Austin<br>
<font color="#888888"><br>
</font></blockquote><div><br>This seems to be a good use for a metaclass, though it's tricky to work around the fact that the new class doesn't exist when the metaclass is called.To get around this, I have the metaclass add the new Parser to a "to-do" list.  The metaclass will be called whenever a subclass is created, so every class that subclasses parser will automatically be added. <br>
<br>BTW, don't create a class and a package with the same name. When you import Parser, python won't know whether you want Parser.py or Parser/__init__.py.<br><br>I'm not very good with metaclasses, so there might be a couple mistakes in here. Note that this won't work if you run this as the main script because then you end up with two copies of Parser<br>
(Parser.Parser and __main__.Parser).<br><br><br><br>class ParserMeta(type) : #the metaclass is called when the class is created<br>    def __new__(cls, *args) :<br>        #args = (name, bases, dict). dict has __module__ in it.<br>
        #we don't want to add the base class<br>        if args[0] != "Parser"  :<br>            Parser._not_loaded_parsers.append(args)<br>        return type.__new__(cls, *args) <br>    <br><br>#note that this is for Python 3.<br>
#for python 2.x do:<br>#class Parser(object) :<br>#    __metaclass__ = ParserMeta<br>class Parser(metaclass=ParserMeta) :<br>    _not_loaded_parsers = [] #the parsers that aren't loaded yet<br>    parsers = {} #the list of parsers- names mapped to the class.<br>
    def parse(self) :<br>        raise NotImplementedError<br><br>    @classmethod<br>    def load(cls) :<br>    """ This method will add the parsers to the dictionary if they aren't already in there"""<br>
        while cls._not_loaded_parsers :<br>            new_parser = cls._not_loaded_parsers.pop()<br>            mod = __import__(new_parser[2]['__module__'], fromlist=['*'])<br>            cls.parsers[new_parser[0]] = mod.__dict__[new_parser[0]]<br>
<br>    @classmethod<br>    def make_parser(cls, which_one) :<br>        """loads the parsers if necessary and returns the parsers"""<br>        cls.load()<br>        return cls.parsers[which_one]()<br>
<br><br>import modules-that-contain-other-parsers<br><br>Parser.load()<br><br> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><font color="#888888"><br>

<br>
<br>
<br>
--<br>
<a href="http://mail.python.org/mailman/listinfo/python-list" target="_blank">http://mail.python.org/mailman/listinfo/python-list</a><br>
</font></blockquote></div><br>