Beispiel #1
0
def _set_translation(path_to_tx, resource, lang, path_to_file):
    """Reusable method to set translation file."""

    proj, res = resource.split('.')
    if not project or not resource:
        raise Exception("\"%s\" is not a valid resource identifier. "
                        "It should be in the following format "
                        "project_slug.resource_slug." % resource)

    _go_to_dir(path_to_tx)

    # Warn the customuser if the file doesn't exist
    if not os.path.exists(path_to_file):
        logger.info("Warning: File '%s' doesn't exist." % path_to_file)

    # instantiate the project.Project
    prj = project.Project(path_to_tx)
    root_dir = os.path.abspath(path_to_tx)

    if root_dir not in os.path.normpath(os.path.abspath(path_to_file)):
        raise Exception("File must be under the project root directory.")

    if lang == prj.config.get("%s.%s" % (proj, res), "source_lang"):
        raise Exception("tx: You cannot set translation file for "
                        "the source language. Source languages contain "
                        "the strings which will be translated!")

    logger.info("Updating translations for resource %s ( %s -> %s )." %
                (resource, lang, path_to_file))
    path_to_file = os.path.relpath(path_to_file, root_dir)
    prj.config.set("%s.%s" % (proj, res), "trans.%s" % lang,
                   posix_path(path_to_file))

    prj.save()
Beispiel #2
0
def regex_from_filefilter(file_filter, root_path=os.path.curdir):
    """Create proper regex from <lang> expression."""
    # Force expr to be a valid regex expr (escaped) but keep <lang> intact
    expr_re = re.escape(
        posix_path(os.path.join(root_path, native_path(file_filter))))
    expr_re = expr_re.replace("\\<lang\\>", '<lang>').replace(
        '<lang>', '([^%(sep)s]+)' % {'sep': re.escape(posix_sep)})

    return "^%s$" % expr_re
Beispiel #3
0
def regex_from_filefilter(file_filter, root_path = os.path.curdir):
    """Create proper regex from <lang> expression."""
    # Force expr to be a valid regex expr (escaped) but keep <lang> intact
    expr_re = re.escape(
        posix_path(os.path.join(root_path, native_path(file_filter)))
    )
    expr_re = expr_re.replace("\\<lang\\>", '<lang>').replace(
        '<lang>', '([^%(sep)s]+)' % { 'sep': re.escape(posix_sep)})

    return "^%s$" % expr_re
Beispiel #4
0
    def get_resource_files(self, resource):
        """
        Get a dict for all files assigned to a resource. First we calculate the
        files matching the file expression and then we apply all translation
        excpetions. The resulting dict will be in this format:

        { 'en': 'path/foo/en/bar.po', 'de': 'path/foo/de/bar.po', 'es': 'path/exceptions/es.po'}

        NOTE: All paths are relative to the root of the project
        """
        tr_files = {}
        if self.config.has_section(resource):
            try:
                file_filter = self.config.get(resource, "file_filter")
            except ConfigParser.NoOptionError:
                file_filter = "$^"
            source_lang = self.config.get(resource, "source_lang")
            source_file = self.get_resource_option(resource,
                                                   'source_file') or None
            if source_file is not None:
                source_file = native_path(source_file)
            expr_re = regex_from_filefilter(file_filter, self.root)
            expr_rec = re.compile(expr_re)
            for f_path in files_in_project(self.root):
                match = expr_rec.match(posix_path(f_path))
                if match:
                    lang = match.group(1)
                    if lang != source_lang:
                        f_path = os.path.relpath(f_path, self.root)
                        if f_path != source_file:
                            tr_files.update({lang: f_path})

            for (name, value) in self.config.items(resource):
                if name.startswith("trans."):
                    value = native_path(value)
                    lang = name.split('.')[1]
                    # delete language which has same file
                    if value in tr_files.values():
                        keys = []
                        for k, v in tr_files.iteritems():
                            if v == value:
                                keys.append(k)
                        if len(keys) == 1:
                            del tr_files[keys[0]]
                        else:
                            raise Exception("Your configuration seems wrong."\
                                " You have multiple languages pointing to"\
                                " the same file.")
                    # Add language with correct file
                    tr_files.update({lang: value})

            return tr_files

        return None
