Example #1
0
    def include_files(self, extensions=None):
        """
        Includes files (usually in the head).
        Can minify and cache local files
        By default, caches in ram for 5 minutes. To change,
        response.cache_includes = (cache_method, time_expire).
        Example: (cache.disk, 60) # caches to disk for 1 minute.
        """
        app = current.request.application

        # We start by building a files list in which adjacent files internal to
        # the application are placed in a list inside the files list.
        #
        # We will only minify and concat adjacent internal files as there's
        # no way to know if changing the order with which the files are apppended
        # will break things since the order matters in both CSS and JS and 
        # internal files may be interleaved with external ones.
        files = []
        # For the adjacent list we're going to use storage List to both distinguish
        # from the regular list and so we can add attributes
        internal = List()  
        internal.has_js = False
        internal.has_css = False
        done = set() # to remove duplicates
        for item in self.files:
            if not isinstance(item, list):
                if item in done:
                    continue
                done.add(item)
            if isinstance(item, (list, tuple)) or not item.startswith('/' + app): # also consider items in other web2py applications to be external
                if internal:
                    files.append(internal)
                    internal = List()
                    internal.has_js = False
                    internal.has_css = False
                files.append(item)
                continue
            if extensions and not item.rpartition('.')[2] in extensions:
                continue
            internal.append(item)
            if item.endswith('.js'):
                internal.has_js = True
            if item.endswith('.css'):
                internal.has_css = True            
        if internal:
            files.append(internal)

        # We're done we can now minify
        if have_minify:
            for i, f in enumerate(files):
                if isinstance(f, List) and ((self.optimize_css and f.has_css) or (self.optimize_js and f.has_js)):
                    # cache for 5 minutes by default
                    key = hashlib_md5(repr(f)).hexdigest()
                    cache = self.cache_includes or (current.cache.ram, 60 * 5)
                    def call_minify(files=f):
                        return List(minify.minify(files,
                                             URL('static', 'temp'),
                                             current.request.folder,
                                             self.optimize_css,
                                             self.optimize_js))
                    if cache:
                        cache_model, time_expire = cache
                        files[i] = cache_model('response.files.minified/' + key,
                                            call_minify,
                                            time_expire)
                    else:
                        files[i] = call_minify()
        
        def static_map(s, item):
            if isinstance(item, str):
                f = item.lower().split('?')[0]
                ext = f.rpartition('.')[2]
                # if static_version we need also to check for
                # static_version_urls. In that case, the _.x.x.x
                # bit would have already been added by the URL()
                # function
                if self.static_version and not self.static_version_urls:
                    item = item.replace(
                        '/static/', '/static/_%s/' % self.static_version, 1)
                tmpl = template_mapping.get(ext)
                if tmpl:
                    s.append(tmpl % item)
            elif isinstance(item, (list, tuple)):
                f = item[0]
                tmpl = template_mapping.get(f)
                if tmpl:
                    s.append(tmpl % item[1])

        s = []
        for item in files:
            if isinstance(item, List):
                for f in item:
                    static_map(s, f)
            else:
                static_map(s, item)
        self.write(''.join(s), escape=False)
Example #2
0
    def include_files(self, extensions=None):
        """
        Includes files (usually in the head).
        Can minify and cache local files
        By default, caches in ram for 5 minutes. To change,
        response.cache_includes = (cache_method, time_expire).
        Example: (cache.disk, 60) # caches to disk for 1 minute.
        """
        files = []
        ext_files = []
        has_js = has_css = False
        for item in self.files:
            if isinstance(item, (list, tuple)):
                ext_files.append(item)
                continue
            if extensions and not item.rpartition('.')[2] in extensions:
                continue
            if item in files:
                continue
            if item.endswith('.js'):
                has_js = True
            if item.endswith('.css'):
                has_css = True
            files.append(item)

        if have_minify and ((self.optimize_css and has_css) or (self.optimize_js and has_js)):
            # cache for 5 minutes by default
            key = hashlib_md5(repr(files)).hexdigest()
            cache = self.cache_includes or (current.cache.ram, 60 * 5)

            def call_minify(files=files):
                return minify.minify(files,
                                     URL('static', 'temp'),
                                     current.request.folder,
                                     self.optimize_css,
                                     self.optimize_js)
            if cache:
                cache_model, time_expire = cache
                files = cache_model('response.files.minified/' + key,
                                    call_minify,
                                    time_expire)
            else:
                files = call_minify()

        files.extend(ext_files)
        s = []
        for item in files:
            if isinstance(item, str):
                f = item.lower().split('?')[0]
                ext = f.rpartition('.')[2]
                # if static_version we need also to check for
                # static_version_urls. In that case, the _.x.x.x
                # bit would have already been added by the URL()
                # function
                if self.static_version and not self.static_version_urls:
                    item = item.replace(
                        '/static/', '/static/_%s/' % self.static_version, 1)
                tmpl = template_mapping.get(ext)
                if tmpl:
                    s.append(tmpl % item)
            elif isinstance(item, (list, tuple)):
                f = item[0]
                tmpl = template_mapping.get(f)
                if tmpl:
                    s.append(tmpl % item[1])

        self.write(''.join(s), escape=False)
