Changeset - 68eee0e7f4f5
[Not reviewed]
dev_requirements.txt
Show inline comments
 
@@ -2,8 +2,8 @@ pytest >= 4.6.6, < 5.5
 
pytest-sugar >= 0.9.2, < 0.10
 
pytest-benchmark >= 3.2.2, < 3.3
 
pytest-localserver >= 0.5.0, < 0.6
 
mock >= 3.0.0, < 4.1
 
Sphinx >= 1.8.0, < 3.1
 
WebTest >= 2.0.6, < 2.1
 
isort == 4.3.21
 
isort == 5.1.2
 
pyflakes == 2.2.0
kallithea/config/app_cfg.py
Show inline comments
 
@@ -83,14 +83,14 @@ base_config.update_blueprint({
 
# DebugBar, a debug toolbar for TurboGears2.
 
# (https://github.com/TurboGears/tgext.debugbar)
 
# To enable it, install 'tgext.debugbar' and 'kajiki', and run Kallithea with
 
# 'debug = true' (not in production!)
 
# See the Kallithea documentation for more information.
 
try:
 
    import kajiki  # only to check its existence
 
    from tgext.debugbar import enable_debugbar
 
    import kajiki # only to check its existence
 
    assert kajiki
 
except ImportError:
 
    pass
 
else:
 
    base_config['renderers'].append('kajiki')
 
    enable_debugbar(base_config)
kallithea/controllers/compare.py
Show inline comments
 
@@ -127,14 +127,14 @@ class CompareController(BaseRepoControll
 
                    b"ancestors(id(%s)) and not ancestors(id(%s)) and not id(%s)",
 
                    ascii_bytes(org_rev), ascii_bytes(other_rev), ascii_bytes(other_rev))
 
            ]
 

	
 
        elif alias == 'git':
 
            if org_repo != other_repo:
 
                from dulwich.client import SubprocessGitClient
 
                from dulwich.repo import Repo
 
                from dulwich.client import SubprocessGitClient
 

	
 
                gitrepo = Repo(org_repo.path)
 
                SubprocessGitClient(thin_packs=False).fetch(other_repo.path, gitrepo)
 

	
 
                gitrepo_remote = Repo(other_repo.path)
 
                SubprocessGitClient(thin_packs=False).fetch(org_repo.path, gitrepo_remote)
kallithea/lib/celerylib/tasks.py
Show inline comments
 
@@ -320,14 +320,14 @@ def send_email(recipients, subject, body
 
    return True
 

	
 

	
 
@celerylib.task
 
@celerylib.dbsession
 
def create_repo(form_data, cur_user):
 
    from kallithea.model.db import Setting
 
    from kallithea.model.repo import RepoModel
 
    from kallithea.model.db import Setting
 

	
 
    DBS = celerylib.get_session()
 

	
 
    cur_user = User.guess_instance(cur_user)
 

	
 
    owner = cur_user
kallithea/lib/db_manage.py
Show inline comments
 
@@ -160,17 +160,15 @@ class DbManage(object):
 
                        sys.exit()
 
            if email is None:
 
                email = input('Specify admin email:')
 
            self.create_user(username, password, email, True)
 
        else:
 
            log.info('creating admin and regular test users')
 
            from kallithea.tests.base import TEST_USER_ADMIN_LOGIN, \
 
                TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \
 
                TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \
 
                TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \
 
                TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL
 
            from kallithea.tests.base import (TEST_USER_ADMIN_EMAIL, TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS, TEST_USER_REGULAR2_EMAIL,
 
                                              TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR_LOGIN,
 
                                              TEST_USER_REGULAR_PASS)
 

	
 
            self.create_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS,
 
                             TEST_USER_ADMIN_EMAIL, True)
 

	
 
            self.create_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS,
 
                             TEST_USER_REGULAR_EMAIL, False)
kallithea/lib/helpers.py
Show inline comments
 
@@ -629,12 +629,13 @@ def email_or_none(author):
 

	
 

	
 
