def mount_routes(self, class_instance): """ Mount the routes from another class instance. The routes must be added to the class via the HttpServer.route annotation and not directly from the bottle.route decorator. """ for callback_name in dir(class_instance): callback = getattr(class_instance, callback_name) if hasattr(callback, self.ROUTES_ATTRIBUTE) or hasattr( callback, self.ERROR_ATTRIBUTE): # Bind the un-annotated callback to this class self._bind_method(class_instance, callback_name) # Apply view annotations if hasattr(callback, self.VIEW_ATTRIBUTE): args, kw = getattr(callback, self.VIEW_ATTRIBUTE) callback = bottle.view(*args, **kw)(callback) setattr(self, callback_name, callback) # Apply route annotations for args, kw in getattr(callback, self.ROUTES_ATTRIBUTE, ()): kw = self._apply_plugins(class_instance, copy.deepcopy(kw)) kw.update(callback=callback) self._app.route(*args, **kw) for error_code in getattr(callback, self.ERROR_ATTRIBUTE, ()): self._app.error(error_code)(callback)
def setup_webserver(self): bottle.route('/')(bottle.view('index')(self.index)) bottle.post('/clear_log')(self.clear_log) bottle.post('/config')(self.config) bottle.post('/function/<function_id>')(self.function) bottle.run(host='0.0.0.0', port=8080)
def wrapper(*args, **kwargs): etag = repository.repo.heads.master.commit.hexsha + \ username(request.auth) if request.headers.get('If-None-Match') == etag: return HTTPResponse('Not Modified', 304) else: response.headers['ETag'] = etag return view(*args, **kwargs)
def decorator(func): def wrapper(*args, **kwargs): try: res = func(*args, **kwargs) except ApplicationError as exc: return {'error': exc} return res return bottle.view(tpl_name, **defaults)(wrapper)
def api_view(*args, **kwargs): try: return make_json_response(view(*args, **kwargs)) except HTTPResponse: raise except Exception as e: traceback.print_exc() return api_error(unicode(e))
def __init__(self, themedir, siteconftemplate): self.installdir = sys.path[0] # Note: this should ideally be gotten from somewhere else. self.wsgiapp = Bottle() self.apiclass = sandbox.csg2api(self.wsgiapp, self.runningsessions) # Parse arguments argparser = argparse.ArgumentParser() argparser.add_argument('sitesfolder', metavar='<site storage folder>', help="path to the folder containing sites") argparser.add_argument('siteroot', metavar='<site name>', help="site name/the folder with config.json") self.parsedargs = argparser.parse_args() # Setup configuration and path to site self.sitepath = os.path.abspath(os.path.join(self.parsedargs.sitesfolder, self.parsedargs.siteroot)) siteconffile = open(os.path.join(self.sitepath, "config.json"), mode="rt", encoding="utf-8") self.siteconf = configman.normalize_config(json.load(siteconffile), self.parsedargs.siteroot) siteconffile.close() # Setup theming themesroot = os.path.abspath(themedir) self.themepath = os.path.join(themesroot, self.siteconf["site"]["theme"]) os.chdir(self.sitepath) # Assign routes (done before the site code to allow overrides) # This is functionally equivalent of what the language does, but makes sure Bottle will call the right instance. self.getrandstaticredirect = self.wsgiapp.route("/rand/<filepath:path>")(self.getrandstaticredirect) self.getstatic = self.wsgiapp.route("/static/<filepath:path>")(self.getstatic) self.compilethemesass = self.wsgiapp.route("/theme/sass/master.scss")(self.compilethemesass) self.getthemeasset = self.wsgiapp.route("/theme/static/<filepath:path>")(self.getthemeasset) self.compilesass = self.wsgiapp.route("/sass/<filename:re:.*\.scss>")(self.compilesass) self.catchall = self.wsgiapp.route("/")( self.wsgiapp.route("/<filepath:path>")( view(os.path.join(self.themepath, "master.tpl"))(self.catchall) ) ) self.dologin = self.wsgiapp.route("/login", method="POST")(self.dologin) # If they have code, run it if "additional_code" in self.siteconf["site"]: oldpath = sys.path sys.path[0] = self.sitepath importlib.invalidate_caches() with open(os.path.join(self.sitepath, self.siteconf["site"]["additional_code"]), mode="rt") as codefile: sandbox.create_box(codefile.read(), self.wsgiapp, apiclass=self.apiclass) # This file is excempt from the linking clauses in the license, allowing it to be non-(A)GPL. sys.path = oldpath importlib.invalidate_caches() # Configure Nginx socketpath = "/tmp/csg2_{}.sock".format(self.siteconf["site"]["domain_name"].replace(".", "_")) print("-> Generating config.") with open(os.path.abspath(siteconftemplate), mode="rt", encoding="utf-8") as sitetemplate: sitetemplatetxt = sitetemplate.read() newsite = sitetemplatetxt.replace("%%SERVERNAME%%", self.siteconf["site"]["domain_name"]).replace("%%SOCKETPATH%%", socketpath) with open("/tmp/{}.csg2nginx".format(self.siteconf["site"]["domain_name"].replace(".", "_")), mode="wt", encoding="utf-8") as newconf: newconf.write(newsite) # Serve site. print("-> Serving up site on '{}'.".format(socketpath)) waitress_serve(self.wsgiapp, unix_socket=socketpath)
def home(): ''' This is the initial view, before the user has clicked "Submit" ''' return view( 'robo_draft', #summary_text='', use_text='', source_text='', # Use an empty FormsDict on initial load so data fields are empty form=FormsDict(), )
def mount_routes(self, cls): """ Mount the routes from another class. The routes must be added to the class via the HttpServer.route annotation. """ for attr in dir(cls): class_attr = getattr(cls, attr) if hasattr(class_attr, HttpServer.VIEW_ATTRIBUTE): args, kw = getattr(class_attr, HttpServer.VIEW_ATTRIBUTE) setattr(self, attr, bottle.view(*args, **kw)(getattr(cls, attr))) if hasattr(class_attr, HttpServer.ROUTES_ATTRIBUTE): self._bind_method(cls, attr) for args, kwargs in getattr(class_attr, HttpServer.ROUTES_ATTRIBUTE): kwargs = copy.deepcopy(kwargs) kwargs.update({'callback': getattr(self, attr)}) self._app.route(*args, **kwargs)
def result(): ''' This is the result view, after the user has clicked "Submit" ''' data = {k: v for k, v in request.forms.items() if v} # summary_text_template = robodrafter.generate_summary_text_template() # summary_text = fill_template(summary_text_template, data) use_text_template = robodrafter.generate_use_text_template(usesSentences) use_text = fill_template(use_text_template, data) source_text_template = robodrafter.generate_source_text_template( sourceSentences) source_text = fill_template(source_text_template, data) return view( 'robo_draft', #summary_text = summary_text, use_text=use_text, source_text=source_text, form=request.forms, )
def mount_routes(self, class_instance): """ Mount the routes from another class instance. The routes must be added to the class via the HttpServer.route annotation and not directly from the bottle.route decorator. """ for callback_name in dir(class_instance): callback = getattr(class_instance, callback_name) if hasattr(callback, self.ROUTES_ATTRIBUTE) or hasattr(callback, self.ERROR_ATTRIBUTE): # Bind the un-annotated callback to this class self._bind_method(class_instance, callback_name) # Apply view annotations if hasattr(callback, self.VIEW_ATTRIBUTE): args, kw = getattr(callback, self.VIEW_ATTRIBUTE) callback = bottle.view(*args, **kw)(callback) setattr(self, callback_name, callback) # Apply route annotations for args, kw in getattr(callback, self.ROUTES_ATTRIBUTE, ()): kw = self._apply_plugins(class_instance, copy.deepcopy(kw)) kw.update(callback=callback) self._app.route(*args, **kw) for error_code in getattr(callback, self.ERROR_ATTRIBUTE, ()): self._app.error(error_code)(callback)
def wrapper(*args, **kwargs): if logged_in(request.auth): return view(*args, **kwargs) return access_denied()
# coding:utf-8 __author__ = "chenghao" from bottle import Bottle, request, redirect, response, JSONPlugin, jinja2_view as view from json import dumps import handler, util from dal import admin_dal admin_app = Bottle() admin_app.install(JSONPlugin(json_dumps=lambda s: dumps(s, cls=util.ComplexEncoder))) ######################### 后台管理 ######################### @admin_app.get("/", apply=[view("./admin/index")]) def index(): return {} ######################### 后台登录 ######################### @admin_app.get("/login", apply=[view("./admin/login")]) def login(): """ 显示登录页面, 如果已经登录就重定向到后台管理主页 :return: """ rid = handler.get_user_id() if rid: redirect("/admin") else: return {}
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """ y用户信息管理部分 """ import hashlib import setting import bottle from bottle import view , route , redirect , request , response , post import re import datetime @route("/login" , apply=[view('login')] , method=['GET' , 'POST']) def user_login(db,users): """ 用户登陆业务 """ db = db.cursor() username = request.forms.get("username" , None) passwd = request.forms.get("passwd", None) ret = {'menu_id':0 , 'msg':''} if username != None and passwd != None: md5pass = hashlib.md5(passwd.encode(encoding="gb2312")) passwd = md5pass.hexdigest() sql = "SELECT id , username,mail FROM users WHERE username = %(user)s and passwd = %(passwd)s and is_del = 0" db.execute(sql, { 'user':username ,
def load_plugin(self, fdir, plugin_dir): logger.debug("[WebUI] loading plugin %s ...", fdir) try: # Put the full qualified path of the module we want to load # for example we will give webui/plugins/eltdetail/ mod_path = os.path.join(plugin_dir, fdir) # Then we load the plugin.py inside this directory m = imp.load_module('%s' % (fdir), *imp.find_module(fdir, [mod_path])) m_dir = os.path.abspath(os.path.dirname(m.__file__)) sys.path.append(m_dir) for (f, entry) in m.pages.items(): # IMPORTANT: apply VIEW BEFORE route! view = entry.get('view', None) if view: f = bottle.view(view)(f) # Maybe there is no route to link, so pass route = entry.get('route', None) name = entry.get('name', None) search_engine = entry.get('search_engine', False) if route: method = entry.get('method', 'GET') # Ok, we will just use the lock for all # plugin page, but not for static objects # so we set the lock at the function level. f = webui_app.route(route, callback=self.lockable_function(f), method=method, name=name, search_engine=search_engine) # If the plugin declare a static entry, register it # and remember: really static! because there is no lock # for them! static = entry.get('static', False) if static: self.add_static_route(fdir, m_dir) # It's a valid widget entry if it got all data, and at least one route # ONLY the first route will be used for Add! widget_lst = entry.get('widget', []) widget_desc = entry.get('widget_desc', None) widget_name = entry.get('widget_name', None) widget_picture = entry.get('widget_picture', None) if widget_name and widget_desc and widget_lst != [] and route: for place in widget_lst: if place not in self.widgets: self.widgets[place] = [] self.widgets[place].append({ 'widget_name': widget_name, 'widget_desc': widget_desc, 'base_uri': route, 'widget_picture': widget_picture }) # And we add the views dir of this plugin in our TEMPLATE # PATH bottle.TEMPLATE_PATH.append(os.path.join(m_dir, 'views')) # And finally register me so the pages can get data and other # useful stuff m.app = self # Load/set plugin configuration f = getattr(m, 'load_config', None) if f and callable(f): logger.debug("[WebUI] calling plugin %s, load configuration", fdir) f(self) logger.info("[WebUI] loaded plugin %s", fdir) except Exception, exp: logger.error("[WebUI] loading plugin %s, exception: %s", fdir, str(exp))
def wrapper(*args, **kwargs): auth = check_func() if auth: return view(*args, **kwargs) return bottle.redirect('/login.html')
def bottle_view(template_file: str) -> Callable[[AnyFunction], AnyFunction]: return bottle.view(template_file) # type: ignore
def __init__(self, themedir, siteconftemplate): self.installdir = sys.path[ 0] # Note: this should ideally be gotten from somewhere else. self.wsgiapp = Bottle() self.apiclass = sandbox.csg2api(self.wsgiapp, self.runningsessions) # Parse arguments argparser = argparse.ArgumentParser() argparser.add_argument('sitesfolder', metavar='<site storage folder>', help="path to the folder containing sites") argparser.add_argument('siteroot', metavar='<site name>', help="site name/the folder with config.json") self.parsedargs = argparser.parse_args() # Setup configuration and path to site self.sitepath = os.path.abspath( os.path.join(self.parsedargs.sitesfolder, self.parsedargs.siteroot)) siteconffile = open(os.path.join(self.sitepath, "config.json"), mode="rt", encoding="utf-8") self.siteconf = configman.normalize_config(json.load(siteconffile), self.parsedargs.siteroot) siteconffile.close() # Setup theming themesroot = os.path.abspath(themedir) self.themepath = os.path.join(themesroot, self.siteconf["site"]["theme"]) os.chdir(self.sitepath) # Assign routes (done before the site code to allow overrides) # This is functionally equivalent of what the language does, but makes sure Bottle will call the right instance. self.getrandstaticredirect = self.wsgiapp.route( "/rand/<filepath:path>")(self.getrandstaticredirect) self.getstatic = self.wsgiapp.route("/static/<filepath:path>")( self.getstatic) self.compilethemesass = self.wsgiapp.route("/theme/sass/master.scss")( self.compilethemesass) self.getthemeasset = self.wsgiapp.route( "/theme/static/<filepath:path>")(self.getthemeasset) self.compilesass = self.wsgiapp.route("/sass/<filename:re:.*\.scss>")( self.compilesass) self.catchall = self.wsgiapp.route("/")( self.wsgiapp.route("/<filepath:path>")(view( os.path.join(self.themepath, "master.tpl"))(self.catchall))) self.dologin = self.wsgiapp.route("/login", method="POST")(self.dologin) # If they have code, run it if "additional_code" in self.siteconf["site"]: oldpath = sys.path sys.path[0] = self.sitepath importlib.invalidate_caches() with open(os.path.join(self.sitepath, self.siteconf["site"]["additional_code"]), mode="rt") as codefile: sandbox.create_box( codefile.read(), self.wsgiapp, apiclass=self.apiclass ) # This file is excempt from the linking clauses in the license, allowing it to be non-(A)GPL. sys.path = oldpath importlib.invalidate_caches() # Configure Nginx socketpath = "/tmp/csg2_{}.sock".format( self.siteconf["site"]["domain_name"].replace(".", "_")) print("-> Generating config.") with open(os.path.abspath(siteconftemplate), mode="rt", encoding="utf-8") as sitetemplate: sitetemplatetxt = sitetemplate.read() newsite = sitetemplatetxt.replace( "%%SERVERNAME%%", self.siteconf["site"]["domain_name"]).replace( "%%SOCKETPATH%%", socketpath) with open("/tmp/{}.csg2nginx".format( self.siteconf["site"]["domain_name"].replace(".", "_")), mode="wt", encoding="utf-8") as newconf: newconf.write(newsite) # Serve site. print("-> Serving up site on '{}'.".format(socketpath)) waitress_serve(self.wsgiapp, unix_socket=socketpath)
from bottle import mako_view as view from bottle import get from bottle import static_file from bottle import url from settings import STATIC_ROOT @get('/static/:path#.+#', name='static_file') def static(path): return static_file(path, root=STATIC_ROOT) @get('/', name='home', apply=[view('index.mako')]) def index(): return { 'url': url, }
# under the License. ################# 外部类库 ################################################### import bottle from bottle import view, route, redirect, request, response, HTTPError import json import setting import datetime import time from mode import ModelBlogs, ModelCategory, ModelTags, db, GlobalHtml def_content = GlobalHtml() ######应用展示界面相关############################################## @route("/", apply=[view("index")]) @route("/cate/<cate>.html", apply=[view("index")]) @route("/tags/<tags>.html", apply=[view("index")]) @route("/sitemap.xml", apply=[view("sitemap")]) def blog_index(cate=None, tags=None, users=None): """ 主页 """ ret = def_content.get_ret() ret["login"] = True ret["page_title"] = "最近更新" user = users.get_user() if user is None or user is False: ret["login"] = False query = db.Query(ModelBlogs)
def view(tplName): return bottle.view(tplName,Helpers=Helpers)
myTokens.put() else: row.token = token row.profile_picture = info['profile_picture'] row.full_name = info['full_name'] row.username = info['username'] row.puid = str(info['id']) row.put() redirect("/pic/inst") except OAuth2AuthExchangeError , e: ret['message'] = "密钥获取超时" return ret @route("/pic/inst",apply=[view('pic_inst')]) def my_inst_pic_lists(users=None): """ jj界面 """ ret = GlobalHtml().get_ret() query = db.Query(ModelTokens) row = query.filter("ptype = " , 'inst').get() if row is None: ret['message'] = '没有连接到Instagen <a href="/oauth/inst/login">现在连接</a>' return ret api = InstagramAPI(access_token=row.token) recent_media, next = api.user_recent_media()
except: traceback.print_exc() init_db() return getderp() get_all_shit = lambda: sorted(getderp(), key=lambda x: float(x.votes), reverse=True) # idk man give me a break i'm too old for this shit fuck_python2 = lambda x: x.decode("utf-8", "replace") if isinstance(x, bytes) else x def find_shit(all_shit, name): for x in all_shit: if fuck_python2(x.name) == fuck_python2(name): return x route('/')(view('index')(lambda: dict(emoticons=get_all_shit()))) DIRECTIONS = { 'up': 1, 'down': -1, 'side': math.pi, } @route('/vote/<where>/<what>') def vote(where, what): existing = find_shit(get_all_shit(), urlunquote(what)) if existing: existing.votes = float(existing.votes) + DIRECTIONS.get(where, 0) existing.commit() return redirect("/")
mc_plugin = MemcachePlugin(servers=['localhost:11211', ]) app.install(mc_plugin) @app.error(404) def error404(error): return "Nothing here." @app.route('/static/<path:path>') def callback(path): path = path.replace('../', '').strip(';') return static_file(path, 'views/static/') @app.get('/', apply=[view('index')]) def index(mc): counts = mc.get('index_counts') if not counts: user_count = User.count() occupation_count = Occupation.count() movie_count = Movie.count() vertex_count = execute_query('g.V.count()') edge_count = execute_query('g.E.count()') counts = {'movieCount': movie_count, 'occupationCount': occupation_count, 'userCount': user_count, 'vertexCount': vertex_count, 'edgeCount': edge_count} mc.set('index_counts', counts) return counts
def auth(user, passwd): """ Validate user and password. :param user: User name :param passwd: Password :return: TRUE if authenticated """ if user == 'curiost' and passwd == '12345': return True return False #@bottle.auth_basic(auth) @app.get('/', apply=[bottle.view('tpl/index.xml.tpl')]) def index(db): """ Show full list of available circles. :param db: Database :return: HTML """ bottle.response.set_header('Content-Type', 'text/xml') return dict( circles=db.execute( """ SELECT c.id, city, tag, COUNT(t.id) AS sum FROM circle AS c JOIN tweet AS t ON c.id = t.circle GROUP BY c.id ORDER BY t.date
# coding:utf-8 __author__ = 'chenghao' from gevent import monkey monkey.patch_all() from bottle import run, Bottle, static_file, view from ueditor import ueditor_bottle bottle = Bottle() @bottle.get("/", apply=[view("./index")]) def index(): pass @bottle.get('/static/<filename:path>') def static(filename): """ Serve static files """ return static_file(filename, root='./static/') bottle.merge(ueditor_bottle) run(server="gevent", app=bottle, host='0.0.0.0', port=8000, reloader=True, debug=True)
def load_pages(self): # Also load the helper lib, and give him myself self.helper = helper self.helper.add_app(self) print "MY SELF __file__ is", __file__ pages_dir = os.path.abspath(os.path.dirname(self.__class__._PAGES_MODULE.__file__)) print "Loading pages directory: %s" % pages_dir # Load the common views into the bottle PATH common_views = os.path.join(os.path.dirname(pages_dir), 'views') print "ADDING COMMON VIEW PATH", common_views bottle.TEMPLATE_PATH.append(common_views) # Load pages directories pages_dirs = [fname for fname in os.listdir(pages_dir) if os.path.isdir(os.path.join(pages_dir, fname))] print "Pages dirs", pages_dirs sys.path.append(pages_dir) # We try to import them, but we keep only the one of # our type for fdir in pages_dirs: print "Try to load", fdir mod_path = self.__class__._MY_LIB_NAME+'.pages.%s.%s' % (fdir, fdir) try: m = __import__(mod_path, fromlist=[mod_path]) m_dir = os.path.abspath(os.path.dirname(m.__file__)) sys.path.append(m_dir) print "Loaded module m", m print m.__file__ pages = m.pages print "Try to load pages", pages for (f, entry) in pages.items(): routes = entry.get('routes', None) v = entry.get('view', None) wraps = entry.get('wraps', []) # First apply wraps, like "need user and put app/user values" for wrap in wraps: if wrap == 'classic': print "before wrap", f f = do_wrap(wrap_classic_page, f, self) print "New wrap is", f if wrap == 'json': print "before wrap", f f = do_wrap(wrap_json_page, f, self) print "New wrap is", f if wrap == 'protected': print "before wrap", f f = do_wrap(wrap_protected_page, f, self) print "New wrap is", f # IMPORTANT: apply VIEW BEFORE route! if v: print "Link function", f, "and view", v f = view(v)(f) # Maybe there is no route to link, so pass if routes: for r in routes: method = entry.get('method', 'GET') print "link function", f, "and route", r, "method", method f = route(r, callback=f, method=method) # And we add the views dir of this plugin in our TEMPLATE # PATH bottle.TEMPLATE_PATH.append(os.path.join(m_dir, 'views')) # And finally register me so the pages can get data and other # useful stuff m.app = self except Exception, exp: print "*"*200 print "Loading page: %s" % exp print "*"*200 output = cStringIO.StringIO() traceback.print_exc(file=output) print "Back trace of this remove: %s" % (output.getvalue()) output.close()
def view(tpl_name, layout=None): if layout: return bottle.view(tpl_name, template_adapter=PystacheTemplate, template_settings={"layout": layout}) else: return bottle.view(tpl_name, template_adapter=PystacheTemplate)
from bottle import route, run, view @route('/') view ("predictions") def index(): return {"date":} @route("/api/test") def api_test(): return { "test_passed": True } run( host="localhost", port=8080, )
def wrapper(*args, **kwargs): referer = request.headers.get('referer') if referer is not None: if urlsplit(referer).netloc == urlsplit(request.url).netloc: return view(*args, **kwargs) return forbidden()
from bottle import route, run from bottle import mako_view as view from bottle import mako_template as template from bottle import request from bottle import static_file from bottle import HTTPError from application import uploader from settings import MEDIA_ROOT from utils import save_file from utils import AttrDict @uploader.get('/', name='home',apply=[view('uploader/index.mako')]) def index(rdb): file_ids = rdb.lrange('file:global:ids',-11,-1) or [] # get ids of last files file_ids.reverse() files = [] for file_id in file_ids: obj = rdb.hgetall('file:%s:data' % file_id) obj = AttrDict(obj) files.append(obj) return { 'files' : files, 'url' : uploader.get_url, } @uploader.post('/upload/', name='upload', apply=[view('uploader/upload.mako')])
def load_plugins(self, app, plugins_dir): # pylint: disable=too-many-locals, too-many-nested-blocks, undefined-loop-variable """ Load plugins from the provided directory If the plugin has - 'pages', declare routes for the pages - 'widgets', declare widgets in the main widgets list Register the plugin 'views' directory in the Bottle views If the plugin has a 'load_config' function, call it """ logger.info("load plugins from: %s", plugins_dir) # Get list of sub directories plugin_names = [ fname for fname in os.listdir(plugins_dir) if os.path.isdir(os.path.join(plugins_dir, fname)) ] # Try to import all found plugins i = 0 for plugin_name in plugin_names: logger.info("trying to load plugin '%s' ...", plugin_name) try: # Import the plugin in the package namespace plugin = import_module( '.%s.%s.%s' % (plugins_dir.rsplit('/')[-1], plugin_name, plugin_name), __package__) # Plugin defined routes ... if hasattr(plugin, 'pages'): for (f, entry) in plugin.pages.items(): logger.debug("page entry: %s", entry) # IMPORTANT: apply the view before the route! page_view = entry.get('view', None) if page_view: f = view(page_view)(f) page_route = entry.get('route', None) if not page_route: page_route = entry.get('routes', None) page_name = entry.get('name', None) # Maybe there is no route to link, so pass if not page_route: continue methods = entry.get('method', 'GET') # Routes are an array of tuples [(route, name), ...] route_url = '' if not isinstance(page_route, list): page_route = [(page_route, page_name)] for route_url, name in page_route: f = app.route( route_url, callback=f, method=methods, name=name, search_engine=entry.get( 'search_engine', False), search_prefix=entry.get('search_prefix', ''), search_filters=entry.get('search_filters', {})) # Plugin is dedicated to a backend endpoint... if hasattr(plugin, 'backend_endpoint'): if route_url == ('/%ss_list' % plugin.backend_endpoint): self.lists['%ss_list' % plugin.backend_endpoint] = { 'id': plugin.backend_endpoint, 'base_uri': route_url, 'function': f } logger.info("Found list '%s' for %s", route_url, plugin.backend_endpoint) # It's a valid widget entry if it got all data, and at least one route if 'widgets' in entry: for widget in entry.get('widgets'): if 'id' not in widget or 'for' not in widget: continue if 'name' not in widget or 'description' not in widget: continue if 'template' not in widget or not page_route: continue for place in widget['for']: if place not in self.widgets: self.widgets[place] = [] self.widgets[place].append({ 'id': widget['id'], 'name': widget['name'], 'description': widget['description'], 'template': widget['template'], 'icon': widget.get('icon', 'leaf'), 'read_only': widget.get('read_only', False), 'options': widget.get('options', None), 'picture': os.path.join( os.path.join( '/static/plugins/', plugin_name), widget.get('picture', '')), 'base_uri': route_url, 'function': f }) logger.info("Found widget '%s' for %s", widget['id'], place) # It's a valid widget entry if it got all data, and at least one route if 'tables' in entry: for table in entry.get('tables'): if 'id' not in table or 'for' not in table: continue if 'name' not in table or 'description' not in table: continue if 'template' not in table or not page_route: continue for place in table['for']: if place not in self.tables: self.tables[place] = [] self.tables[place].append({ 'id': table['id'], 'name': table['name'], 'description': table['description'], 'template': table['template'], 'icon': table.get('icon', 'leaf'), 'base_uri': page_route, 'function': f, 'actions': table.get('actions', {}) }) logger.info("Found table '%s' for %s", table['id'], place) # Add the views sub-directory of the plugin in the Bottle templates path dir_views = os.path.join( os.path.join(plugins_dir, plugin_name), 'views') if os.path.isdir(dir_views): TEMPLATE_PATH.append( os.path.join(os.path.join(plugins_dir, plugin_name), 'views')) logger.debug( "register views directory '%s'", os.path.join(os.path.join(plugins_dir, plugin_name), 'views')) # Self register in the plugin so the pages can get my data plugin.webui = self # Load/set plugin configuration f = getattr(plugin, 'load_config', None) if f and callable(f): logger.info( "plugin '%s' needs to load its configuration. Configuring...", plugin_name) cfg_files = [ '/usr/local/etc/%s/plugin_%s.cfg' % (self.app_config['name'].lower(), plugin_name), '/etc/%s/plugin_%s.cfg' % (self.app_config['name'].lower(), plugin_name), '~/%s/plugin_%s.cfg' % (self.app_config['name'].lower(), plugin_name), os.path.join(os.path.join(plugins_dir, plugin_name), 'settings.cfg') ] config = f(app, cfg_files) if config: logger.info("plugin '%s' configured.", plugin_name) else: # pragma: no cover - if any ... logger.warning("plugin '%s' configuration failed.", plugin_name) i += 1 self.plugins.append({'name': plugin_name, 'module': plugin}) logger.info("registered plugin '%s'", plugin_name) except Exception as e: # pragma: no cover - simple security ... logger.error("loading plugin %s, exception: %s", plugin_name, str(e)) logger.error("traceback: %s", traceback.format_exc()) logger.info("loaded %d plugins from: %s", i, plugins_dir) # exit() return i
def load_plugin(self, fdir, plugin_dir): logger.debug("[WebUI] loading plugin %s ...", fdir) try: # Put the full qualified path of the module we want to load # for example we will give webui/plugins/eltdetail/ mod_path = os.path.join(plugin_dir, fdir) # Then we load the plugin.py inside this directory m = imp.load_module('%s' % (fdir), *imp.find_module(fdir, [mod_path])) m_dir = os.path.abspath(os.path.dirname(m.__file__)) sys.path.append(m_dir) for (f, entry) in m.pages.items(): logger.debug("[WebUI] entry: %s", entry) # IMPORTANT: apply VIEW BEFORE route! view = entry.get('view', None) if view: f = bottle.view(view)(f) # Maybe there is no route to link, so pass route = entry.get('route', None) name = entry.get('name', None) search_engine = entry.get('search_engine', False) if route: method = entry.get('method', 'GET') # Ok, we will just use the lock for all # plugin page, but not for static objects # so we set the lock at the function level. f = webui_app.route(route, callback=self.lockable_function(f), method=method, name=name, search_engine=search_engine) # If the plugin declare a static entry, register it # and remember: really static! because there is no lock # for them! static = entry.get('static', False) if static: self.add_static_route(fdir, m_dir) # It's a valid widget entry if it got all data, and at least one route # ONLY the first route will be used for Add! widget_lst = entry.get('widget', []) widget_desc = entry.get('widget_desc', None) widget_name = entry.get('widget_name', None) widget_picture = entry.get('widget_picture', None) deprecated = entry.get('deprecated', False) if widget_name and widget_desc and widget_lst != [] and route: for place in widget_lst: if place not in self.widgets: self.widgets[place] = [] self.widgets[place].append({ 'widget_name': widget_name, 'widget_desc': widget_desc, 'base_uri': route, 'widget_picture': widget_picture, 'deprecated': deprecated }) # And we add the views dir of this plugin in our TEMPLATE # PATH logger.info("[WebUI] plugin views dir: %s", os.path.join(m_dir, 'views')) bottle.TEMPLATE_PATH.append(os.path.join(m_dir, 'views')) # And finally register me so the pages can get data and other # useful stuff m.app = self # Load/set plugin configuration f = getattr(m, 'load_config', None) if f and callable(f): logger.debug("[WebUI] calling plugin %s, load configuration", fdir) f(self) logger.info("[WebUI] loaded plugin %s", fdir) except Exception, exp: logger.error("[WebUI] loading plugin %s, exception: %s", fdir, str(exp))
from bottle import route, run from bottle import mako_view as view from bottle import mako_template as template from bottle import request from bottle import static_file from bottle import HTTPError from application import uploader from settings import MEDIA_ROOT from utils import save_file from utils import AttrDict @uploader.get('/', name='home', apply=[view('uploader/index.mako')]) def index(rdb): file_ids = rdb.lrange('file:global:ids', -11, -1) or [ ] # get ids of last files file_ids.reverse() files = [] for file_id in file_ids: obj = rdb.hgetall('file:%s:data' % file_id) obj = AttrDict(obj) files.append(obj) return { 'files': files, 'url': uploader.get_url, }
from bottle import mako_view as view from bottle import get from bottle import static_file from bottle import url from settings import STATIC_ROOT @get('/static/:path#.+#', name='static_file') def static(path): return static_file(path, root = STATIC_ROOT) @get('/', name='home', apply=[view('index.mako')]) def index(): return { 'url' : url, }