cmspsgp31/anubis

View on GitHub
setup.py

Summary

Maintainability
C
7 hrs
Test Coverage
# Copyright © 2014-16, Ugo Pozo
#             2014-16, Câmara Municipal de São Paulo

# setup.py - installation procedure

# This file is part of Anubis.

# Anubis is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# Anubis is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import subprocess
import os
import shutil
import sys
import json
import glob

from setuptools import setup
from setuptools.command.install import install
from setuptools.command.develop import develop


def shell(*args, **kwargs):
    kwargs.update(stdout=sys.stdout, stderr=sys.stderr, shell=True,
                  close_fds=False)
    proc = subprocess.Popen(*args, **kwargs)
    try:
        proc.communicate(timeout=7200)
    except subprocess.TimeoutExpired:
        print("Timeout expired!")
        proc.kill()


def shell_output(*args, **kwargs):
    kwargs.update(stdout=subprocess.PIPE, shell=True)

    proc = subprocess.Popen(*args, **kwargs)
    try:
        out, _ = proc.communicate(timeout=600)
    except subprocess.TimeoutExpired:
        print("Timeout expired!")
        proc.kill()
        return None
    else:
        return out

class CompileHaskellMixin:
    def initialize_options(self):
        self.force_parselib = False

        super().initialize_options()

    def compile_url_parser(self, package_dir, clean_beforehand):
        working = os.path.join(package_dir, "parseurl")

        if clean_beforehand:
            shell("stack clean", cwd=working)

        shell("stack install", cwd=working)

    def run(self):
        super().run()

        target_path = self.install_lib if self.install_lib is not None \
            else os.path.abspath(self.setup_path)

        package_dir = os.path.join(target_path, "anubis")
        final_product = os.path.join(package_dir, "libParseUrl.so")

        final_product_exists = os.path.isfile(final_product)

        should_compile = not final_product_exists or self.force_parselib

        if should_compile:
            self.compile_url_parser(package_dir, final_product_exists)

class CompileFrontendMixin:
    def initialize_options(self):
        self.force_frontend = False

        super().initialize_options()

    def compile_frontend(self, package_dir):
        working = os.path.join(package_dir, "frontend")

        env = dict(os.environ, NODE_ENV=self.frontend_env)

        if shutil.which("yarn") is not None:
            shell("yarn", cwd=working)
        else:
            shell("npm install", cwd=working)

        shell("node_modules/.bin/webpack", cwd=working, env=env)

    def run(self):
        super().run()

        target_path = self.install_lib if self.install_lib is not None \
            else os.path.abspath(self.setup_path)

        package_dir = os.path.join(target_path, "anubis")
        final_product = os.path.join(package_dir, "app", "static", "anubis",
                                     "anubis.js")

        should_compile = not os.path.isfile(final_product) or \
            self.force_frontend

        if should_compile:
            self.compile_frontend(package_dir)


class InstallAnubis(CompileFrontendMixin, CompileHaskellMixin, install):
    frontend_env = "production"

class DevelopAnubis(CompileFrontendMixin, CompileHaskellMixin, develop):
    frontend_env = "development"

    user_options = develop.user_options + [
        ("force-frontend", None, "Forces rebuilding the frontend application."),
        ("force-parselib", None, "Forces rebuilding the parser library."),
    ]

    boolean_options = develop.boolean_options + ['force-frontend',
                                                 'force-parselib']

setup(
    name="anubis",
    version="1.0a10",
    packages=[
        "anubis",
        "anubis.app",
        "anubis.app.management",
        "anubis.app.management.commands",
        "anubis.views",
        "anubis.operations",
    ],
    install_requires=[
        "Django >=1.11, <2",
        "djangorestframework",
        "psycopg2-binary"],
    extras_require={
        'caching': ['redis', 'django-redis']
    },
    package_data={
        'anubis': [
            'frontend/webpack.config.js',
            'frontend/package.json',
            'frontend/src/*.js',
            'frontend/src/reducers/*.js',
            'frontend/src/components/*.js',
            'frontend/src/components/TokenField/*.js',
            'parseurl/LICENSE',
            'parseurl/stack.yaml',
            'parseurl/parseurl.cabal',
            'parseurl/Setup.hs',
            'parseurl/src/*.hs',
        ],
        'anubis.app': [
            'static/anubis/.gitignore',
            'templates/*.jsx']},
    cmdclass={
        'install': InstallAnubis,
        'develop': DevelopAnubis
    })