def person(author, show_attr="username"):
 
    """Find the user identified by 'author', return one of the users attributes,
 
    default to the username attribute, None if there is no user"""
 
    from kallithea.model.db import User
 

	
 
    # if author is already an instance use it for extraction
 
    if isinstance(author, User):
 
        return getattr(author, show_attr)
 

	
 
    value = user_attr_or_none(author, show_attr)
 
    if value is not None:
 
@@ -643,12 +644,13 @@ def person(author, show_attr="username")
 
    # Still nothing?  Just pass back the author name if any, else the email
 
    return author_name(author) or email(author)
 

	
 

	
 
def person_by_id(id_, show_attr="username"):
 
    from kallithea.model.db import User
 

	
 
    # maybe it's an ID ?
 
    if str(id_).isdigit() or isinstance(id_, int):
 
        id_ = int(id_)
 
        user = User.get(id_)
 
        if user is not None:
 
            return getattr(user, show_attr)
 
@@ -971,25 +973,27 @@ def gravatar(email_address, cls='', size
 
            .format(cls=cls, size=size))
 

	
 
    return literal(html)
 

	
 

	
 
def gravatar_url(email_address, size=30, default=''):
 
    # doh, we need to re-import those to mock it later
 
    from kallithea.config.routing import url
 
    from kallithea.model.db import User
 
    from tg import tmpl_context as c
 

	
 
    if not c.visual.use_gravatar:
 
        return ""
 

	
 
    _def = 'anonymous@kallithea-scm.org'  # default gravatar
 
    email_address = email_address or _def
 

	
 
    if email_address == _def:
 
        return default
 

	
 
    # re-import url so tests can mock it
 
    from kallithea.config.routing import url
 
    from kallithea.model.db import User
 

	
 
    parsed_url = urllib.parse.urlparse(url.current(qualified=True))
 
    url = (c.visual.gravatar_url or User.DEFAULT_GRAVATAR_URL) \
 
               .replace('{email}', email_address) \
 
               .replace('{md5email}', hashlib.md5(safe_bytes(email_address).lower()).hexdigest()) \
 
               .replace('{netloc}', parsed_url.netloc) \
 
               .replace('{scheme}', parsed_url.scheme) \
 
@@ -1019,14 +1023,13 @@ def fancy_file_stats(stats):
 
    """
 
    Displays a fancy two colored bar for number of added/deleted
 
    lines of code on file
 

	
 
    :param stats: two element list of added/deleted lines of code
 
    """
 
    from kallithea.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
 
        MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE
 
    from kallithea.lib.diffs import BIN_FILENODE, CHMOD_FILENODE, DEL_FILENODE, MOD_FILENODE, NEW_FILENODE, RENAMED_FILENODE
 

	
 
    a, d = stats['added'], stats['deleted']
 
    width = 100
 

	
 
    if stats['binary']:
 
        # binary mode
kallithea/lib/hooks.py
Show inline comments
 
@@ -304,12 +304,13 @@ def _hook_environment(repo_path):
 

	
 
    Git hooks are executed as subprocess of Git while Kallithea is waiting, and
 
    they thus need enough info to be able to create an app environment and
 
    connect to the database.
 
    """
 
    import paste.deploy
 

	
 
    import kallithea.config.application
 

	
 
    extras = get_hook_environment()
 

	
 
    path_to_ini_file = extras['config']
 
    kallithea.CONFIG = paste.deploy.appconfig('config:' + path_to_ini_file)
kallithea/lib/middleware/pygrack.py
Show inline comments
 
@@ -165,14 +165,15 @@ class GitRepository(object):
 
            log.error(traceback.format_exc())
 
            raise exc.HTTPExpectationFailed()
 

	
 
        if git_command in ['git-receive-pack']:
 
            # updating refs manually after each push.
 
            # Needed for pre-1.7.0.4 git clients using regular HTTP mode.
 
            from dulwich.server import update_server_info
 

	
 
            from kallithea.lib.vcs import get_repo
 
            from dulwich.server import update_server_info
 
            repo = get_repo(self.content_path)
 
            if repo:
 
                update_server_info(repo._repo)
 

	
 
        resp = Response()
 
        resp.content_type = 'application/x-%s-result' % git_command.encode('utf-8')
 
@@ -220,9 +221,9 @@ class GitDirectory(object):
 
            else:
 
                return exc.HTTPNotFound()(environ, start_response)
 
        return app(environ, start_response)
 

	
 

	
 
def make_wsgi_app(repo_name, repo_root):
 
    from dulwich.web import LimitedInputFilter, GunzipFilter
 
    from dulwich.web import GunzipFilter, LimitedInputFilter
 
    app = GitDirectory(repo_root, repo_name)
 
    return GunzipFilter(LimitedInputFilter(app))
kallithea/lib/utils2.py
Show inline comments
 
@@ -328,15 +328,14 @@ def get_changeset_safe(repo, rev):
 
    Safe version of get_changeset if this changeset doesn't exists for a
 
    repo it returns a Dummy one instead
 

	
 
    :param repo:
 
    :param rev:
 
    """
 
    from kallithea.lib.vcs.backends.base import BaseRepository
 
    from kallithea.lib.vcs.backends.base import BaseRepository, EmptyChangeset
 
    from kallithea.lib.vcs.exceptions import RepositoryError
 
    from kallithea.lib.vcs.backends.base import EmptyChangeset
 
    if not isinstance(repo, BaseRepository):
 
        raise Exception('You must pass an Repository '
 
                        'object as first argument got %s' % type(repo))
 

	
 
    try:
 
        cs = repo.get_changeset(rev)
