How do I pass libsass configuration variables into a flask_assets bundle? - python

My goal is to set LIBSASS_STYLE="expanded" via flask_assets.Bundle. The webassets libsass documentation says I can do it, but doesn't say how.
My base app controller looks like the following.
from flask import Flask, render_template
from flask_assets import Environment, Bundle
app = Flask(__name__)
# ... Typical flask controller stuff
if __name__ == "__main__":
assets = Environment(app)
css = Bundle(
'sass/*.scss', # input scss files
filters='libsass', # to be compiled by libsass
output='css/style.css' # and outputed to style.css
)
assets.register("asset_css", css)
app.run(debug=True)
This outputs a valid css file (which is great) but not in the format that I desire since I simply have no idea where I can slip any libsass options.
Any help on this issue is greatly welcome. Thanks!

You need to instantiate libsass filter explicitly to pass options to it
from flask_assets import Bundle
from webassets.filter import get_filter
libsass = get_filter(
'libsass',
as_output=True,
style='compressed',
)
css = Bundle(
'sass/*.scss',
filters=(libsass),
output='css/style.css'
)

Related

How to remove older css files after webassets rebuilds the scss for a python flask app?

I have a Python 3.9 flask app which uses the flask_assets library.
My flask init.py file looks like:
import logging
import os
from flask import Flask, request, current_app
from config import Config
from flask_assets import Environment
from app.utils.assets import bundles
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(config_class)
assets = Environment(app)
assets.debug = True
assets.versions = 'timestamp'
# assets.cache = False
from app.main import bp as main_bp
app.register_blueprint(main_bp)
assets.register(bundles)
if not app.debug and not app.testing:
app.logger.setLevel(logging.INFO)
app.logger.info('Application starting.')
return app
Since flask_assets is built on top of webassets, I import the Environment and a css Bundle I created which compiles my scss code to css.
Here is how my Bundle looks like:
from flask_assets import Bundle
bundles = {
'css': Bundle (
'scss/_main.scss',
'scss/_base.scss',
'scss/_typography.scss',
'scss/_page_home.scss',
'scss/_page_technote.scss',
filters='pyscss',
depends=('**/*.scss'),
output='css/style.%(version)s.scss.css'
)
}
The problem I have:
Every time I make a change to my scss files, the css successfully rebuilds with a new version for cache busting. However, the older css files remain.
What's the best automatic way to remove them every time a rebuild happens? Is there any reason for keeping the older files?
Also - side question - is it possible for the Bundle object to automatically consider all files of certain type in a directory? Rather than me listing every file individually?
Here is how my files look like:
Thank you!
You can use rmtree. Even though I believe a better way exists, this does it.
from os.path import join
from shutil import rmtree
app = Flask(__name__)
rmtree(join(app.static_folder, 'css'), ignore_errors=True)
You can improve this by checking the file meta by date or similar to not delete the unchanged ones.

Is there anyway to specify templates and static folders(other than default) for Connexion app?

I'm initializing app using connexion 2.4.0 library like this:
connex_app = connexion.App(__name__, specification_dir='./')
app = connex_app.app
I need to specify the path to my static and templates directories somehow since they are not located in the root directory.
In Flask I would use something like this
app = Flask(__name__, static_folder='../frontEnd/static', template_folder='../frontEnd/templates')
I know that connexion looks for static and templates in the root by default, but is there any way to indicate another path?
Has an opening issue about this problem:
https://github.com/zalando/connexion/issues/441
And a opening pull request:
https://github.com/zalando/connexion/pull/710
But the problem is not solved.
You can you this approach How to set static_url_path in Flask application just remember to use app.app to access the flask instance.
This is now possible following the merge of https://github.com/spec-first/connexion/pull/1173
You can now specify these arguments in the server_args constructor argument e.g.
connexion.FlaskApp(
server_args={'static_url_path': '/your/path/'}
)
Gids is technically correct, you can now pass flask keyword arguments to the created app.
The correct combination for your two code snippets would be:
connex_app = connexion.App(__name__, specification_dir='./', server_args={'static_folder'='../frontEnd/static', 'template_folder'='../frontEnd/templates'})
app = connex_app.app

Configure Python Flask RESTplus app via TOML file

