0

I have list of content block 'instances' which as the list is processed the content for each block is generated in an instance of a content type class (if that makes sense).

As I iterate through the list I am trying to set the attributes of the modules instance with output from an instance of the named module from extra_modules. If there is a better way to to write this question please feel free to edit.

The following is just an example of the testing code I'm trying to run using the Python Bottle framework. I'm trying to get a test output to begin with before I actually put content generating code into the photoGallery class.

core.py:

import extra_modules

module_blocks_in_db = [
    # module-ID, module-sys-name, module-sys-desc, module-function, module-variables
    [1, 'photo_gallery_main', 'A little intro gallery', 'photoGallery', '{"images": ["photo1.jpg", "photo2.jpg", "photo3.jpg"]}'],
]


class moduleBlocks:
    def __init__(self, mbidb):
        for i in mbidb:
            setattr(self, i[1], getattr(extra_modules, i[3])(i[4]))


@route('/')
def home():
    page_id = 1
    modules = moduleBlocks(module_blocks_in_db)
    return modules.photo_gallery_main

extra_modules.py:

class photoGallery:
    def __init__(self, *args):
        self.output = 'Output from photoGallery class instance'
        return self.output

This is the error I'm getting from Bottle's development server:

File "core.py", line 46, in __init__
setattr(self, i[1], getattr(extra_modules, i[3])(i[4]))
TypeError: __init__() should return None

I'm really not understanding this error well and the more I'm looking at the code the more I'm confusing myself. I've tried several different ways now to grab output from a class instance and assign it as an attribute of the moduleBlocks class in my example. Where am I going wrong with this?

EDIT: I have now changed my setattr line to two separate lines and got rid of the return output in the extra_modules photoGallery class and things are now working fine, thanks:

x = getattr(extra_modules, i[3])(i[4])
setattr(self, i[1], x.output)
  • What are you trying to do with this line? `setattr(self, i[1], getattr(extra_modules, i[3])(i[4]))` – mbatchkarov Jun 24 '13 at 15:47
  • I'm using getattr to create an instance of photoGallery class, which in def __init__ generates content and returns the output. I'm then wanting to set the relevant attribute of the moduleBlocks instance with that output. –  Jun 24 '13 at 15:57

2 Answers2

2

The following is incorrect:

class photoGallery:
    def __init__(self, *args):
        self.output = 'Output from photoGallery class instance'
        return self.output

"_init_" is the constructor for photoGallery which has the responsibility of initialising the photoGallery object. As such it doesn't make sense for it to to return anything. Get rid of return self.output and try again

pgpython
  • 279
  • 2
  • 8
  • So self.output is set, but how do I return the value of self.output in this line: `setattr(self, i[1], getattr(extra_modules, i[3])(i[4]))` –  Jun 24 '13 at 16:01
  • @zilog6502: the `photoGallery` object itself is the output of that call. What are you trying to do? – Martijn Pieters Jun 24 '13 at 16:35
0

Ok, I think see what your trying to do and i can tell you that approach is problematic to say the least. The problem is you try to access each class output variable you essential every controller class you create has to define the output variable and it has to be documented that each controller must define the output variable.

There are several solutions to solve the problem and some are better than others.

So here are some options for you.

  1. Do you really need photoGallery as a class. If all it does it return a string and there is no interaction or change of state it makes no sense for it to be a class. change it and similar controllers to be a function and thats all you need to do.

  2. Maybe there is some state change happpening to it elsewhere then my recommendation is to be transparent. python doesn't have interfaces but it does have abc (abstract base class). you can all make all you controllers inherit from a abc and define a method like get_ouput. then you would have:

    setattr(self, i[1], getattr(extra_modules, i[3])(i[4]).get_output())

  3. Don't recommend this as its really yucky and will bit you later:

    setattr(self, i[1], getattr(extra_modules, i[3])(i[4]).output)

pgpython
  • 279
  • 2
  • 8
  • I like number 1 of your solutions here. I did manage to get it working using classes and was headed this way because I wanted to use classes like a plugin system, but I really like the simplicity of the functions, thanks. –  Jun 24 '13 at 19:38