kallithea/lib/vcs/utils/helpers.py
Show inline comments
 
@@ -105,14 +105,14 @@ def get_highlighted_code(name, code, typ
 
    try:
 
        import pygments
 
        pygments
 
    except ImportError:
 
        return code
 
    from pygments import highlight
 
    from pygments.lexers import guess_lexer_for_filename, ClassNotFound
 
    from pygments.formatters import TerminalFormatter
 
    from pygments.lexers import ClassNotFound, guess_lexer_for_filename
 

	
 
    try:
 
        lexer = guess_lexer_for_filename(name, code)
 
        formatter = TerminalFormatter()
 
        content = highlight(code, lexer, formatter)
 
    except ClassNotFound:
kallithea/model/db.py
Show inline comments
 
@@ -304,14 +304,16 @@ class Setting(Base, BaseDbModel):
 
            fd.update({key: row.app_settings_value})
 

	
 
        return fd
 

	
 
    @classmethod
 
    def get_server_info(cls):
 
        import platform
 

	
 
        import pkg_resources
 
        import platform
 

	
 
        from kallithea.lib.utils import check_git_version
 
        mods = [(p.project_name, p.version) for p in pkg_resources.working_set]
 
        info = {
 
            'modules': sorted(mods, key=lambda k: k[0].lower()),
 
            'py_version': platform.python_version(),
 
            'platform': platform.platform(),
 
@@ -592,13 +594,14 @@ class User(Base, BaseDbModel):
 
    def get_from_cs_author(cls, author):
 
        """
 
        Tries to get User objects out of commit author string
 

	
 
        :param author:
 
        """
 
        from kallithea.lib.helpers import email, author_name
 
        from kallithea.lib.helpers import author_name, email
 

	
 
        # Valid email in the attribute passed, see if they're in the system
 
        _email = email(author)
 
        if _email:
 
            user = cls.get_by_email(_email)
 
            if user is not None:
 
                return user
kallithea/model/repo.py
Show inline comments
 
@@ -106,13 +106,14 @@ class RepoModel(object):
 
            if perm in ['repository.read', 'repository.write', 'repository.admin']
 
            ]
 
        return Repository.query().filter(Repository.repo_name.in_(repos))
 

	
 
    @classmethod
 
    def _render_datatable(cls, tmpl, *args, **kwargs):
 
        from tg import tmpl_context as c, request, app_globals
 
        from tg import app_globals, request
 
        from tg import tmpl_context as c
 
        from tg.i18n import ugettext as _
 

	
 
        _tmpl_lookup = app_globals.mako_lookup
 
        template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
 

	
 
        tmpl = template.get_def(tmpl)
 
@@ -125,13 +126,15 @@ class RepoModel(object):
 
        """Return repository list for use by DataTable.
 
        repos_list: list of repositories - but will be filtered for read permission.
 
        repo_groups_list: added at top of list without permission check.
 
        admin: return data for action column.
 
        """
 
        _render = self._render_datatable
 
        from tg import tmpl_context as c, request
 
        from tg import request
 
        from tg import tmpl_context as c
 

	
 
        from kallithea.model.scm import ScmModel
 

	
 
        def repo_lnk(name, rtype, rstate, private, fork_of):
 
            return _render('repo_name', name, rtype, rstate, private, fork_of,
 
                           short_name=short_name)
 

	
kallithea/model/repo_group.py
Show inline comments
 
@@ -186,14 +186,14 @@ class RepoGroupModel(object):
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def _update_permissions(self, repo_group, perms_new=None,
 
                            perms_updates=None, recursive=None,
 
                            check_perms=True):
 
        from kallithea.lib.auth import HasUserGroupPermissionLevel
 
        from kallithea.model.repo import RepoModel
 
        from kallithea.lib.auth import HasUserGroupPermissionLevel
 

	
 
        if not perms_new:
 
            perms_new = []
 
        if not perms_updates:
 
            perms_updates = []
 

	
kallithea/model/user.py
Show inline comments
 
@@ -56,14 +56,13 @@ class UserModel(object):
 
        return User.guess_instance(user)
 

	
 
    def create(self, form_data, cur_user=None):
 
        if not cur_user:
 
            cur_user = getattr(get_current_authuser(), 'username', None)
 

	
 
        from kallithea.lib.hooks import log_create_user, \
 
            check_allowed_create_user
 
        from kallithea.lib.hooks import check_allowed_create_user, log_create_user
 
        _fd = form_data
 
        user_data = {
 
            'username': _fd['username'],
 
            'password': _fd['password'],
 
            'email': _fd['email'],
 
            'firstname': _fd['firstname'],
 
@@ -108,15 +107,14 @@ class UserModel(object):
 
        :param extern_type:
 
        :param cur_user:
 
        """
 
        if not cur_user:
 
            cur_user = getattr(get_current_authuser(), 'username', None)
 

	
 
        from kallithea.lib.auth import get_crypt_password, check_password
 
        from kallithea.lib.hooks import log_create_user, \
 
            check_allowed_create_user
 
        from kallithea.lib.auth import check_password, get_crypt_password
 
        from kallithea.lib.hooks import check_allowed_create_user, log_create_user
 
        user_data = {
 
            'username': username, 'password': password,
 
            'email': email, 'firstname': firstname, 'lastname': lastname,
 
            'active': active, 'admin': admin
 
        }
 
        # raises UserCreationError if it's not allowed
 
@@ -165,14 +163,14 @@ class UserModel(object):
 
            return new_user
 
        except (DatabaseError,):
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def create_registration(self, form_data):
 
        import kallithea.lib.helpers as h
 
        from kallithea.model.notification import NotificationModel
 
        import kallithea.lib.helpers as h
 

	
 
        form_data['admin'] = False
 
        form_data['extern_type'] = User.DEFAULT_AUTH_TYPE
 
        form_data['extern_name'] = ''
 
        new_user = self.create(form_data)
 

	
 
@@ -314,15 +312,15 @@ class UserModel(object):
 
        Sends email with a password reset token and link to the password
 
        reset confirmation page with all information (including the token)
 
        pre-filled. Also returns URL of that page, only without the token,
 
        allowing users to copy-paste or manually enter the token from the
 
        email.
 
        """
 
        import kallithea.lib.helpers as h
 
        from kallithea.lib.celerylib import tasks
 
        from kallithea.model.notification import EmailNotificationModel
 
        import kallithea.lib.helpers as h
 

	
 
        user_email = data['email']
 
        user = User.get_by_email(user_email)
 
        timestamp = int(time.time())
 
        if user is not None:
 
            if self.can_change_password(user):
 
@@ -383,14 +381,14 @@ class UserModel(object):
 
                                                       h.session_csrf_secret_token())
 
        log.debug('computed password reset token: %s', expected_token)
 
        log.debug('received password reset token: %s', token)
 
        return expected_token == token
 

	
 
    def reset_password(self, user_email, new_passwd):
 
        from kallithea.lib import auth
 
        from kallithea.lib.celerylib import tasks
 
        from kallithea.lib import auth
 
        user = User.get_by_email(user_email)
 
        if user is not None:
 
            if not self.can_change_password(user):
 
                raise Exception('trying to change password for external user')
 
            user.password = auth.get_crypt_password(new_passwd)
 
            Session().commit()
kallithea/tests/api/api_base.py
Show inline comments
 
@@ -142,13 +142,13 @@ class _BaseTestApi(object):
 
        assert option1() is None
 

	
 
        assert 1 == Optional.extract(Optional(1))
 
        assert 'trololo' == Optional.extract('trololo')
 

	
 
    def test_Optional_OAttr(self):
 
        from kallithea.controllers.api.api import Optional, OAttr
 
        from kallithea.controllers.api.api import OAttr, Optional
 

	
 
        option1 = Optional(OAttr('apiuser'))
 
        assert 'apiuser' == Optional.extract(option1)
 

	
 
    def test_OAttr_object(self):
 
        from kallithea.controllers.api.api import OAttr
kallithea/tests/other/test_libs.py
Show inline comments
 
@@ -153,14 +153,15 @@ class TestLibs(base.TestController):
 
        (dict(years= -1, months= -10), '1 year and 10 months ago'),
 
        (dict(years= -2, months= -4), '2 years and 4 months ago'),
 
        (dict(years= -2, months= -11), '2 years and 11 months ago'),
 
        (dict(years= -3, months= -2), '3 years and 2 months ago'),
 
    ])
 
    def test_age(self, age_args, expected):
 
        from dateutil import relativedelta
 

	
 
        from kallithea.lib.utils2 import age
 
        from dateutil import relativedelta
 
        with test_context(self.app):
 
            n = datetime.datetime(year=2012, month=5, day=17)
 
            delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs)
 
            assert age(n + delt(**age_args), now=n) == expected
 

	
 
    @base.parametrize('age_args,expected', [
 
@@ -178,14 +179,15 @@ class TestLibs(base.TestController):
 
        (dict(years= -2, months= -4), '2 years ago'),
 
        (dict(years= -2, months= -11), '3 years ago'),
 
        (dict(years= -3, months= -2), '3 years ago'),
 
        (dict(years= -4, months= -8), '5 years ago'),
 
    ])
 
    def test_age_short(self, age_args, expected):
 
        from dateutil import relativedelta
 

	
 
        from kallithea.lib.utils2 import age
 
        from dateutil import relativedelta
 
        with test_context(self.app):
 
            n = datetime.datetime(year=2012, month=5, day=17)
 
            delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs)
 
            assert age(n + delt(**age_args), show_short_version=True, now=n) == expected
 

	
 
    @base.parametrize('age_args,expected', [
 
@@ -197,14 +199,15 @@ class TestLibs(base.TestController):
 
        (dict(hours=24 * 5), 'in 5 days'),
 
        (dict(months=1), 'in 1 month'),
 
        (dict(months=1, days=1), 'in 1 month and 1 day'),
 
        (dict(years=1, months=1), 'in 1 year and 1 month')
 
    ])
 
    def test_age_in_future(self, age_args, expected):
 
        from dateutil import relativedelta
 

	
 
        from kallithea.lib.utils2 import age
 
        from dateutil import relativedelta
 
        with test_context(self.app):
 
            n = datetime.datetime(year=2012, month=5, day=17)
 
            delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs)
 
            assert age(n + delt(**age_args), now=n) == expected
 

	
 
    def test_tag_extractor(self):
 
