Beispiel #1
0
    def run(self):
        if not os.path.exists(self.path):
            os.makedirs(self.path)

        folders = ['content', 'templates', 'static', 'data']

        for folder in folders:
            folder_path = os.path.join(self.path, folder)
            if os.path.exists(folder_path) and not os.path.isdir(folder_path):
                logger.error(
                    'content folder already exists and is not a folder')
                sys.exit(1)
            elif not os.path.exists(folder_path):
                os.mkdir(folder_path)

        routing_file_path = os.path.join(self.path, 'data/routing.json')
        if not os.path.exists(routing_file_path):
            with open(routing_file_path, 'w+') as routing_file:
                routing_file.write('[]')

        config_path = os.path.join(self.path, 'sitic.yml')
        config = {
            'title': 'My Sitic site',
            'base_url': 'www.example.org',
        }

        if not os.path.exists(config_path):
            with open(config_path, 'w+') as config_file:
                config_file.write(yaml.dump(config, default_flow_style=False))
Beispiel #2
0
    def generate_po_file(self):
        for language in config.get_languages():
            locale_path = os.path.join(config.locales_path, language,
                                       'LC_MESSAGES')
            po_file_path = os.path.join(locale_path, self.po_filename)

            po_content = ''
            if not os.path.isdir(locale_path):
                os.makedirs(locale_path)

            if not os.path.exists(po_file_path):
                with open(self.pot_file_path, 'r') as f:
                    po_content = f.read()
            else:
                msgmerge_args = ['msgmerge'] + self.msgmerge_options + [
                    po_file_path, self.pot_file_path
                ]
                po_content, errors, status = call_subprocess(msgmerge_args)
                if status != constants.STATUS_OK and errors:
                    logger.error(
                        "errors happened while running msgmerge\n{}".format(
                            errors))
                    sys.exit(1)
                elif errors:
                    logger.error(errors)

            with open(po_file_path, 'w', encoding='utf-8') as f:
                f.write(po_content)

            logger.info(
                '«.po» file generated for language «{}» at «{}»'.format(
                    language, po_file_path))
Beispiel #3
0
    def __init__(self, path):

        if os.path.isfile(path):
            logger.error('Not valid path, its a file')
            sys.exit(1)

        self.path = path
Beispiel #4
0
    def __init__(self, filepath):
        self.filepath = filepath

        self.full_path = os.path.join(config.content_path, self.filepath)
        if not os.path.isfile(self.full_path):
            logger.error('File {} does no exists'.format(self.filepath))
            sys.exit(1)
Beispiel #5
0
    def __init__(self, filepath, title, frontmatter_format):
        self.filepath = filepath
        self.title = title
        self.frontmatter_format = frontmatter_format

        parts = os.path.split(self.filepath)
        self.filename = parts[-1]
        self.path = parts[0:-1]

        valid_extension = False
        for extension in VALID_CONTENT_EXTENSIONS:
            if self.filename.endswith(extension):
                valid_extension = True
                break

        if not valid_extension:
            logger.error('Not valid file extesion, valid ones: {}'.format(
                ', '.join(VALID_CONTENT_EXTENSIONS)))
            sys.exit(1)

        full_path = os.path.join(config.content_path, self.filepath)
        if os.path.isfile(full_path):
            logger.error('File {} already exists'.format(self.filepath))
            sys.exit(1)

        while not self.title:
            self.title = click.prompt('Please enter a title',
                                      default=None,
                                      type=str)
Beispiel #6
0
    def __init__(self, language):
        self.loader = FileSystemLoader(
            [config.templates_path, config.files_path])
        self.environment = Environment(loader=self.loader,
                                       extensions=['jinja2.ext.i18n'])

        translations = self.get_translations(language)
        self.environment.install_gettext_translations(translations, True)

        for name, function in inspect.getmembers(filters,
                                                 predicate=inspect.isfunction):
            self.environment.filters[name] = function

        self.environment.globals['get_search_url'] = functions.get_search_url

        # Get filters defined by user
        if config.custom_filters:
            try:
                spec = importlib.util.spec_from_file_location(
                    "custom_filters", config.custom_filters)
                custom_filters = importlib.util.module_from_spec(spec)
                spec.loader.exec_module(custom_filters)
                for name, function in inspect.getmembers(
                        custom_filters, predicate=inspect.isfunction):
                    if not name.startswith('custom_'):
                        name = '{}_{}'.format('custom', name)
                    self.environment.filters[name] = function
            except:
                logger.error(
                    'Could not get custom filters, make sure it\'s a valid python file'
                )
Beispiel #7
0
    def __init__(self):

        languages = config.get_languages()
        if len(languages) == 1 and languages[0] == constants.DEFAULT_LANG:
            logger.error(
                'No languages configuration detected, can\'t create messages')
            sys.exit(1)

        self.po_filename = '{}.po'.format(constants.GETTEXT_DOMAIN)
        self.mo_filename = '{}.mo'.format(constants.GETTEXT_DOMAIN)
Beispiel #8
0
def force_text(s, encoding='utf-8', errors='strict'):
    if issubclass(type(s), str):
        return s
    try:
        if isinstance(s, bytes):
            s = str(s, encoding, errors)
        else:
            s = str(s)
    except UnicodeDecodeError as e:
        logger.error('Error: {}'.format(str(e)))
        sys.exit(1)
    return s
Beispiel #9
0
def call_subprocess(args, stdout_encoding='utf-8'):
    """
    Friendly wrapper around Popen.

    Return stdout output, stderr output, and OS status code.
    """
    try:
        p = Popen(args,
                  shell=False,
                  stdout=PIPE,
                  stderr=PIPE,
                  close_fds=os.name != 'nt')
    except OSError as err:
        logger.error('Error executing: {}'.format(args[0]))
        sys.exit(1)
    output, errors = p.communicate()
    return (force_text(output), force_text(errors), p.returncode)
Beispiel #10
0
    def load_config(self, config_file_path):
        self.config_path = config_file_path

        self.base_path = os.path.dirname(os.path.abspath(self.config_path))

        # Default
        self.content_path = os.path.join(self.base_path, constants.DEFAULT_CONTENT_PATH)
        self.public_path = os.path.join(self.base_path, constants.DEFAULT_PUBLIC_PATH)
        self.static_path = os.path.join(self.base_path, constants.DEFAULT_STATIC_PATH)
        self.templates_path = os.path.join(self.base_path, constants.DEFAULT_TEMPLATES_PATH)
        self.locales_path = os.path.join(self.base_path, constants.DEFAULT_LOCALES_PATH)
        self.routing_path = os.path.join(self.base_path, constants.DEFAULT_ROUTING_FILE_PATH)

        path_options = ['public_path', 'content_path', 'static_path', 'custom_filters']
        with open(self.config_path, 'r') as config_file:
            parsed_config = yaml.load(config_file)

            if not parsed_config:
                logger.warning('Config file completely empty')
                parsed_config = []

            for param in parsed_config:
                value = parsed_config[param]
                if param in path_options:
                    value = value if os.path.isdir(value) else os.path.join(self.base_path, value)
                setattr(self, param, value)

        if not os.path.isdir(self.content_path):
            logger.error('Invalid path for content. Folder not found')
            sys.exit(1)

        if self.custom_filters and not os.path.isfile(self.custom_filters):
            logger.error('Specified filters file not found.')
            self.custom_filters = None
            return

        # TODO: make patterns configurables
        self.ignore_files_regex = [re.compile(i) for i in constants.IGNORE_FILES_PATTERN]

        self._format_languages()
        self.set_main_language()

        self.check_taxonomies_format()

        current_file_path = os.path.abspath(os.path.dirname(__file__))
        self.files_path = os.path.join(current_file_path, 'files/')
Beispiel #11
0
    def __init__(self):

        languages = config.get_languages()
        if len(languages) == 1 and languages[0] == constants.DEFAULT_LANG:
            logger.error(
                'No languages configuration detected, can\'t create messages')
            sys.exit(1)

        loader = FileSystemLoader(config.files_path)

        self.env = Environment(extensions=['jinja2.ext.i18n'], loader=loader)
        self.env.filters['clean_msg'] = clean_msg

        self.translations = []
        self.pot_filename = '{}.pot'.format(constants.GETTEXT_DOMAIN)
        self.po_filename = '{}.po'.format(constants.GETTEXT_DOMAIN)
        self.pot_file_path = os.path.join(config.locales_path,
                                          self.pot_filename)
Beispiel #12
0
    def render(self, content, output_path, context, meta_tag, js_includes):
        template = self.get_content_template(content)
        if template:
            try:
                content = template.render(**context)
                content = content.replace('</head>',
                                          "{}\n\n</head>".format(meta_tag))

                js_includes = '\n'.join(js_includes)
                content = content.replace('</body>',
                                          "{}\n\n</body>".format(js_includes))

                with open(output_path, 'w') as output_file:
                    output_file.write(content)
            except Exception as error:
                template_path = '/' + template.filename.replace(
                    config.base_path, '').lstrip('/')
                logger.error('Rendering template {} for content {}: {}'.format(
                    template_path, content, str(error)))
        else:
            logger.warning(
                'No template found for content - {}'.format(content))
Beispiel #13
0
    def generate_pot_file(self):
        pot_template = self.env.get_template('pot_template.jinja')
        pot_content = pot_template.render({'translations': self.translations})

        if not os.path.isdir(config.locales_path):
            os.makedirs(config.locales_path)

        with open(self.pot_file_path, 'w', encoding='utf-8') as f:
            f.write(pot_content)

        msguniq_args = ['msguniq'
                        ] + self.msguniq_options + [self.pot_file_path]
        output, errors, status = call_subprocess(msguniq_args)

        if status != constants.STATUS_OK and errors:
            logger.error(
                "errors happened while running msguniq\n{}".format(errors))
            sys.exit(1)
        elif errors:
            logger.error(errors)

        # Replace pot file with msguniq output
        with open(self.pot_file_path, 'w', encoding='utf-8') as f:
            f.write(output)
Beispiel #14
0
    def compile(self):
        for language in config.get_languages():
            locale_path = os.path.join(config.locales_path, language,
                                       'LC_MESSAGES')
            po_file_path = os.path.join(locale_path, self.po_filename)
            mo_file_path = os.path.join(locale_path, self.mo_filename)

            if has_bom(po_file_path):
                logger.error("The {} file has a BOM (Byte Order Mark). "
                             "Sitic only supports .po files encoded in "
                             "UTF-8 and without any BOM.".format(po_file_path))

            if not os.path.exists(po_file_path):
                logger.warning(
                    "Not .po file found for language «{}»."
                    "Run «makemessages» to generate it.".format(language))
                continue

            msgmt_args = ['msgfmt'] + self.msgfmt_options + [
                '-o', mo_file_path, po_file_path
            ]
            output, errors, status = call_subprocess(msgmt_args)

            if status != constants.STATUS_OK and errors:
                logger.error(
                    "errors happened while running msgmerge\n{}".format(
                        errors))
                sys.exit(1)
            elif errors:
                logger.error(errors)

            logger.info(
                'Messages successfully compiled for language «{}»'.format(
                    language))

        logger.warning(
            'Please, keep in mind that «msgfmt» won\'t generate any «.mo» file if no translation modified'
        )