Beispiel #5
0
    def get_resource_files(self, resource):
        """Get a dict for all files assigned to a resource.
        First we calculate the files matching the file expression and
        then we apply all translation excpetions.
        The resulting dict will be in this format:

        { 'en': 'path/foo/en/bar.po',
        'de': 'path/foo/de/bar.po',
        'es': 'path/exceptions/es.po'}

        NOTE: All paths are relative to the root of the project
        """
        tr_files = {}
        if self.config.has_section(resource):
            try:
                file_filter = self.config.get(resource, "file_filter")
            except configparser.NoOptionError:
                file_filter = "$^"
            source_lang = self.config.get(resource, "source_lang")
            source_file = self.get_source_file(resource)
            expr_re = utils.regex_from_filefilter(file_filter, self.root)
            expr_rec = re.compile(expr_re)
            for f_path in utils.files_in_project(self.root):
                match = expr_rec.match(posix_path(f_path))
                if match:
                    lang = match.group(1)
                    if lang != source_lang:
                        f_path = os.path.relpath(f_path, self.root)
                        if f_path != source_file:
                            tr_files.update({lang: f_path})

            for (name, value) in self.config.items(resource):
                if name.startswith("trans."):
                    value = native_path(value)
                    lang = name.split('.')[1]
                    # delete language which has same file
                    if value in list(tr_files.values()):
                        keys = []
                        for k, v in six.iteritems(tr_files):
                            if v == value:
                                keys.append(k)
                        if len(keys) == 1:
                            del tr_files[keys[0]]
                        else:
                            raise Exception("Your configuration seems wrong. "
                                            "You have multiple languages "
                                            "pointing to the same file.")
                    # Add language with correct file
                    tr_files.update({lang: value})

            return tr_files

        return None
Beispiel #6
0
def _set_source_file(path_to_tx, resource, lang, path_to_file):
    """Reusable method to set source file."""
    proj, res = resource.split('.')
    if not proj or not res:
        raise Exception("\"%s.%s\" is not a valid resource identifier. "
                        "It should be in the following format "
                        "project_slug.resource_slug." %
                        (proj, res))
    if not lang:
        raise Exception("You haven't specified a source language.")

    try:
        _go_to_dir(path_to_tx)
    except UnInitializedError as e:
        utils.logger.error(e)
        return

    if not os.path.exists(path_to_file):
        raise Exception("tx: File ( %s ) does not exist." %
                        os.path.join(path_to_tx, path_to_file))

    # instantiate the project.Project
    prj = project.Project(path_to_tx)
    root_dir = os.path.abspath(path_to_tx)

    if root_dir not in os.path.normpath(os.path.abspath(path_to_file)):
        raise Exception("File must be under the project root directory.")

    logger.info("Setting source file for resource %s.%s ( %s -> %s )." % (
        proj, res, lang, path_to_file))

    path_to_file = os.path.relpath(path_to_file, root_dir)

    prj = project.Project(path_to_tx)

    # FIXME: Check also if the path to source file already exists.
    try:
        try:
            prj.config.get("%s.%s" % (proj, res), "source_file")
        except configparser.NoSectionError:
            prj.config.add_section("%s.%s" % (proj, res))
        except configparser.NoOptionError:
            pass
    finally:
        prj.config.set(
            "%s.%s" % (proj, res), "source_file", posix_path(path_to_file)
        )
        prj.config.set("%s.%s" % (proj, res), "source_lang", lang)

    prj.save()
Beispiel #7
0
def _set_source_file(path_to_tx, resource, lang, path_to_file):
    """Reusable method to set source file."""
    proj, res = resource.split('.')
    if not proj or not res:
        raise Exception("\"%s.%s\" is not a valid resource identifier. "
                        "It should be in the following format "
                        "project_slug.resource_slug." %
                        (proj, res))
    if not lang:
        raise Exception("You haven't specified a source language.")

    try:
        _go_to_dir(path_to_tx)
    except UnInitializedError as e:
        utils.logger.error(e)
        return

    if not os.path.exists(path_to_file):
        raise Exception("tx: File ( %s ) does not exist." %
                        os.path.join(path_to_tx, path_to_file))

    # instantiate the project.Project
    prj = project.Project(path_to_tx)
    root_dir = os.path.abspath(path_to_tx)

    if root_dir not in os.path.normpath(os.path.abspath(path_to_file)):
        raise Exception("File must be under the project root directory.")

    logger.info("Setting source file for resource %s.%s ( %s -> %s )." % (
        proj, res, lang, path_to_file))

    path_to_file = os.path.relpath(path_to_file, root_dir)

    prj = project.Project(path_to_tx)

    # FIXME: Check also if the path to source file already exists.
    try:
        try:
            prj.config.get("%s.%s" % (proj, res), "source_file")
        except configparser.NoSectionError:
            prj.config.add_section("%s.%s" % (proj, res))
        except configparser.NoOptionError:
            pass
    finally:
        prj.config.set(
            "%s.%s" % (proj, res), "source_file", posix_path(path_to_file)
        )
        prj.config.set("%s.%s" % (proj, res), "source_lang", lang)

    prj.save()
Beispiel #8
0
def get_project_files(curpath, expression):
    """
    Iterate over the files in the project that match the given expression.
    Return a tuple with the absolute file path and the language code of the
    language that is associated with it.
    """
    # Strip the reference to the current directory, if it exists
    if expression.startswith(".{}".format(os.sep)):
        expression = expression[2:]
    # Split the expression into parts
    expression_parts = expression.split(os.sep)
    # Merge the expression's path into 'curpath' until the <lang> placeholder
    # is specified in order to reduce the search tree
    while _can_walk(curpath, expression_parts):
        curpath = os.path.realpath(os.path.join(curpath, expression_parts[0]))
        expression_parts = expression_parts[1:]
    expr_re = regex_from_filefilter(os.path.join(*expression_parts), curpath)
    expression_regex = re.compile(expr_re)

    visited = set()
    for root, dirs, files in os.walk(curpath, followlinks=True):
        root_realpath = os.path.realpath(root)

        # Don't visit any subdirectory
        if root_realpath in visited:
            del dirs[:]
            continue

        for file_path in files:
            full_path = os.path.realpath(os.path.join(root, file_path))
            match = expression_regex.match(posix_path(full_path))
            if match:
                try:
                    lang = match.group(1)
                except IndexError:
                    msg = ("File filter '{}' does not contain the '<lang>' "
                           "placeholder".format(expression))
                    raise MalformedConfigFile(msg)
                yield full_path, lang

        visited.add(root_realpath)

        # Find which directories are already visited and remove them from
        # further processing
        removals = list(d for d in dirs
                        if os.path.realpath(os.path.join(root, d)) in visited)
        for removal in removals:
            dirs.remove(removal)
Beispiel #9
0
def _set_translation(path_to_tx, resource, lang, path_to_file):
    """Reusable method to set translation file."""

    proj, res = resource.split('.')
    if not project or not resource:
        raise Exception("\"%s\" is not a valid resource identifier. "
                        "It should be in the following format "
                        "project_slug.resource_slug." %
                        resource)

    try:
        _go_to_dir(path_to_tx)
    except UnInitializedError as e:
        utils.logger.error(e)
        return

    # Warn the user if the file doesn't exist
    if not os.path.exists(path_to_file):
        logger.info("Warning: File '%s' doesn't exist." % path_to_file)

    # instantiate the project.Project
    prj = project.Project(path_to_tx)
    root_dir = os.path.abspath(path_to_tx)

    if root_dir not in os.path.normpath(os.path.abspath(path_to_file)):
        raise Exception("File must be under the project root directory.")

    if lang == prj.config.get("%s.%s" % (proj, res), "source_lang"):
        raise Exception("tx: You cannot set translation file for "
                        "the source language. Source languages contain "
                        "the strings which will be translated!")

    logger.info("Updating translations for resource %s ( %s -> %s )." % (
                resource, lang, path_to_file))
    path_to_file = os.path.relpath(path_to_file, root_dir)
    prj.config.set(
        "%s.%s" % (proj, res), "trans.%s" % lang, posix_path(path_to_file)
    )

    prj.save()
