Skip to content
Snippets Groups Projects
Commit 03dd389a authored by Elke Kreim's avatar Elke Kreim
Browse files

Fix watchassets

parent 86d38a57
Branches version2
Tags v2.1.2
No related merge requests found
......@@ -28,5 +28,3 @@ SCSS_INCLUDE_PATHS = [
# URI to the live service.it portal
SERVICE_IT_URI = 'https://service.it.hs-hannover.de/'
from django.core.management.base import BaseCommand
from hshassets import utils
from hshassets import logger
import os
import time
import shutil
import traceback
from watchdog import events
from watchdog.observers import Observer
class AssetBuildHandler(events.PatternMatchingEventHandler):
def __init__(self, scss_include_paths, *args, **kwargs):
super().__init__(*args, **kwargs)
self.scss_include_paths = scss_include_paths
def on_modified(self, event):
if isinstance(event, events.FileModifiedEvent):
print('File modified: \033[35m{}\033[0m'.format(event.src_path))
try:
app_name, app_directories = utils.discover_app(event.src_path)
utils.build_specific(app_name, app_directories, event.src_path, self.scss_include_paths)
except Exception as e:
print('Failed! \033[31m(✖_✖)\033[0m\n')
traceback.print_exc()
class ImageHandler(events.PatternMatchingEventHandler):
def dispatch(self, event):
print('Image change detected, \033[35m{}\033[0m'.format(event.src_path))
app_name, app_directories = utils.discover_app(event.src_path)
utils.copy_images(app_directories)
class FontHandler(events.PatternMatchingEventHandler):
def dispatch(self, event):
print('Font change detected, \033[35m{}\033[0m'.format(event.src_path))
app_name, app_directories = utils.discover_app(event.src_path)
utils.copy_fonts(app_directories)
class AssetsHandler(events.FileSystemEventHandler):
def on_created(self, event):
app_name = utils.get_appname_from_assets_path(event.src_path)
if not event.is_directory:
logger.info("Found new file {} in {}.".format(os.path.basename(event.src_path), event.src_path))
file_extension = utils.get_file_extension(event.src_path)
if file_extension == 'css':
utils.copy_and_compile_assets_css_to_static(app_name)
elif file_extension == 'js':
utils.copy_and_compile_assets_js_to_static(app_name)
elif file_extension == 'scss':
utils.build_app_css_from_scss(app_name)
else:
static_path = utils.get_static_path(app_name)
assets_path = utils.get_assets_path(app_name)
destination_path = str(event.src_path).replace(assets_path, static_path)
source_path = os.path.dirname(event.src_path)
destination_path = os.path.dirname(destination_path)
utils.copy_directory_tree(source_path, destination_path)
def on_deleted(self, event):
app_name = utils.get_appname_from_assets_path(event.src_path)
base = os.path.basename(event.src_path)
subfolder = utils.get_assets_subdirectory(event.src_path)
if event.is_directory:
if subfolder == base or subfolder not in ['css', 'js', 'sass']:
utils.remove_static_content(app_name, event.src_path)
if subfolder == 'css':
utils.copy_and_compile_assets_css_to_static(app_name)
elif subfolder == 'js':
utils.copy_and_compile_assets_js_to_static(app_name)
elif subfolder == 'sass':
logger.info("Noticed directory 'sass' has been deleted.")
styles = os.path.join(utils.get_static_path(app_name), 'styles.min.css')
utils.remove_file(styles)
styles = os.path.join(utils.get_static_path(app_name), 'styles.css')
utils.remove_file(styles)
else:
logger.info("Noticed '{}' has been deleted".format(base))
static_path = utils.get_static_path(app_name)
assets_path = utils.get_assets_path(app_name)
path = str(event.src_path).replace(assets_path, static_path)
utils.remove_empty_directory(os.path.basename(path[0]))
else:
extension = utils.get_file_extension(event.src_path)
if extension == subfolder in ['js', 'css']:
utils.remove_static_minimized_file(app_name, event.src_path)
elif base == '_init.scss':
logger.info("Noticed '_init.scss' has been deleted.")
utils.build_app_css_from_scss(app_name)
sass_path = os.path.join(utils.get_assets_path(app_name), 'sass')
utils.remove_empty_directory(sass_path)
else:
logger.info("Noticed '{}' has been deleted".format(base))
static_path = utils.get_static_path(app_name)
assets_path = utils.get_assets_path(app_name)
path = str(event.src_path).replace(assets_path, static_path)
utils.remove_file(path)
utils.remove_empty_directory(os.path.basename(path[0]))
class Command(BaseCommand):
......@@ -46,29 +78,27 @@ class Command(BaseCommand):
def handle(self, *args, **options):
print('Building assets initially ...')
utils.do_everything()
utils.build_assets()
print('Done. Watching now for changes \033[94m(ಠ_ಠ)\033[0m ...\n')
observer = Observer()
asset_directories = utils.get_asset_directories()
scss_include_paths = utils.get_scss_include_paths(asset_directories)
assets_handler = AssetsHandler()
build_handler = AssetBuildHandler(scss_include_paths, patterns=['*.js', '*.sass', '*.scss', '*.css'])
image_handler = ImageHandler(patterns=['*'])
for app_name, app_directories in asset_directories.items():
apps = utils.get_installed_apps_with_asset_directory(include_project=True)
if not os.path.isdir(app_directories['static_path']):
os.makedirs(app_directories['static_path'])
for app_name in apps:
observer.schedule(build_handler, app_directories['asset_path'], recursive=True)
asset_path = utils.get_assets_path(app_name)
if os.path.isdir(app_directories['asset_path'] + '/img'):
observer.schedule(image_handler, app_directories['asset_path'] + '/img', recursive=True)
observer.schedule(assets_handler, asset_path, recursive=True)
observer.start()
try:
observer.join()
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
print('\033[2DBye \033[95mʕʘ‿ʘʔ\033[0m')
observer.join()
from django.test import TestCase
from hshassets.utils import (
get_file_extension,
)
"""
If you want to execute tests, please make sure your user has rights to create test database:
You can alter user permissions in your postgres database by using: ALTER USER username CREATEDB;
"""
class UtilsTestCase(TestCase):
def test_get_file_extension(self):
"""Get correct extension of file."""
self.assertEqual(get_file_extension("/my/path/to/file/base.js"), "js")
self.assertEqual(get_file_extension("/my/path/to/file/base.js.js"), "js")
self.assertEqual(get_file_extension("/my/path/to/file/base"), "")
......@@ -170,6 +170,27 @@ def remove_empty_directory(path):
remove_empty_directory(path)
def remove_directory(path):
"""
Delete subdirectory of path even if empty or not.
:param path: as string
:return: no return
"""
if os.path.isdir(path):
shutil.rmtree(path)
def remove_file(path):
"""
Delete file
:param path: as string
:return: no return
"""
if os.path.isfile(path):
os.remove(path)
logger.info("Delete file '{}' in '{}'.".format(os.path.split(path)[-1], os.path.split(path)[0]))
def remove_static_minimized_file(app_name, source_path):
"""
Removes the js and js min file if found in static directory of app_name.
......@@ -178,9 +199,9 @@ def remove_static_minimized_file(app_name, source_path):
:return: no return
"""
subdirectory = str(get_file_extension(source_path)).strip('.')
extension = get_file_extension(source_path)
static_path = os.path.join(get_static_path(app_name), subdirectory)
static_path = os.path.join(get_static_path(app_name), extension)
file_name = os.path.basename(source_path)
min_file_name = get_min_name(file_name)
......@@ -196,6 +217,21 @@ def remove_static_minimized_file(app_name, source_path):
remove_empty_directory(static_path)
def remove_static_content(app_name, path):
"""
Removes static file or directory according to an asset file or directory that has been removed.
:param app_name: as string
:param path: assets path as string
:return: no return
"""
static_path = get_static_path(app_name)
assets_path = get_assets_path(app_name)
dest_path = str(path).replace(assets_path, static_path)
if os.path.exists(dest_path):
shutil.rmtree(dest_path)
remove_empty_directory(os.path.dirname(dest_path))
def minimize_js(app_name, js_file_path):
"""
Minimize js file which means remove whitspaces and calls function write_files to save minimized js in static
......@@ -338,6 +374,7 @@ def copy_directory_tree(source, destination):
(os.path.join(source)),
(os.path.join(destination))
)
logger.info("Copy assets directory '{}' to '{}'.".format(os.path.basename(source), destination))
def copy_and_compile_assets_css_to_static(app_name):
......@@ -467,9 +504,11 @@ def init_assets(name=None, empty_scss=False):
# create empty scss file
init_file = open(os.path.join(sass_path, '_init.scss'), 'w')
init_file.close()
logger.info("Create '_init.scss' in '{}'.".format(get_sass_path(name)))
else:
# copy default scss file from hshassets
shutil.copyfile(get_default_scss_path(), os.path.join(get_sass_path(name), '_init.scss'))
logger.info("Save '_init.scss' in '{}'.".format(get_sass_path(name)))
def build_specific(app_name, file_path):
......@@ -507,9 +546,9 @@ def get_assets_subdirectory(path):
def get_file_extension(path):
"""
Returns the extension of path, for example "/home/..../base.js" returns ".js". If no extension found
empty string will be returned
Returns the extension of path, for example "/home/..../base.js" returns "js".
If no extension found empty string will be returned
:param path: path as string
:return: extension as string or empty string
"""
return os.path.splitext(path)[-1]
return (os.path.splitext(path)[-1]).strip(".")
......@@ -7,7 +7,7 @@ os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
setup(
name='django-hshassets',
version='2.1.0',
version='2.1.2',
packages=find_packages(),
include_package_data=True,
license='MIT License',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment