Giter VIP home page Giter VIP logo

pyramid_webassets's Introduction

Installation

Build Status Coverage

Install the package:

$ pip install pyramid_webassets

EITHER add it to your Pyramid production.ini and development.ini:

pyramid.includes =
    pyramid_debugtoolbar
    pyramid_tm
    pyramid_webassets

OR include it when configuring your application, usually in __init__.py:

def main(global_config, **settings):
    ...
    config.include('pyramid_webassets')

Configuration

You are required to set base_dir and base_url, the rest are optional, but we currently support:

  • base_dir: The directory to output and search for assets
  • base_url: The url static assets will be located
  • debug: If webassets should be in debug mode (i.e no compression)
  • updater: Different update configurations (i.e always, timestamp)
  • cache: If we should use webassets cache (if boolean), or override default path to cache directory
  • jst_compiler: A custom jst compiler, by default it uses underscore
  • url_expire: If a cache-busting query string should be added to URLs
  • static_view: If assets should be registered as a static view using Pyramid config.add_static_view()
  • cache_max_age: If static_view is true, this is passed as the static view's cache_max_age argument (allowing control of expires and cache-control headers)
  • paths: A JSON dictionary of PATH=URL mappings to add paths to alternative asset locations (URL can be null to only add the path)
  • bundles: filename or [asset-spec] (or a list of either) (http://docs.pylonsproject.org/projects/pyramid/en/latest/glossary.html#term-asset-specification) of a YAML bundle spec whose bundles will be auto-registered
webassets.base_dir              = %(here)s/app/static
webassets.base_url              = static
webassets.debug                 = True
webassets.updater               = timestamp
webassets.cache                 = False
webassets.jst_compiler          = Handlebars.compile
webassets.url_expire            = False
webassets.static_view           = True
webassets.cache_max_age         = 3600
webassets.bundles               = mypackage:webassets.yaml

Then you can just use config.add_webasset to add bundles to your environment

from webassets import Bundle

jst = Bundle('templates/*.html',
        filters='jst',
        output='js/jst.js', debug=False)

config.add_webasset('jst', jst)

All other configurations are passed through to webassets, including filter settings. These are adjusted as follows: if a value is exactly true or false, then it is converted to a boolean; if a value is prefixed with the string json:, then it is JSON-parsed. This allows pyramid-webassets to handle basic extensible filter configurations without needing any python code, for example:

webassets.less_run_in_debug     = true
webassets.less_extra_args       = json:["--line-numbers=mediaquery", "-O2"]

Use asset specs instead of files and urls

It's possible to use an asset specifications (package:file) instead of simple file names.

  • If the asset specifications declares a path outside the base_dir, the file will be copied.
  • Otherwise, it will work like a normal bundle file.

If files are bundled from other packages and those packages act like pyramid plugins adding their own add_static_view, webassets will use those static view urls to show the individual files if needed (for example, in development mode).

If you have defined your own static route and you want to use it with webassets, for example:

config.add_static_view('static-stuff', 'my.super.app:static')

Setting the base url configuration option to an asset specification:

base_url = my.super.app:static

Will make webassets use the /static-stuff route for your assets. Note: the absolute or relative path depends on where is your application is deployed.

Use with templates

Included are helpers that you can use with your templates. Additional helpers are documented below in the section labeled "Extras".

Mako

You can use the global webassets tag:

% for url in webassets(request, 'css/bootstrap.css', 'css/bootstrap-responsive.css', output='css/generated.css', filters='cssmin'):
    <link href="${url}" rel="stylesheet">
% endfor

or you can grab the environment from the request.

Jinja2

If you are using Jinja2, you can just do the following configuration (this assumes use of pyramid_jinja2):

config.add_jinja2_extension('webassets.ext.jinja2.AssetsExtension')
assets_env = config.get_webassets_env()
jinja2_env = config.get_jinja2_environment()
jinja2_env.assets_environment = assets_env

and then:

{% assets "jst" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}

Generic

It's always possible to access the environment from the request.

jst_urls = request.webassets_env['jst'].urls()

Extras

There are a few more utility methods you can use to make working with webassets within your Pyramid application easier.

Configuration

These methods can be called on the Configurator instance during startup:

add_webasset(name, bundle): Registers a bundle with webassets

add_webassets_setting(key, value): Update the environment configuration

add_webassets_path(path, url): Append a URL mapping to the environment

get_webassets_env_from_settings(settings, prefix='static_assets'): Pass a dictionary of your settings and an optional keyword argument of the prefix in your configuration and it will return a webassets environment.

get_webassets_env(): This will pull the environment out of the registry.

Request handling

These properties and helpers are attached to the Request object:

request.webassets_env: Access the webassets environment

request.webassets(*bundle_names, **kwargs): Build the named bundles. Keyword arguments will be passed to webassets to influence bundling.

Building assets from a script

The webassets module includes a command line script, also called webassets, which can be used to build bundles offline. When integrating with Pyramid, it can be helpful to bootstrap the environment using paster instead, like so:

import pyramid.paster
import webassets.script

app_env = pyramid.paster.bootstrap('config.ini')
assets_env = app_env['request'].webassets_env
webassets.script.main(['build'], assets_env)

pyramid_webassets's People

Contributors

dannymidnight avatar deimos avatar domenkozar avatar graffic avatar groner avatar ianjosephwilson avatar jdeuce avatar keitheis avatar longhotsummer avatar metagriffin avatar mikewirth avatar mmerickel avatar omh avatar oohlaf avatar rclmenezes avatar sontek avatar tilgovi 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyramid_webassets's Issues

Document missing settings

The auto_build, manifest and load_path settings have been implemented, but are missing from the documentations. Also updater should be renamed to versions to avoid confusion, with an alias for compatibility.

compass_config loaded via json: setting will fail due to python2 unicode markers

The compass filter takes an optional compass_config argument. Using the new json configuration loading mechanism to pass this parameter to the Environment will fail using webassets < 0.10.dev due to the presence of unicode markers (explanation below)

Note: This issue has been taken care of in miracle2k/webassets#265, but the current version of pyramid_webassets has not been updated to be compatible with the changes in the Resolver api introduced in webassets 0.10.dev

I'm wondering if it makes sense to ensure that json loaded strings are bytestrings in general. A simple fix is to use the yaml loader to parse a json:-prefixed asset setting.

Another option would be to special case the compass_config kwarg to ensure it does not contain unicode values.

Explanation

A config like:

webassets.compass_config = json:{
    "project_path" : "%(here)s/static/assets",
    "sass_dir"     : "/styles",
    "images_dir"   : "/styles/ui/images/"
    }

yields properly uni-decoded dict values that will be passed to the Environment:

'compass_config': {
    u'project_path': u'/some/path/to/static/assets',
    u'sass_dir': u'/styles',
    u'images_dir': u'/styles/ui/images/'
}

This is passed through to the Compass filter, which creates a temporary config.rb for compass by taking the repr of each value in the config. This results in an invalid config file like:

images_dir = u'/styles/ui/images/'
project_path = u'/Users/ltvolks/project/static/assets'
sass_dir = u'/styles'

Compass fails with this inscrutable error:

FilterError: compass: subprocess had error: stderr=NoMethodError on line ["264"] of /Users/ltvolks/.rvm/gems/ruby-1.9.2-p136/gems/compass-0.12.6/lib/compass/configuration/inheritance.rb: u
Run with --trace to see the full backtrace
, stdout=, returncode=1

Support all settings

Thanks for writing this! I love seeing wider framework support for webassets.

One thing I noticed: It seems like you currently are only supporting a select number of settings, which would mean that other filter's settings (SASS_BIN etc). would not be supported. There is actually a way to support settings in a generic manner: You can create the webassets Environment with a custom config_storage_class attribute. It's a relatively simple class that would wrap the Pyramid settings object.

If you look at how the Django wrapper does this:

https://github.com/miracle2k/flask-assets/blob/master/src/flaskext/assets.py

It goes through the extra effort of only using a prefix for the core settings, but not for any that filters might use, i.e. within Django, it would be ASSETS_UPDATER, but SASS_BIN, but that might or might not be appropriate for Pyramid.

By wrapping the settings in a generic fashion, you also gain better upwards-compatibility. For example, the "updater" setting will likely be replaced with one called "auto_build" in the future.

UnicodeEncodeError: 'ascii' codec can't encode character exception in BaseHunk class

Tue Aug 26 11:06:22 2014] [error] [client 192.168.21.146] File "/opt/lang/python/virtualenvs/3.4/bi/lib/python3.4/site-packages/webassets/merge.py", line 60, in save [Tue Aug 26 11:06:22 2014] [error] [client 192.168.21.146] f.write(self.data()) [Tue Aug 26 11:06:22 2014] [error] [client 192.168.21.146] UnicodeEncodeError: 'ascii' codec can't encode character '\\xa0' in position 158569: ordinal not in range(128)

