[mod_python] kid template decorator [prev: Current Working Directory not set?]

Sean Jamieson sean at barriescene.com
Fri Jan 27 20:42:26 EST 2006


OK, so here is my decorator solution:

# @template decorator
def template( relpath = 'templates', template=None, abspath=None ):
    def decor( func ):
        if abspath:
            path = abspath
        else:
            path = os.path.join( os.path.dirname( __file__ ), relpath )
        if template:
            path = os.path.join( path, template )
        else:
            path = os.path.join( path, '%s_%s.kid' % 
(func.__module__.split('.')[-1], func.func_name) )
        def template_wrapper( *args, **kwargs ):
            kwargs['req'].content_type = 'text/html'
            values = func( *args, **kwargs )
            return Template( file=path, **values )
        # just so debug output makes sense
        template_wrapper.func_name = '%s(%s)' % ( 
template_wrapper.func_name, func.func_name )
        return template_wrapper
    return decor

@template()
def index( req ):
    title = 'some title'
    message = 'Keep it simple, stupid.'
    return vars()

... or something like that...

Comments?

Sean

Sean Jamieson wrote:

> ...and I completely forgot about decorators, I'm going to come up with 
> something later, to make this more sane using a decorator.
>
>
> Sean Jamieson wrote:
>
>> Thanks for all the options Graham.
>>
>> I've come up with the following code template, if anyone see anything 
>> obviously wrong/bad please let me know:
>> import os
>> import sys
>> from mod_python import apache, util
>> from kid import Template
>>
>> # this file's current directory
>> __dir__ = os.path.dirname( __file__ )
>>
>> # set the templates path under this file's directory
>> __templates__ = os.path.join( __dir__, "templates" )
>>
>> def index( req ): _page='index'
>>    req.content_type = 'text/html'
>>    ## function body ##
>>    return Template( file=os.path.join( __templates__, '%s_%s.kid' % 
>> (__name__, _page) ), **vars() )
>>
>>
>> I'm expecting someone might say something about my use of **vars().
>> The overall result of my return Template(..) statement is that it 
>> will match [script's dir]/templates/[script name]_[function name].kid
>>
>> Comments?
>>
>> Sean
>>
>> Graham Dumpleton wrote:
>>
>>>
>>> On 28/01/2006, at 6:53 AM, Sean Jamieson wrote:
>>>
>>>> Hello everybody,
>>>> I don't know if there's already been a discussion about this, it 
>>>> seems like a small but obvious issue.
>>>
>>>
>>>
>>>
>>> Many times. ;-)
>>>
>>>> The current working directory does not apear to be set when a 
>>>> mod_python.publisher script runs; or rather it's set to "/" which 
>>>> is not useful. This becomes quite a pain, as I'm forced to do many 
>>>> things to work around it.
>>>
>>>
>>>
>>>
>>> As someone else said, working directory can't be changed because of 
>>> multithreading
>>> abilities of mod_python.
>>>
>>>> i.e.
>>>> 1) I've started using kid templates, and I have to use:
>>>>     Template( file=req.document_root().'template.kid', ... )
>>>> or
>>>>    Template( 
>>>> file=req.document_root().'project_dir/templates/template.kid', ... )
>>>> rather then the more natural:
>>>>    Template( file='templates/template.kid )
>>>> this should find the 'templates' directory in the same directory as 
>>>> the running script
>>>
>>>
>>>
>>>
>>> Don't use req.document_root(). Instead, in that specific Python code 
>>> file,
>>> include at global scope:
>>>
>>>   import os
>>>   __here__ = os.path.dirname(__file__)
>>>   __templates__ = os.path.join(__here__,"templates")
>>>
>>> That will give you the directory that file is located in, in a handy 
>>> variable
>>> which you can then use.
>>>
>>>     Template( file=os.path.join(__templates__,"template.kid") )
>>>
>>> This is only useful though if all your publisher handlers are in the 
>>> one directory.
>>> If you have stuff spread over subdirectories, you start having to 
>>> use relative
>>> paths as appropriate in subdirectory handler files.
>>>
>>>   import os
>>>   __here__ = os.path.dirname(__file__)
>>>   __templates__ = os.path.join(__here__,"..","templates")
>>>
>>> Thus, you may be better off doing something like:
>>>
>>>   def _templates(req,path):
>>>     return os.path.join(req.hlist.directory,"templates",path)
>>>
>>>   ...
>>>
>>>     Template( file=_template("template.kid") )
>>>
>>> The req.hlist.directory variable will be set to the directory for 
>>> which PythonHandler
>>> is specified, thus giving you a root anchor point which you can use 
>>> to describe all
>>> paths relative to. Doing this means you have more flexibility as far 
>>> as moving code
>>> files around between directories without having to modify code.
>>>
>>> The other reference point you might use is:
>>>
>>>   def _templates(req,path):
>>>     directory = os.path.dirname(req.filename)
>>>     return os.path.join(directory,path)
>>>
>>>   ...
>>>
>>>     Template( file=_template("templates/template.kid") )
>>>
>>> The req.filename object is similar to using __file__ for most cases, 
>>> but getting the
>>> information from the request object instead.
>>>
>>> You might even create your own derived class from Kid's Template 
>>> class so you can
>>> pass it a 'req' object and relative template file path and have that 
>>> derived class
>>> constructor do the calculation of where the file is relative to 
>>> PythonHandler root
>>> or req.filename.
>>>
>>> In other words, to be more transparent, the template system would 
>>> need to know about
>>> the environment it is used in.
>>>
>>>> 2) I have to fully qualify imports from the document root, as the 
>>>> document root is added to sys.modules, but the current directory is 
>>>> not. So, if I'm in a subdirectory under the document root I have to 
>>>> do:
>>>>    import project_dir.subpackage.module
>>>> when the current directory is 'project_dir'. This is silly, I 
>>>> should be able to import something in, or under, the current 
>>>> working directory:
>>>>    import subpackage.module
>>>
>>>
>>>
>>>
>>> If these packages contain reusable code used across various pages 
>>> and don't have
>>> actual code in them for generating pages, it is not a good idea to 
>>> put them under
>>> your document root. This is because with the right URL they may be 
>>> able to be
>>> invoked by a remote user because of publishers automatic mapping. 
>>> Thus you need to
>>> be very careful.
>>>
>>> If they do contain code for generating pages, you should not be 
>>> using "import"
>>> to access them as at the same time they could be getting loaded by 
>>> publisher using
>>> a different module loading system which will cause various problems.
>>>
>>> As suggested by someone else, look at using "apache.import_module()".
>>>
>>>> I would have to do some hack involving seperating the dirname of 
>>>> __file__ and adding it to sys.modules
>>>
>>>
>>>
>>>
>>> I think you must have meant into sys.path. Same above, Modifying 
>>> sys.path directly
>>> in mod_python is not usually a good idea either. The use of 
>>> PythonHandler will
>>> automatically put that root directory in sys.path for you without 
>>> having to resort
>>> to using PythonPath. This all assumes you have already set 
>>> PythonPath explicitly
>>> and aren't using Location directive instead of Directory directive 
>>> to specify context
>>> in which mod_python is used.
>>>
>>> Graham
>>>
>>>
>>>
>>
>> _______________________________________________
>> Mod_python mailing list
>> Mod_python at modpython.org
>> http://mailman.modpython.org/mailman/listinfo/mod_python
>>
>>
>
> _______________________________________________
> Mod_python mailing list
> Mod_python at modpython.org
> http://mailman.modpython.org/mailman/listinfo/mod_python
>
>



More information about the Mod_python mailing list