Partial classes

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Sanjay

    Partial classes

    Hi All,

    Not being able to figure out how are partial classes coded in Python.

    Example: Suppose I have a code generator which generates part of a
    business class, where as the custome part is to be written by me. In
    ruby (or C#), I divide the code into two source files. Like this:

    GeneratedPerson .rb
    Class Person
  • alex23

    #2
    Re: Partial classes

    Sanjay wrote:
    Not being able to figure out how are partial classes coded in Python.
    Hi Sanjay,

    To the best of my knowledge, Python currently has no support for
    partial classes.

    However, BOO (http://boo.codehaus.org/) - which is a Python-like
    language for the .NET CLI)- _does_ support partial classes
    (http://jira.codehaus.org/browse/BOO-224). While it _isn't_ Python,
    there could be enough similarities to make this worthwhile for you if
    you absolutely have to have partial classes.

    (Disclaimer: I've never used BOO)

    Hope this helps.

    -alex23

    Comment

    • Kay Schluehr

      #3
      Re: Partial classes


      Sanjay wrote:
      Hi All,
      >
      Not being able to figure out how are partial classes coded in Python.
      >
      Example: Suppose I have a code generator which generates part of a
      business class, where as the custome part is to be written by me. In
      ruby (or C#), I divide the code into two source files. Like this:
      >
      GeneratedPerson .rb
      Class Person
      .
      .
      .
      >
      End Class
      >
      HandcraftedPers on.rb
      Class Person
      .
      .
      .
      End Class
      >
      The intrepretor adds the code in both to compose the class Person.
      >
      What is the equivalent in Python? Inheriting is a way, but is not
      working in all scenerios.
      >
      Thanks
      Sanjay
      Python has no notion of a partial class because it is a pure compile
      time construct. You might merge different class definitions by means of
      a meta class that puts everything together but whether or not certain
      methods in the merged class are available depends on which modules are
      imported. This might give rise to a "virtual" or runtime module. It is
      not a module that refers to a physical file on the disc but is a pure
      runtime construct. When creating this module all physical modules that
      define class fragments might be put together by means of the metaclass
      mechanism. I indeed used this construction to unify different access
      points before I reimplemented it using partial classes in C# which are
      very fine IMO.

      Comment

      • Sanjay

        #4
        Re: Partial classes

        Hi Alex,

        Thanks for the input.

        Being new to Python, and after having selected Python in comparison to
        ruby (Turbogears vs Rails) , is jerks me a bit. In my openion it should
        be an obvious and easy to implement feature and must be, if not already
        have been, planned in future releases of Python.

        Would love to listen to others.

        Sanjay

        Comment

        • Marc 'BlackJack' Rintsch

          #5
          Re: Partial classes

          In <1153292410.476 691.218950@i3g2 000cwc.googlegr oups.com>, Sanjay wrote:
          Being new to Python, and after having selected Python in comparison to
          ruby (Turbogears vs Rails) , is jerks me a bit. In my openion it should
          be an obvious and easy to implement feature and must be, if not already
          have been, planned in future releases of Python.
          Can you flesh out your use case a little bit and tell why you can't solve
          the problem with inheritance or a meta class?

          Ciao,
          Marc 'BlackJack' Rintsch

          Comment

          • Dave Benjamin

            #6
            Re: Partial classes

            On Wed, 18 Jul 2006, Sanjay wrote:
            What is the equivalent in Python? Inheriting is a way, but is not
            working in all scenerios.
            Have you tried multiple inheritance? For example:

            from GeneratedPerson import GeneratedPerson
            from HandcraftedPers on import HandcraftedPers on

            class Person(Generate dPerson, HandcraftedPers on):
            pass

            If this doesn't work for you, can you explain why?

            Dave

            Comment

            • Daniel Dittmar

              #7
              Re: Partial classes

              Sanjay wrote:
              Hi All,
              >
              Not being able to figure out how are partial classes coded in Python.
              >
              Example: Suppose I have a code generator which generates part of a
              business class, where as the custome part is to be written by me. In
              ruby (or C#), I divide the code into two source files. Like this:
              >
              GeneratedPerson .rb
              Class Person
              .
              .
              .
              >
              End Class
              >
              HandcraftedPers on.rb
              Class Person
              .
              .
              .
              End Class
              >
              The intrepretor adds the code in both to compose the class Person.
              >
              What is the equivalent in Python? Inheriting is a way, but is not
              working in all scenerios.
              # HandcraftedPers on.py
              import GeneratedPerson

              class Person:
              def somemethod (self):
              pass


              GeneratedPerson .Person.somemet hod = Person.somemeth od

              Using reflection to merge all methods of HandcraftedPers on.Person into
              GeneratedPerson .Person is left as an exercise.

              Daniel

              Comment

              • Peter Otten

                #8
                Re: Partial classes

                Sanjay wrote:
                Hi All,
                >
                Not being able to figure out how are partial classes coded in Python.
                >
                Example: Suppose I have a code generator which generates part of a
                business class, where as the custome part is to be written by me. In
                ruby (or C#), I divide the code into two source files. Like this:
                >
                GeneratedPerson .rb
                Class Person
                .
                .
                .
                >
                End Class
                >
                HandcraftedPers on.rb
                Class Person
                .
                .
                .
                End Class
                >
                The intrepretor adds the code in both to compose the class Person.
                >
                What is the equivalent in Python? Inheriting is a way, but is not
                working in all scenerios.
                I, like everybody else it seems, am interested to know why/when (multiple)
                inheritance doesn't work. Meanwhile

                # this is a hack
                import inspect
                import textwrap

                class Generated:
                def generated(self) :
                print "generated"

                def class_body(Clas s):
                return textwrap.dedent (inspect.getsou rce(Class).spli t("\n", 1)[1])

                class Handmade:
                exec class_body(Gene rated)
                def handmade(self):
                print "handmade"

                if __name__ == "__main__":
                print dir(Handmade)
                Handmade().gene rated()

                Peter

                Comment

                • Sanjay

                  #9
                  Re: Partial classes

                  Can you flesh out your use case a little bit and tell why you can't solve
                  the problem with inheritance or a meta class?
                  I have to study about metaclass and see whether this can be handled. It
                  seemed inheritence is not working.

                  PROBLEM: Separating plumbing code and business logic while using
                  SQLAlchemy ORM.

                  Database script:

                  CREATE TABLE person (
                  id SERIAL,
                  passport VARCHAR(50) NOT NULL,
                  blocked BOOLEAN NOT NULL DEFAULT FALSE,
                  first_name VARCHAR(30) NOT NULL,
                  middle_name VARCHAR(30) NULL,
                  last_name VARCHAR(30) NOT NULL,
                  email VARCHAR(100) NOT NULL,
                  used_bytes INTEGER NOT NULL DEFAULT 0,
                  PRIMARY KEY(id)
                  );

                  CREATE TABLE contact (
                  person_id INTEGER NOT NULL REFERENCES person,
                  contact_id INTEGER NOT NULL REFERENCES person,
                  favorite BOOLEAN NOT NULL DEFAULT FALSE,
                  PRIMARY KEY(person_id, contact_id)
                  );

                  DB definitions and plumbing code goes into one module, say db.py:

                  import sqlalchemy.mods .threadlocal
                  from sqlalchemy import *

                  global_connect( 'postgres://userid:password @localhost:5432/tm')
                  person_tbl = Table('person', default_metadat a, autoload = True)
                  class Person(object):
                  pass
                  contact_tbl = Table('contact' , default_metadat a, autoload = True)
                  class Contact(object) :
                  pass
                  assign_mapper(P erson, person_tbl, properties = {
                  'contacts' :
                  relation(Contac t,
                  primaryjoin=per son_tbl.c.id==c ontact_tbl.c.pe rson_id,
                  association=Per son)
                  })

                  assign_mapper(C ontact, contact_tbl, properties = {
                  'person' :
                  relation(Person ,
                  primaryjoin=per son_tbl.c.id==c ontact_tbl.c.co ntact_id)
                  })

                  Business logic in another module, say bo.py

                  Class PersonBO(Person ):
                  def Block():
                  blocked = True

                  While using PersonBO in another module, like this:

                  p1 = PersonBO(passpo rt = "skpatel20@hotm ail.com", first_name='joh n',
                  last_name='smit h', email = "skpatel20@yaho o.com")
                  p2 = PersonBO(passpo rt = "skpatel20@yaho o.com", first_name='ed' ,
                  last_name='helm s', email = "skpatel20@yaho o.com")
                  p3 = PersonBO(passpo rt = "skpatel20@yaho o.com", first_name='jon athan',
                  last_name='laco ur', email = "skpatel20@yaho o.com")

                  # add a contact
                  p1.contacts.app end(Contact(per son=p2))

                  the following error message occurs:

                  AttributeError: 'PersonBO' object has no attribute 'contacts'

                  What I guess, from my limited knowledge of the technologies involved,
                  is that assign_mapper does some magic only on Person class, and things
                  work. But after inheritence, it is not working.

                  The point in general, to my knowledge, about inheritance is that it
                  can't be a substitute for all the usages of partical classes. Metaclass
                  is a new concept for me, which I have to study.

                  As far as my project is concerned, I have found out some other way of
                  doing the things, and it is no more an issue.

                  Thanks a lot,
                  Sanjay

                  Comment

                  • Bruno Desthuilliers

                    #10
                    Re: Partial classes

                    Sanjay wrote:
                    Hi Alex,
                    >
                    Thanks for the input.
                    >
                    Being new to Python, and after having selected Python in comparison to
                    ruby (Turbogears vs Rails) , is jerks me a bit. In my openion it should
                    be an obvious and easy to implement feature and must be, if not already
                    have been, planned in future releases of Python.
                    >
                    Would love to listen to others.
                    I've never had a use case for this kind of feature in the past seven years.

                    --
                    bruno desthuilliers
                    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
                    p in 'onurb@xiludom. gro'.split('@')])"

                    Comment

                    • Kay Schluehr

                      #11
                      Re: Partial classes


                      Bruno Desthuilliers wrote:
                      Sanjay wrote:
                      Hi Alex,

                      Thanks for the input.

                      Being new to Python, and after having selected Python in comparison to
                      ruby (Turbogears vs Rails) , is jerks me a bit. In my openion it should
                      be an obvious and easy to implement feature and must be, if not already
                      have been, planned in future releases of Python.

                      Would love to listen to others.
                      >
                      I've never had a use case for this kind of feature in the past seven years.
                      Interesting. Are there other use cases you did not have too?

                      Comment

                      • brianmce@gmail.com

                        #12
                        Re: Partial classes

                        Sanjay wrote:
                        Hi All,
                        >
                        Not being able to figure out how are partial classes coded in Python.
                        >
                        Example: Suppose I have a code generator which generates part of a
                        business class, where as the custome part is to be written by me. In
                        ruby (or C#), I divide the code into two source files. Like this:
                        I would do this by inheritance if really needed - what isn't working?
                        That said, you can get this behaviour fairly easy with a metaclass:

                        class PartialMeta(typ e):
                        registry = {}
                        def __new__(cls,nam e,bases,dct):
                        if name in PartialMeta.reg istry:
                        cls2=PartialMet a.registry[name]
                        for k,v in dct.items():
                        setattr(cls2, k, v)
                        else:
                        cls2 = type.__new__(cl s,name,bases,dc t)
                        PartialMeta.reg istry[name] = cls2
                        return cls2

                        class PartialClass(ob ject):
                        __metaclass__=P artialMeta

                        use:
                        #generatedperso n.py
                        class Person(PartialC lass):
                        def foo(self): print "foo"

                        #gandcraftedper son.py
                        import generatedperson
                        class Person(PartialC lass):
                        def bar(self): print "bar"

                        and you should get similar behaviour.

                        Caveats:
                        I've used just the name to determine the class involved to be the
                        same as your Ruby example. However, this means that any class in any
                        namespace with the name Person and inheriting from PartialClass will be
                        interpreted as the same - this might not be desirable if some other
                        library code has a different Person object doing the same thing. Its
                        easy to change to checking for some property instead - eg. have your
                        handcrafted class have the line "__extends__=ge neratedperson.P erson" ,
                        and check for it in the metaclass instead of looking in a name
                        registry.

                        Also, if two or more classes define the same name, the last one
                        evaluated will overwrite the previous one.

                        Comment

                        • Bruno Desthuilliers

                          #13
                          Re: Partial classes

                          Kay Schluehr wrote:
                          Bruno Desthuilliers wrote:
                          >
                          >>Sanjay wrote:
                          >>
                          >>>Hi Alex,
                          >>>
                          >>>Thanks for the input.
                          >>>
                          >>>Being new to Python, and after having selected Python in comparison to
                          >>>ruby (Turbogears vs Rails) , is jerks me a bit. In my openion it should
                          >>>be an obvious and easy to implement feature and must be, if not already
                          >>>have been, planned in future releases of Python.
                          >>>
                          >>>Would love to listen to others.
                          >>
                          >>I've never had a use case for this kind of feature in the past seven years.
                          >
                          >
                          Interesting. Are there other use cases you did not have too?
                          >
                          Probably quite a lot, why ?-)


                          --
                          bruno desthuilliers
                          python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
                          p in 'onurb@xiludom. gro'.split('@')])"

                          Comment

                          • Sanjay

                            #14
                            Re: Partial classes

                            Thanks for the code showing how to implement partial classes. Infact, I
                            was searching for this code pattern. I will have a study on metaclass
                            and then try it.

                            Thanks
                            Sanjay

                            Comment

                            • Kay Schluehr

                              #15
                              Re: Partial classes


                              brianmce@gmail. com wrote:
                              Sanjay wrote:
                              Hi All,

                              Not being able to figure out how are partial classes coded in Python.

                              Example: Suppose I have a code generator which generates part of a
                              business class, where as the custome part is to be written by me. In
                              ruby (or C#), I divide the code into two source files. Like this:
                              >
                              I would do this by inheritance if really needed - what isn't working?
                              That said, you can get this behaviour fairly easy with a metaclass:
                              >
                              class PartialMeta(typ e):
                              registry = {}
                              def __new__(cls,nam e,bases,dct):
                              if name in PartialMeta.reg istry:
                              cls2=PartialMet a.registry[name]
                              for k,v in dct.items():
                              setattr(cls2, k, v)
                              else:
                              cls2 = type.__new__(cl s,name,bases,dc t)
                              PartialMeta.reg istry[name] = cls2
                              return cls2
                              >
                              class PartialClass(ob ject):
                              __metaclass__=P artialMeta
                              This definition lacks a check for disjointness of the parts. No two
                              partial classes shall contain a method with the same name.

                              Comment

                              Working...