Example #3
0
            def wrapped_f():
                if current.request.env.request_method != 'GET':
                    return func()

                if quick:
                    session_ = True if 'S' in quick else False
                    vars_ = True if 'V' in quick else False
                    lang_ = True if 'L' in quick else False
                    user_agent_ = True if 'U' in quick else False
                    public_ = True if 'P' in quick else False
                else:
                    (session_, vars_, lang_, user_agent_, public_) = \
                        (session, vars, lang, user_agent, public)

                expires = 'Fri, 01 Jan 1990 00:00:00 GMT'
                if time_expire:
                    cache_control = 'max-age=%(time_expire)s, s-maxage=%(time_expire)s' % dict(time_expire=time_expire)
                    expires = (current.request.utcnow + datetime.timedelta(seconds=time_expire)).strftime(
                        '%a, %d %b %Y %H:%M:%S GMT')
                else:
                    cache_control = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
                cache_control += ', public' if not session_ and public_ else ', private'

                if cache_model:
                    # figure out the correct cache key
                    cache_key = [current.request.env.path_info, current.response.view]
                    if session_:
                        cache_key.append(current.response.session_id)
                    elif user_agent_:
                        if user_agent_ is True:
                            cache_key.append("%(is_mobile)s_%(is_tablet)s" % current.request.user_agent())
                        else:
                            cache_key.append(str(list(user_agent_.items())))
                    if vars_:
                        cache_key.append(current.request.env.query_string)
                    if lang_:
                        cache_key.append(current.T.accepted_language)
                    cache_key = hashlib_md5('__'.join(cache_key)).hexdigest()
                    if prefix:
                        cache_key = prefix + cache_key
                    try:
                        # action returns something
                        rtn = cache_model(cache_key, lambda: func(), time_expire=time_expire)
                        http, status = None, current.response.status
                    except HTTP as e:
                        # action raises HTTP (can still be valid)
                        rtn = cache_model(cache_key, lambda: e.body, time_expire=time_expire)
                        http, status = HTTP(e.status, rtn, **e.headers), e.status
                    else:
                        # action raised a generic exception
                        http = None
                else:
                    # no server-cache side involved
                    try:
                        # action returns something
                        rtn = func()
                        http, status = None, current.response.status
                    except HTTP as e:
                        # action raises HTTP (can still be valid)
                        status = e.status
                        http = HTTP(e.status, e.body, **e.headers)
                    else:
                        # action raised a generic exception
                        http = None
                send_headers = False
                if http and isinstance(valid_statuses, list):
                    if status in valid_statuses:
                        send_headers = True
                elif valid_statuses is None:
                    if str(status)[0] in '123':
                        send_headers = True
                if send_headers:
                    headers = {'Pragma': None,
                               'Expires': expires,
                               'Cache-Control': cache_control}
                    current.response.headers.update(headers)
                if cache_model and not send_headers:
                    # we cached already the value, but the status is not valid
                    # so we need to delete the cached value
                    cache_model(cache_key, None)
                if http:
                    if send_headers:
                        http.headers.update(current.response.headers)
                    raise http
                return rtn
Example #4
0
    def include_files(self, extensions=None):
        """
        Includes files (usually in the head).
        Can minify and cache local files
        By default, caches in ram for 5 minutes. To change,
        response.cache_includes = (cache_method, time_expire).
        Example: (cache.disk, 60) # caches to disk for 1 minute.
        """
        app = current.request.application

        # We start by building a files list in which adjacent files internal to
        # the application are placed in a list inside the files list.
        #
        # We will only minify and concat adjacent internal files as there's
        # no way to know if changing the order with which the files are apppended
        # will break things since the order matters in both CSS and JS and
        # internal files may be interleaved with external ones.
        files = []
        # For the adjacent list we're going to use storage List to both distinguish
        # from the regular list and so we can add attributes
        internal = List()
        internal.has_js = False
        internal.has_css = False
        done = set() # to remove duplicates
        for item in self.files:
            if not isinstance(item, list):
                if item in done:
                    continue
                done.add(item)
            if isinstance(item, (list, tuple)) or not item.startswith('/' + app): # also consider items in other web2py applications to be external
                if internal:
                    files.append(internal)
                    internal = List()
                    internal.has_js = False
                    internal.has_css = False
                files.append(item)
                continue
            if extensions and not item.rpartition('.')[2] in extensions:
                continue
            internal.append(item)
            if item.endswith('.js'):
                internal.has_js = True
            if item.endswith('.css'):
                internal.has_css = True
        if internal:
            files.append(internal)

        # We're done we can now minify
        if have_minify:
            for i, f in enumerate(files):
                if isinstance(f, List) and ((self.optimize_css and f.has_css) or (self.optimize_js and f.has_js)):
                    # cache for 5 minutes by default
                    key = hashlib_md5(repr(f)).hexdigest()
                    cache = self.cache_includes or (current.cache.ram, 60 * 5)
                    def call_minify(files=f):
                        return List(minify.minify(files,
                                             URL('static', 'temp'),
                                             current.request.folder,
                                             self.optimize_css,
                                             self.optimize_js))
                    if cache:
                        cache_model, time_expire = cache
                        files[i] = cache_model('response.files.minified/' + key,
                                            call_minify,
                                            time_expire)
                    else:
                        files[i] = call_minify()

        def static_map(s, item):
            if isinstance(item, str):
                f = item.lower().split('?')[0]
                ext = f.rpartition('.')[2]
                # if static_version we need also to check for
                # static_version_urls. In that case, the _.x.x.x
                # bit would have already been added by the URL()
                # function
                if self.static_version and not self.static_version_urls:
                    item = item.replace(
                        '/static/', '/static/_%s/' % self.static_version, 1)
                tmpl = template_mapping.get(ext)
                if tmpl:
                    s.append(tmpl % item)
            elif isinstance(item, (list, tuple)):
                f = item[0]
                tmpl = template_mapping.get(f)
                if tmpl:
                    s.append(tmpl % item[1])

        s = []
        for item in files:
            if isinstance(item, List):
                for f in item:
                    static_map(s, f)
            else:
                static_map(s, item)
        self.write(''.join(s), escape=False)
Example #5
0
    def include_files(self, extensions=None):
        """
        Includes files (usually in the head).
        Can minify and cache local files
        By default, caches in ram for 5 minutes. To change,
        response.cache_includes = (cache_method, time_expire).
        Example: (cache.disk, 60) # caches to disk for 1 minute.
        """
        files = []
        ext_files = []
        has_js = has_css = False
        for item in self.files:
            if isinstance(item, (list, tuple)):
                ext_files.append(item)
                continue
            if extensions and not item.rpartition('.')[2] in extensions:
                continue
            if item in files:
                continue
            if item.endswith('.js'):
                has_js = True
            if item.endswith('.css'):
                has_css = True
            files.append(item)

        if have_minify and ((self.optimize_css and has_css) or (self.optimize_js and has_js)):
            # cache for 5 minutes by default
            key = hashlib_md5(repr(files)).hexdigest()
            cache = self.cache_includes or (current.cache.ram, 60 * 5)

            def call_minify(files=files):
                return minify.minify(files,
                                     URL('static', 'temp'),
                                     current.request.folder,
                                     self.optimize_css,
                                     self.optimize_js)
            if cache:
                cache_model, time_expire = cache
                files = cache_model('response.files.minified/' + key,
                                    call_minify,
                                    time_expire)
            else:
                files = call_minify()

        files.extend(ext_files)
        s = []
        for item in files:
            if isinstance(item, str):
                f = item.lower().split('?')[0]
                ext = f.rpartition('.')[2]
                # if static_version we need also to check for
                # static_version_urls. In that case, the _.x.x.x
                # bit would have already been added by the URL()
                # function
                if self.static_version and not self.static_version_urls:
                    item = item.replace(
                        '/static/', '/static/_%s/' % self.static_version, 1)
                tmpl = template_mapping.get(ext)
                if tmpl:
                    s.append(tmpl % item)
            elif isinstance(item, (list, tuple)):
                f = item[0]
                tmpl = template_mapping.get(f)
                if tmpl:
                    s.append(tmpl % item[1])

        self.write(''.join(s), escape=False)
Example #6
0
            def wrapped_f():
                if current.request.env.request_method != 'GET':
                    return func()

                if quick:
                    session_ = True if 'S' in quick else False
                    vars_ = True if 'V' in quick else False
                    lang_ = True if 'L' in quick else False
                    user_agent_ = True if 'U' in quick else False
                    public_ = True if 'P' in quick else False
                else:
                    (session_, vars_, lang_, user_agent_, public_) = \
                        (session, vars, lang, user_agent, public)

                expires = 'Fri, 01 Jan 1990 00:00:00 GMT'
                if time_expire:
                    cache_control = 'max-age=%(time_expire)s, s-maxage=%(time_expire)s' % dict(
                        time_expire=time_expire)
                    expires = (current.request.utcnow +
                               datetime.timedelta(seconds=time_expire)
                               ).strftime('%a, %d %b %Y %H:%M:%S GMT')
                else:
                    cache_control = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
                cache_control += ', public' if not session_ and public_ else ', private'

                if cache_model:
                    # figure out the correct cache key
                    cache_key = [
                        current.request.env.path_info, current.response.view
                    ]
                    if session_:
                        cache_key.append(current.response.session_id)
                    elif user_agent_:
                        if user_agent_ is True:
                            cache_key.append("%(is_mobile)s_%(is_tablet)s" %
                                             current.request.user_agent())
                        else:
                            cache_key.append(str(list(user_agent_.items())))
                    if vars_:
                        cache_key.append(current.request.env.query_string)
                    if lang_:
                        cache_key.append(current.T.accepted_language)
                    cache_key = hashlib_md5('__'.join(cache_key)).hexdigest()
                    if prefix:
                        cache_key = prefix + cache_key
                    try:
                        # action returns something
                        rtn = cache_model(cache_key,
                                          lambda: func(),
                                          time_expire=time_expire)
                        http, status = None, current.response.status
                    except HTTP as e:
                        # action raises HTTP (can still be valid)
                        rtn = cache_model(cache_key,
                                          lambda: e.body,
                                          time_expire=time_expire)
                        http, status = HTTP(e.status, rtn,
                                            **e.headers), e.status
                    else:
                        # action raised a generic exception
                        http = None
                else:
                    # no server-cache side involved
                    try:
                        # action returns something
                        rtn = func()
                        http, status = None, current.response.status
                    except HTTP as e:
                        # action raises HTTP (can still be valid)
                        status = e.status
                        http = HTTP(e.status, e.body, **e.headers)
                    else:
                        # action raised a generic exception
                        http = None
                send_headers = False
                if http and isinstance(valid_statuses, list):
                    if status in valid_statuses:
                        send_headers = True
                elif valid_statuses is None:
                    if str(status)[0] in '123':
                        send_headers = True
                if send_headers:
                    headers = {
                        'Pragma': None,
                        'Expires': expires,
                        'Cache-Control': cache_control
                    }
                    current.response.headers.update(headers)
                if cache_model and not send_headers:
                    # we cached already the value, but the status is not valid
                    # so we need to delete the cached value
                    cache_model(cache_key, None)
                if http:
                    if send_headers:
                        http.headers.update(current.response.headers)
                    raise http
                return rtn