Coder Social home page Coder Social logo

frozen-flask / frozen-flask Goto Github PK

View Code? Open in Web Editor NEW
784.0 18.0 78.0 431 KB

Freezes a Flask application into a set of static files.

Home Page: https://frozen-flask.readthedocs.io

License: Other

Python 99.46% CSS 0.06% HTML 0.44% JavaScript 0.03%
python flask static-site-generation

frozen-flask's Introduction

Frozen-Flask

Freezes a Flask application into a set of static files. The result can be hosted without any server-side software other than a traditional web server.

See documentation: https://frozen-flask.readthedocs.io/

Contributing

  • Fork the upstream repository and clone your fork
  • Create a feature branch for the thing you want to work on
  • Create a virtual environment and activate it
  • Run pip install -e .[doc,test,check] to install dependencies
  • Add your changes
  • Make sure tests pass with pytest
  • Make sure you followed the style guide with flake8 and isort
  • Send a pull request to the upstream repository

You can also use Hatch to automatically install dependencies, launch tests, check style and build documentation:

$ hatch run test:run
$ hatch run check:run
$ hatch run doc:build

Status

This project is currently maintained by CourtBouillon.

It’s been previously maintained by @honzajavorek and @tswast, and has been originally created by @SimonSapin.

License

Frozen-Flask uses a BSD 3-clause license. See LICENSE.

Copyrights are retained by their contributors, no copyright assignment is required to contribute to Frozen-Flask. Unless explicitly stated otherwise, any contribution intentionally submitted for inclusion is licensed under the BSD 3-clause license, without any additional terms or conditions. For full authorship information, see the version control history.

frozen-flask's People

Contributors

benvinegar avatar christianp avatar encukou avatar equalsraf avatar goutte avatar heyimalex avatar homeworkprod avatar honzajavorek avatar hroncok avatar jayaddison avatar jokull avatar kartikchugh avatar lize avatar massood avatar max-k avatar mblayman avatar mgorny avatar mivade avatar rduplain avatar siecje avatar simonsapin avatar singingwolfboy avatar smbsimon avatar timgates42 avatar tswast avatar vaus avatar zmwangx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

frozen-flask's Issues

Support duplication of static files to root directory

There are a few URLs that certain clients give special treatment to: for example, /favicon.ico and /apple-touch-icon.png. I have these files in my static directory, and I want them to be accessible under /static/favicon.ico and /static/apple-touch-icon.png, but I also want the special root-level URL versions to work. As a result, I have this code in my views, to explicitly indicate the root-level URLs:

from functools import partial
from myapp import app
ROOT_ASSETS = ("favicon.ico", "apple-touch-icon.png")

for asset in ROOT_ASSETS:
    url = "/"+asset
    name = asset.replace(".", "_")
    app.add_url_rule(url, name, partial(app.send_static_file, filename=asset))

I would expect that using frozen_flask to freeze this project would result in two copies of these static files: one in the root of the build directory, and one the static directory inside of the build directory. In fact, the files appear only in the latter location, not the former.

Feature Request : Skip existing files

Hello !

I'm generating a huge website (the generation can take several days, and yes I optimized it as best as I can) ; some pages are quite long to generate (about half a minute).

I plan on adding more pages in the future, and I'd rather not re-generate everything every time.
I know I can mess with my URL generators to hack that feature, but it's dirty and not good design. Besides, I have to guess what the output file's name will be, and frozen-flask already knows this internally.

So I'm suggesting a FREEZER_SKIP_EXISTING configuration option, defaulted to False. Is this doable ? Would you agree ?

Relative URLs are only generated with Jinja templates