Based on the Configuration Handling Documents for Flask the section of Configuring from Files mentions a possibility to configure the App using files however it provides no example or mention of files that are not Python Files.
Is it possible to configure apps via files like config.yml or config.toml?
My Current flask app has configurations for two distinct databases and since I am using flask-restplus there are additional configurations for Swagger documentations.
Snippet:
from flask import Flask
app = Flask(__name__)
def configure_app(flask_app):
# MongoDB Setting
flask_app.config['MONGO_URI'] = 'mongodb://user:password#mongo_db_endpoint:37018/myDB?authSource=admin'
flask_app.config['MONGO_DBNAME'] = 'myDB'
# InfluxDB Setting
flask_app.config['INFLUXDB_HOST'] = 'my_influxdb_endpoint'
flask_app.config['INFLUXDB_PORT'] = 8086
flask_app.config['INFLUXDB_USER'] = 'influx_user'
flask_app.config['INFLUXDB_PASSWORD'] = 'influx_password'
flask_app.config['INFLUXDB_SSL'] = True
flask_app.config['INFLUXDB_VERIFY_SSL'] = False
flask_app.config['INFLUXDB_DATABASE'] = 'IoTData'
# Flask-Restplus Swagger Configuration
flask_app.config['RESTPLUS_SWAGGER_UI_DOC_EXPANSION'] = 'list'
flask_app.config['RESTPLUS_VALIDATE'] = True
flask_app.config['RESTPLUS_MASK_SWAGGER'] = False
flask_app.config['ERROR_404_HELP'] = False
def main():
configure_app(app)
if __name__ == "__main__":
main()
I would like to avoid setting large number of Environment Variables and wish to configure them using a config.toml file?
How is this achieved in flask?
You can use the .cfg files and from_envvar to achieve this. Create config file with all your environment variables.
my_config.cfg
MONGO_URI=mongodb://user:password#mongo_db_endpoint:37018
..
..
ERROR_404_HELP=False
Then set the env var APP_ENVS=my_config.cfg. Now all you need to do is use from_envvars given by Flask.
def configure_app(flask_app):
flask_app.config.from_envvar('APP_ENVS')
# configure any other things
# register blue prints if you have any
Quoting from documentation:
Configuring from Data Files
It is also possible to load configuration from a file in a format of
your choice using from_file(). For example to load from a TOML file:
import toml
app.config.from_file("config.toml", load=toml.load)
Or from a JSON file:
import json
app.config.from_file("config.json", load=json.load)
EDIT: The above feature is new for v2.0.
Link to the documentation reference:
Class Flask.config, method from_file(filename, load, silent=False)

Change static folder from config in Flask

Has anyone tried this snippet flask config based static folder code cnippet?
The code:
import flask
class MyFlask(flask.Flask):
#property
def static_folder(self):
if self.config.get('STATIC_FOLDER') is not None:
return os.path.join(self.root_path,
self.config.get('STATIC_FOLDER'))
#static_folder.setter
def static_folder(self, value):
self.config.get('STATIC_FOLDER') = value
# Now these are equivalent:
app = Flask(__name__, static_folder='foo')
app = MyFlask(__name__)
app.config['STATIC_FOLDER'] = 'foo'
In my case in complains about this line:
self.config.get('STATIC_FOLDER') = value
The error message: Can't assign to function call
Does anyone how to set the static_folder from the config.py file in Flask?
Okay, I assume you want to use a custom path to the static folder for whatever reason. I wanted to do the same for the sake of better app modularity.
Here's my app folder structure:
instance/
core/
|_templates/
|_static/
|_views.py
run.py
config.py
As you can see, my static folder is inside the core folder.
In run.py, you can do the following:
app = Flask(__name__, static_url_path=None)
if __name__ == '__main__':
app.config.from_object('config')
# config file has STATIC_FOLDER='/core/static'
app.static_url_path=app.config.get('STATIC_FOLDER')
# set the absolute path to the static folder
app.static_folder=app.root_path + app.static_url_path
print(app.static_url_path)
print(app.static_folder)
app.run(
host=app.config.get('HOST'),
port=app.config.get('PORT'),
threaded=True
)
This is what I did, and it works perfectly fine. I'm using flask 0.12.
I don't know anything about that snippet, but
some_function(...) = some_value
is never valid Python (Python doesn't have l-values). It looks like config has a dict-like interface, so the offending line should probably just be
self.config['STATIC_FOLDER'] = value
Probably a copy-and-paste error from the getter definition above the setter.
app = Flask(__name__, static_url_path="/STATIC_FOLDER", static_folder='STATIC_FOLDER')
Yes, In one of my projects I am using/setting a custom path for STATIC_FOLDER. You can set the path to STATIC_FOLDER in config.py like below:
STATIC_PATH = '<project-name>/<path-to-static-folder>/'
ex:
STATIC_PATH = 'myApp/static/'
If you can write your project structure then I can answer it as per your requirements.
FYI if you want your directory to be outside of the server directory the best solutions I found so far are either to make a copy of your directory into the server directory before startup in your main(), or to create a symlink.

Flask_Scss not compiling scss file in simple app

I'm trying to use Flask-Scss to compile a scss file in my flask app. Here is my app:
from flask import Flask, jsonify, render_template, request
from flask_scss import Scss
app = Flask(__name__)
app.debug = True
Scss(app, static_dir='static', asset_dir='assets/scss/')
#app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
This file is in a directory that also contains a static directory and assets directory. Furthermore, assets contains a scss directory, which holds the file test.scss. When I run the app, I don't see any css files getting created inside of static. Can someone please tell me what I'm doing wrong?
You have to put absolute path for it to work. Assuming your structure is app/init.py then this should be your code:
Scss(app, static_dir='app/static', asset_dir='app/assets/scss')
NOTE: Don't forget to reload the page for the compiling to happen. If you don't reload the page then scss files will not be compiled to css.
I recommend using libsass, it works for both Sass and SCSS files. After you import sass simply use the compile function with the dirname keyword argument, like this:
sass.compile(dirname=('path/to/source', 'path/to/target'))
You also have the option to set the output style, for example:
sass.compile(dirname=('path/to/source', 'path/to/target'), output_style='compressed')
If you want to watch a file or directory for automatic compilation on every edit use boussole.

Categories