Freezes a Flask application into a set of static files.

Overview

Frozen-Flask

https://img.shields.io/pypi/v/Frozen-Flask.svg?maxAge=2592000

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://pythonhosted.org/Frozen-Flask/

Build Status

https://github.com/Frozen-Flask/Frozen-Flask/workflows/CI/badge.svg?branch=master

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 . to install dependencies
  • Use tox or python -m flask_frozen.tests to run tests
  • Do your changes, make sure tests pass
  • Send a Pull Request to the upstream repository

License

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

Comments
  • Ignore certain endpoints

    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?

    opened by mblayman 18
  • Add .freeze_yield() that freezes the app and yields URLs and paths

    Add .freeze_yield() that freezes the app and yields URLs and paths

    This change enables the user of Frozen-Flask to iterate over the URLs beeing frozen and visualize the progress (i.e. by printing the URLs to the stdout or using some kind of progressbar).

    opened by hroncok 12
  • Compatibility with Python 3.9

    Compatibility with Python 3.9

    I'm getting following warnings:

    /Users/honza/.local/share/virtualenvs/python.cz-s2NxYiyq/lib/python3.7/site-packages/flask_frozen/__init__.py:29
      /Users/honza/.local/share/virtualenvs/python.cz-s2NxYiyq/lib/python3.7/site-packages/flask_frozen/__init__.py:29:
      DeprecationWarning: Using or importing the ABCs from 'collections' instead
      of from 'collections.abc' is deprecated since Python 3.3,and in 3.9 it will stop working
        from collections import Mapping, namedtuple
    
    tests/views_test.py::test_get_involved_cs_renders_ordinary_issue
      /Users/honza/.local/share/virtualenvs/python.cz-s2NxYiyq/lib/python3.7/site-packages/ics/icalendar.py:59:
      DeprecationWarning: Using or importing the ABCs from 'collections' instead
      of from 'collections.abc' is deprecated since Python 3.3,and in 3.9 it will stop working
        elif isinstance(imports, collections.Iterable):
    
    opened by honzajavorek 10
  • Add an ignored files config to prevent freezing from overwriting/removing files

    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 the 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).

    The changes I've made in this pull request introduce a new config setting FREEZER_IGNORED_FILES to fix this issue. The ignored files setting takes a list of file and directory names (relative to the destination directory) and expands those into a list of ignored file paths.

    So, for example, if you wanted to ignore all files within the .git directory of a Git repo and a CNAME file within the top level of the destination directory, you could add the following to your script:

    FREEZER_IGNORED_FILES = ['.git', 'CNAME']
    
    opened by croach 10
  • Project maintenance

    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.

    opened by SimonSapin 9
  • Add FREEZER_STATIC_IGNORE config option.

    Add FREEZER_STATIC_IGNORE config option.

    Allows you to stop certain static files (anything served by send_static_file) from being built with your project based on a list of fnmatch style patterns. Had to add a main.js static file to the test app and change the test_all_urls_method to work with the built_app context manager.

    opened by heyimalex 9
  • Add file extension to files without extensions

    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.

    opened by markhildreth 8
  • Add `Freezer.error_handler_spec` for saving errors

    Add `Freezer.error_handler_spec` for saving errors

    I needed to be able to generate a 404 page when freezing my Flask application, so I figured I'd add a generic way to make Frozen-Flask freeze any HTTP error page. The code works, and the unit test suite has been updated as well, but there is currently not documentation. I decided to mirror Flask.error_handler_spec as closely as possible, but I'm not certain that was the right decision, since it means that we have to use a nested dictionary due to blueprints providing their own exception handlers. I'm open to suggestions for other ways to implement this that make sense.

    opened by singingwolfboy 8
  • save html with wrong guessed mimetype as folder with index.html

    save html with wrong guessed mimetype as folder with index.html

    These patches rewrite the destination paths for html content with the wrong guessed mimetype to be stored as index.html. For example for a path /site/content/ the content wound be stored in /site/content/index.html. The commit adds a new option FREEZER_REWRITE_HTML_AS_FOLDER (default False) that enables this behaviour.

    This trick works well for web servers that accept paths with or without the trailing slash as being the equivalent. This is the case for github's static pages (for example http://equalsraf.github.com/ was generated from http://ruiabreu.org/). However this does not work for Freezer.run().

    opened by equalsraf 8
  • Not clear how to write URL generators based on documentation

    Not clear how to write URL generators based on documentation

    I've read the documentation found at https://pythonhosted.org/Frozen-Flask/#url-generators and to be fair I'm just confused by it.

    I've tried a multitude of approaches, but nothing worked.

    Here's my current code:

    @app.route('/category/<category_slug>')
    def articles(category_slug):
        data = []
        for article in ARTICLES:
            if article.metadata['category'] == category_slug:
                data.append(article)
        return render_template('category.html', articles=data)
    
    
    @freezer.register_generator
    def articles_generator():
        for article in ARTICLES:
            yield {'/articles/' + article.metadata['slug'], article}
    
    
    @app.route('/articles/<slug>')
    def article(slug):
        for article in ARTICLES:
            if article.metadata['slug'] == slug:
                return render_template('article.html', article=article, thumb=article.metadata['thumb'])
        return page_not_found(404)
    
    @freezer.register_generator
    def article_generator():
        yield {'article', article.metadata['slug']}
    

    the error I get is as follows:

    MissingURLGeneratorWarning: Nothing frozen for endpoints articles, article. Did you forget a URL generator?
      return set(page.url for page in self.freeze_yield())
    

    Any clarifications would be greatly appreciated.

    opened by Zenahr 7
  • Support unquoting URLs that contain multi-byte unicode characters

    Support unquoting URLs that contain multi-byte unicode characters

    The Python 2.7 urllib.unquote implementation does not handle decoding non-ASCII characters; instead use werkzeug's encoding-aware implementation.

    Fixes #103

    opened by jayaddison 7
  • New feature: pretty relative urls

    New feature: pretty relative urls

    Hey Frozen-Flask team! I was going through my old issues and decided to have another shot at a feature request I made here 4 years ago. I'm too deep into JS now, so I actually don't know if kids new to programming these days still build websites with Python and then host them on static servers like I used to, but if they do, now they can have pretty URLs without the ugly /index.html just like I wanted to.


    Why it's necessary to first append the /index.html and then remove it (i.e. why the approach I said I tried in the original issue didn't work): if the index.html isn't there, relpath resolves a path to the directory itself, which obviously doesn't include the trailing slash. But after that it isn't anymore possible to disambiguate if the resolved URL is a directory ../example, or a file ../example. So we need to keep it, resolve the relpath, and then again strip query+fragment, check for index.html, remove it and then put everything back together again.

    Fixes #90

    opened by mvolfik 0
  • docs: fix simple typo, unmodifies -> unmodified

    docs: fix simple typo, unmodifies -> unmodified

    There is a small typo in flask_frozen/init.py.

    Should read unmodified rather than unmodifies.

    Semi-automated pull request generated by https://github.com/timgates42/meticulous/blob/master/docs/NOTE.md

    opened by timgates42 0
  • Question: What is the best way to have run multiple threads/processes?

    Question: What is the best way to have run multiple threads/processes?

    the whole process of freezing ~2k urls takes upto 20 mins. Is there a way to run the freeze script with multiple threads/processes to speed up the static site generation?

    I have implemented something here, and appreciate any feedback for improvements, thanks :) reference: https://github.com/vedupraity/ancientknowledgewebserver/blob/master/freeze.py

    opened by vedupraity 2
  • Question about URL generators

    Question about URL generators

    So, I am making a blog and I am trying to freeze it with Frozen-Flask. I have the following URL generator in my code:

    @app.route('/blog/<path:path>.html')
    def page(path):
        page = pages.get_or_404(path)
        return render_template('page.html', page=page)
    

    How can I make Frozen-Flask register the URL generator?

    opened by ghost 1
  • How to remove trailing slash?

    How to remove trailing slash?

    Hi,

    I made a site with this (https://util123.com/) but i need now remove the last slash.

    Can anyone help me?

    The main project is Kaktos (https://github.com/paulocoutinhox/kaktos).

    Thanks for any help.

    opened by paulocoutinhox 2
  • During build: string concatenation in url_for() fails when data comes from render_template()

    During build: string concatenation in url_for() fails when data comes from render_template()

    When running Flask normally, everything described below works absolutely fine.

    When running a build in Frozen-Flask however, I run into the issue where my dynamically built route string won't allow me to concatenate a variable (containing a string) with a string for use in a url_for() function within Jinja2. But only when the variable data is originating from Python such as render_template().

    routes.py

    @app.route('/some-route/')
    def some_route():
        return render_template('my_template.html', foo='bar')
    

    base.html

    {% import "includes.html" as includes %}
    {{ includes.my_macro(foo) }}
    

    includes.html

    # The following does NOT work
    {% macro my_macro(foo) %}
        <a href="{{ url_for('index_' ~ foo) }}">Link text</a>
    {% endmacro %}
    

    Although the above runs fine in Flask, when I do a build with Frozen-Flask I get the following error:

    werkzeug.routing.BuildError: Could not build url for endpoint 'index_'. Did you mean...
    

    As you can see, the value of foo (or the string value bar) is missing. It should have been index_bar.

    So I tried this instead:

    # This also does NOT work
    {% macro my_macro(foo) %}
        {% set route = 'index_' ~ foo %}
        <a href="{{ url_for(route) }}">Link text</a>
    {% endmacro %}
    

    The above produces the exact same error.

    So I tried this to try to better understand the problem:

    # This works correctly
    {% macro my_macro(foo) %}
        {% set route = 'index_' ~ 'bar' %}
        <a href="{{ url_for(route) }}">Link text</a>
    {% endmacro %}
    

    So I further tried this:

    # This also works correctly
    {% macro my_macro(foo) %}
        {% set foo2 = 'bar' %}
        {% set route = 'index_' ~ foo2 %}
        <a href="{{ url_for(route) }}">Link text</a>
    {% endmacro %}
    

    So basically, I can create a dynamic route string for use by url_for() but only when the variable data doesn't come from the Flask routes file (such as my routes.py), only if the variable is created within Jinja2.

    opened by LokiWijnen 2
Releases(v0.15)
Socket.IO integration for Flask applications.

Flask-SocketIO Socket.IO integration for Flask applications. Installation You can install this package as usual with pip: pip install flask-socketio

Miguel Grinberg 4.9k Jan 02, 2023
PatientDB is a flask app to store patient information.

PatientDB PatientDB on Heroku "PatientDB is a simple web app that stores patient information, able to edit the information, and able to query the data

rbb 2 Jan 31, 2022
Flask Apps - Open-Source And Paid | AppSeed

Flask Apps Open-Source web apps built with automation tools, HTML parsing and boilerplated code in Flask - - Provided by AppSeed App Generator. What i

App Generator 120 Oct 04, 2022
Flask + marshmallow for beautiful APIs

Flask-Marshmallow Flask + marshmallow for beautiful APIs Flask-Marshmallow is a thin integration layer for Flask (a Python web framework) and marshmal

marshmallow-code 770 Jan 05, 2023
A web application made with Flask that works with a weather service API to get the current weather from all over the world.

Weather App A web application made with Flask that works with a weather service API to get the current weather from all over the world. Uses data from

Christian Jairo Sarmiento 19 Dec 02, 2022
A Flask app template with integrated SQLAlchemy, authentication, and Bootstrap frontend

Flask-Bootstrap Flask-Bootstrap is an Flask app template for users to clone and customize as desired, as opposed to a Flask extension that you can ins

Eric S. Bullington 204 Dec 26, 2022
A simple FastAPI web service + Vue.js based UI over a rclip-style clip embedding database.

Explore CLIP Embeddings in a rclip database A simple FastAPI web service + Vue.js based UI over a rclip-style clip embedding database. A live demo of

18 Oct 15, 2022
A flask extension using pyexcel to read, manipulate and write data in different excel formats: csv, ods, xls, xlsx and xlsm.

Flask-Excel - Let you focus on data, instead of file formats Support the project If your company has embedded pyexcel and its components into a revenu

247 Dec 27, 2022
Flaskr: Intro to Flask, Test-Driven Development (TDD), and JavaScript

Flaskr - Intro to Flask, Test-Driven Development, and JavaScript Share on Twitter As many of you know, Flaskr -- a mini-blog-like-app -- is the app th

Michael Herman 2.2k Jan 04, 2023
i18n and l10n support for Flask based on Babel and pytz

Flask Babel Implements i18n and l10n support for Flask. This is based on the Python babel module as well as pytz both of which are installed automatic

397 Dec 15, 2022
Flask extension for Pusher

Flask-Pusher Flask extension for Pusher. It is a thin wrapper around the official client, binding Flask app to Pusher client. Installation Install Fla

Iuri de Silvio 9 May 29, 2021
Flask Multiple Database Login

Flask Multiple Database Login Handle login with flask using two diferent databases: UE | European; BR | Brazilian; These databases are separed to resp

Jose Pedro 1 Dec 16, 2021
The Snoopy boilerplate in flask framework for development enterprise application.

Snoopy What is snoopy! The "Snoopy" boilerplate in flask framework for development enterprise application. Motivation In my 10 years of development ex

Bekhzod 2 Sep 29, 2022
MongoEngine flask extension with WTF model forms support

Flask-MongoEngine Info: MongoEngine for Flask web applications. Repository: https://github.com/MongoEngine/flask-mongoengine About Flask-MongoEngine i

MongoEngine 815 Jan 03, 2023
SeCl - A really easy to deploy and use made-on Flask API to manage your files remotely from Terminal

SeCl SeCl it's a really easy to deploy and use made-on Flask API to manage your

ZSendokame 3 Jan 15, 2022
This is a simple web application using Python Flask and MySQL database.

Simple Web Application This is a simple web application using Python Flask and MySQL database. This is used in the demonstration of development of Ans

Alaaddin Tarhan 1 Nov 16, 2021
Sample Dockerized flask app deployed on Kubernetes on Azure using AKS

Sample Dockerized flask app deployed on Kubernetes on Azure using AKS

Ahmed khémiri 22 Sep 08, 2021
SQL Alchemy dialect for Neo4j

SQL Alchemy dialect for Neo4j This package provides the SQL dialect for Neo4j, using the official JDBC driver (the Neo4j "BI Connector" ) Installation

Beni Ben zikry 8 Jan 02, 2023
REST API with mongoDB and Flask.

Flask REST API with mongoDB py 3.10 First, to install all dependencies: python -m pip install -r requirements.txt Second, into the ./src/ folder, cop

Luis Quiñones Requelme 3 Mar 05, 2022
Easy file uploads for Flask.

Library that works with Flask & SqlAlchemy to store files on your server & in your database Read the docs: Documentation Installation Please install t

Joe Gasewicz 145 Jan 06, 2023