2024-03-06 13:38:26 +01:00
|
|
|
|
#! /usr/bin/env python
|
|
|
|
|
|
2024-03-29 11:05:17 +01:00
|
|
|
|
import functools
|
2024-03-06 13:38:26 +01:00
|
|
|
|
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
|
2024-03-19 15:39:06 +01:00
|
|
|
|
from multiprocessing.pool import ThreadPool
|
2024-03-06 13:38:26 +01:00
|
|
|
|
|
|
|
|
|
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')
|
|
|
|
|
|
2024-03-29 11:05:17 +01:00
|
|
|
|
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)
|
|
|
|
|
|
2024-03-06 13:38:26 +01:00
|
|
|
|
|
|
|
|
|
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]
|
|
|
|
|
|
2024-03-19 15:39:06 +01:00
|
|
|
|
with ThreadPool() as pool:
|
2024-03-06 13:38:26 +01:00
|
|
|
|
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',
|
|
|
|
|
]
|
2024-03-15 22:45:15 +01:00
|
|
|
|
if self.distribution.commands == ['install']:
|
|
|
|
|
cmds = [f'{x} --skip-existing' for x in cmds]
|
|
|
|
|
|
2024-03-06 13:38:26 +01:00
|
|
|
|
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',
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
|
2024-03-19 15:39:06 +01:00
|
|
|
|
with ThreadPool() as pool:
|
2024-03-06 13:38:26 +01:00
|
|
|
|
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',
|
2024-03-19 09:17:06 +01:00
|
|
|
|
'.py', # prepare-template.py
|
2024-03-06 13:38:26 +01:00
|
|
|
|
]
|
|
|
|
|
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,
|
|
|
|
|
},
|
|
|
|
|
)
|