Skip to content
Snippets Groups Projects
Verified Commit 08b3b177 authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

Port from bower to yarn.

parent bbb9deb6
No related branches found
No related tags found
No related merge requests found
Showing
with 154 additions and 79 deletions
[run] [run]
include = djangobower* include = django_yarnpkg*
violations:
pep8: pep8 . --exclude='*migrations*,*settings*,*components*,*docs*'
sloccount: sloccount .
py_unittest: cat test_out
Version 6.0 (2019-12-07)
=====================================================
* Fork and port to yarnpkg
Version 4.8 (2013-10-02) Version 4.8 (2013-10-02)
===================================================== =====================================================
......
Django-bower Django-yarnpkg
============ ==============
.. image:: https://travis-ci.org/nvbn/django-bower.png Easy way to use `yarnpkg <http://yarnpkg.com/>`_ with your `Django <https://www.djangoproject.com/>`_ project.
:alt: Build Status
:target: https://travis-ci.org/nvbn/django-bower
.. image:: https://coveralls.io/repos/nvbn/django-bower/badge.png?branch=develop
:alt: Coverage Status
:target: https://coveralls.io/r/nvbn/django-bower
.. image:: https://pypip.in/v/django-bower/badge.png
:target: https://crate.io/packages/django-bower/
.. image:: https://pypip.in/d/django-bower/badge.png
:target: https://crate.io/packages/django-bower/
Easy way to use `bower <http://bower.io/>`_ with your `Django <https://www.djangoproject.com/>`_ project. This is a fork of `django-bower <https://github.com/nvbn/django-bower>` by Vladimir Iakovlev.
Bower is a package manager for the web. It offers a generic, unopinionated solution to the problem of front-end package management, while exposing the package dependency model via an API that can be consumed by a more opinionated build stack. There are no system wide dependencies, no dependencies are shared between different apps, and the dependency tree is flat. Read full documentation on `read-the-docs <https://django-yarnpkg.readthedocs.io/en/latest/>`_.
Read full documentation on `read-the-docs <https://django-bower.readthedocs.io/en/latest/>`_.
Installation Installation
------------ ------------
Install django-bower package: Install django-yarnpkg package:
.. code-block:: bash .. code-block:: bash
pip install django-bower pip install django-yarnpkg
Add django-bower to `INSTALLED_APPS` in your settings: Add django-bower to `INSTALLED_APPS` in your settings:
.. code-block:: python .. code-block:: python
'djangobower', 'django_yarnpkg',
Add staticfinder to `STATICFILES_FINDERS`: Add staticfinder to `STATICFILES_FINDERS`:
.. code-block:: python .. code-block:: python
'djangobower.finders.BowerFinder', 'django_yarnpkg.finders.NodeModulesFinder',
Specify path to components root (you need to use an absolute path): Specify path to components root (you need to use an absolute path):
.. code-block:: python .. code-block:: python
BOWER_COMPONENTS_ROOT = '/PROJECT_ROOT/components/' NODE_MODULES_ROOT = os.path.join(BASE_DIR, 'node_modules')
If you need, you can manually set the path to bower: If you need, you can manually set the path to yarnpkg:
.. code-block:: python .. code-block:: python
BOWER_PATH = '/usr/bin/bower' YARN_PATH = '/usr/bin/yarnpkg'
You can see an example settings file in `example project <https://github.com/nvbn/django-bower/blob/master/example/example/settings.py>`_. You can see an example settings file in `example project <https://github.com/Natureshadow/django-yarnpkg/blob/master/example/example/settings.py>`_.
Usage Usage
----- -----
Specify `BOWER_INSTALLED_APPS` in settings, like: Specify `YARN_INSTALLED_APPS` in settings, like:
.. code-block:: python .. code-block:: python
BOWER_INSTALLED_APPS = ( YARN_INSTALLED_APPS = (
'jquery#1.9', 'bootstrap@^4.4.1',
'underscore', 'underscore@^1.6.1',
) )
Download bower packages with the management command: Download yarn packages with the management command:
.. code-block:: bash .. code-block:: bash
./manage.py bower install ./manage.py yarn install
Add scripts in the template, like: Add scripts in the template, like:
...@@ -79,32 +68,26 @@ Add scripts in the template, like: ...@@ -79,32 +68,26 @@ Add scripts in the template, like:
{% load static %} {% load static %}
<script type="text/javascript" src='{% static 'jquery/dist/jquery.js' %}'></script> <script type="text/javascript" src='{% static 'jquery/dist/jquery.js' %}'></script>
In production you need to call `bower install` before `collectstatic`: In production you need to call `yarnpkg install` before `collectstatic`:
.. code-block:: bash .. code-block:: bash
./manage.py bower install ./manage.py yarn install
./manage.py collectstatic ./manage.py collectstatic
If you need to pass arguments to bower, like `--allow-root`, use: If you need to pass arguments to yarnpkg, like `--flat`, use:
.. code-block:: bash
./manage.py bower install -- --allow-root
You can use `bower freeze` to receive `BOWER_INSTALLED_APPS` with fixed current versions:
.. code-block:: bash .. code-block:: bash
./manage.py bower freeze ./manage.py yarn install -- --flat
You can call bower commands like `info` and `update` with: You can call yarnpkg commands like `info` and `update` with:
.. code-block:: bash .. code-block:: bash
./manage.py bower info backbone ./manage.py yarn info backbone
./manage.py bower update ./manage.py yarn update
Python 3 support Python 3 support
---------------- ----------------
django-bower supports python 3.3+ django-yarnpkg supports python 3.3+
File moved
# -*- coding: utf-8 -*-
from distutils.spawn import find_executable
import os
import sys
from django.conf import settings
__all__ = ['NODE_MODULES_ROOT', 'YARN_PATH']
NODE_MODULES_ROOT = getattr(settings, 'NODE_MODULES_ROOT', os.path.abspath(os.path.dirname(__name__)))
default_yarn_path = find_executable('yarn') or find_executable('yarnpkg')
YARN_PATH = getattr(settings, 'YARN_PATH', default_yarn_path)
...@@ -6,26 +6,23 @@ from django.conf import settings ...@@ -6,26 +6,23 @@ from django.conf import settings
from django.utils.datastructures import OrderedSet from django.utils.datastructures import OrderedSet
def read_mains(): def read_files():
for component in settings.BOWER_INSTALLED_APPS: for component in settings.YARN_INSTALLED_APPS:
component = component.split('#')[0] component = component.split('#')[0]
try: try:
with open(os.path.join( with open(os.path.join(
settings.BOWER_COMPONENTS_ROOT, settings.NODE_MODULES_ROOT,
'bower_components', 'node_modules',
component, component,
'bower.json')) as bower_json: 'package.json')) as package_json:
main = json.load(bower_json).get('main') files = json.load(bower_json).get('files')
if isinstance(main, six.string_types): for f in files:
yield '%s/%s' % (component, main) yield '%s/%s' % (component, f)
elif isinstance(main, list):
for m in main:
yield '%s/%s' % (component, m)
except FileNotFoundError: except FileNotFoundError:
continue continue
def bower_components(request): def node_modules(request):
return { return {
'bower_components': OrderedSet([main for main in read_mains()]), 'node_modules': OrderedSet([f for f in read_files()]),
} }
from django.core.management.base import CommandError
class YarnNotInstalled(CommandError):
"""Custom command error"""
def __init__(self):
super(YarnNotInstalled, self).__init__(
"Yarn not installed, read instruction here - http://yarnpkg.com/",
)
...@@ -9,14 +9,14 @@ from . import conf ...@@ -9,14 +9,14 @@ from . import conf
import os import os
class BowerFinder(FileSystemFinder): class NodeModulesFinder(FileSystemFinder):
"""Find static files installed with bower""" """Find static files installed with yarnpkg"""
def __init__(self, apps=None, *args, **kwargs): def __init__(self, apps=None, *args, **kwargs):
self.locations = [] self.locations = []
self.storages = OrderedDict() self.storages = OrderedDict()
root = self._get_bower_components_location() root = self._get_node_modules_location()
if root is not None: if root is not None:
prefix = '' prefix = ''
self.locations.append((prefix, root)) self.locations.append((prefix, root))
...@@ -25,13 +25,10 @@ class BowerFinder(FileSystemFinder): ...@@ -25,13 +25,10 @@ class BowerFinder(FileSystemFinder):
filesystem_storage.prefix = prefix filesystem_storage.prefix = prefix
self.storages[root] = filesystem_storage self.storages[root] = filesystem_storage
def _get_bower_components_location(self): def _get_node_modules_location(self):
""" """
Return the bower components location, or None if one does not exist. Return the node modules location, or None if one does not exist.
""" """
# Bower 0.10 changed the default folder from 'components' to 'bower_components'. path = os.path.join(conf.NODE_MODULES_ROOT, 'node_modules')
# Try 'bower_components' first, then fall back to trying 'components'. if os.path.exists(path):
for name in ['bower_components', 'components']: return path
path = os.path.join(conf.COMPONENTS_ROOT, name)
if os.path.exists(path):
return path
from pprint import pformat from pprint import pformat
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.conf import settings from django.conf import settings
from ..bower import bower_adapter from ..yarn import yarn_adapter
from ..exceptions import BowerNotInstalled from ..exceptions import YarnNotInstalled
class BaseBowerCommand(BaseCommand): class BaseYarnCommand(BaseCommand):
"""Base management command with bower support""" """Base management command with yarn support"""
requires_system_checks = False requires_system_checks = False
...@@ -15,21 +15,13 @@ class BaseBowerCommand(BaseCommand): ...@@ -15,21 +15,13 @@ class BaseBowerCommand(BaseCommand):
option_list = () option_list = ()
def handle(self, *args, **options): def handle(self, *args, **options):
self._check_bower_exists() self._check_yarn_exists()
bower_adapter.create_components_root() yarn_adapter.create_node_modules_root()
def _check_bower_exists(self): def _check_yarn_exists(self):
"""Check bower exists or raise exception""" """Check yarn exists or raise exception"""
if not bower_adapter.is_bower_exists(): if not yarn_adapter.is_yarn_exists():
raise BowerNotInstalled() raise YarnNotInstalled()
def _install(self, args): def _install(self, args):
bower_adapter.install(settings.BOWER_INSTALLED_APPS, *args) yarn_adapter.install(settings.YARN_INSTALLED_APPS, *args)
def _freeze(self):
packages = list(bower_adapter.freeze())
packages.sort()
output = 'BOWER_INSTALLED_APPS = {0}'.format(
pformat(packages),
)
self.stdout.write(output)
from ...bower import bower_adapter from ...yarn import yarn_adapter
from ..base import BaseBowerCommand from ..base import BaseYarnCommand
class Command(BaseBowerCommand): class Command(BaseYarnCommand):
args = 'command' args = 'command'
help = 'Call bower in components root ({0}).'.format( help = 'Call yarn in node modules root ({0}).'.format(
bower_adapter._components_root) yarn_adapter._node_modules_root)
# for Django>=1.10
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('command', nargs='*') parser.add_argument('command', nargs='*')
...@@ -16,10 +15,8 @@ class Command(BaseBowerCommand): ...@@ -16,10 +15,8 @@ class Command(BaseBowerCommand):
args = args or tuple(options.pop('command')) args = args or tuple(options.pop('command'))
if self._is_single_command('install', args): if self._is_single_command('install', args):
self._install([]) self._install([])
elif self._is_single_command('freeze', args):
self._freeze()
else: else:
bower_adapter.call_bower(args) yarn_adapter.call_bower(args)
def _is_single_command(self, name, args): def _is_single_command(self, name, args):
return len(args) == 1 and args[0] == name return len(args) == 1 and args[0] == name
from ..base import BaseBowerCommand from optparse import make_option
from ..base import BaseYarnCommand
class Command(BaseBowerCommand): class Command(BaseYarnCommand):
help = 'Freeze bower apps' help = 'Install yarn apps'
def handle(self, *args, **options): def handle(self, *args, **options):
super(Command, self).handle(*args, **options) super(Command, self).handle(*args, **options)
self._freeze() self._install(args)
File moved
...@@ -7,22 +7,3 @@ def is_executable(path): ...@@ -7,22 +7,3 @@ def is_executable(path):
executable = os.access(path, os.X_OK) or path.lower().endswith(".cmd") executable = os.access(path, os.X_OK) or path.lower().endswith(".cmd")
return os.path.isfile(path) and executable return os.path.isfile(path) and executable
return os.path.isfile(path) and os.access(path, os.X_OK) return os.path.isfile(path) and os.access(path, os.X_OK)
def which(program):
"""
Find by path and check exists.
Analog of unix `which` command.
"""
path, name = os.path.split(program)
if path:
if is_executable(program):
return program
else:
for path in os.environ["PATH"].split(os.pathsep):
path = path.strip('"')
exe_file = os.path.join(path, program)
if is_executable(exe_file):
return exe_file
return None
...@@ -24,13 +24,13 @@ script_template = template.Template( ...@@ -24,13 +24,13 @@ script_template = template.Template(
def tags(context, args, type): def tags(context, args, type):
components = ( components = (
[arg for arg in args if arg in context['bower_components']] [arg for arg in args if arg in context['node_modules']]
if args else context['bower_components'] if args else context['node_modules']
) )
files = [] files = []
for component in components: for component in components:
files.append(component) files.append(component)
context['bower_components'].remove(component) context['node_modules'].remove(component)
return {'files': [ return {'files': [
static.static(f) static.static(f)
for f in files for f in files
...@@ -39,10 +39,10 @@ def tags(context, args, type): ...@@ -39,10 +39,10 @@ def tags(context, args, type):
@register.inclusion_tag(style_template, takes_context=True) @register.inclusion_tag(style_template, takes_context=True)
def bower_styles(context, *args): def yarn_styles(context, *args):
return tags(context, args, 'css') return tags(context, args, 'css')
@register.inclusion_tag(script_template, takes_context=True) @register.inclusion_tag(script_template, takes_context=True)
def bower_scripts(context, *args): def yarn_scripts(context, *args):
return tags(context, args, 'js') return tags(context, args, 'js')
...@@ -8,21 +8,21 @@ TEST_PROJECT_ROOT = os.path.abspath( ...@@ -8,21 +8,21 @@ TEST_PROJECT_ROOT = os.path.abspath(
BASE_DIR = TEST_PROJECT_ROOT BASE_DIR = TEST_PROJECT_ROOT
BOWER_COMPONENTS_ROOT = os.path.join(TEST_PROJECT_ROOT, 'bower_components') NODE_MODULES_ROOT = os.path.join(TEST_PROJECT_ROOT, 'node_modules')
STATIC_ROOT = os.path.join(TEST_PROJECT_ROOT, 'bower_static') STATIC_ROOT = os.path.join(TEST_PROJECT_ROOT, 'yarnpkg_static')
STATIC_URL = '/static/' STATIC_URL = '/static/'
BOWER_INSTALLED_APPS = ( YARN_INSTALLED_APPS = (
'jquery#1.9', 'jquery#1.9',
'underscore', 'underscore',
) )
SECRET_KEY = 'iamdjangobower' SECRET_KEY = 'iamdjangoyarnpkg'
INSTALLED_APPS = ( INSTALLED_APPS = (
'djangobower', 'django_yarnpkg',
) )
DATABASES = { DATABASES = {
......
File moved
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment