Redundant code in multiple methods

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

    #1

    Redundant code in multiple methods

    No you don't need to know Zope to help me. The whole reason I'd even
    want to do this is because of Zope though. I made a Zope product, and
    now want to perfect it.

    some simple example code...

    <code>
    class User:

    def View(self):
    # play with data here
    myHtmlDoc = "pretend this is a uper profile"
    return myHtmlDoc
    index_html = View

    def Edit(self):
    # play with data here
    myHtmlDoc = "editing the user"
    return myHtmlDoc
    </code>

    So when visiting "website.co m/User" zope will call User.index_html () or
    when you visit "website.co m/User/View" zope will call User.View() In
    all of the testing/learning I've done on Zope I'm pretty sure that last
    item (index_html or View) must be a method, but possible it only needs
    to have an __doc__ attribute (otherwise Zope will Error)

    The problem comes when I want to have code put into every method.
    Perhaps a counter I want to increment on every visit to a User page.
    I can do this..

    <snippet>
    def View(self):
    incrementCounte r()
    # play with data here
    myHtmlDoc = "pretend this is a uper profile"
    return myHtmlDoc
    index_html = View

    def Edit(self):
    incrementCounte r()
    # play with data here
    myHtmlDoc = "editing the user"
    return myHtmlDoc
    </snippet>

    .... but in reality in my real code that one counter increment line ends
    up being 20 lines long. An al lot of that "counter code" is actaully
    setting up variables I'd like to access within the scope of the given
    method. So if you follow me so far, I was wondering how I might change
    things to only have one place where I have to maintain the "setup my
    method" code, which is pretty much a lot of the same code typed over
    and over into all of the methods.
    (for a more real life example of things) -

    <snippet>
    def View(self):
    REQUEST = self.REQUEST
    SESSION = REQUEST.SESSION
    dbConnection = self.getDBConne ction()
    logger = self.getLogger( )
    trackStatsHere( )
    # set up some local variables here
    # change some global variables here
    try:
    myHtmlDoc = """make the htmldocument here using all
    of the previous variables"""
    # play with data here
    return myHtmlDoc
    except:
    raise "handle the error here"
    finally:
    dbConnection.cl ose()
    index_html = View

    def Edit(self):
    REQUEST = self.REQUEST
    SESSION = REQUEST.SESSION
    dbConnection = self.getDBConne ction()
    logger = self.getLogger( )
    trackStatsHere( )
    # set up some local variables here
    # change some global variables here
    try:
    myHtmlDoc = """make the htmldocument here using all
    of the previous variables"""
    # play with data here
    return myHtmlDoc
    except:
    raise "handle the error here"
    finally:
    dbConnection.cl ose()
    </snippet>

    I would ideally like to do something such as this this, or something
    where I don't have all of that redundant code.

    <snippet>
    def __allmethods__( self, methodname):
    "gets called when all methods are called"
    REQUEST = self.REQUEST
    SESSION = REQUEST.SESSION
    dbConnection = self.getDBConne ction()
    logger = self.getLogger( )
    trackStatsHere( )
    # set up some local variables here
    # change some global variables here
    try:
    methodname(loca lvariables)
    except:
    raise "handle the error here"
    finally:
    dbConnection.cl ose()

    def View(self, localvariables) :
    myHtmlDoc = """make the htmldocument here using all
    of the previous variables"""
    # play with data here
    return myHtmlDoc
    index_html = View

    def Edit(self):
    myHtmlDoc = """make the htmldocument here using all
    of the previous variables"""
    # play with data here
    return myHtmlDoc
    </snippet>

    __getattr__ almost does the trick but not quite. So any suggestions on
    how to streamline my code here and make it slightly more maintainable.

  • Sam Pointon

    #2
    Re: Redundant code in multiple methods

    How about using a class, with __call__, as a wrapper instead of the
    function itself?


    class FunctionWrapper (object):
    def __init__(self, cls, function):
    self._function = function
    self._cls = cls

    def __call__(self, *args, **kwargs):
    REQUEST = self.REQUEST
    SESSION = REQUEST.SESSION
    dbConnection = self._cls.getDB Connection()
    logger = self._cls.getLo gger()
    trackStatsHere( )
    # set up some local variables here
    # change some global variables here
    try:
    return self._function( self._cls, *args, **kwargs)
    except:
    raise "handle the error here"
    finally:
    dbConnection.cl ose()

    class User(object):
    def __init__(self):
    def View(cls, self, localvariables) : #Needs the cls argument
    before self to take the FunctionWrapper first argument
    myHtmlDoc = """make the htmldocument here using all
    of the previous variables"""
    # play with data here
    return myHtmlDoc
    self.View = FunctionWrapper (self, View)

    def Edit(cls, self): #Ditto
    myHtmlDoc = """make the htmldocument here using all
    of the previous variables"""
    # play with data here
    return myHtmlDoc
    self.Edit = FunctionWrapper (self, Edit)

    #the rest of the class

    Comment

    • bruno modulix

      #3
      Re: Redundant code in multiple methods

      Rob Conner wrote:[color=blue]
      > No you don't need to know Zope to help me. The whole reason I'd even
      > want to do this is because of Zope though. I made a Zope product, and
      > now want to perfect it.
      >
      > some simple example code...
      >
      > <code>
      > class User:
      >
      > def View(self):
      > # play with data here
      > myHtmlDoc = "pretend this is a uper profile"
      > return myHtmlDoc
      > index_html = View
      >
      > def Edit(self):
      > # play with data here
      > myHtmlDoc = "editing the user"
      > return myHtmlDoc
      > </code>
      >
      > So when visiting "website.co m/User" zope will call User.index_html () or
      > when you visit "website.co m/User/View" zope will call User.View() In
      > all of the testing/learning I've done on Zope I'm pretty sure that last
      > item (index_html or View) must be a method,[/color]

      Anything that returns HTML is ok. Can be a method, a data attribute, a
      class attribute pointing to a ZPT or DTML file (like you do for ZMI
      forms), and even any aquired component ! (the view and index_html
      attributes doesnt need to live in the class...)
      [color=blue]
      >
      > The problem comes when I want to have code put into every method.
      > Perhaps a counter I want to increment on every visit to a User page.
      > I can do this..
      >
      > <snippet>
      > def View(self):
      > incrementCounte r()
      > # play with data here
      > myHtmlDoc = "pretend this is a uper profile"
      > return myHtmlDoc
      > index_html = View
      >
      > def Edit(self):
      > incrementCounte r()
      > # play with data here
      > myHtmlDoc = "editing the user"
      > return myHtmlDoc
      > </snippet>
      >
      > ... but in reality in my real code that one counter increment line ends
      > up being 20 lines long.[/color]

      This is typically what AOP is all about - and Python offers a quite
      usable support for "ad hoc" aspects, via the function wrapper idiom. The
      simplest way is to use closures:

      def wrapper(fun, wargs):
      def wrapped(fargs):
      do_something_be fore_funcall(wa rgs, fargs)
      res = fun(fargs)
      do_something_af ter_funcall(war gs, fargs)
      return res
      return wrapped

      class Machin(object):
      def to_be_wrapped(s elf, args):
      # code here...
      # Zope 2.x uses Python 2.3.x, so no @decorator syntax
      to_be_wrapped = wrapper(to_be_w rapped, wargs)

      If you need something more complex, see Sam's example with a callable
      object.

      (snip longer code exemple)


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

      Comment

      • Rob Conner

        #4
        Re: Redundant code in multiple methods

        Genius!
        Thanks guys that was exactly the help I was looking for. I'll be
        implementing this later today. I don't forsee any problems, so if I
        don't post anything else, thank you so much for the help.

        Comment

        • bruno modulix

          #5
          Re: Redundant code in multiple methods

          Rob Conner wrote:[color=blue]
          > Genius![/color]

          Nope. Just common Python idioms...
          [color=blue]
          > Thanks guys that was exactly the help I was looking for. I'll be
          > implementing this later today. I don't forsee any problems, so if I
          > don't post anything else, thank you so much for the help.[/color]

          You're welcome.

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

          Comment

          Working...