@@ -294,12 +297,13 @@ class TestLibs(base.TestController):
 
        """
 
        Changes `some text url[foo]` => `some text <a href="/">foo</a>
 

	
 
        :param text:
 
        """
 
        import re
 

	
 
        # quickly change expected url[] into a link
 
        url_pattern = re.compile(r'(?:url\[)(.+?)(?:\])')
 

	
 
        def url_func(match_obj):
 
            _url = match_obj.groups()[0]
 
            return tmpl % (url_ or '/repo_name/changeset/%s' % _url, _url)
 
@@ -567,17 +571,17 @@ class TestLibs(base.TestController):
 
        ('http://www.example.org', 'abc/xyz/', 'http://www.example.org/abc/xyz/'),
 
        ('http://www.example.org', 'about', 'http://www.example.org/about-page'),
 
        ('http://www.example.org/repos/', 'abc/xyz/', 'http://www.example.org/repos/abc/xyz/'),
 
        ('http://www.example.org/kallithea/repos/', 'abc/xyz/', 'http://www.example.org/kallithea/repos/abc/xyz/'),
 
    ])
 
    def test_canonical_url(self, canonical, test, expected):
 
        from kallithea.lib.helpers import canonical_url
 
        # setup url(), used by canonical_url
 
        import routes
 
        from tg import request
 

	
 
        # setup url(), used by canonical_url
 
        import routes
 
        from kallithea.lib.helpers import canonical_url
 
        m = routes.Mapper()
 
        m.connect('about', '/about-page')
 
        url = routes.URLGenerator(m, {'HTTP_HOST': 'http_host.example.org'})
 

	
 
        config_mock = {
 
            'canonical_url': canonical,
 
@@ -591,17 +595,18 @@ class TestLibs(base.TestController):
 
    @base.parametrize('canonical,expected', [
 
        ('http://www.example.org', 'www.example.org'),
 
        ('http://www.example.org/repos/', 'www.example.org'),
 
        ('http://www.example.org/kallithea/repos/', 'www.example.org'),
 
    ])
 
    def test_canonical_hostname(self, canonical, expected):
 
        from kallithea.lib.helpers import canonical_hostname
 
        import routes
 
        from tg import request
 

	
 
        from kallithea.lib.helpers import canonical_hostname
 

	
 
        # setup url(), used by canonical_hostname
 
        import routes
 
        m = routes.Mapper()
 
        url = routes.URLGenerator(m, {'HTTP_HOST': 'http_host.example.org'})
 

	
 
        config_mock = {
 
            'canonical_url': canonical,
 
        }
kallithea/tests/vcs/test_workdirs.py
Show inline comments
 
@@ -65,12 +65,13 @@ class WorkdirTestCaseMixin(_BackendTestM
 
        # Make sure that old head is still there after update to default branch
 
        self.repo.workdir.checkout_branch(self.default_branch)
 
        assert self.repo.workdir.get_changeset() == old_head
 

	
 
    def test_checkout_branch(self):
 
        from kallithea.lib.vcs.exceptions import BranchDoesNotExistError
 

	
 
        # first, 'foobranch' does not exist.
 
        with pytest.raises(BranchDoesNotExistError):
 
            self.repo.workdir.checkout_branch(branch='foobranch')
 
        # create new branch 'foobranch'.
 
        self.imc.add(FileNode('file1', content='blah'))
 
        self.imc.commit(message='asd', author='john', branch='foobranch')
scripts/i18n
Show inline comments
 
@@ -16,13 +16,12 @@
 

	
 
import os
 
import shutil
 
import sys
 

	
 
import click
 

	
 
import i18n_utils
 

	
 

	
 
"""
 
Tool for maintenance of .po and .pot files
 

	
 
@@ -87,17 +86,14 @@ def normalized_merge(local, base, other,
 
        [merge-tools]
 
        i18n.executable = /path/to/scripts/i18n
 
        i18n.args = normalized-merge $local $base $other $output
 

	
 
    and then invoke merge/rebase/graft with the additional argument '--tool i18n'.
 
    """
 
    from mercurial import (
 
        context,
 
        simplemerge,
 
        ui as uimod,
 
    )
 
    from mercurial import context, simplemerge
 
    from mercurial import ui as uimod
 

	
 
    print('i18n normalized-merge: normalizing and merging %s' % output)
 

	
 
    i18n_utils._normalize_po_file(local, merge_pot_file=merge_pot_file, strip=strip)
 
    i18n_utils._normalize_po_file(base, merge_pot_file=merge_pot_file, strip=strip)
 
    i18n_utils._normalize_po_file(other, merge_pot_file=merge_pot_file, strip=strip)
0 comments (0 inline, 0 general)