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

Add management command initassets, review utils

parent ed0e748f
Branches
Tags
No related merge requests found
from .defaults import * from .defaults import *
from .logging import *
from django import conf from django import conf
# merge defaults with customized user settings # merge defaults with customized user settings
for setting_name in [k for k in globals().keys() if k.isupper()]: for setting_name in [k for k in globals().keys() if k.isupper()]:
......
import logging.config
LOGGING_CONFIG = None
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse',
},
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'formatters': {
'with_timestamp': {
'format': '[%(asctime)s %(levelname)s %(thread)d] %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
},
'without_timestamp': {
'format': '%(name)s %(levelname)s: %(message)s',
}
},
'handlers': {
'console': {
'level': 'INFO',
'class': 'logging.StreamHandler',
'formatter': 'with_timestamp'
},
'null': {
'class': 'logging.NullHandler',
},
'console_without_timestamp': {
'level': 'INFO',
'class': 'logging.StreamHandler',
'formatter': 'without_timestamp'
}
},
'loggers': {
'': {
'handlers': ['console'],
'level': 'INFO'
},
'django': {
'level': 'WARNING',
'handlers': ['console'],
'propagate': False,
},
'django.db': {
'level': 'INFO',
'handlers': ['console'],
'propagate': False,
},
'django.request': {
'handlers': ['console'],
'level': 'WARNING',
'propagate': False,
},
'django.server': {
'handlers': ['console'],
'level': 'WARNING',
'propagate': False,
},
'django.security': {
'handlers': ['console'],
'level': 'WARNING',
'propagate': False,
},
'django.template': {
'handlers': ['console'],
'level': 'INFO',
'propagate': False,
},
'hshassets': {
'handlers': ['console_without_timestamp', ],
'level': 'INFO',
'propagate': False,
},
}
}
logging.config.dictConfig(LOGGING)
...@@ -38,13 +38,13 @@ $custom-colors: ($hsh-colors); ...@@ -38,13 +38,13 @@ $custom-colors: ($hsh-colors);
// COLOR SCHEME FOR CORPORATE DESIGN // COLOR SCHEME FOR CORPORATE DESIGN
// by default service will be used, if you need another one comment and uncomment approprate // by default service will be used, if you need another one comment and uncomment approprate
//@import "cd/f1.scss"; //@import "cd/f1";
//@import "cd/f2.scss"; //@import "cd/f2";
//@import "cd/f3.scss"; //@import "cd/f3";
//@import "cd/f4.scss"; //@import "cd/f4";
//@import "cd/f5.scss"; //@import "cd/f5";
@import "cd/service.scss"; // default color scheme for hshassets @import "cd/service"; // default color scheme for hshassets
//@import "cd/zsw.scss"; //@import "cd/zsw";
@import "lib/bulma-0.7.2/sass/utilities/derived-variables"; @import "lib/bulma-0.7.2/sass/utilities/derived-variables";
...@@ -151,4 +151,4 @@ $panel-block-hover-background-color: $cd-link-hover; ...@@ -151,4 +151,4 @@ $panel-block-hover-background-color: $cd-link-hover;
// import customized hshstyle // import customized hshstyle
@import "corporate_design"; @import "corporate_design";
@import "hshstyles.scss"; @import "hshstyles";
\ No newline at end of file \ No newline at end of file
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.conf import settings
from hshassets import utils from hshassets import utils
from importlib import import_module
import os
import sass
import jsmin
class Command(BaseCommand): class Command(BaseCommand):
help = 'Builds the projects assets' help = 'Builds the projects assets'
def handle(self, *args, **options): def handle(self, *args, **options):
verbose = bool(options.get('verbosity', 0)) utils.build_assets()
print('\nStart generating styles ...\n')
utils.do_everything(verbose=verbose)
print('Everything finished! \033[92m(ಠ‿↼)\033[0m\n')
from django.core.management.base import BaseCommand
from django.conf import settings
from hshassets import utils
from hshassets import logger
class Command(BaseCommand):
help = 'Initializes the projects assets by creating an assets directory and copying scss file'
def add_arguments(self, parser):
parser.add_argument('app_name', nargs='?', type=str)
parser.add_argument(
'-e',
'--empty',
action="store_true",
dest='empty',
help='Create an empty _init.scss file and directories',
)
def handle(self, *args, **options):
app_name = options.get('app_name')
if options['empty']:
empty=True
else:
empty=False
if app_name is None or app_name in settings.INSTALLED_APPS:
logger.debug('\nStart initalise assets.\n')
utils.init_assets(app_name, empty)
logger.debug('Initialisation finished!\n')
else:
logger.info('The name is not found in installed apps of your project, no initialisation possible.')
if options['empty']:
pass
\ No newline at end of file
from django.conf import settings from django.conf import settings
from hshassets import logger
from hshassets.app_settings import SCSS_INCLUDE_PATHS from . import logger
from importlib import import_module from importlib import import_module
import os import os
import time
import sass import sass
import jsmin import jsmin
import shutil import shutil
import re import re
def get_asset_directories(): def get_installed_apps_with_asset_directory(include_project=False):
""" """
Get all apps and app path of installed apps that contains an asset directory on its root. Returns a list of all installed apps that have an asset directory, except 'hshassets' and
:return: dictionary of apps with path according to parameter without_project with or without the project itself.
:return: list of appnames
""" """
asset_apps = {} apps = []
for app_name in settings.INSTALLED_APPS: for app_name in settings.INSTALLED_APPS:
asset_apps.update(get_directories(app_name)) if os.path.isdir(get_assets_path(app_name)):
if app_name is not 'hshassets':
apps.append(app_name)
if not include_project and get_projectname() in apps:
apps.remove(get_projectname())
return asset_apps return apps
def get_directories(app_name): def get_app_path(app_name):
""" """
Create a dictionary for each app that includes asset directory. Returns the path of the app.
The dictionary includes information about app path, static directory path, :param app_name: string
asset directory path and variable to save color scheme of that app. :return: path of app as string
:param app_name: name of the app as string
:return: dictionary including information of app with its associated paths for
app, static and assets and color scheme
""" """
app_module = import_module(app_name) app_module = import_module(app_name)
app_path = app_module.__path__[0] app_path = app_module.__path__[0]
app_dirs = {} return app_path
def get_static_path(app_name):
"""
Returns path of static directory with app directory included regardless it exists.
:param app_name: name of the app as string, app_path as string
:return: static app path as string
"""
return os.path.join(get_app_path(app_name), 'static', app_name)
def get_assets_path(app_name):
"""
Returns path of assets directory regardless it exists.
:param app_name as string
:return: assets app path as string
"""
return os.path.join(get_app_path(app_name), 'assets')
if os.path.isdir(os.path.join(app_path, 'assets')): # directory assets exist in app def get_sass_path(app_name):
app_dirs = {app_name: {'app_path': app_path, """
'static_path': os.path.join(app_path, 'static', app_name), Returns path of sass directory regardless it exists.
'asset_path': os.path.join(app_path, 'assets'), :param app_name: path of app as string
'color_scheme': None, :return: path of sass directory as string
}} """
return app_dirs return os.path.join(get_assets_path(app_name), 'sass')
def get_color_scheme(app_name, asset_path): def get_init_scss_path(app_name):
"""
Returns the path of the '_init.scss'-file if exists otherwise None
:param app_name: name as string
:return: path as string or None
"""
return os.path.join(get_sass_path(app_name), '_init.scss')
def get_color_scheme(source):
""" """
Search for given color scheme in _init.scss file by searching for command to import corporate colors, Search for given color scheme in _init.scss file by searching for command to import corporate colors,
for example @import 'cd/service.scss'. for example @import 'cd/service.scss'.
:param asset_path: path where sass/_init.scss can be found (asset path does not contain sass/_init.scss)
:return: color scheme as string or None if no color scheme can be found :return: color scheme as string or None if no color scheme can be found
""" """
color = None color = None
print('Searching for color scheme of {} ...'.format(app_name)) logger.info('Searching for color scheme ...')
if app_name == 'hshassets':
scss_file = os.path.join(asset_path, 'sass', 'default.scss')
else:
scss_file = os.path.join(asset_path, 'sass', '_init.scss')
if os.path.isfile(scss_file): if os.path.isfile(source):
with open(scss_file, 'r') as scss: with open(source, 'r') as scss:
content = scss.read() + '\n' content = scss.read() + '\n'
# Search whether or rather which color is imported into init.scss # Search whether or rather which color is imported into init.scss
color = re.search(r"^@import [\'\"]cd/(?P<cd_color>[a-z0-9]*)[.sc]*[\'\"];", content, re.MULTILINE) color = re.search(r"^@import [\'\"]cd/(?P<cd_color>[a-z0-9]*)[\'\"];", content, re.MULTILINE)
if color: if color:
color_scheme = (color.groupdict().get('cd_color')) color_scheme = (color.groupdict().get('cd_color'))
print('Found color scheme', color_scheme, '\n') logger.info('Found color scheme {} \n'.format(color_scheme))
else: else:
color_scheme = None color_scheme = None
print('No color scheme found.\n') logger.info('No color scheme found.\n')
return color_scheme return color_scheme
def separate_asset_directories(asset_directories): def copy_favicon(app_name, color_scheme):
# Separating the app directories from the project directories for further processing """
Copies favicon.ico from 'hshassets' depending on chosen color scheme to static 'img' directory of an app.
If no 'img' directory exists it will be created.
:param app_name:
:param color_scheme:
:return: no return
"""
img_path = os.path.join(get_static_path(app_name), 'img')
# get name of the django project # no color, no favicon to copy
project_name = os.path.basename(settings.BASE_DIR) if color_scheme:
project_directories = {} # get favicon source in hshassets
favicon_source = os.path.join(get_assets_path('hshassets'), 'img', 'hsh_brand', 'favicons', color_scheme,
'favicon.ico')
if project_name in asset_directories.keys(): # project has asset directory # create img directory in static to save favicon inside
project_directories.update({project_name: asset_directories.pop(project_name)}) if not os.path.isdir(img_path):
else: os.makedirs(img_path)
# the project has no asset directory logger.info('Create "img" directory to save favicon.')
app_path = os.path.join(os.path.dirname(settings.BASE_DIR), 'swamp')
project_directories = ({project_name: {'app_path': app_path,
'static_path': app_path + '/static/' + project_name,
'asset_path': app_path + '/assets',
'color_scheme': None}})
return asset_directories, project_directories shutil.copyfile(favicon_source, os.path.join(img_path, 'favicon.ico')) # favicon for every app
logger.info('Copy favicon for color scheme {} to static'.format(color_scheme))
else:
if os.path.isfile(os.path.join(img_path, 'favicon.ico')):
os.remove(os.path.join(img_path, 'favicon.ico'))
def get_hshassets_directories(): def get_filepaths(path, file_ending):
""" """
Get the information for hshassets Returns a list of paths to files. The type of files is determined by parameter file_ending. They are
:return: dictionary with app_path, static_path, asset_path and color_scheme searched in sub directory of path that is named equal to file_ending. For example: JavaScript files
with ending '.js' are searched in subdirectory 'js' or css-files in sub directory 'css'.
:param path: path as string
:param file_ending: type of files as string
:return: list of filepaths
""" """
return (get_directories('hshassets')).get('hshassets') files_list = []
for dirpath, dirs, files in os.walk(os.path.join(path, file_ending)):
for file in files:
if file.endswith(file_ending):
files_list.append(os.path.join(dirpath, file))
return files_list
def get_scss_include_paths(asset_directories): def remove_empty_directory(path):
""" Get additional include_paths for the scss parser - to be able to load e.g. bulma without getting insane """ """
include_paths = [] Deletes subdirectory of path as long as they are empty.
for app_name, rel_paths in SCSS_INCLUDE_PATHS: Checks if directory is empty and deletes it if
if app_name in asset_directories.keys(): :param path: string
app_meta = asset_directories[app_name] :return: no return
for rel_path in rel_paths: """
lib_path = os.path.join(app_meta['asset_path'], rel_path) try:
if os.path.exists(lib_path): count_path_entries = len(os.listdir(path))
include_paths.append(lib_path) except FileNotFoundError:
else: logger.debug('This path does not belong to a directory.')
logger.warning('You specified an additional scss path which can not be found: {}'.format(lib_path))
else: else:
logger.warning( if count_path_entries == 0:
'You specified the app {} in "SCSS_INCLUDE_PATHS" that can not be found. Is it in INSTALLED_APPS?' os.rmdir(path)
.format(app_name) logger.info('Remove empty directory {}'.format(os.path.basename(path)))
) path = os.path.dirname(path)
return include_paths remove_empty_directory(path)
def build_static(app_name, app_directories):
print('Building \033[34mstatic\033[0m for app \033[31m{}\033[0m ...\n'.format(app_name)) def remove_static_minimized_file(app_name, source_path):
create_static_directory(app_directories['static_path']) """
copy_directories(app_name, app_directories) Removes the js and js min file if found in static directory of app_name.
:param app_name: name as string
:param source_path: path as string
:return: no return
"""
subdirectory = str(get_file_extension(source_path)).strip('.')
def create_static_directory(static_path): static_path = os.path.join(get_static_path(app_name), subdirectory)
# delete old static folders of app
if os.path.isdir(static_path):
shutil.rmtree(static_path)
print('Remove directory: {}'.format(static_path))
# logger.info('Remove directory: {}'.format(static_path))
# create new static folder of app
os.makedirs(static_path)
print('Create directory: {}\n'.format(static_path))
# logger.info('Create directory: {}'.format(static_path))
file_name = os.path.basename(source_path)
min_file_name = get_min_name(file_name)
def copy_css_directories(app_name, app_drectories): if os.path.isfile(os.path.join(static_path, file_name)):
os.remove(os.path.join(static_path, file_name))
logger.info('Removed {} from static of {}.'.format(file_name, app_name))
if os.path.isfile(os.path.join(static_path, min_file_name)):
os.remove(os.path.join(static_path, min_file_name))
logger.info('Removed {} from static of {}.'.format(min_file_name, app_name))
css_files = [] # if directory is empty now remove directory
for root, dirs, files in os.walk(os.path.join(app_directories['asset_path'], 'css')): remove_empty_directory(static_path)
for f in files:
if f.endswith('.css'):
css_files.append(os.path.join(root, f))
for css_file in css_files:
expand, mini = build_scss_output(css_file) 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
directory of the app
:param app_name: name as string
:param js_file_path: path as string
:return: no return
"""
static_js_path = os.path.join(get_static_path(app_name), 'js')
with open(css_file, 'r') as infile: with open(js_file_path, 'r') as infile:
content = infile.read() content = infile.read()
dest_js_path = os.path.join(app_directories['static_path'], 'js') min_content = (jsmin.jsmin(content))
dest_file_name = os.path.basename(js_file)
dest_file_name_stripped, dest_file_extenstion = os.path.splitext(dest_file_name)
if not os.path.isdir(dest_js_path): dest_file_name = os.path.basename(js_file_path)
os.makedirs(dest_js_path)
with open(os.path.join(dest_js_path, dest_file_name), 'w') as outfile: if not os.path.isdir(static_js_path):
outfile.write(content + '\n') os.makedirs(static_js_path)
with open(os.path.join(dest_js_path, dest_file_name_stripped + '.min' + dest_file_extenstion), 'w') as outfile: write_files(static_js_path, dest_file_name, content, min_content)
outfile.write(jsmin.jsmin(content))
def copy_directories(app_name, app_directories): def copy_and_compile_assets_js_to_static(app_name):
"""
if not os.path.isdir(app_directories['asset_path']): Copies js directory in assets directory to static. If js exists in static it will be removed with content files.
print('No asset directory found.') Catch all js files found in assets/js and calls function minimize_js to minimize content of js files.
return :param app_name: name as string
:return: no return
# copy all directories from assets to static except sass and js """
for entry in os.scandir(app_directories['asset_path']): logger.info('Building \033[33mjavascript\033[0m for app "{}" ...'.format(app_name))
if entry.is_dir and not entry.name in ['sass', 'js']:
print('Found {} in assets directory of {}'.format(entry.name, app_name))
print('Start copying {} to static ...'.format(entry.name))
if os.path.isdir(os.path.join(app_directories['static_path'], entry.name)):
shutil.rmtree(os.path.join(app_directories['static_path'], entry.name))
shutil.copytree(
(os.path.join(app_directories['asset_path'], entry.name)),
(os.path.join(app_directories['static_path'], entry.name))
)
print('Done!\n')
assets_path = get_assets_path(app_name)
static_js_path = os.path.join(get_static_path(app_name), 'js')
def copy_favicon(static_path, color_scheme): # remove existing js directory in static
# no color, no favicon to copy if os.path.exists(static_js_path):
if not color_scheme: shutil.rmtree(static_js_path)
return logger.debug('Removed found directory {} in static directory'.format(os.path.basename(static_js_path)))
# get directories to copy the corresponding favicon js_files = get_filepaths(assets_path, 'js')
hshassets_directories = get_hshassets_directories()
# create img directory in static to save favicon inside for js_file in js_files:
if not os.path.isdir(os.path.join(static_path, 'img')): minimize_js(app_name, js_file)
os.makedirs(os.path.join(static_path, 'img'))
logger.info('Create "img" directory to save favicon.')
# copy favicon from hshassets to static directory
shutil.copy2(
os.path.join(hshassets_directories['asset_path'], 'img', 'hsh_brand', 'favicons', color_scheme, 'favicon.ico'),
os.path.join(static_path, 'img', 'favicon.ico') # favicon for every app
)
logger.info('Copy favicon for color scheme {} to static'.format(color_scheme)) def build_css_from_scss(app_name):
"""
Write style css files for an app based on scss files. If no scss file exists as sass source
the default scss in hshassets will be taken. This is only useful for project if the style
is based on hshassets without any changes.
:param app_name: name as string
:return: no return
"""
sass_source = get_init_scss_path(app_name)
# if no path to a sass file exists in projekt take the default sass file of 'hshassets'
if not os.path.isfile(sass_source) and app_name is get_projectname():
sass_source = get_default_scss_path()
def build_javascript(app_name, app_directories, verbose=True): if os.path.isfile(sass_source):
if verbose: destination_path = get_static_path(app_name)
print('Building \033[33mjavascript\033[0m for app "{}" ...'.format(app_name))
start = time.time() # list of path to find sass source files to @import
include_paths = [get_sass_path('hshassets'), get_sass_path(app_name)]
js_files = [] expanded_content, compressed_content = get_compiled_css(sass_source, include_paths)
for root, dirs, files in os.walk(os.path.join(app_directories['asset_path'], 'js')): write_files(destination_path, 'styles.css', expanded_content, compressed_content)
for f in files:
if f.endswith('.js'):
js_files.append(os.path.join(root, f))
for js_file in js_files:
with open(js_file, 'r') as infile:
content = infile.read()
dest_js_path = os.path.join(app_directories['static_path'], 'js') def get_min_name(file_name):
dest_file_name = os.path.basename(js_file) """
dest_file_name_stripped, dest_file_extenstion = os.path.splitext(dest_file_name) Returns the name of file with additional '.min' in front of file extension.
:param file_name: file name as string
:return: name as string or None, example: 'name.min.css'
"""
min_name = None
if not os.path.isdir(dest_js_path): name, extension = os.path.splitext(file_name)
os.makedirs(dest_js_path)
with open(os.path.join(dest_js_path, dest_file_name), 'w') as outfile: if extension:
outfile.write(content + '\n') min_name = '{}.min{}'.format(name, extension)
with open(os.path.join(dest_js_path, dest_file_name_stripped + '.min' + dest_file_extenstion), 'w') as outfile: return min_name
outfile.write(jsmin.jsmin(content))
def build_css_for_app(app_name, app_directories): def write_files(path, file_name, expanded_output, compressed_output):
""" """
Function gets the source file for further handling regarding to the appname which means it differs Writes at the destination determined by parameter path an expanded file with name file_name
between hshassets app and other apps to get the scss source. Calls function build_scss_output with source file and a minimized file with 'min' included in name.
and calls function write_scss_files to write style.css and style.min.css. :param path: destination for files as string
:param app_name: :param file_name: name file as string
:param app_directories: :param expanded_output: string content
:return: - :param compressed_output: minimized string content
:return: no return
""" """
hshassets_directories = get_hshassets_directories() min_file_name = get_min_name(file_name)
include_paths = [os.path.join(hshassets_directories['asset_path'], 'sass')]
sass_dir = os.path.join(app_directories['asset_path'], 'sass')
if os.path.isdir(sass_dir):
if app_name == 'hshassets':
source_file = os.path.join(sass_dir, 'default.scss')
else:
source_file = os.path.join(app_directories['asset_path'], 'sass', '_init.scss')
include_paths.append(sass_dir)
if os.path.isfile(source_file):
expanded_output, compressed_output = build_scss_output(source_file, include_paths)
write_css_files(app_directories, expanded_output, compressed_output)
if not os.path.exists(path):
os.makedirs(path)
def build_css_for_project(app_name, app_directories): with open(os.path.join(path, file_name), 'w') as outfile:
""" outfile.write(expanded_output)
Function gets the source file for further handling. If the project does not contain a scss source to compile it
takes the hshsassets scss source to compile into css. Calls function build_scss_output with source file
and calls function write_scss_files to write style.css and style.min.css.
:param app_name:
:param app_directories:
:return: -
"""
hshassets_directories = get_hshassets_directories()
source_file = os.path.join(hshassets_directories['asset_path'], 'sass', 'default.scss')
include_paths = [os.path.join(hshassets_directories['asset_path'], 'sass')]
# if no asset directory exist, css will be build of hshasset scss files logger.info('Write {}'.format(file_name))
if os.path.isdir(os.path.join(app_directories['asset_path'], 'sass')):
if os.path.isfile(os.path.join(app_directories['asset_path'], 'sass', '_init.scss')):
source_file = os.path.join(app_directories['asset_path'], 'sass', '_init.scss')
include_paths.append(os.path.join(app_directories['asset_path'], 'sass'))
expanded_output, compressed_output = build_scss_output(source_file, include_paths) with open(os.path.join(path, min_file_name), 'w') as outfile:
outfile.write(compressed_output)
write_css_files(app_directories, expanded_output, compressed_output) logger.info('Write {}'.format(min_file_name))
def build_scss_output(source_file, include_paths=None): def get_compiled_css(source_file, include_paths=None):
""" """
This function compiles sass input into css string. This function compiles sass input into css string.
:param source_file: filename of sass/scss source code to compile :param source_file: filename of sass/scss source code to compile
...@@ -320,328 +321,194 @@ def build_scss_output(source_file, include_paths=None): ...@@ -320,328 +321,194 @@ def build_scss_output(source_file, include_paths=None):
return expanded_output, compressed_output return expanded_output, compressed_output
def write_css_files(app_directories, expanded_output, compressed_output): def copy_directory_tree(source, destination):
"""
Copy directory tree located in source path to destination path.
If directory tree in destination path already exists it will be removed before copying.
:param source: path as string
:param destination: path as string
:return: no return
"""
# remove subdirectories
if os.path.isdir(destination):
shutil.rmtree(destination)
with open(os.path.join(app_directories['static_path'], 'styles.css'), 'w') as outfile: # copy directory tree
outfile.write(expanded_output) shutil.copytree(
(os.path.join(source)),
(os.path.join(destination))
)
logger.info('Write style.css')
with open(os.path.join(app_directories['static_path'], 'styles.min.css'), 'w') as outfile: def copy_and_compile_assets_css_to_static(app_name):
outfile.write(compressed_output) """
Copies each css file found in assets subdirectory css, compiles css files to minimized css files
and calls write_file functions to write css files to static app directory.
:param app_name:
:return: no return
"""
asset_css_path = get_assets_path(app_name)
static_css_path = os.path.join(get_static_path(app_name), 'css')
logger.info('Write style.min.css') if os.path.exists(static_css_path):
shutil.rmtree(static_css_path)
# no directory 'css', no need to copy...
if os.path.isdir(os.path.join(asset_css_path, 'css')):
css_files = get_filepaths(asset_css_path, 'css')
for css_file in css_files:
file_name = os.path.basename(css_file)
expanded_content, compressed_content = get_compiled_css(css_file)
write_files(static_css_path, file_name, expanded_content, compressed_content)
def build_scss(app_directories, content, include_paths):
expanded_output = sass.compile(string=content, include_paths=include_paths, output_style='expanded') def copy_assets_dirs_to_static(app_name):
compressed_output = sass.compile(string=content, include_paths=include_paths, output_style='compressed') """
Copies recursive all sub directories found in assets directory except sub directories 'scss', 'css' and 'js'
because they have to be treated differently.
:param app_name: as string
:return: no return
"""
asset_path = get_assets_path(app_name)
# copy all directories from assets to static except sass, css and js
if os.path.isdir(asset_path):
static_path = get_static_path(app_name)
if not os.path.isdir(static_path):
os.makedirs(static_path)
logger.info('Create static directory for {}'.format(app_name))
else:
logger.info('Remove {} from "{}"'.format(static_path, app_name))
shutil.rmtree(static_path)
for assets_entry in os.scandir(asset_path):
if assets_entry.is_dir and assets_entry.name not in ['sass', 'js', 'css']:
with open(os.path.join(app_directories['static_path'], 'styles.css'), 'w') as outfile: logger.info('Found {} in assets directory of {}'.format(assets_entry.name, app_name))
outfile.write(expanded_output)
logger.info('Write style.scss')
with open(os.path.join(app_directories['static_path'], 'styles.min.css'), 'w') as outfile: destination_path = os.path.join(get_static_path(app_name), assets_entry.name)
outfile.write(compressed_output) source_path = os.path.join(get_assets_path(app_name), assets_entry.name)
copy_directory_tree(source_path, destination_path)
logger.info('Write style.min.scss') logger.info('Copied {} to static'.format(assets_entry.name))
else:
logger.info('No assets directory found in {}'.format(app_name))
def do_everything(verbose=False): def get_projectname():
""" """
Function initiates building css files for project and apps on base of hshassets respectively bulma. Returns name of the project
The way of handling is different for apps and project. Even if the project does not include an assetfolder :return: name as string
a style.css or style.min.css file will be generate by on base of hshassets.
A style.css for an app will be only generated if an app includes an asset folder with _init.scss.
:param verbose:
:return: -
""" """
asset_directories = get_asset_directories() # directories for apps and project app project_name = os.path.basename(settings.BASE_DIR)
# get color schemes for all apps return project_name
for app_name, app_directories in asset_directories.items():
app_directories['color_scheme'] = get_color_scheme(app_name, app_directories['asset_path'])
# separate apps and prdject directories for different treatment
app_asset_directories, project_asset_directories = separate_asset_directories(asset_directories)
# include_paths = (os.path.join(get_hshassets_directories()['asset_path'], 'sass')) def get_default_scss_path():
"""
Returns path to default.scss file in hshassets.
:return: path as string
"""
return os.path.join(get_sass_path('hshassets'), 'default.scss')
# hshassets_directories = get_hshassets_directories()
# build_static('hshassets', hshassets_directories)
# if hshassets_directories['color_scheme']:
# copy_favicon(hshassets_directories)
def build_app_css_from_scss(app_name):
for project_name, project_directories in project_asset_directories.items(): init_path = get_init_scss_path(app_name)
build_static(project_name, project_directories) build_css_from_scss(app_name)
# get favicon according to the given information in _intitial.scss
if project_directories['color_scheme']:
copy_favicon(project_directories['static_path'], project_directories['color_scheme'])
else:
hshassets_directories = get_hshassets_directories()
# copy favicon according to default color scheme of hshassets
copy_favicon(project_directories['static_path'], hshassets_directories['color_scheme'])
build_javascript(project_name, project_directories, verbose=verbose)
build_css_for_project(project_name, project_directories)
if os.path.isfile(init_path):
color_scheme = get_color_scheme(init_path)
else:
color_scheme = None
for app_name, app_directories in app_asset_directories.items(): if not color_scheme and app_name == get_projectname():
build_static(app_name, app_directories) # get default color scheme from HSHASSETS
if app_directories['color_scheme']: color_scheme = get_color_scheme(get_default_scss_path()) or 'service'
copy_favicon(app_directories['static_path'], app_directories['color_scheme'])
build_javascript(app_name, app_directories, verbose=verbose)
build_css_for_app(app_name, app_directories)
copy_favicon(app_name, color_scheme)
def build_specific(app_name, app_directories, file_path, scss_include_paths):
if file_path.endswith(('.sass', '.scss', '.css')):
build_scss(app_name, app_directories, scss_include_paths)
elif file_path.endswith('.js'):
build_javascript(app_name, app_directories)
def build_assets():
"""
This function calls all functions needed for execution.
"""
# PROJECT
project_name = get_projectname()
apps = get_installed_apps_with_asset_directory(include_project=True)
if project_name not in apps:
apps.append(project_name)
def create_asset_directory(): for app_name in apps:
copy_assets_dirs_to_static(app_name)
copy_and_compile_assets_css_to_static(app_name)
copy_and_compile_assets_js_to_static(app_name)
build_app_css_from_scss(app_name)
project_name = os.path.basename(settings.BASE_DIR)
project_path = get_app_path(project_name)
if not os.path.isdir(os.path.join(project_path, 'assets')): def init_assets(name=None, empty_scss=False):
os.mkdir(os.path.join(project_path, 'assets')) """
logger.info('Create asset directory.') Creates directories for assets and sass if not existing and copy hshassets default.scss file
to _init.scss if empty_scss is False. If empty_scss is True it creates an empty _init.scss file instead.
If name is None the projectname will be used, apps can be initialised if parameter name is app name.
Also an app can be initialised by using its name.
:param name: app name as sting
:param empty_scss: boolean
:return: no return
"""
if name is None:
name = get_projectname()
# create directories on path to sass directory if not existing
sass_path = get_sass_path(name)
if not os.path.isdir(sass_path):
os.makedirs(sass_path)
if empty_scss:
# create empty scss file
init_file = open(os.path.join(sass_path, '_init.scss'), 'w')
init_file.close()
else: else:
logger.info("Asset directory already exists.") # copy default scss file from hshassets
shutil.copyfile(get_default_scss_path(), os.path.join(get_sass_path(name), '_init.scss'))
def create_init_scss(app_name): def build_specific(app_name, file_path):
pass if file_path.endswith('.scss'):
build_css_from_scss(app_name)
elif file_path.endswith('.css'):
copy_and_compile_assets_css_to_static(app_name)
elif file_path.endswith('.js'):
copy_and_compile_assets_js_to_static(app_name)
def get_app_path(app_name): def get_appname_from_assets_path(path):
"""
Returns the app name extract from asset path. The last-but-one element
of the path is equal to the app name.
:param path: path to asset directory as string
:return: name of app as string
"""
app_path = path.rsplit('/assets', maxsplit=2)[0]
app_name = app_path.rsplit('/', maxsplit=1)[-1]
if app_name in get_installed_apps_with_asset_directory(include_project=True):
return app_name
else:
return None
app_module = import_module(app_name)
app_path = app_module.__path__[0]
return app_path def get_assets_subdirectory(path):
"""
:param path: path as string
:return: subdirectory as string
"""
return (path.rsplit('/assets/', maxsplit=1)[-1]).split('/', maxsplit=1)[0]
def get_projectname():
# get name of the django project def get_file_extension(path):
name = os.path.basename(settings.BASE_DIR) """
Returns the extension of path, for example "/home/..../base.js" returns ".js". If no extension found
return name empty string will be returned
:param path: path as string
:return: extension as string or empty string
# """
# def get_asset_directories(): return os.path.splitext(path)[-1]
# ''' get every app path that contains an "asset" folder on its root '''
#
# asset_apps = {}
#
# for app_name in settings.INSTALLED_APPS:
# app_module = import_module(app_name)
# app_path = app_module.__path__[0]
#
# if os.path.isdir(app_path + '/assets'):
# asset_apps.update({
# app_name: {
# 'app_path': app_path,
# 'static_path': app_path + '/static/' + app_name,
# 'asset_path': app_path + '/assets'
# }
# })
#
# return asset_apps
#
#
# def get_scss_include_paths(asset_directories):
# """ Get additional include_paths for the scss parser - to be able to load e.g. bulma without getting insane """
# include_paths = []
# for app_name, rel_paths in SCSS_INCLUDE_PATHS:
# if app_name in asset_directories.keys():
# app_meta = asset_directories[app_name]
# for rel_path in rel_paths:
# lib_path = os.path.join(app_meta['asset_path'], rel_path)
# if os.path.exists(lib_path):
# include_paths.append(lib_path)
# else:
# logger.warning('You specified an additional scss path which can not be found: {}'.format(lib_path))
# else:
# logger.warning(
# 'You specified the app {} in "SCSS_INCLUDE_PATHS" that can not be found. Is it in INSTALLED_APPS?'
# .format(app_name)
# )
# return include_paths
#
#
# def insert_corporate_design_import(filepath):
# content = ''
# tmp_filename = '/sass/_cd_init.tmp.scss'
#
# with open(filepath + '/sass/_init.scss', 'r') as scss_file:
# content = scss_file.read()
#
# content = '@import "cd/{}.scss";\n\n'.format(COLOR_SCHEME) + content
#
# with open(filepath + tmp_filename, 'w') as tmp_scss_file:
# tmp_scss_file.write(content)
#
# return filepath + tmp_filename
#
#
# def remove_corporate_design_import(filepath):
# os.remove(filepath)
#
#
# def build_scss(app_name, app_directories, include_paths, verbose=True):
# if verbose:
# print('Building \033[36msass\033[0m for app "{}" ...'.format(app_name))
#
# start = time.time()
#
# init_file_path = app_directories['asset_path'] + '/sass/_init.scss'
#
# if not os.path.isdir(os.path.dirname(init_file_path)):
# return
# elif not os.path.isfile(init_file_path):
# print('Init scss file not found! Searched for "{}"'.format(init_file_path))
# return
#
# with open(init_file_path, 'r') as init_scss_file:
# content = init_scss_file.read()
#
# if app_name == 'hshassets':
# style_file = app_directories['asset_path'] + '/sass/cd/{}.scss'.format(COLOR_SCHEME)
#
# if os.path.isfile(style_file):
# with open(style_file, 'r') as cdfile:
# content = cdfile.read() + '\n\n' + content
#
# # add this apps sass folder to the include paths
# include_paths = [os.path.join(app_directories['asset_path'], 'sass')] + include_paths
#
# expanded_output = sass.compile(string=content, include_paths=include_paths, output_style='expanded')
# compressed_output = sass.compile(string=content, include_paths=include_paths, output_style='compressed')
#
# with open(app_directories['static_path'] + '/styles.css', 'w') as outfile:
# outfile.write(expanded_output)
# with open(app_directories['static_path'] + '/styles.min.css', 'w') as outfile:
# outfile.write(compressed_output)
#
# if verbose:
# print('Finished after {:.3f} seconds\n'.format(time.time() - start))
#
#
# def build_javascript(app_name, app_directories, verbose=True):
# if verbose:
# print('Building \033[33mjavascript\033[0m for app "{}" ...'.format(app_name))
#
# start = time.time()
#
# js_files = []
# for root, dirs, files in os.walk(app_directories['asset_path'] + '/js'):
# for f in files:
# if f.endswith('.js'):
# js_files.append(root + '/' + f)
#
# for js_file in js_files:
# with open(js_file, 'r') as infile:
# content = infile.read()
#
# dest_js_path = app_directories['static_path'] + '/js/'
# dest_file_name = os.path.basename(js_file)
# dest_file_name_stripped, dest_file_extenstion = os.path.splitext(dest_file_name)
#
# if not os.path.isdir(dest_js_path):
# os.makedirs(dest_js_path)
#
# with open(dest_js_path + dest_file_name, 'w') as outfile:
# outfile.write(content + '\n')
#
# with open(dest_js_path + dest_file_name_stripped + '.min' + dest_file_extenstion, 'w') as outfile:
# outfile.write(jsmin.jsmin(content))
#
# if verbose:
# print('Finished after {:.3f} seconds\n'.format(time.time() - start))
#
#
# def copy_images(app_name, app_directories, verbose=True):
# if not os.path.isdir(app_directories['asset_path'] + '/img'):
# return
#
# if app_name == 'hshassets':
# shutil.copy2(
# app_directories['asset_path'] + '/img/hsh_brand/favicons/{}/favicon.ico'.format(COLOR_SCHEME),
# app_directories['static_path'] + '/../favicon.ico' # favicon for every app
# )
#
# start = time.time()
# if verbose:
# print('Copying images ...')
#
# if os.path.isdir(app_directories['static_path'] + '/img'):
# shutil.rmtree(app_directories['static_path'] + '/img')
#
# shutil.copytree(
# app_directories['asset_path'] + '/img',
# app_directories['static_path'] + '/img'
# )
#
# if verbose:
# print('Finished after {:.3f} seconds\n'.format(time.time() - start))
#
#
# def copy_fonts(app_name, app_directories, verbose=True):
# if not os.path.isdir(app_directories['asset_path'] + '/fonts'):
# return
#
# start = time.time()
# if verbose:
# print('Copying fonts ...')
#
# if os.path.isdir(app_directories['static_path'] + '/fonts'):
# shutil.rmtree(app_directories['static_path'] + '/fonts')
#
# shutil.copytree(
# app_directories['asset_path'] + '/fonts',
# app_directories['static_path'] + '/fonts'
# )
#
# if verbose:
# print('Finished after {:.3f} seconds\n'.format(time.time() - start))
#
#
# def discover_app(file_path):
# app_directories = {}
#
# for app_name, current_app_directories in get_asset_directories().items():
# if file_path.startswith(current_app_directories['app_path']):
# app_directories = current_app_directories
# break
#
# return app_name, app_directories
#
#
# def do_everything(verbose=False):
# asset_directories = get_asset_directories()
# include_paths = get_scss_include_paths(asset_directories)
# for app_name, app_directories in asset_directories.items():
#
# if os.path.isdir(app_directories['static_path']):
# shutil.rmtree(app_directories['static_path'])
#
# os.makedirs(app_directories['static_path'])
#
# build_scss(app_name, app_directories, include_paths, verbose=verbose)
# build_javascript(app_name, app_directories, verbose=verbose)
# copy_images(app_name, app_directories, verbose=verbose)
# copy_fonts(app_name, app_directories, verbose=verbose)
#
#
# def build_specific(app_name, app_directories, file_path, scss_include_paths):
# if file_path.endswith(('.sass', '.scss', '.css')):
# build_scss(app_name, app_directories, scss_include_paths)
# elif file_path.endswith(('.js')):
# build_javascript(app_name, app_directories)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment