301 lines
10 KiB
Python
301 lines
10 KiB
Python
#! /usr/bin/env python
|
||
|
||
import functools
|
||
import glob
|
||
import os
|
||
import subprocess
|
||
import sys
|
||
from distutils.cmd import Command as BaseCommand
|
||
from distutils.command.build import build as _build
|
||
from distutils.command.sdist import sdist
|
||
from distutils.errors import CompileError
|
||
from distutils.spawn import find_executable
|
||
from multiprocessing.pool import ThreadPool
|
||
|
||
from setuptools import find_packages, setup
|
||
from setuptools.command.install_lib import install_lib as _install_lib
|
||
|
||
inkscape = os.path.abspath(os.path.join(os.path.dirname(__file__), 'src', 'inkscape_wrapper.py'))
|
||
|
||
|
||
class Command(BaseCommand):
|
||
user_options = []
|
||
|
||
def initialize_options(self):
|
||
pass
|
||
|
||
def finalize_options(self):
|
||
pass
|
||
|
||
|
||
class eo_sdist(sdist):
|
||
def run(self):
|
||
print('creating VERSION file')
|
||
if os.path.exists('VERSION'):
|
||
os.remove('VERSION')
|
||
version = get_version()
|
||
version_file = open('VERSION', 'w')
|
||
version_file.write(version)
|
||
version_file.close()
|
||
sdist.run(self)
|
||
print('removing VERSION file')
|
||
if os.path.exists('VERSION'):
|
||
os.remove('VERSION')
|
||
|
||
def local_findall(self, dir=os.curdir):
|
||
# override default file search to allow for duplicates (as some themes have
|
||
# multiple variants that are just symlinks)
|
||
files = [
|
||
os.path.join(base, file) for base, dirs, files in os.walk(dir, followlinks=True) for file in files
|
||
]
|
||
if dir == os.curdir:
|
||
make_rel = functools.partial(os.path.relpath, start=dir)
|
||
files = map(make_rel, files)
|
||
self.filelist.allfiles = list(filter(os.path.isfile, files))
|
||
|
||
def get_file_list(self):
|
||
self.filelist.findall = self.local_findall
|
||
super().get_file_list()
|
||
|
||
def copy_file(self, *args, **kwargs):
|
||
# do not allow hardlinking as hardlinks would get inserted as is in
|
||
# the tarball, and would not extract properly.
|
||
kwargs.pop('link', None)
|
||
super().copy_file(*args, **kwargs)
|
||
|
||
|
||
def get_version():
|
||
'''Use the VERSION, if absent generates a version with git describe, if not
|
||
tag exists, take 0.0- and add the length of the commit log.
|
||
'''
|
||
if os.path.exists('VERSION'):
|
||
with open('VERSION') as v:
|
||
return v.read()
|
||
if os.path.exists('.git'):
|
||
p = subprocess.Popen(
|
||
['git', 'describe', '--dirty=.dirty', '--match=v*'],
|
||
stdout=subprocess.PIPE,
|
||
stderr=subprocess.PIPE,
|
||
)
|
||
result = p.communicate()[0]
|
||
if p.returncode == 0:
|
||
result = result.decode('ascii').strip()[1:] # strip spaces/newlines and initial v
|
||
if '-' in result: # not a tagged version
|
||
real_number, commit_count, commit_hash = result.split('-', 2)
|
||
version = '%s.post%s+%s' % (real_number, commit_count, commit_hash)
|
||
else:
|
||
version = result.replace('.dirty', '+dirty')
|
||
return version
|
||
else:
|
||
return '0.0.post%s' % len(subprocess.check_output(['git', 'rev-list', 'HEAD']).splitlines())
|
||
return '0.0'
|
||
|
||
|
||
class compile_translations(Command):
|
||
description = 'compile message catalogs to MO files via django compilemessages'
|
||
user_options = []
|
||
|
||
def run(self):
|
||
curdir = os.getcwd()
|
||
try:
|
||
from django.core.management import call_command
|
||
|
||
for path, dirs, files in os.walk('publik_base_theme'):
|
||
if 'locale' not in dirs:
|
||
continue
|
||
os.chdir(os.path.realpath(path))
|
||
call_command('compilemessages')
|
||
os.chdir(curdir)
|
||
except ImportError:
|
||
sys.stderr.write('!!! Please install Django >= 1.4 to build translations\n')
|
||
finally:
|
||
os.chdir(curdir)
|
||
|
||
|
||
class build_themes_json(Command):
|
||
def run(self):
|
||
subprocess.run(['python3', 'create_themes_json.py'])
|
||
|
||
|
||
def get_css_files(include_map_files=False):
|
||
for dirname in sorted(os.listdir('static')):
|
||
config = os.path.join('static', dirname, 'config.json')
|
||
if not os.path.exists(config):
|
||
continue
|
||
yield 'static/%s/style.css' % dirname
|
||
if include_map_files:
|
||
yield 'static/%s/style.css.map' % dirname
|
||
if os.path.exists(os.path.join('static', dirname, 'backoffice.scss')):
|
||
yield 'static/%s/backoffice.css' % dirname
|
||
if include_map_files:
|
||
yield 'static/%s/backoffice.css.map' % dirname
|
||
yield 'static/portal-agent/css/agent-portal.css'
|
||
yield 'static/includes/gadjo-extra.css'
|
||
|
||
|
||
def subprocess_run(command):
|
||
kwargs = {
|
||
'env': {'LC_ALL': 'C.UTF-8'},
|
||
}
|
||
if isinstance(command, list):
|
||
print(' '.join(command))
|
||
else:
|
||
print(command)
|
||
kwargs['shell'] = True
|
||
return bool(subprocess.run(command, **kwargs).returncode == 0)
|
||
|
||
|
||
class compile_scss(Command):
|
||
description = 'compile scss files into css files'
|
||
|
||
def run(self):
|
||
sass_bin = find_executable('sassc')
|
||
if not sass_bin:
|
||
raise CompileError(
|
||
'A sass compiler is required but none was found. See sass-lang.com for choices.'
|
||
)
|
||
|
||
for dirname in ('includes', 'toodego', 'lille', 'lomme', 'hellemmes', 'toulouse-2022'):
|
||
subprocess.run(['python3', 'make_data_uris.py', os.path.join('static', dirname)], check=True)
|
||
|
||
def get_build_commands():
|
||
for css_filename in get_css_files():
|
||
yield ['sassc', '--sourcemap', css_filename.replace('.css', '.scss'), css_filename]
|
||
|
||
with ThreadPool() as pool:
|
||
for result in pool.imap_unordered(subprocess_run, get_build_commands()):
|
||
if not result:
|
||
raise CompileError('error compiling css')
|
||
|
||
|
||
class build_icons(Command):
|
||
def run(self):
|
||
cmds = [
|
||
'python3 src/render-imgs-dashboard.py static/chateauroux/img/ --normal 333333 '
|
||
'--selected 0779B7 --title FFFFFF --title-width 80',
|
||
'python3 src/render-imgs-categories.py static/orleans/img/ --primary f05923 --secondary 34697D',
|
||
'python3 src/render-imgs-dashboard.py static/orleans/img/ --normal FFFFFF '
|
||
'--normal-width 30 --selected f05923 --selected-width 30 --title FFFFFF --title-width 80',
|
||
'python3 src/render-imgs-categories.py static/publik/img/',
|
||
'python3 src/render-imgs-dashboard.py static/publik/img/ --normal 4D4D4D '
|
||
'--selected DF017A --title FFFFFF --title-width 80',
|
||
'python3 src/render-imgs-categories.py static/somme-cd80/img/ --primary A8002B '
|
||
'--secondary A8002B',
|
||
'python3 src/render-imgs-dashboard.py static/somme-cd80/img/ --normal 4D4D4D '
|
||
'--selected 87A738 --title FFFFFF --title-width 80',
|
||
]
|
||
if self.distribution.commands == ['install']:
|
||
cmds = [f'{x} --skip-existing' for x in cmds]
|
||
|
||
if not os.path.exists('static/tournai/img'):
|
||
os.mkdir('static/tournai/img')
|
||
for image in glob.glob('static/tournai/assets/*.svg'):
|
||
target_filename = 'static/tournai/img/' + os.path.basename(image).replace('.svg', '.png')
|
||
if (
|
||
os.path.exists(target_filename)
|
||
and os.stat(image).st_mtime < os.stat(target_filename).st_mtime
|
||
):
|
||
continue
|
||
cmds.append(
|
||
[
|
||
inkscape,
|
||
'--without-gui',
|
||
'--file',
|
||
image,
|
||
'--export-area-drawing',
|
||
'--export-area-snap',
|
||
'--export-png',
|
||
target_filename,
|
||
'--export-width',
|
||
'40',
|
||
]
|
||
)
|
||
|
||
with ThreadPool() as pool:
|
||
for result in pool.imap_unordered(subprocess_run, cmds):
|
||
if not result:
|
||
raise CompileError('error building icons')
|
||
|
||
|
||
class build(_build):
|
||
sub_commands = [
|
||
('build_themes_json', None),
|
||
('build_icons', None),
|
||
('compile_scss', None),
|
||
('compile_translations', None),
|
||
] + _build.sub_commands
|
||
|
||
|
||
class install_lib(_install_lib):
|
||
def run(self):
|
||
self.run_command('compile_translations')
|
||
super().run()
|
||
|
||
|
||
def data_tree(destdir, sourcedir):
|
||
extensions = [
|
||
'.html',
|
||
'.txt',
|
||
'.scss',
|
||
'.css',
|
||
'.js',
|
||
'.ico',
|
||
'.gif',
|
||
'.png',
|
||
'.jpg',
|
||
'.jpeg',
|
||
'.woff',
|
||
'.woff2',
|
||
'.ttf',
|
||
'.css',
|
||
'.map',
|
||
'.svg',
|
||
'.eot',
|
||
'.otf',
|
||
'.py', # prepare-template.py
|
||
]
|
||
r = []
|
||
for root, dirs, files in os.walk(sourcedir):
|
||
l = [os.path.join(root, x) for x in files if os.path.splitext(x)[1] in extensions]
|
||
r.append((root.replace(sourcedir, destdir, 1), l))
|
||
return r
|
||
|
||
|
||
setup(
|
||
name='publik_base_theme',
|
||
version=get_version(),
|
||
license='AGPLv3 or later',
|
||
description='Themes for Publik',
|
||
url='https://dev.entrouvert.org/projects/publik-base-theme/',
|
||
author='Entr’ouvert',
|
||
author_email='info@entrouvert.com',
|
||
packages=find_packages(),
|
||
include_package_data=True,
|
||
data_files=data_tree('share/publik/themes/publik-base/static', 'static')
|
||
+ data_tree('share/publik/themes/publik-base/templates', 'templates')
|
||
+ [('share/publik/themes/publik-base', ['themes.json'])],
|
||
setup_requires=[
|
||
'django>=2.2',
|
||
],
|
||
classifiers=[
|
||
'Development Status :: 5 - Stable',
|
||
'Environment :: Web Environment',
|
||
'Framework :: Django',
|
||
'Intended Audience :: Developers',
|
||
'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
|
||
'Operating System :: OS Independent',
|
||
'Programming Language :: Python',
|
||
'Programming Language :: Python :: 3',
|
||
],
|
||
zip_safe=False,
|
||
cmdclass={
|
||
'build': build,
|
||
'build_icons': build_icons,
|
||
'build_themes_json': build_themes_json,
|
||
'compile_scss': compile_scss,
|
||
'compile_translations': compile_translations,
|
||
'install_lib': install_lib,
|
||
'sdist': eo_sdist,
|
||
},
|
||
)
|