Beispiel #10
0
def get_project_files(curpath, expression):
    """
    Iterate over the files in the project that match the given expression.
    Return a tuple with the absolute file path and the language code of the
    language that is associated with it.
    """
    # Strip the reference to the current directory, if it exists
    if expression.startswith(".{}".format(os.sep)):
        expression = expression[2:]
    # Split the expression into parts
    expression_parts = expression.split(os.sep)
    # Merge the expression's path into 'curpath' until the <lang> placeholder
    # is specified in order to reduce the search tree
    while _can_walk(curpath, expression_parts):
        curpath = os.path.realpath(os.path.join(curpath, expression_parts[0]))
        expression_parts = expression_parts[1:]
    expr_re = regex_from_filefilter(os.path.join(*expression_parts), curpath)
    expression_regex = re.compile(expr_re)

    initial_depth = curpath.count(os.sep)
    max_depth = 50
    for root, dirs, files in os.walk(curpath, followlinks=True):

        # Don't visit any subdirectory
        if root.count(os.sep) > initial_depth + max_depth:
            del dirs[:]
            continue

        for file_path in files:
            path_to_match = os.path.join(root, file_path)
            full_path = os.path.realpath(os.path.join(root, file_path))
            match = expression_regex.match(posix_path(path_to_match))
            if match:
                try:
                    lang = match.group(1)
                except IndexError:
                    msg = ("File filter '{}' does not contain the '<lang>' "
                           "placeholder".format(expression))
                    raise MalformedConfigFile(msg)
                yield full_path, lang
Beispiel #11
0
 def test_posix_path_in_unix_does_nothing(self):
     orig_path = os.path.abspath(os.getcwd())
     path = posix_path(orig_path)
     self.assertEqual(orig_path, path)
Beispiel #12
0
    path_to_file = os.path.relpath(path_to_file, root_dir)

    prj = project.Project(path_to_tx)

    # FIXME: Check also if the path to source file already exists.
    try:
        try:
            prj.config.get("%s.%s" % (proj, res), "source_file")
        except ConfigParser.NoSectionError:
            prj.config.add_section("%s.%s" % (proj, res))
        except ConfigParser.NoOptionError:
            pass
    finally:
        prj.config.set(
            "%s.%s" % (proj, res), "source_file", posix_path(path_to_file)
        )
        prj.config.set("%s.%s" % (proj, res), "source_lang", lang)

    prj.save()


def _set_translation(path_to_tx, resource, lang, path_to_file):
    """Reusable method to set translation file."""

    proj, res = resource.split('.')
    if not project or not resource:
        raise Exception("\"%s\" is not a valid resource identifier. It should"
            " be in the following format project_slug.resource_slug." %
            resource)
Beispiel #13
0
 def test_posix_path_in_unix_does_nothing(self):
     orig_path = os.path.abspath(os.getcwd())
     path = posix_path(orig_path)
     self.assertEqual(orig_path, path)
Beispiel #14
0
 def test_posix_path_in_windows_replaces_backslashes(self):
     orig_path = posix_path(os.path.abspath(os.getcwd()))
     expected_path = orig_path.replace('/', '\\')
     self.assertEqual(expected_path, native_path(orig_path))