I noticed that the relative URL feature only modifies the url_for method in the Jinja environment. I have URLs that I generate internally in my Flask app (because I'm rendering some Markdown with custom links before sending to the Jinja template) with url_for, but they don't benefit from relative_url_for wrapper within frozen_flask.

I looked for other potential ways to do this so that the call would work regardless of where url_for is called. In Flask's url_for, it builds a URL by calling a url_adapter that it pulls from the request context. I'm wondering if request context could be modified to supply a different url_adapter. The current behavior in relative_url_for would need to be pushed down into url_adapter's build method.

Totally silent logger

I'm trying to make frozen flask go completely silent with regard to logging because I'm attempting to integrate it into a tool that I'm writing. Even when I set log_url_for to False, I'm still getting some output from a route (I think it's the index, but I'm not sure how to narrow it down).

I would love to see frozen flask be able to completely suppress all command line output.

Creating 9 million static pages - how to?

I am trying to find a solution to a problem and wondered if frozen-flask could be that solution. My company has been asked to create a lot of pages for a travel site, nearly 9 million (!) that are the same template but contain different data taken from an API call. We'd ideally like to serve them statically because of the expensive API call and to reduce server load. Now to query the API to fetch the data to generate the template takes in order of 0.1 of a second on average so it could take 10 days or something to create all the pages! So my question is: is Frozen Flask only designed to create the static pages in "a oner" or can it be configured somehow to chew through the page creation in a batch as a job or can it go live like a regular Flask app and when a page is requested a static version is created and the next time that url is queried the static version is served?

Version name

The documentation says the current version is 0.1, following 0.9, 0.8, 0.7... The current version should be v1.0, right?

FREEZER_REDIRECT_POLICY=meta

I would like to add another redirect policy called meta. It would create a HTML page with a meta refresh tag. Something like:

<html>
  <head>
    <meta http-equiv="refresh" content="0;url=http://example.com/foo/" />
    <link rel="canonical" href="http://example.com/foo/" />
  </head>
</html>

Would such change be accepted?

Relative URLs without /index.html ?

Hello,
is it possible to add option like FREEZER_RELATIVE_URLS_WITHOUT_INDEX, which would disable adding index.html to paths like ../foobar/? Because I develop application which is then frozen and served as normal website. I need relative urls, because it's not placed in web root, but I don't like that index.html.
I tried removing lines 533 and 534, but it created urls like /foobar. Can you please help?
Thanks, m.volfik

405-errors cause `freeze` to fail

As of v0.13 the crawler in the _build_one-function will cause the application to fail if it receives any response codes other than 200, 404, 301, or 302. I believe this may be intended to catch response errors in the 500-range because an unresponsive server shouldn't be processed, however applications with endpoints that allow POST-requests but not GET-requests will always fail. Likewise, 403-errors would also cause the application to fail.

I believe it may be better to either explicitly catch errors in the 500-range, or add a configuration-option to ignore all 400-errors (like FREEZER_IGNORE_404_NOT_FOUND).

[Feature Request] Compile to single page js app.

Hi! It would be amazing if frozen-flask could compile the generated static files into a single html file (single page app), with routing controlled by one of the many js frameworks (Angular, React, Ember etc.).

Ignore endpoints in no_argument_rules()?

I'm currently using Frozen-Flask to generate static content for my website, to be served by Nginx. However, I'm also using flask running normally provide dynamic content for the website. With nginx's 'try_urls' ability, if Frozen-Flask generates a static page it's served by nginx, otherwise the request is forwarded to the Flask app running normally.

The one problem with this setup is that Frozen-Flask generates static pages for the paths which should be dynamic. Because they accept parameters in the form of ?param=value, Frozen-Flask sees them as 'no_argument' rules, and thus static files are generated where the app should serve dynamic ones.

This is my current workaround:

app.config['FREEZER_IGNORE_ENDPOINTS'] = ['endpoint1', 'endpoint2']


# This is a copy of Freezer.no_argument_rules() modified to ignore certain paths
def no_argument_rules_urls_with_ignore():
    """URL generator for URL rules that take no arguments."""
    ignored = app.config.get('FREEZER_IGNORE_ENDPOINTS', [])
    for rule in app.url_map.iter_rules():
        if rule.endpoint not in ignored and not rule.arguments and 'GET' in rule.methods:
            yield rule.endpoint, {}


freezer = Freezer(app=app, with_no_argument_rules=False)
freezer.register_generator(no_argument_rules_urls_with_ignore)

Could something like this be included in Frozen-Flask by default?

This is similar to #44, but I don't think Frozen-Flask needs to process all generated urls, just ones in no_argument_rules. All other generated urls can be controlled other ways, either by the user editing his/her generators, or adding with_static_files=False.

New release

Hi Simon,

What about a new official release, so that the Pypi repo reflects better the Github one ?

Feature request: Show exact path where error occurs

First of all thanks a lot for this brilliant module. It has helped us a lot with transparency projects such as this one: http://haushalt.frankfurt-gestalten.de/. Freeze is for us also a great test module to see where a page is broken. But the challenge is that often the error does not tell us where the problem occurs. For example in the above budget transparency page we have a template, which builds a thousand pages.

Therefore is it possible to extend the module, so it gives you a path, where the problem occurred? Thanks in advance for any hint or advise.

CLI freezer

Hi Simon,

First of all, thanks for the package. It works beautifully.

Having said that, I think it would be nicer if it comes with a command line interface that generates static files without worrying about custom URL generators. So I'm proposing a command with the following interface:

$ flask-freezer [OPTIONS] APP_MODULE space-separated-urls < additional-new-line-separated-urls

where:

  • [OPTIONS] are the same as current frozen_flask options. (i.e. destination, destination-ignore, etc)
  • APP_MODULE is of the pattern $(MODULE_NAME):$(FLASK_VARIABLE_NAME).
  • space-separated-urls is a list of urls to be used in the generator

Additionally, the command can accept list of urls via stdin.

Internally, it would a create Freezer instance and with an URL generator that iterates over the URLs.

Thoughts?

Frozen-Flask and Flask-Classy

Hi,

I'm setting a website using Flask-Classy and Frozen-Flask, but I fail to understand how can i link the two:
How frozen-flask generator should be configure to work with flask-classy?

For example, I have this Flask-Classy view:

class FooView(FlaskView):
    def bar(self, something):
        return render_template('bar.html', something=something)

My url is then:

/foo/bar/<something>

How should I write the Frozen-Flask generator:

@freezer.register_generator
def XXX():
    for s in something_db:
        yield {'something': something}

I fail to name properly XXX. Of course I could try forcing flask-classy to use a defined endpoint, but I would loose one of the advantage of flask-classy.

Thanks in advance for your help.

Not compatible with Flask-Assets ?

I have a blueprint structure very much like this. I use Flask-Assets but there seems to be some url issue when I am trying to freeze my application. I have output looking like this

<link rel=stylesheet type=text/css href="/static/css/home.css?221fdbd6">

Instead I guess it should be

<link rel=stylesheet type=text/css href="static/css/home.css">

The above html are rendered from the following source code

{% assets "home_css" %}
    <link rel=stylesheet type=text/css href="{{ ASSET_URL }}">
{% endassets %}

where home_css is a Bundle defined by

from flask_assets import Environment, Bundle
assets = Environment(app)
assets.register(
    'home_css',
    Bundle(
        'home/home.scss',
        filters=['libsass', 'autoprefixer6'],
        output='css/home.css'
    )
assets.init_app(app)

Deploying locally I have

FREEZER_RELATIVE_URLS = True

Option to ignore certain static files

I've had to set with_static_files=False to avoid having all my raw .scss and non-compressed javascript copied into the build directory, and created a url generator to pull in the non-linked static files I do want, such as css-referenced images and webfonts.

This works fine, but it'd be nice if there was a setting to prevent certain static directories from being copied, so I didn't have to write the generator.

Great app all the same!

Detect the endpoint when a URL is passed in an URL generator

Problem: MissingURLGeneratorWarning although a page has been frozen for the endpoint.

Example:

# Generate a feed
@app.route('/<path:path>/feed.atom')
def feed(path):
    ...
    return feed

# Generate URLs for all feeds
@freezer.register_generator
def generator():
    for blog in blogs:
        yield '/' + blog + '/feed.atom'

# Warning during freezing:
# MissingURLGeneratorWarning: Nothing frozen for endpoints feed. Did you forget an URL generator?

In this example, "/some/blog/feed.atom" was frozen.

Explanation: I yield a URL but Frozen-Flask doesn’t check which endpoint that URL maps to.

Workaround: yield 'feed', {'path': blog}

In that case, it goes through url_for and knows the endpoint.

Serving static files from a subdomain

Is it possible to make all static file URLs in the frozen site point to a subdomain?

For example, so that during freezing:

<img src="/static/icon.png">

becomes:

<img src="http://static.example.com/icon.png">

One use case would be domain sharding.

Feature request: more granular skipping with user-supplied filter function

Currently Frozen-Flask either regenerates all files, or skips all existing files when FREEZER_SKIP_EXISTING is set to True. This poses a difficulty when part of the site is slow to generate but only needs to be generated once, while the rest of the site changes all the time (see example app below). It would be nice to be able to supply a filter function skip(url, path) -> bool to decide whether to skip a URL.

Please excuse me if this functionality is already possible.


Example app: Each day a new page for that day is added; this page is expensive to generate, but its content is fixed once generated. The index needs to be regenerated every time a new page is added. The whole site takes minutes to generate, but it really should take ~1s to generate what's new or changed.

#!/usr/bin/env python3

import datetime
import time

import flask


app = flask.Flask(__name__)


INDEX_TEMPLATE = '''\
<html>
<head><title>Days</title></head>
<body>
  <ul>
    {% for date in dates -%}
    <li><a href="{{ url_for('day', date=date) }}">{{ date }}</a></li>
    {% endfor -%}
  </ul>
</body>
</html>
'''


@app.route('/')
def index():
    date = datetime.date(2017, 1, 1)
    dates = []
    while date <= datetime.date.today():
        dates.append(str(date))
        date += datetime.timedelta(1)
    return flask.render_template_string(INDEX_TEMPLATE, dates=dates)


@app.route('/<date>.txt')
def day(date):
    time.sleep(1)
    return flask.Response(date, mimetype='text/plain')


if __name__ == '__main__':
    app.run(debug=True)

A simple filter function would solve the problem:

def skip(url, path):
    return url.endswith('.txt') and os.path.exists(os.path.join('build', path))

Ignore URLs or Endpoints

Hello, I use Frozen-Flask along with Flask-Admin for CRUD-work.

Vanilla Frozen-Flask will produce an error like this ValueError: Unexpected status '404 NOT FOUND' on URL /admin/category/ajax/lookup/ but I have a local package installed that has a loop in the freeze function like this:

    def freeze(self):
        ...

        for url, endpoint in self._generate_all_urls():
            blacklist = self.app.config['FREEZER_ENDPOINT_BLACKLIST']
            filtered = [b for b in blacklist if b in url]
            if filtered.__len__() > 0:
                continue

I would like to see something like this in the official version, thank you.

Tests with unicode filenames fail on OS X

Amit Bansil has reported that tests with unicode filenames fail on OS X with this kind of errors:

Traceback (most recent call last):
  File "/private/tmp/Frozen-Flask/flaskext/frozen/tests/__init__.py", line 196, in test_nothing_else_matters
    self.assertEquals(set(walk_directory(dest)), expected_files)
AssertionError: set(['index.html', 'where_am_i/index.html', 'robots.txt', 'admin/static/style.css', 'static/style.css', 'admin/index.html', 'page/I l\xc3\xb8ve\xcc\x88 Unicode/index.html', 'product_1/index.html', 'product_0/index.html', 'product_2/index.html']) != set(['index.html', 'where_am_i/index.html', 'robots.txt', 'admin/static/style.css', 'admin/index.html', 'static/style.css', 'product_1/index.html', 'product_0/index.html', 'product_2/index.html', 'page/I l\xc3\xb8v\xc3\xab Unicode/index.html'])

What is going on is that different sequences of Unicode code points can be equivalent. In this example, a 'LATIN SMALL LETTER E WITH DIAERESIS' (U+00EB) is equivalent to a 'LATIN SMALL LETTER E' (U+0065) followed by a 'COMBINING DIAERESIS' (U+0308), and both are represented as ë. Mac OS X normalizes filenames before storing them, so a filename we get with listdir() might not be the same as the one we wrote. They will be equivalent, but may not compare equal in Python. Linux just stores bytes without changing them so I did not see this problem. However if you open() a file to read it the same normalization happens as when you wrote it, so normalization should not be a problem for Frozen-Flask outside of tests.

I think that the correct solution here is to normalize all filenames before comparing them in tests. What normalization is used does not matter as long as it is the same on both sides of ==.

test suite is locale dependent - breaks on non enlish locale

Hello,

Thanks for the great work in frozen-flask. I have found an error in the test suite due to some locale configuration.
When my locale is set to en_US.UTF-8 the test suite works perfectly fine. On the other hand when it is set to fr_CH.UTF-8 then 60 tests fail because of this same error:

frozen-flask/frozen-flask-0.11/flask_frozen/__init__.py", line 287, in _build_one
    if not os.path.isdir(dirname):
  File "/usr/lib/python3.4/genericpath.py", line 42, in isdir
    st = os.stat(s)
UnicodeEncodeError: 'ascii' codec can't encode character '\xf8' in position 25: ordinal not in range(128)

It seems to me that there are some issues with the UTF-8 support. I can bypass that error by utf-encoding the dirname but then other glitches arise.

Multiple routes

Hello. This code builds just /b/ route. Shouldn't it also build /a/?

from flask import Flask
from flask_frozen import Freezer

app = Flask(__name__)

@app.route('/a/')
@app.route('/b/')
def page():
    return 'page'

freezer = Freezer(app)

if __name__ == '__main__':
    freezer.freeze()

Ignore certain endpoints

Ok, I think I have a real "issue" this time. :)

I am running my app through Frozen Flask and the app has basic CRUD operations. The problem that I'm encountering is that the freeze process is following the delete endpoint. This has the unfortunate side-effect of actually deleting all the page content in my app. Thus, the next time I run the freeze method, there is a lot less frozen stuff.

I didn't see any method in the documentation for getting freeze to ignore certain endpoints. Is this possible or desired?

Add an ignored files config to prevent freezing from overwriting/removing files

I am using Frozen-Flask to create my blog which I publish through Github Pages. The problem is that freezing removes all of the files in the .git directory of my blog's github repo which kills the repository. I could build to a different destination and then copy over all of the files to my github repo, but that is a tedious and error prone process. Instead, it would be nice to have a config setting that would allow you to specify files and directories to ignore during the freezing process (something akin to the .gitignore file).

Project maintenance

Hi all,

Having moved on to other things, I’m not interested in spending time on Frozen-Flask anymore. It has been effectively abandoned for some time. Still, there are a few open issues and pull requests and people occasionally file/submit new ones. The project needs a maintainer to live on, but it won’t be me.

I’ve you’d like to do this, comment here and I’ll give you access on github and PyPI. (Please include your PyPI username in the comment.)

CC people who have contributed pull requests: @tswast, @smbsimon, @MykolaBilyi, @mblayman, @aventurella, @singingwolfboy, @sodastsai, @mivade, @max-k, @heyimalex, @homeworkprod, @croach, @grayj, @vaus, @equalsraf, @benvinegar, @jokull, @amit-bansil, @rduplain.

Protected pages?

I was looking into this module for archiving pages for audit purposes but the site i'm developing has protected pages. Is there any configuration settings that will allow frozen to still capture protected pages?

Add file extension to files without extensions

Assume you have a site that looks something like this...

@app.route('/')
def index():
    #...

@app.route('/archive')
def archive():
    #...

@app.route('/archive/<int:year>')
def archive_year(year):
    #...

This should generate urls such as below:

  • /
  • /archive
  • /archive/2013

The way I've handled these URLs in the past is to have my URLs mapped to the filenames shown below using the web server (Nginx):

  • / => /index.html
  • /archive => /archive.html
  • /archive/2013 => /archive/2013.html

I don't see a way to generate the filenames the way I've shown with Frozen Flask. For example, the "archive" page will always be created as the filename /archive. I can't change the URL from /archive to /archive/ or /archive.html without breaking existing links. I also can't change the web server to just look for /archive at /archive/index.html because Frozen-Flask can't actually generate the application I've shown above (since it will create the archive file, and then be unable to create the archive directory).

I am thinking on working on a patch that would add a new configuration item, something like FREEZER_FORCE_HTML_EXTENSION. This would take any file that wouldn't ordinarily have a .html extension for the generated file and give it one (if the response was actually an HTML content type). Thus, when /archive is generated, the view renders it as text/html, and therefore gives it an html file extension when generated.

Before putting effort into this, I wanted to see if this is a feature that would be accepted if I created it. Additionally, I am wondering if you had any input or tips on its development, specifically on writing the tests. It seems all of the tests work on the assumption that the files will always be generated with the same names, where as this feature would obviously not hold to that assumption.

Frozen-Flask and Flask-Bable(ex)

Hi all,

If we use Babel, we have to define a localeselector function where we will use the right locale in function of the parameters of the browser. But in the case of Frozen-Flask, how can we simulate the selection of a language ? For example, french or english ?

The reason, I would like to freeze an i18n website.

Is it possible? I don't have a code to explain, but it's just a question.

Thank you,

mimetype vs. filename extension

File ".../Flask_Static-0.1-py2.6.egg/flaskext/static.py", line 131, in _build_one
% (basename, guessed_type, response.content_type)
AssertionError: Filaname extension of 'mail_recovery_token' (type application/octet-stream) does not match Content-Type: text/html; charset=utf-8

a) Typo "Filaname"