The fopen method fails to set the encoding when writing bytes back out to the cached file.

def save(self, filename):
    with open(filename, 'w') as f:
        f.write(self.data())

I will be submitting a pull request for this.

Broken Python 3.x support

There are two lines in the __init__.py, which break Python 3.x:

Traceback (most recent call last):
  ...
  File ".../devenv/lib/python3.4/site-packages/pyramid_webassets/__init__.py", line 15
    except ImportError, e:
                      ^
SyntaxError: invalid syntax

Traceback (most recent call last):
  ...
  File ".../devenv/lib/python3.4/site-packages/pyramid_webassets/__init__.py", line 42
    except ValueError, e:
                     ^
SyntaxError: invalid syntax

Could you please change them to:

except Exception as e:

I also recommend you to use Tox for testing package against various versions of Python.

Need to include a MANIFEST.in

Right now installing from pip fails for me because setup.py tries to read from README and CHANGES but they are not included in the package.

Update asset spec support to latest webassets trunk

Just a heads up, webassets trunk has a new hook for resolving bundle contents to full paths. The _normalize_source_path method is gone; instead, an Environment subclass can provide a custom Resolver class.

One specific benefit of the new API is the possibility to rewrite glob instructions as well, though I don't know how possible that is in Pyramid (it's looks like it won't be straightforward in Django).