Beispiel #15
0
    path_to_file = os.path.relpath(path_to_file, root_dir)

    prj = project.Project(path_to_tx)

    # FIXME: Check also if the path to source file already exists.
    try:
        try:
            prj.config.get("%s.%s" % (proj, res), "source_file")
        except ConfigParser.NoSectionError:
            prj.config.add_section("%s.%s" % (proj, res))
        except ConfigParser.NoOptionError:
            pass
    finally:
        prj.config.set(
            "%s.%s" % (proj, res), "source_file", posix_path(path_to_file)
        )
        prj.config.set("%s.%s" % (proj, res), "source_lang", lang)

    prj.save()


def _set_translation(path_to_tx, resource, lang, path_to_file):
    """Reusable method to set translation file."""

    proj, res = resource.split('.')
    if not project or not resource:
        raise Exception("\"%s\" is not a valid resource identifier. It should"
            " be in the following format project_slug.resource_slug." %
            resource)
Beispiel #16
0
 def test_posix_path_in_windows_replaces_backslashes(self):
     orig_path = os.path.abspath(os.getcwd())
     path = orig_path.replace("/", "\\")
     self.assertEqual(orig_path, posix_path(path))
Beispiel #17
0
 def test_posix_path_in_windows_replaces_backslashes(self):
     orig_path = posix_path(os.path.abspath(os.getcwd()))
     expected_path = orig_path.replace("/", "\\")
     self.assertEqual(expected_path, native_path(orig_path))
Beispiel #18
0
def _auto_local(path_to_tx, resource, source_language, expression,
                execute=False, source_file=None, regex=False):
    """Auto configure local project."""
    # The path everything will be relative to
    curpath = os.path.abspath(os.curdir)

    # Force expr to be a valid regex expr (escaped) but keep <lang> intact
    if not expression:
        raise Exception("You need to specify an expression to define where "
                        "translation files should be saved.")

    if not execute:
        logger.info("Only printing the commands which will be run if the "
                    "--execute switch is specified.")

    # First, let's construct a dictionary of all matching files.
    # Note: Only the last matching file of a language will be stored.
    translation_files = {}
    for f_path, lang in utils.get_project_files(curpath, expression):
        if lang == source_language and not source_file:
            source_file = f_path
        else:
            translation_files[lang] = f_path

    if not source_file:
        raise Exception("Could not find a source language file. Please run "
                        "set --source manually and then re-run this command "
                        "or provide the source file with the -s flag.")
    if execute:
        logger.info("Updating source for resource %s ( %s -> %s )." % (
                    resource, source_language, os.path.relpath(
                        source_file, path_to_tx)
                    ))
        _set_source_file(path_to_tx, resource, source_language,
                         os.path.relpath(source_file, path_to_tx))
    else:
        logger.info('\ntx set --source -r %(res)s -l %(lang)s %(file)s\n' % {
            'res': resource,
            'lang': source_language,
            'file': os.path.relpath(source_file, curpath)})

    prj = project.Project(path_to_tx)

    if execute:
        try:
            prj.config.get("%s" % resource, "source_file")
        except configparser.NoSectionError:
            raise Exception("No resource with slug \"%s\" was found.\nRun "
                            "'tx set auto-local -r %s \"expression\"' to "
                            "do the initial configuration." % resource)

    # Now let's handle the translation files.
    if execute:
        logger.info("Updating file expression for resource %s ( %s )." % (
                    resource, expression))
        # Evaluate file_filter relative to root dir
        file_filter = posix_path(
            os.path.relpath(os.path.join(curpath, expression), path_to_tx)
        )
        prj.config.set("%s" % resource, "file_filter", file_filter)
    else:
        for (lang, f_path) in sorted(translation_files.items()):
            logger.info('tx set -r %(res)s -l %(lang)s %(file)s' % {
                'res': resource,
                'lang': lang,
                'file': os.path.relpath(f_path, curpath)})

    if execute:
        prj.save()
Beispiel #19
0
 def test_posix_path_in_windows_replaces_backslashes(self):
     orig_path = os.path.abspath(os.getcwd())
     path = orig_path.replace('/', '\\')
     self.assertEqual(orig_path, posix_path(path))