Commits

imbolc committed d599799

template_loader, view decorator, path template slug

  • Participants
  • Parent commits 6af9db9

Comments (0)

Files changed (8)

 PySi Changelog
 ===============
 
+0.3
+---
+
+- добавлен декоратор view
+- в роутинг добавлен <*:path> 
+- добавлена кастомизация загрузчика шаблонов
+
+
 0.2
 ---
 

File pysi/__init__.py

 from exceptions import NotFound, Redirect, PermanentRedirect, BasicAuth
 from routing import urls, add_apps, add_urls, url4, auto_routing
 from decorators import as_response, as_text, as_html, as_json, to_template
-from decorators import route, error, basic_auth, anticache
+from decorators import route, error, basic_auth, anticache, view
 from template import render_to_string, render_to_response

File pysi/config.py

     }
     TEMPLATE_CACHE_SIZE = 250
     TEMPLATE_AUTO_RELOAD = False
+    TEMPLATE_LOADER = 'pysi.template.file_loader'
     FLASH_COOKIE_NAME = u'pysi.flash'
 
     def set_defaults(self, **kwargs):

File pysi/decorators.py

 from template import render_to_response
 
 
-def route(url, name=None):
+def route(url, urlname=None):
     ''' Декоратор роутинга '''
     def wrapper(func):
-        urls.add_rule(url, func, name)
+        urls.add_rule(url, func, urlname)
         return func
     return wrapper
 
     def decorator(func):
         def wrapper(rq, *args, **kwargs):
             res = func(rq, *args, **kwargs)
-            if isinstance(res, Response):
+            if not isinstance(res, dict):
                 return res
             return render_to_response(
                 rq, fn, res, **response_kwargs)
         rq.basic_user
         return func(rq, *args, **kwargs)
     return wrapper
+    
+def view(url_or_list, template='text', **response_kwargs):
+    '''
+    Роутинг + шаблонизация + дефолтный урлнейм (app.func_name)
+    '''
+    def wrapper(func):
+        mod_name = func.func_globals['__name__']
+        app_name = mod_name[:-6] if mod_name.endswith('.views') else None
+        urlname = '%s.%s' % (app_name, func.__name__) if app_name else func.__name__
+        if template == 'text':
+            func = as_text(**response_kwargs)(func)
+        elif template == 'json':
+            func = as_json(**response_kwargs)(func)
+        elif template == 'html':
+            func = as_html(**response_kwargs)(func)
+        else:
+            func = to_template(template, **response_kwargs)(func)
+        for url in [url_or_list] if isinstance(url_or_list, basestring) else url_or_list:
+            urls.add_rule(url, func, urlname)
+        return func
+    return wrapper
+

File pysi/routing.py

         cur = self.tree
         res = None, {}
         vals = []
-        for i, dir in enumerate(dirs):
+        i = 0
+        while i < len(dirs):
             for d, node in cur:
-                match, val = node['match'](dir)
+                match, val = node['match'](dirs[i])
                 if match:
                     if val is not None:
-                        vals.append(val)
+                        if val == '<//__slug__//>':
+                            vals.append('/'.join(dirs[i:]))
+                            i = len(dirs) - 1
+                        else:
+                            vals.append(val)
                     break
             else:
                 break
             cur = node['next']
+            i += 1
         else:
-            if i == len(dirs) - 1:
-                vars = dict((node['vars'][i], vals[i])
-                    for i in xrange(len(vals))) if vals else {}
-                res = node['target'], vars
+            vars = dict((node['vars'][i], vals[i])
+                for i in xrange(len(vals))) if vals else {}
+            res = node['target'], vars
         return res
         
 def match_const(var):
         return True, datetime.date(dt.year, dt.month, dt.day)
     return f
 
+def match_slug(var):
+    return lambda dir: (True, '<//__slug__//>')
+
+
 MATCHS = {
     'int': match_int,
     'str': match_str,
     'date': match_date,
+    '*': match_slug,
 }
 
 def get_match(dir):
     'int': lambda var: '%%(%s)i' % var,
     'str': lambda var: '%%(%s)s' % var,
     'date': lambda var: '%%(%s)s' % var,
+    '*': lambda var: '%%(%s)s' % var,
 }
 
 

File pysi/template.py

 # -*- coding: utf-8 -*-
-import jinja2
+from os import getcwd
+from os.path import normpath, join, getmtime
+try:
+    import jinja2
+except ImportError, ex:
+    jinja2_ex = ex
 import wsgi
 from config import cfg
-from os.path import normpath, join, getmtime
-from os import getcwd
+from util import obj_from_str
 
-def load_template(fn):
+
+def file_loader(fn):
     ERR_MSG = 'template not found: %s' % fn
     try:
         f = open('templates/%s' % fn)
     try:
         return _ENV.get_template(fn).render(context)
     except NameError:
-        _ENV = jinja2.Environment(
-            loader = jinja2.FunctionLoader(load_template),
-            autoescape = True,
-            cache_size = cfg.TEMPLATE_CACHE_SIZE,
-            auto_reload = cfg.TEMPLATE_AUTO_RELOAD,
-            extensions = ['jinja2.ext.with_'],
-        )        
+        try:
+            _ENV = jinja2.Environment(
+                loader = jinja2.FunctionLoader(obj_from_str(cfg.TEMPLATE_LOADER)),
+                autoescape = True,
+                cache_size = cfg.TEMPLATE_CACHE_SIZE,
+                auto_reload = cfg.TEMPLATE_AUTO_RELOAD,
+                extensions = ['jinja2.ext.with_'],
+            )
+        except NameError:
+            raise jinja2_ex
         return _ENV.get_template(fn).render(context)
     
 def render_to_response(rq, fn, context=None, **response_kwargs):
         if k not in context:
             context[k] = v
     return wsgi.Response(render_to_string(fn, context), **response_kwargs)
+
     

File pysi/wsgi.py

             else:
                 body = TemporaryFile(mode='w+b')
             while maxread > 0:
-                part = stream.read(min(maxread, cfg.POST_MAX_MEMFILE))
+                if cfg.POST_MAX_MEMFILE:
+                    part = stream.read(min(maxread, cfg.POST_MAX_MEMFILE))
+                else:
+                    part = stream.read()
                 if not part:  # TODO: Wrong content_length. Error? Do nothing?
                     break
                 body.write(part)
 from setuptools import setup
 
 PACKAGE = 'pysi'
-VERSION = '0.2.5'
+VERSION = '0.3'
 
 if __name__ == '__main__':
     # Compile the list of packages available, because distutils doesn't have