mirror of
https://github.com/ansible/awx.git
synced 2026-04-10 20:49:24 -02:30
flake8 compliance
This commit is contained in:
@@ -624,8 +624,8 @@ class UnifiedJobSerializer(BaseSerializer):
|
|||||||
obj_size = obj.result_stdout_size
|
obj_size = obj.result_stdout_size
|
||||||
if obj_size > settings.STDOUT_MAX_BYTES_DISPLAY:
|
if obj_size > settings.STDOUT_MAX_BYTES_DISPLAY:
|
||||||
return _("Standard Output too large to display (%(text_size)d bytes), "
|
return _("Standard Output too large to display (%(text_size)d bytes), "
|
||||||
"only download supported for sizes over %(supported_size)d bytes") \
|
"only download supported for sizes over %(supported_size)d bytes") % {
|
||||||
% {'text_size': obj_size, 'supported_size': settings.STDOUT_MAX_BYTES_DISPLAY}
|
'text_size': obj_size, 'supported_size': settings.STDOUT_MAX_BYTES_DISPLAY}
|
||||||
return obj.result_stdout
|
return obj.result_stdout
|
||||||
|
|
||||||
|
|
||||||
@@ -682,8 +682,8 @@ class UnifiedJobStdoutSerializer(UnifiedJobSerializer):
|
|||||||
obj_size = obj.result_stdout_size
|
obj_size = obj.result_stdout_size
|
||||||
if obj_size > settings.STDOUT_MAX_BYTES_DISPLAY:
|
if obj_size > settings.STDOUT_MAX_BYTES_DISPLAY:
|
||||||
return _("Standard Output too large to display (%(text_size)d bytes), "
|
return _("Standard Output too large to display (%(text_size)d bytes), "
|
||||||
"only download supported for sizes over %(supported_size)d bytes") \
|
"only download supported for sizes over %(supported_size)d bytes") % {
|
||||||
% {'text_size': obj_size, 'supported_size': settings.STDOUT_MAX_BYTES_DISPLAY}
|
'text_size': obj_size, 'supported_size': settings.STDOUT_MAX_BYTES_DISPLAY}
|
||||||
return obj.result_stdout
|
return obj.result_stdout
|
||||||
|
|
||||||
def get_types(self):
|
def get_types(self):
|
||||||
@@ -1849,7 +1849,7 @@ class JobOptionsSerializer(LabelsListMixin, BaseSerializer):
|
|||||||
job_type = attrs.get('job_type', self.instance and self.instance.job_type or None)
|
job_type = attrs.get('job_type', self.instance and self.instance.job_type or None)
|
||||||
if not project and job_type != PERM_INVENTORY_SCAN:
|
if not project and job_type != PERM_INVENTORY_SCAN:
|
||||||
raise serializers.ValidationError({'project': _('This field is required.')})
|
raise serializers.ValidationError({'project': _('This field is required.')})
|
||||||
if project and playbook and force_text(playbook) not in project.playbooks:
|
if project and playbook and force_text(playbook) not in project.playbook_files:
|
||||||
raise serializers.ValidationError({'playbook': _('Playbook not found for project.')})
|
raise serializers.ValidationError({'playbook': _('Playbook not found for project.')})
|
||||||
if project and not playbook:
|
if project and not playbook:
|
||||||
raise serializers.ValidationError({'playbook': _('Must select playbook for project.')})
|
raise serializers.ValidationError({'playbook': _('Must select playbook for project.')})
|
||||||
@@ -2324,6 +2324,11 @@ class WorkflowJobTemplateNodeSerializer(WorkflowNodeBaseSerializer):
|
|||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
"job_type": _("%(job_type)s is not a valid job type. The choices are %(choices)s.") % {
|
"job_type": _("%(job_type)s is not a valid job type. The choices are %(choices)s.") % {
|
||||||
'job_type': attrs['char_prompts']['job_type'], 'choices': job_types}})
|
'job_type': attrs['char_prompts']['job_type'], 'choices': job_types}})
|
||||||
|
if self.instance is None and ('workflow_job_template' not in attrs or
|
||||||
|
attrs['workflow_job_template'] is None):
|
||||||
|
raise serializers.ValidationError({
|
||||||
|
"workflow_job_template": _("Workflow job template is missing during creation")
|
||||||
|
})
|
||||||
ujt_obj = attrs.get('unified_job_template', None)
|
ujt_obj = attrs.get('unified_job_template', None)
|
||||||
if isinstance(ujt_obj, (WorkflowJobTemplate, SystemJobTemplate)):
|
if isinstance(ujt_obj, (WorkflowJobTemplate, SystemJobTemplate)):
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
@@ -2832,7 +2837,7 @@ class ActivityStreamSerializer(BaseSerializer):
|
|||||||
rel = {}
|
rel = {}
|
||||||
if obj.actor is not None:
|
if obj.actor is not None:
|
||||||
rel['actor'] = reverse('api:user_detail', args=(obj.actor.pk,))
|
rel['actor'] = reverse('api:user_detail', args=(obj.actor.pk,))
|
||||||
for fk, _ in SUMMARIZABLE_FK_FIELDS.items():
|
for fk, __ in SUMMARIZABLE_FK_FIELDS.items():
|
||||||
if not hasattr(obj, fk):
|
if not hasattr(obj, fk):
|
||||||
continue
|
continue
|
||||||
allm2m = getattr(obj, fk).distinct()
|
allm2m = getattr(obj, fk).distinct()
|
||||||
|
|||||||
@@ -2343,8 +2343,8 @@ class JobTemplateSurveySpec(GenericAPIView):
|
|||||||
if "variable" not in survey_item:
|
if "variable" not in survey_item:
|
||||||
return Response(dict(error=_("'variable' missing from survey question %s.") % str(idx)), status=status.HTTP_400_BAD_REQUEST)
|
return Response(dict(error=_("'variable' missing from survey question %s.") % str(idx)), status=status.HTTP_400_BAD_REQUEST)
|
||||||
if survey_item['variable'] in variable_set:
|
if survey_item['variable'] in variable_set:
|
||||||
return Response(dict(error=_("'variable' '%(item)s' duplicated in survey question %(survey)s.") %
|
return Response(dict(error=_("'variable' '%(item)s' duplicated in survey question %(survey)s.") % {
|
||||||
{'item': survey_item['variable'], 'survey': str(idx)}), status=status.HTTP_400_BAD_REQUEST)
|
'item': survey_item['variable'], 'survey': str(idx)}), status=status.HTTP_400_BAD_REQUEST)
|
||||||
else:
|
else:
|
||||||
variable_set.add(survey_item['variable'])
|
variable_set.add(survey_item['variable'])
|
||||||
if "required" not in survey_item:
|
if "required" not in survey_item:
|
||||||
@@ -3568,8 +3568,8 @@ class UnifiedJobStdout(RetrieveAPIView):
|
|||||||
obj_size = unified_job.result_stdout_size
|
obj_size = unified_job.result_stdout_size
|
||||||
if request.accepted_renderer.format != 'txt_download' and obj_size > settings.STDOUT_MAX_BYTES_DISPLAY:
|
if request.accepted_renderer.format != 'txt_download' and obj_size > settings.STDOUT_MAX_BYTES_DISPLAY:
|
||||||
response_message = _("Standard Output too large to display (%(text_size)d bytes), "
|
response_message = _("Standard Output too large to display (%(text_size)d bytes), "
|
||||||
"only download supported for sizes over %(supported_size)d bytes") % \
|
"only download supported for sizes over %(supported_size)d bytes") % {
|
||||||
{'text_size': obj_size, 'supported_size': settings.STDOUT_MAX_BYTES_DISPLAY}
|
'text_size': obj_size, 'supported_size': settings.STDOUT_MAX_BYTES_DISPLAY}
|
||||||
if request.accepted_renderer.format == 'json':
|
if request.accepted_renderer.format == 'json':
|
||||||
return Response({'range': {'start': 0, 'end': 1, 'absolute_end': 1}, 'content': response_message})
|
return Response({'range': {'start': 0, 'end': 1, 'absolute_end': 1}, 'content': response_message})
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
# Copyright (c) 2015 Ansible, Inc.
|
|
||||||
# All Rights Reserved.
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Copyright (c) 2015 Ansible, Inc.
|
|
||||||
# All Rights Reserved.
|
|
||||||
|
|
||||||
'''
|
|
||||||
Compability library for support of both Django 1.4.x and Django 1.5.x.
|
|
||||||
'''
|
|
||||||
|
|
||||||
try:
|
|
||||||
from django.utils.html import format_html
|
|
||||||
except ImportError:
|
|
||||||
from django.utils.html import conditional_escape
|
|
||||||
from django.utils.safestring import mark_safe
|
|
||||||
|
|
||||||
def format_html(format_string, *args, **kwargs):
|
|
||||||
args_safe = map(conditional_escape, args)
|
|
||||||
kwargs_safe = dict([(k, conditional_escape(v)) for (k, v) in
|
|
||||||
kwargs.items()])
|
|
||||||
return mark_safe(format_string.format(*args_safe, **kwargs_safe))
|
|
||||||
|
|
||||||
try:
|
|
||||||
from django.utils.log import RequireDebugTrue
|
|
||||||
except ImportError:
|
|
||||||
import logging
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
class RequireDebugTrue(logging.Filter):
|
|
||||||
def filter(self, record):
|
|
||||||
return settings.DEBUG
|
|
||||||
|
|
||||||
try:
|
|
||||||
from django.utils.text import slugify # noqa
|
|
||||||
except ImportError:
|
|
||||||
from django.template.defaultfilters import slugify # noqa
|
|
||||||
@@ -1195,7 +1195,10 @@ class JobAccess(BaseAccess):
|
|||||||
return True
|
return True
|
||||||
return self.org_access(obj, role_types=['auditor_role', 'admin_role'])
|
return self.org_access(obj, role_types=['auditor_role', 'admin_role'])
|
||||||
|
|
||||||
def can_add(self, data):
|
def can_add(self, data, validate_license=True):
|
||||||
|
if validate_license:
|
||||||
|
self.check_license()
|
||||||
|
|
||||||
if not data: # So the browseable API will work
|
if not data: # So the browseable API will work
|
||||||
return True
|
return True
|
||||||
if not self.user.is_superuser:
|
if not self.user.is_superuser:
|
||||||
@@ -1219,7 +1222,9 @@ class JobAccess(BaseAccess):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def can_change(self, obj, data):
|
def can_change(self, obj, data):
|
||||||
return obj.status == 'new' and self.can_read(obj) and self.can_add(data)
|
return (obj.status == 'new' and
|
||||||
|
self.can_read(obj) and
|
||||||
|
self.can_add(data, validate_license=False))
|
||||||
|
|
||||||
@check_superuser
|
@check_superuser
|
||||||
def can_delete(self, obj):
|
def can_delete(self, obj):
|
||||||
|
|||||||
@@ -173,3 +173,21 @@ register(
|
|||||||
category=_('Jobs'),
|
category=_('Jobs'),
|
||||||
category_slug='jobs',
|
category_slug='jobs',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
register(
|
||||||
|
'DEFAULT_JOB_TIMEOUTS',
|
||||||
|
field_class=fields.DictField,
|
||||||
|
default={
|
||||||
|
'Job': 0,
|
||||||
|
'InventoryUpdate': 0,
|
||||||
|
'ProjectUpdate': 0,
|
||||||
|
},
|
||||||
|
label=_('Default Job Timeouts'),
|
||||||
|
help_text=_('Maximum time to allow jobs to run. Use sub-keys of Job, '
|
||||||
|
'InventoryUpdate, and ProjectUpdate to configure this value '
|
||||||
|
'for each job type. Use value of 0 to indicate that no '
|
||||||
|
'timeout should be imposed. A timeout set on an individual '
|
||||||
|
'job template will override this.'),
|
||||||
|
category=_('Jobs'),
|
||||||
|
category_slug='jobs',
|
||||||
|
)
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ from django.conf import settings
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils.encoding import smart_str, smart_text
|
from django.utils.encoding import smart_str, smart_text
|
||||||
|
from django.utils.text import slugify
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.utils.timezone import now, make_aware, get_default_timezone
|
from django.utils.timezone import now, make_aware, get_default_timezone
|
||||||
|
|
||||||
# AWX
|
# AWX
|
||||||
from awx.lib.compat import slugify
|
|
||||||
from awx.main.models.base import * # noqa
|
from awx.main.models.base import * # noqa
|
||||||
from awx.main.models.jobs import Job
|
from awx.main.models.jobs import Job
|
||||||
from awx.main.models.notifications import (
|
from awx.main.models.notifications import (
|
||||||
|
|||||||
@@ -140,7 +140,6 @@ class WorkflowNodeBase(CreatedModifiedModel):
|
|||||||
'inventory', 'credential', 'char_prompts']
|
'inventory', 'credential', 'char_prompts']
|
||||||
|
|
||||||
class WorkflowJobTemplateNode(WorkflowNodeBase):
|
class WorkflowJobTemplateNode(WorkflowNodeBase):
|
||||||
# TODO: Ensure the API forces workflow_job_template being set
|
|
||||||
workflow_job_template = models.ForeignKey(
|
workflow_job_template = models.ForeignKey(
|
||||||
'WorkflowJobTemplate',
|
'WorkflowJobTemplate',
|
||||||
related_name='workflow_job_template_nodes',
|
related_name='workflow_job_template_nodes',
|
||||||
@@ -149,7 +148,7 @@ class WorkflowJobTemplateNode(WorkflowNodeBase):
|
|||||||
default=None,
|
default=None,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('api:workflow_job_template_node_detail', args=(self.pk,))
|
return reverse('api:workflow_job_template_node_detail', args=(self.pk,))
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,8 @@ def mk_user(name, is_superuser=False, organization=None, team=None, persisted=Tr
|
|||||||
|
|
||||||
def mk_project(name, organization=None, description=None, persisted=True):
|
def mk_project(name, organization=None, description=None, persisted=True):
|
||||||
description = description or '{}-description'.format(name)
|
description = description or '{}-description'.format(name)
|
||||||
project = Project(name=name, description=description)
|
project = Project(name=name, description=description,
|
||||||
|
playbook_files=['helloworld.yml', 'alt-helloworld.yml'])
|
||||||
if organization is not None:
|
if organization is not None:
|
||||||
project.organization = organization
|
project.organization = organization
|
||||||
if persisted:
|
if persisted:
|
||||||
@@ -134,7 +135,7 @@ def mk_job_template(name, job_type='run',
|
|||||||
extra_vars = json.dumps(extra_vars)
|
extra_vars = json.dumps(extra_vars)
|
||||||
|
|
||||||
jt = JobTemplate(name=name, job_type=job_type, extra_vars=extra_vars,
|
jt = JobTemplate(name=name, job_type=job_type, extra_vars=extra_vars,
|
||||||
playbook='mocked')
|
playbook='helloworld.yml')
|
||||||
|
|
||||||
jt.inventory = inventory
|
jt.inventory = inventory
|
||||||
if jt.inventory is None:
|
if jt.inventory is None:
|
||||||
|
|||||||
@@ -1,22 +1,15 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import mock
|
|
||||||
|
|
||||||
# AWX
|
# AWX
|
||||||
from awx.api.serializers import JobTemplateSerializer, JobLaunchSerializer
|
from awx.api.serializers import JobTemplateSerializer, JobLaunchSerializer
|
||||||
from awx.main.models.jobs import Job
|
from awx.main.models.jobs import Job
|
||||||
from awx.main.models.projects import ProjectOptions
|
|
||||||
from awx.main.migrations import _save_password_keys as save_password_keys
|
from awx.main.migrations import _save_password_keys as save_password_keys
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
|
||||||
@property
|
|
||||||
def project_playbooks(self):
|
|
||||||
return ['mocked', 'mocked.yml', 'alt-mocked.yml']
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@mock.patch.object(ProjectOptions, "playbooks", project_playbooks)
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"grant_project, grant_credential, grant_inventory, expect", [
|
"grant_project, grant_credential, grant_inventory, expect", [
|
||||||
(True, True, True, 201),
|
(True, True, True, 201),
|
||||||
@@ -38,11 +31,10 @@ def test_create(post, project, machine_credential, inventory, alice, grant_proje
|
|||||||
'project': project.id,
|
'project': project.id,
|
||||||
'credential': machine_credential.id,
|
'credential': machine_credential.id,
|
||||||
'inventory': inventory.id,
|
'inventory': inventory.id,
|
||||||
'playbook': 'mocked.yml',
|
'playbook': 'helloworld.yml',
|
||||||
}, alice, expect=expect)
|
}, alice, expect=expect)
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@mock.patch.object(ProjectOptions, "playbooks", project_playbooks)
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"grant_project, grant_credential, grant_inventory, expect", [
|
"grant_project, grant_credential, grant_inventory, expect", [
|
||||||
(True, True, True, 200),
|
(True, True, True, 200),
|
||||||
@@ -67,11 +59,10 @@ def test_edit_sensitive_fields(patch, job_template_factory, alice, grant_project
|
|||||||
'project': objs.project.id,
|
'project': objs.project.id,
|
||||||
'credential': objs.credential.id,
|
'credential': objs.credential.id,
|
||||||
'inventory': objs.inventory.id,
|
'inventory': objs.inventory.id,
|
||||||
'playbook': 'alt-mocked.yml',
|
'playbook': 'alt-helloworld.yml',
|
||||||
}, alice, expect=expect)
|
}, alice, expect=expect)
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@mock.patch.object(ProjectOptions, "playbooks", project_playbooks)
|
|
||||||
def test_edit_playbook(patch, job_template_factory, alice):
|
def test_edit_playbook(patch, job_template_factory, alice):
|
||||||
objs = job_template_factory('jt', organization='org1', project='prj', inventory='inv', credential='cred')
|
objs = job_template_factory('jt', organization='org1', project='prj', inventory='inv', credential='cred')
|
||||||
objs.job_template.admin_role.members.add(alice)
|
objs.job_template.admin_role.members.add(alice)
|
||||||
@@ -80,16 +71,15 @@ def test_edit_playbook(patch, job_template_factory, alice):
|
|||||||
objs.inventory.use_role.members.add(alice)
|
objs.inventory.use_role.members.add(alice)
|
||||||
|
|
||||||
patch(reverse('api:job_template_detail', args=(objs.job_template.id,)), {
|
patch(reverse('api:job_template_detail', args=(objs.job_template.id,)), {
|
||||||
'playbook': 'alt-mocked.yml',
|
'playbook': 'alt-helloworld.yml',
|
||||||
}, alice, expect=200)
|
}, alice, expect=200)
|
||||||
|
|
||||||
objs.inventory.use_role.members.remove(alice)
|
objs.inventory.use_role.members.remove(alice)
|
||||||
patch(reverse('api:job_template_detail', args=(objs.job_template.id,)), {
|
patch(reverse('api:job_template_detail', args=(objs.job_template.id,)), {
|
||||||
'playbook': 'mocked.yml',
|
'playbook': 'helloworld.yml',
|
||||||
}, alice, expect=403)
|
}, alice, expect=403)
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@mock.patch.object(ProjectOptions, "playbooks", project_playbooks)
|
|
||||||
def test_edit_nonsenstive(patch, job_template_factory, alice):
|
def test_edit_nonsenstive(patch, job_template_factory, alice):
|
||||||
objs = job_template_factory('jt', organization='org1', project='prj', inventory='inv', credential='cred')
|
objs = job_template_factory('jt', organization='org1', project='prj', inventory='inv', credential='cred')
|
||||||
jt = objs.job_template
|
jt = objs.job_template
|
||||||
@@ -121,10 +111,6 @@ def jt_copy_edit(job_template_factory, project):
|
|||||||
project=project)
|
project=project)
|
||||||
return objects.job_template
|
return objects.job_template
|
||||||
|
|
||||||
@property
|
|
||||||
def project_playbooks(self):
|
|
||||||
return ['mocked', 'mocked.yml', 'alt-mocked.yml']
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_job_template_role_user(post, organization_factory, job_template_factory):
|
def test_job_template_role_user(post, organization_factory, job_template_factory):
|
||||||
objects = organization_factory("org",
|
objects = organization_factory("org",
|
||||||
@@ -143,7 +129,6 @@ def test_job_template_role_user(post, organization_factory, job_template_factory
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@mock.patch.object(ProjectOptions, "playbooks", project_playbooks)
|
|
||||||
def test_jt_admin_copy_edit_functional(jt_copy_edit, rando, get, post):
|
def test_jt_admin_copy_edit_functional(jt_copy_edit, rando, get, post):
|
||||||
|
|
||||||
# Grant random user JT admin access only
|
# Grant random user JT admin access only
|
||||||
|
|||||||
@@ -110,7 +110,8 @@ def team_member(user, team):
|
|||||||
def project(instance, organization):
|
def project(instance, organization):
|
||||||
prj = Project.objects.create(name="test-proj",
|
prj = Project.objects.create(name="test-proj",
|
||||||
description="test-proj-desc",
|
description="test-proj-desc",
|
||||||
organization=organization
|
organization=organization,
|
||||||
|
playbook_files=['helloworld.yml', 'alt-helloworld.yml']
|
||||||
)
|
)
|
||||||
return prj
|
return prj
|
||||||
|
|
||||||
|
|||||||
@@ -10,16 +10,17 @@ from datetime import timedelta
|
|||||||
|
|
||||||
from kombu import Queue, Exchange
|
from kombu import Queue, Exchange
|
||||||
|
|
||||||
# Update this module's local settings from the global settings module.
|
# global settings
|
||||||
from django.conf import global_settings
|
from django.conf import global_settings
|
||||||
|
# ugettext lazy
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
# Update this module's local settings from the global settings module.
|
||||||
this_module = sys.modules[__name__]
|
this_module = sys.modules[__name__]
|
||||||
for setting in dir(global_settings):
|
for setting in dir(global_settings):
|
||||||
if setting == setting.upper():
|
if setting == setting.upper():
|
||||||
setattr(this_module, setting, getattr(global_settings, setting))
|
setattr(this_module, setting, getattr(global_settings, setting))
|
||||||
|
|
||||||
# gettext
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||||
|
|
||||||
@@ -805,7 +806,7 @@ LOGGING = {
|
|||||||
'()': 'django.utils.log.RequireDebugFalse',
|
'()': 'django.utils.log.RequireDebugFalse',
|
||||||
},
|
},
|
||||||
'require_debug_true': {
|
'require_debug_true': {
|
||||||
'()': 'awx.lib.compat.RequireDebugTrue',
|
'()': 'django.utils.log.RequireDebugTrue',
|
||||||
},
|
},
|
||||||
'require_debug_true_or_test': {
|
'require_debug_true_or_test': {
|
||||||
'()': 'awx.main.utils.RequireDebugTrueOrTest',
|
'()': 'awx.main.utils.RequireDebugTrueOrTest',
|
||||||
|
|||||||
@@ -25,24 +25,42 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from subprocess import PIPE, Popen, call
|
from subprocess import PIPE, Popen
|
||||||
|
from xml.etree import ElementTree as ET
|
||||||
|
from xml.etree.ElementTree import ParseError
|
||||||
|
|
||||||
import django
|
import django
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
|
|
||||||
|
|
||||||
PROJECT_CONFIG = "tools/scripts/zanata_config/backend-trans-config.xml"
|
PROJECT_CONFIG = "tools/scripts/zanata_config/backend-translations.xml"
|
||||||
MIN_TRANS_PERCENT_SETTING = False
|
MIN_TRANS_PERCENT_SETTING = False
|
||||||
MIN_TRANS_PERCENT = '10'
|
MIN_TRANS_PERCENT = '10'
|
||||||
|
|
||||||
|
|
||||||
|
def _get_zanata_project_url():
|
||||||
|
project_url = ''
|
||||||
|
try:
|
||||||
|
zanata_config = ET.parse(PROJECT_CONFIG).getroot()
|
||||||
|
server_url = zanata_config.getchildren()[0].text
|
||||||
|
project_id = zanata_config.getchildren()[1].text
|
||||||
|
version_id = zanata_config.getchildren()[2].text
|
||||||
|
middle_url = "iteration/view/" if server_url[-1:] == '/' else "/iteration/view/"
|
||||||
|
project_url = server_url + middle_url + project_id + "/" + version_id + "/documents"
|
||||||
|
except (ParseError, IndexError):
|
||||||
|
print("Please re-check zanata project configuration.")
|
||||||
|
return project_url
|
||||||
|
|
||||||
|
|
||||||
def _handle_response(output, errors):
|
def _handle_response(output, errors):
|
||||||
if not errors and '\n' in output:
|
if not errors and '\n' in output:
|
||||||
for response in output.split('\n'):
|
for response in output.split('\n'):
|
||||||
print(response)
|
print(response)
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
print(errors.strip())
|
print(errors.strip())
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _check_diff(base_path):
|
def _check_diff(base_path):
|
||||||
@@ -82,10 +100,11 @@ def push(lang=None, both=None):
|
|||||||
(1) project_type should be podir - {locale}/{filename}.po format
|
(1) project_type should be podir - {locale}/{filename}.po format
|
||||||
(2) only required languages should be kept enabled
|
(2) only required languages should be kept enabled
|
||||||
"""
|
"""
|
||||||
p = Popen("zanata push --project-config %(config)s --disable-ssl-cert" %
|
p = Popen("zanata push --project-config %(config)s --push-type source --disable-ssl-cert" %
|
||||||
{'config': PROJECT_CONFIG}, stdout=PIPE, stderr=PIPE, shell=True)
|
{'config': PROJECT_CONFIG}, stdout=PIPE, stderr=PIPE, shell=True)
|
||||||
output, errors = p.communicate()
|
output, errors = p.communicate()
|
||||||
_handle_response(output, errors)
|
if _handle_response(output, errors):
|
||||||
|
print("Zanata URL: %s\n" % _get_zanata_project_url())
|
||||||
|
|
||||||
|
|
||||||
def stats(lang=None, both=None):
|
def stats(lang=None, both=None):
|
||||||
@@ -104,7 +123,8 @@ def stats(lang=None, both=None):
|
|||||||
|
|
||||||
def update(lang=None, both=None):
|
def update(lang=None, both=None):
|
||||||
"""
|
"""
|
||||||
Update the awx/locale/django.pot files with
|
Update (1) awx/locale/django.pot and/or
|
||||||
|
(2) awx/ui/po/ansible-tower.pot files with
|
||||||
new/updated translatable strings.
|
new/updated translatable strings.
|
||||||
"""
|
"""
|
||||||
settings.configure()
|
settings.configure()
|
||||||
|
|||||||
Reference in New Issue
Block a user