def enable(self, route='auth/', uses=(), env=None): """enables Auth, aka generates login/logout/register/etc pages""" self.route = route """This assumes the bottle framework and exposes all actions as /{app_name}/auth/{path}""" def responder(path, env=env): return self.action(path, request.method, request.query, request.json, env=env) action(route + '<path:path>', method=['GET','POST'])(action.uses(self, *uses)(responder))
def __init__(self, path, session, search_placeholder=None, signer=None, db=None, auth=None): """ Displays a grid. :param path: Path where the grid is loaded via AJAX. :param session: used by the signer. :param signer: singer for URLs. :param db: specify a db if you need it added as widget. :param auth: specify auth if you need it added as widget. """ self.path = path self.search_placeholder = search_placeholder self.signer = signer or URLSigner(session) # Creates an action (an entry point for URL calls), # mapped to the api method, that can be used to request pages # for the table. self.__prerequisites__ = [session] args = list(filter(None, [session, db, auth, self.signer.verify()])) f = action.uses(*args)(self.api) action(self.path, method=["GET"])(f)
def __init__(self, url, session, signer=None, db=None, auth=None, dumpDir="dump"): self.dumpDir = dumpDir self.url = url self.signer = signer or URLSigner(session) self.__prerequisites__ = [session] args = list(filter(None, [session, db, auth, self.signer.verify()])) f = action.uses(*args)(self.api) action(self.url + "/<id>", method=["POST"])(f)
def __init__(self, db, policy=None, auth=None, path="service/{uuid}/<tablename>"): self.db = db self.policy = policy self.restapi = RestAPI(self.db, policy) self.path = path.format(uuid=str(uuid.uuid4())) args = [db, auth] if auth else [db] f = action.uses(*args)(self.api) f = action(self.path, method=["GET", "POST"])(f) f = action(self.path + "/<id:int>", method=["PUT", "DELETE"])(f)
def enable(self, route='auth/'): self.route = route """This assumes the bottle framework and exposes all actions as /{app_name}/auth/{path}""" def responder(path): return self.action(path, request.method, request.query, request.json) action(route + '<path:path>', method=['GET', 'POST'])(action.uses(self)(responder))
def __init__(self, path, session, signer=None, db=None, auth=None): self.path = path self.signer = signer or URLSigner(session) # Creates an action (an entry point for URL calls), # mapped to the api method, that can be used to request pages # for the table. self.__prerequisites__ = [session] args = list(filter(None, [session, db, auth, self.signer.verify()])) f = action.uses(*args)(self.api) action(self.path + "/<id>", method=["POST"])(f)
def __init__(self, url, session, signer=None, db=None, auth=None): self.url = url + '/get' self.callback_url = url + '/set' self.signer = signer or URLSigner(session) self.__prerequisites__ = [session] args = list(filter(None, [session, db, auth, self.signer.verify()])) func = action.uses(*args)(self.get_rating) action(self.url + '/<id>', method=['GET'])(func) func = action.uses(*args)(self.set_rating) action(self.callback_url + '/<id>', method=["GET"])(func)
def __init__(self, db, policy=None, auth=None, path='service/{uuid}/<tablename>'): self.db = db self.policy = policy self.restapi = RestAPI(self.db, policy) self.path = path.format(uuid=str(uuid.uuid4())) args = [db, auth] if auth else [db] f = action.uses(*args)(self.api) f = action(self.path, method=['GET', 'POST'])(f) f = action(self.path + '/<id:int>', method=['PUT', 'DELETE'])(f)
def __init__(self, url, session, signer=None, db=None, auth=None): self.url = url + '/get' self.callback_url = url + '/set' self.signer = signer or URLSigner(session) # Creates an action (an entry point for URL calls), # mapped to the api method, that can be used to request pages # for the table. self.__prerequisites__ = [session] args = list(filter(None, [session, db, auth, self.signer.verify()])) f = action.uses(*args)(self.get_rating) action(self.url + "/<id>", method=["GET"])(f) f = action.uses(*args)(self.set_rating) action(self.callback_url + "/<id>", method=["GET"])(f)
def make_action(func, path=path, method=method, template=template): if not path: path = func.__name__ for name in func.__code__.co_varnames[: func.__code__.co_argcount]: path += "/<%s>" % name fixtures = [f for f in self.fixtures] if template is None: template = func.__name__ + ".html" if template: fixtures.append(template) new_func = action.uses(*fixtures)(func) action(path, method=method)(new_func) return func
def __init__(self, url, session, signer=None, db=None, auth=None): self.get_url = url + '/get' self.add_url = url + '/add' self.edit_url = url + '/edit' self.delete_url = url + '/delete' self.signer = signer or URLSigner(session) self.db = db self.auth = auth # creates actions (entry points of the calls) # same as decorators but registered on object creation # very similar to Luca's old component creation self.__prerequisites__ = [session] args = list(filter(None, [session, db, auth, self.signer.verify()])) # function definition f = action.uses(*args)(self.get_comments) action(self.get_url + "/<id>", method=["GET"])(f) f = action.uses(*args)(self.add_comment) action(self.add_url, method=["POST"])(f) f = action.uses(*args)(self.edit_comment) action(self.edit_url, method=["POST"])(f) f = action.uses(*args)(self.delete_comment) action(self.delete_url, method=["POST"])(f)
def __init__(self, path, session, signer=None, db=None, auth=None): """ :param path: path at which the star rating does the AJAX calls :param session: session, used to validate access and sign. :param signer: A URL signer, or else one is created. :param db: Used in case db should be one of the widgets. :param auth: Used in case auth should be one of the widgets. """ self.path = path self.signer = signer or URLSigner(session) # Creates an action (an entry point for URL calls), # mapped to the api method, that can be used to request pages # for the table. self.__prerequisites__ = [session] args = list(filter(None, [session, db, auth, self.signer.verify()])) f = action.uses(*args)(self.get_stars) action(self.path + "/<id>", method=["GET"])(f) f = action.uses(*args)(self.set_stars) action(self.path + "/<id>", method=["POST"])(f)
def __init__( self, path, session, use_id=False, search_placeholder=None, signer=None, db=None, sort_fields=None, default_sort=None, auth=None, page_size=20, ): """ Displays a grid. :param path: Path where the grid is loaded via AJAX. :param session: used by the signer. :param signer: singer for URLs. :param use_id: does the AJAX call come with an id? :param db: specify a db if you need it added as widget. :param sort_fields: list of fields that are sortable. If a field is not sortable, use None. E.g.: [db.user.name, None, db.user.email] :param default_sort: array that indicates the default sorting order. :param auth: specify auth if you need it added as widget. """ assert session is not None, "You must provide a session." self.path = path self.search_placeholder = search_placeholder self.signer = signer or URLSigner(session) # Creates an action (an entry point for URL calls), # mapped to the api method, that can be used to request pages # for the table. self.use_id = use_id self.__prerequisites__ = [self.signer] args = list(filter(None, [session, db, auth, self.signer.verify()])) f = action.uses(*args)(self.api) p = "/".join([self.path, "<id>"]) if use_id else self.path action(p, method=["GET"])(f) # Some defaults. Over-ride them in subclasses. self.sort_fields = sort_fields self.default_sort = default_sort self.page_size = page_size
def __init__(self, path, session, fields_or_table, redirect_url=None, readonly=False, signer=None, db=None, auth=None, url_params=None, validate=None): """fields_or_table is a list of Fields from DAL, or a table. If a table is passed, the fields that are marked writable (or readable, if readonly=True) are included. session is used to sign the URLs. The other parameters are optional, and are used only if they will be needed to process the get and post metods. @param path: path used for form GET/POST @param session: session, used to validate access and sign. @param fields_or_table: list of Field for a database table, or table itself. @param redirect_url: redirect URL after success. @param readonly: If true, the form is readonly. @param signer: signer for URLs, or else, a new signer is created. @param db: database. Used by implementation. @param auth: auth. Used by implementation. @param url_params: parameters for AJAX URLs. @param validate: A function that takes as arguments the dictionary of fields, and performs any desired extra validation. If an error is set, then the form is not acted upon, and the error is shown to the user. """ self.path_form = path + '/form' self.path_check = path + '/check' self.redirect_url = redirect_url self.db = db self.__prerequisites__ = [session] self.signer = signer or URLSigner(session) self.validate = validate # Creates entry points for giving the blank form, and processing form submissions. # There are three entry points: # - Form setup GET: This gets how the form is set up, including the types of the fields. # - Form GET: This gets the values of the fields. # - Form PUT: This gives the values of the fields, and performs whatever # action needs to be peformed. # This division is done so that the GET and PUT action, but not the setup_GET, # need to be over-ridden when the class is subclassed. url_params = url_params or [] # NOTE: we need a list below, as the iterator otherwise can be used only once. # Iterators by default are a very lame idea indeed. args = list(filter(None, [session, db, auth, self.signer.verify()])) f = action.uses(*args)(self.get) action('/'.join([self.path_form] + url_params), method=["GET"])(f) f = action.uses(*args)(self.post) action('/'.join([self.path_form] + url_params), method=["POST"])(f) f = action.uses(*args)(self.validate_field) action('/'.join([self.path_check] + url_params), method=["POST"])(f) # Stores the parameters that are necessary for creating the form. # Generates the list of field descriptions. self.readonly = readonly self.fields = collections.OrderedDict() for field in fields_or_table: self.fields[field.name] = dict( field=field, # Field in the form specification. error=None, # Any error found. value=None, validated_value=None, )
def __init__(self, url, session, signer=None, db=None, auth=None): # Creating generic get/set URLS self.url = url + '/get' self.callback_url = url + '/set' # Setting URL Signer self.signer = signer or URLSigner(session) # self.__prerequisites__ = [session] # Set each element to None in args args = list(filter(None, [session, db, auth, self.signer.verify()])) # *var in a function call unpacks a list or tuple into positional arguments # Gets the rating from database based on id # Equivalent of: # @action('url/<id>', method=["GET"]) # @action.uses(session, db, auth, signer.verify()) # def get_thumb(): f = action.uses(*args)(self.get_rating) action(self.url + "/<id>", method=["GET"])(f) # Sets/Updates the rating in database based on id # Equivalent of: # @action('callback_url</id>', method=["GET"]) # @action.uses(session, db, auth, signer.verify()) # def set_thumb(): f = action.uses(*args)(self.set_rating) action(self.callback_url + "/<id>", method=["GET"])(f)
def decorator(func): nonlocal path if not path: name = path = func.__name__ else: name = path.split('/')[0] if name not in self.routes: self.routes.append(name) @functools.wraps(func) def wrapper(*args, **kwargs): if request.query.get('is_spa'): response.set_header('X-py4web-spa',name) return func(*args, **kwargs) return self.main_pg() return action(path)(wrapper)
def define_routes(self, args, method, url, class_func): func = action.uses(*args)(class_func) action(url, method=method)(func)
def create_route(self, url, method, protocol): func = action.uses(*self.args)(method) action(url, method=[protocol])(func)