For reference, here are the patches for Flask-Assets:

miracle2k/flask-assets@3d9913f

And django-assets:

miracle2k/django-assets@6e57fee

base_dir should accept an asset spec

Rather than requiring the abspath to the assets (which makes deploying with eggs difficult), we should all specifying an asset spec...

webassets.base_dir = mypackage:static

This would be similar to how mako templates are specified:

mako.directories = mypackage:templates

This can be achieved using pyramid.path.AssetResolver

Incompatible with Pyramid 1.10 due to removal of set_request_property

Pyramid 1.10 has removed the pyramid.config.Configurator.set_request_property method (which has been deprecated since 1.5): https://docs.pylonsproject.org/projects/pyramid/en/latest/whatsnew-1.10.html#backward-incompatibilities

pyramid_webassets uses this, so it currently crashes when used with Pyramid 1.10:

config.set_request_property(get_webassets_env_from_request,
'webassets_env', reify=True)
config.set_request_property(assets, 'webassets', reify=True)

Static URL construction for path mapping

When webassets.static_view is True we add a static view configuration in Pyramid for the base directory and base URL. This allows the base URL to be specified as a relative path and have Pyramid make them absolute at the time the request is handled.

Should we do the same with config.add_webassets_path and the paths JSON?

Asset resolver resolve_output_to_url problem

In the pyramid tutorial (And I guess in the scaffold), you can find the static asset view defined as:

config.add_static_view('static', 'static', cache_max_age=3600)

The current resolve_output_to_url requires a static view defined with an absolute path. So webassets wont work till a static_view based on the 'here' parameter is added.

At the same time, the current resolve_output_to_url takes into account the env configuration setting instead of the directory. (See the following code).

    def resolve_output_to_url(self, target):
        """Given ``target``, this has to return the url through
        which the output file can be referenced.

        ``target`` may be a relative or absolute path, and is
        usually taking from the :attr:`Bundle.output` property.

        This is different from :meth:`resolve_source_to_url` in
        that you do not passed along the result of
        :meth:`resolve_output_to_path`. This is because in many
        use cases, the filesystem is not available at the point
        where the output url is needed (the media server may on
        a different machine).
        """
        if not path.isabs(target):
            # If relative, output files are written to env.directory,
            # thus we can simply base all values off of env.url.
            return url_prefix_join(self.env.url, target)
        else:
            # If an absolute output path was specified, then search
            # the url mappings.
            return self.query_url_mapping(target)

The url_prefix_join won't work with a base_url like app:static/, so the new resolve_output_to_url cannot be totally erased, but a simple path.join can be used.

My suggestion is a method like this:

      def resolve_output_to_url(self, item):
          request = get_current_request()
          if not path.isabs(item):
              item = path.join(self.env.url, item)
              return request.static_url(item)
          try:
              url = request.static_url(self.search_for_source(item))

              return url
          except ValueError as e:
              if ':' in item:
                  e.message += '(%s)' % item

              raise BundleError(e)

But perhaps I'm talking nonsense :)

TypeError: __init__() missing 1 required positional argument: 'env' with webassets 0.10

Just found one issue with webassets 0.10. It works fine with webassets 0.9.

  File "./virtualenvs/34/lib/python3.4/site-packages/pyramid/config/__init__.py", line 755, in include
    c(configurator)
  File "./uest/Python/pyramid_webassets/pyramid_webassets/__init__.py", line 286, in includeme
    assets_env = get_webassets_env_from_settings(config.registry.settings)
  File "./uest/Python/pyramid_webassets/pyramid_webassets/__init__.py", line 222, in get_webassets_env_from_settings
    assets_env = Environment(asset_dir, asset_url, **kwargs)
  File "./virtualenvs/34/lib/python3.4/site-packages/webassets/env.py", line 750, in __init__
    super(Environment, self).__init__(**more_config)
  File "./virtualenvs/34/lib/python3.4/site-packages/webassets/env.py", line 707, in __init__
    self.config.setdefault('resolver', self.resolver_class())
TypeError: __init__() missing 1 required positional argument: 'env'

Stop assuming all config values are strings!

I'm configuring Pyramid with normal Python objects (coming from another config system) and pyramid_webassets dies when I try to crazy things like set webassets.debug to True. I don't want to have to convert all these values to "true", etc!

webassets settings

This is actually more of a question. Is webassets.updater the same as the versions setting for the webassets environment?

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.