b) that assertion is problematic anyway. I tried to do a static html dump functionality for MoinMoin Wiki (moin2), but there are usually no "extensions" on the item names, mimetype is ONLY supplied as content-type. Even if there was some item url ".../foo.zip", the default rendering of it would be text/html, not the zip mimetype. So, for moin2 this means: forget about extensions, use content-type only.

c) If one wants to use the dump directly with a browser (without web server), one would need generated filename extensions for the dumped static files, because there is no server generating content-type. Even if there was some server generating content-type, it would be wrong (see above).

I guess all this means flask-static needs to append an appropriate filename extensions based on the supplied content-type at dumping time.

Links to those resources then of course also need that filename extension...

`relative_url_for` trips on anchors

The relative_url_for method introduced in version 0.10 uses the naïve approach of appending index.html if an URL ends with a slash.

This, however, fails for URLs with an anchor (e. g. http://wiki.example.com/pages/Bacon#Positive-Effects-on-the-Human-Mind or /items/123/#some-superb-item).

Flask introduced the _anchor keyword argument to url_for (http://flask.pocoo.org/docs/api/#flask.url_for) in version 0.9.

Generate changelog as part of `freeze` build process

I use Frozen-Flask in conjunction with Flask-Flatpages to build my blog locally. I then have a Grunt task which publishes the entire site to my server running IIS. The problem is that as my site grows, deploys take incrementally longer because I'm republishing everything.

As part of the freeze process performed by Frozen-Flask, is there any way that it can generate a changelog of files which have been changed? I could then use that log file to only upload new files to the remote server.

Thoughts?

Should I expect Frozen-Flask to be slow?

My flask site is a product catalog which has about 2000 products. I attempted to use Frozen-Flask to freeze my site. However, freezer.freeze() seems to take forever to complete. Is it expected? Or there might be something wrong with my site.

It breaks with SERVER_NAME defined

I'm trying to freeze my app, I get a ValueError when SERVER_NAME is defined.

SERVER_NAME = 'www.example.com'

The url_for try to generate the external URL without scheme (://www.example.com). I'm using Flask 0.10.1 and last Frozen-Flask.

Documentation - example using `run_with_reloader`

The following snippet proved handy to avoid manually restarting the app during development, it should be mentioned somehow in the documentation:

def main():
    freezer.freeze()
    freezer.serve()

if __name__ == '__main__':
    from werkzeug.serving import run_with_reloader
    run_with_reloader(main)

Static files cause error during freezing after switching to Python 3

After switching to Python 3 this error occurs for every file in /static/:

Traceback (most recent call last):
  File "site.py", line 621, in <module>
    freezer.freeze()
  File "/home/me/dev/site/lib/python3.4/site-packages/flask_frozen/__init__.py", line 149, in freeze
    new_filename = self._build_one(url)
  File "/home/me/dev/site/lib/python3.4/site-packages/flask_frozen/__init__.py", line 257, in _build_one
    base_url=base_url)
  File "/home/me/dev/site/lib/python3.4/site-packages/werkzeug/test.py", line 774, in get
    return self.open(*args, **kw)
  File "/home/me/dev/site/lib/python3.4/site-packages/flask/testing.py", line 108, in open
    follow_redirects=follow_redirects)
  File "/home/me/dev/site/lib/python3.4/site-packages/werkzeug/test.py", line 742, in open
    response = self.run_wsgi_app(environ, buffered=buffered)
  File "/home/me/dev/site/lib/python3.4/site-packages/werkzeug/test.py", line 661, in run_wsgi_app
    self.cookie_jar.extract_wsgi(environ, rv[2])
  File "/home/me/dev/site/lib/python3.4/site-packages/werkzeug/test.py", line 187, in extract_wsgi
    U2Request(get_current_url(environ)),
  File "/usr/lib64/python3.4/urllib/request.py", line 266, in __init__
    self.full_url = url
  File "/usr/lib64/python3.4/urllib/request.py", line 292, in full_url
    self._parse()
  File "/usr/lib64/python3.4/urllib/request.py", line 321, in _parse
    raise ValueError("unknown url type: %r" % self.full_url)
ValueError: unknown url type: ':///static/zipped.zip'

I am using this setting:

app.config['FREEZER_BASE_URL'] = '/'

Not setting FREEZER_BASE_URL resolves the error.

I tried the current git version of Frozen-Flask with the same result.

Mimetype guessing is unreliable, not cross-platform

I'm curious why Frozen-Flask throws an exception if the mimetype of the generated file doesn't match it's own guess (from mimetypes.guess_type). I've found that mimetypes.guess_type is wholly unreliable, and returns different results depending on the platform.

For example, on Windows, mimetypes.guess_type('file.js'), returns application/x-javascript, but on OS X, it returns just application/javascript. There are others like this (.json is another).

Basically, this means that if I want to write cross-platform code that builds a static website using Flask-Frozen, I have to use mimetypes.guess_type myself, just to make sure I'm passing the same mimetype that Flask-Frozen expects. That seems to defeat the purpose. I'd ask that you just remove this check, because while it's a good sanity check in theory, it doesn't work in practice.

Should warn when an URL generator seems to be missing

A suggestion from Ron DuPlain:

  • Do not silently build an app that has URL rules with arguments that
    do not have a URL generator. Warn or raise an error, providing
    options in app.config.

This seems to be a good idea, but the desired behavior is not obvious.

In Flask each app has a URL map. That map has several rules. Each rules has an endpoint, and have zero or more arguments. url_for() takes and endpoint (the name of the view function as a string when we use @app.route(...)) as well as the values for arguments. The important detail is that more than one URl rule may have the same endpoint.

Frozen-Flask takes URL generator functions. These may return parameters for url_for() or plain URLs as strings, or a mix of both. Usually we make an URL generator function for each view/endpoint but this is not a requirement: the same generator could give URLs for more that one endpoint, or for all of them.

So endpoints may have more than one URL rule (with varying parameter number), a generator may give results for more than one endpoint, and results may not even go through the url_for/endpoint system at all.

We can start by warning when and endpoint in the URL map has no generated URL at all. Are there more cases when the feedback can be more helpful?

Generate relative urls

I'm writing a Jekyll-like static generator based on Frozen-Flask and I thought it would be neat if the final generated website had only relative urls and could be browsed or shared to others without a web server around.

I propose adding a FREEZER_RELATIVE_URLS option to Frozen-Flask. Here is a snippet that hooks Flask's url_for to generate relative urls based on the current request:

from flask import request, url_for
import posixpath

def relative_url_for(endpoint, **values):
    """Like url_for, but generates relative paths for each request."""
    request_path = request.path.lstrip('/')
    url = url_for(endpoint, **values).lstrip('/')

    if not request_path or request_path.endswith('/'):
        request_path += 'index.html'

    if not url or url.endswith('/'):
        url += 'index.html'

    return posixpath.relpath(url, posixpath.dirname(request_path))

app.jinja_env.globals['url_for'] = relative_url_for

Note that it should only be used with Frozen-Flask, as Flask itself (when running live) distinguishes between routes like / and /index.html. Please, integrate it into Frozen-Flask if you think it's worth it.

Project should pass flake8 linter

  • Add flake8 to a requirements-dev.txt file (not a package dependency).
  • Fix current flake8 warnings and errors.
  • Add flake8 to Travis builds.

Output from flake8 command

./setup.py:5:80: E501 line too long (80 > 79 characters)
./docs/conf.py:6:80: E501 line too long (80 > 79 characters)
./docs/conf.py:14:11: E401 multiple imports on one line
./docs/conf.py:19:1: E265 block comment should start with '# '
./docs/conf.py:22:80: E501 line too long (80 > 79 characters)
./docs/conf.py:25:1: E265 block comment should start with '# '
./docs/conf.py:27:80: E501 line too long (80 > 79 characters)
./docs/conf.py:41:1: E265 block comment should start with '# '
./docs/conf.py:55:1: E265 block comment should start with '# '
./docs/conf.py:56:1: E402 module level import not at top of file
./docs/conf.py:65:1: E265 block comment should start with '# '
./docs/conf.py:69:1: E265 block comment should start with '# '
./docs/conf.py:71:1: E265 block comment should start with '# '
./docs/conf.py:77:80: E501 line too long (80 > 79 characters)
./docs/conf.py:78:1: E265 block comment should start with '# '
./docs/conf.py:81:1: E265 block comment should start with '# '
./docs/conf.py:85:1: E265 block comment should start with '# '
./docs/conf.py:89:1: E265 block comment should start with '# '
./docs/conf.py:92:1: E265 block comment should start with '# '
./docs/conf.py:95:1: E265 block comment should start with '# '
./docs/conf.py:98:80: E501 line too long (80 > 79 characters)
./docs/conf.py:107:1: E265 block comment should start with '# '
./docs/conf.py:111:1: E122 continuation line missing indentation or outdented
./docs/conf.py:119:1: E265 block comment should start with '# '
./docs/conf.py:122:1: E265 block comment should start with '# '
./docs/conf.py:126:1: E265 block comment should start with '# '
./docs/conf.py:131:1: E265 block comment should start with '# '
./docs/conf.py:140:1: E265 block comment should start with '# '
./docs/conf.py:144:1: E265 block comment should start with '# '
./docs/conf.py:151:1: E265 block comment should start with '# '
./docs/conf.py:154:1: E265 block comment should start with '# '
./docs/conf.py:157:1: E265 block comment should start with '# '
./docs/conf.py:160:1: E265 block comment should start with '# '
./docs/conf.py:163:1: E265 block comment should start with '# '
./docs/conf.py:166:1: E265 block comment should start with '# '
./docs/conf.py:169:1: E265 block comment should start with '# '
./docs/conf.py:174:1: E265 block comment should start with '# '
./docs/conf.py:177:1: E265 block comment should start with '# '
./docs/conf.py:183:80: E501 line too long (80 > 79 characters)
./docs/conf.py:186:1: E265 block comment should start with '# '
./docs/conf.py:189:1: E265 block comment should start with '# '
./docs/conf.py:192:80: E501 line too long (80 > 79 characters)
./docs/conf.py:200:1: E265 block comment should start with '# '
./docs/conf.py:204:1: E265 block comment should start with '# '
./docs/conf.py:207:1: E265 block comment should start with '# '
./docs/conf.py:210:1: E265 block comment should start with '# '
./docs/conf.py:213:1: E265 block comment should start with '# '
./docs/conf.py:216:1: E265 block comment should start with '# '
./docs/conf.py:219:1: E265 block comment should start with '# '
./docs/conf.py:222:80: E501 line too long (80 > 79 characters)
./flask_frozen/__init__.py:20:1: E402 module level import not at top of file
./flask_frozen/__init__.py:21:1: E402 module level import not at top of file
./flask_frozen/__init__.py:22:1: E402 module level import not at top of file
./flask_frozen/__init__.py:23:1: E402 module level import not at top of file
./flask_frozen/__init__.py:24:1: E402 module level import not at top of file
./flask_frozen/__init__.py:25:1: E402 module level import not at top of file
./flask_frozen/__init__.py:26:1: E402 module level import not at top of file
./flask_frozen/__init__.py:27:1: E402 module level import not at top of file
./flask_frozen/__init__.py:28:1: E402 module level import not at top of file
./flask_frozen/__init__.py:29:1: E402 module level import not at top of file
./flask_frozen/__init__.py:30:1: E402 module level import not at top of file
./flask_frozen/__init__.py:37:1: E402 module level import not at top of file
./flask_frozen/__init__.py:37:1: F401 'werkzeug.exceptions.HTTPException' imported but unused
./flask_frozen/__init__.py:38:1: E402 module level import not at top of file
./flask_frozen/__init__.py:55:1: E302 expected 2 blank lines, found 1
./flask_frozen/__init__.py:58:1: E302 expected 2 blank lines, found 1
./flask_frozen/__init__.py:61:1: E302 expected 2 blank lines, found 1
./flask_frozen/__init__.py:285:67: E502 the backslash is redundant between brackets
./flask_frozen/__init__.py:286:21: E128 continuation line under-indented for visual indent
./flask_frozen/__init__.py:303:80: E501 line too long (80 > 79 characters)
./flask_frozen/__init__.py:304:80: E501 line too long (81 > 79 characters)
./flask_frozen/__init__.py:429:48: E272 multiple spaces before keyword
./flask_frozen/tests.py:24:5: E128 continuation line under-indented for visual indent
./flask_frozen/tests.py:25:5: E128 continuation line under-indented for visual indent
./flask_frozen/tests.py:106:13: E131 continuation line unaligned for hanging indent
./flask_frozen/tests.py:162:13: E261 at least two spaces before inline comment
./flask_frozen/tests.py:307:35: E127 continuation line over-indented for visual indent
./flask_frozen/tests.py:331:35: E127 continuation line over-indented for visual indent
./flask_frozen/tests.py:345:35: E127 continuation line over-indented for visual indent
./flask_frozen/tests.py:358:35: E127 continuation line over-indented for visual indent
./flask_frozen/tests.py:377:13: E301 expected 1 blank line, found 0
./flask_frozen/tests.py:385:13: E301 expected 1 blank line, found 0
./flask_frozen/tests.py:393:35: E127 continuation line over-indented for visual indent
./flask_frozen/tests.py:407:80: E501 line too long (81 > 79 characters)
./flask_frozen/tests.py:432:1: E303 too many blank lines (3)
./flask_frozen/tests.py:457:54: E231 missing whitespace after ','
./flask_frozen/test_app/__init__.py:63:80: E501 line too long (82 > 79 characters)
./flask_frozen/test_app/__init__.py:73:5: F811 redefinition of unused 'product' from line 65
./flask_frozen/test_app/admin/__init__.py:15:5: E128 continuation line under-indented for visual indent
./flask_frozen/test_app/admin/__init__.py:16:5: E128 continuation line under-indented for visual indent

Best way to handle sessions?

Our company purchases advertising to drive users to our site.
We love the durability and scalability of Frozen Flask.
We need to be able to to pass parameters in when a user lands on the site, cookie the user, and then pass the session_id associated with the user when the user ultimately clicks on an affiliate referral link.
What is the best way to do this with Frozen Flask?

IsADirectory is a File flask on routes

Hi, I'm running HEAD master

I get an error (IsADirectory or file exists) when Frozen is trying to create a page for /posts and then /posts/<post_id>
where /posts is a summary page of posts and /posts/<post_id> is content

I'm working around this with renaming the route to /posts -> /posts_index
but i'm wondering if this is an issue with how i'm using Frozen or otherwise?

thanks

FREEZER_BASE_URL did not support below domain root

I'm trying to freeze my project's documentation and host it on pythonhosted.org. I got the impression that FREEZER_BASE_URL was the way to do that. I set:

FREEZER_BASE_URL = 'http://pythonhosted.org/MyProject/'

When I ran, I got a 404 from a route and the freezing process aborted. Just to compare, I got rid of 'MyProject/' so that just the URL was specified. In that case, everything worked.

Is this not the way to specify paths below the domain root?

My assumption was based on the documentation stating "or if your application is not at the root of its domain name."

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.