diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml
index 89f512c..27505fd 100644
--- a/.zuul.d/jobs.yaml
+++ b/.zuul.d/jobs.yaml
@@ -9,3 +9,10 @@
parent: tox
vars:
tox_envlist: py3
+
+- job:
+ name: tox-format
+ parent: tox
+ nodeset: ubuntu-bionic
+ vars:
+ tox_envlist: format
diff --git a/.zuul.d/project.yaml b/.zuul.d/project.yaml
index d0a6430..773c38f 100644
--- a/.zuul.d/project.yaml
+++ b/.zuul.d/project.yaml
@@ -7,9 +7,12 @@
jobs:
- ara-server-ansible-integration:
voting: false
+ - tox-format
- tox-py3
- tox-pep8
gate:
jobs:
+ - tox-format
- tox-py3
- tox-pep8
+
diff --git a/ara/api/admin.py b/ara/api/admin.py
index a359b9c..8705336 100644
--- a/ara/api/admin.py
+++ b/ara/api/admin.py
@@ -1,7 +1,8 @@
-from ara.api import models
from django.contrib import admin
from django.contrib.auth.models import Group
+from ara.api import models
+
class RecordAdmin(admin.ModelAdmin):
list_display = ("id", "key", "value", "type")
diff --git a/ara/api/migrations/0001_initial.py b/ara/api/migrations/0001_initial.py
index d10d813..81088a7 100644
--- a/ara/api/migrations/0001_initial.py
+++ b/ara/api/migrations/0001_initial.py
@@ -1,8 +1,8 @@
# Generated by Django 2.1.1 on 2018-09-07 17:53
-from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
+from django.db import migrations, models
class Migration(migrations.Migration):
diff --git a/ara/api/serializers.py b/ara/api/serializers.py
index a0855f5..46bbd54 100644
--- a/ara/api/serializers.py
+++ b/ara/api/serializers.py
@@ -15,14 +15,16 @@
# You should have received a copy of the GNU General Public License
# along with ARA. If not, see .
-import json
import hashlib
+import json
import logging
import zlib
-from ara.api import models
+
from django.utils import timezone
from rest_framework import serializers
+from ara.api import models
+
DATE_FORMAT = "(iso-8601: 2016-05-06T17:20:25.749489-04:00)"
DURATION_FORMAT = "([DD] [HH:[MM:]]ss[.uuuuuu])"
logger = logging.getLogger("ara.api.serializers")
diff --git a/ara/api/tests/factories.py b/ara/api/tests/factories.py
index 083dfa5..d5374df 100644
--- a/ara/api/tests/factories.py
+++ b/ara/api/tests/factories.py
@@ -20,7 +20,6 @@ import factory
from ara.api import models
from ara.api.tests import utils
-
# constants for things like compressed byte strings or objects
FILE_CONTENTS = "---\n# Example file"
HOST_FACTS = {"ansible_fqdn": "hostname", "ansible_distribution": "CentOS"}
diff --git a/ara/api/tests/tests_file.py b/ara/api/tests/tests_file.py
index ec783ca..ff598e4 100644
--- a/ara/api/tests/tests_file.py
+++ b/ara/api/tests/tests_file.py
@@ -18,8 +18,7 @@
from rest_framework.test import APITestCase
from ara.api import models, serializers
-from ara.api.tests import factories
-from ara.api.tests import utils
+from ara.api.tests import factories, utils
class FileTestCase(APITestCase):
diff --git a/ara/api/tests/tests_host.py b/ara/api/tests/tests_host.py
index d39c22f..87704d7 100644
--- a/ara/api/tests/tests_host.py
+++ b/ara/api/tests/tests_host.py
@@ -18,8 +18,7 @@
from rest_framework.test import APITestCase
from ara.api import models, serializers
-from ara.api.tests import factories
-from ara.api.tests import utils
+from ara.api.tests import factories, utils
class HostTestCase(APITestCase):
diff --git a/ara/api/tests/tests_label.py b/ara/api/tests/tests_label.py
index 5986217..1fba362 100644
--- a/ara/api/tests/tests_label.py
+++ b/ara/api/tests/tests_label.py
@@ -18,8 +18,7 @@
from rest_framework.test import APITestCase
from ara.api import models, serializers
-from ara.api.tests import factories
-from ara.api.tests import utils
+from ara.api.tests import factories, utils
class LabelTestCase(APITestCase):
diff --git a/ara/api/tests/tests_play.py b/ara/api/tests/tests_play.py
index 9d6a006..a7bec6f 100644
--- a/ara/api/tests/tests_play.py
+++ b/ara/api/tests/tests_play.py
@@ -16,6 +16,7 @@
# along with ARA. If not, see .
import datetime
+
from django.utils import timezone
from rest_framework.test import APITestCase
diff --git a/ara/api/tests/tests_playbook.py b/ara/api/tests/tests_playbook.py
index 26e4bff..adade71 100644
--- a/ara/api/tests/tests_playbook.py
+++ b/ara/api/tests/tests_playbook.py
@@ -16,12 +16,12 @@
# along with ARA. If not, see .
import datetime
+
from django.utils import timezone
from rest_framework.test import APITestCase
from ara.api import models, serializers
-from ara.api.tests import factories
-from ara.api.tests import utils
+from ara.api.tests import factories, utils
class PlaybookTestCase(APITestCase):
diff --git a/ara/api/tests/tests_result.py b/ara/api/tests/tests_result.py
index 82cb68b..320411c 100644
--- a/ara/api/tests/tests_result.py
+++ b/ara/api/tests/tests_result.py
@@ -18,8 +18,7 @@
from rest_framework.test import APITestCase
from ara.api import models, serializers
-from ara.api.tests import factories
-from ara.api.tests import utils
+from ara.api.tests import factories, utils
class ResultTestCase(APITestCase):
diff --git a/ara/api/tests/tests_task.py b/ara/api/tests/tests_task.py
index 87eb960..cc8f8fc 100644
--- a/ara/api/tests/tests_task.py
+++ b/ara/api/tests/tests_task.py
@@ -16,12 +16,12 @@
# along with ARA. If not, see .
import datetime
+
from django.utils import timezone
from rest_framework.test import APITestCase
from ara.api import models, serializers
-from ara.api.tests import factories
-from ara.api.tests import utils
+from ara.api.tests import factories, utils
class TaskTestCase(APITestCase):
diff --git a/ara/api/urls.py b/ara/api/urls.py
index 646a52e..67371ef 100644
--- a/ara/api/urls.py
+++ b/ara/api/urls.py
@@ -16,6 +16,7 @@
# along with ARA. If not, see .
from rest_framework_extensions.routers import ExtendedDefaultRouter
+
from ara.api import views
router = ExtendedDefaultRouter(trailing_slash=False)
diff --git a/ara/server/settings.py b/ara/server/settings.py
index 297bed5..ce23f3f 100644
--- a/ara/server/settings.py
+++ b/ara/server/settings.py
@@ -1,8 +1,9 @@
import logging
import os
import sys
-from envparse import env
+
from django.utils.crypto import get_random_string
+from envparse import env
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
diff --git a/ara/server/urls.py b/ara/server/urls.py
index 7bfc451..02dbb2b 100644
--- a/ara/server/urls.py
+++ b/ara/server/urls.py
@@ -1,5 +1,4 @@
-from django.urls import include, path
from django.contrib import admin
-
+from django.urls import include, path
urlpatterns = [path("api/v1/", include("ara.api.urls")), path("admin/", admin.site.urls)]
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..0a71b18
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,3 @@
+[tool.black]
+line-length = 120
+exclude = '(migrations|ara/server/settings.py)'
diff --git a/setup.cfg b/setup.cfg
index d376214..92ba992 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -56,3 +56,25 @@ universal = 1
[pbr]
skip_authors = True
skip_changelog = True
+
+[flake8]
+# E123, E125 skipped as they are invalid PEP-8.
+# E741, short ambiguous variable names
+# H106 Don’t put vim configuration in source files
+# H203 Use assertIs(Not)None to check for None
+max-line-length = 120
+ignore = E123,E125,E741
+enable-extensions=H106,H203
+show-source = True
+exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,ara/api/migrations
+
+[isort]
+known_first_party = ara
+default_section = THIRDPARTY
+skip = build,.git,.tox,.cache,.venv
+not_skip = __init__.py
+multi_line_output=3
+include_trailing_comma=True
+force_grid_wrap=0
+combine_as_imports=True
+line_length=88
diff --git a/test-requirements.txt b/test-requirements.txt
index 9f82842..996d1f6 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -4,3 +4,5 @@ coverage
flake8
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2
sphinx-rtd-theme
+black==18.9b0 ; python_version >= '3.6' # Exact version for prerelease
+isort
diff --git a/tox.ini b/tox.ini
index 95bff38..de8dea0 100644
--- a/tox.ini
+++ b/tox.ini
@@ -58,13 +58,7 @@ commands =
coverage run -a {toxinidir}/manage.py test ara/api
coverage html
-[flake8]
-# E123, E125 skipped as they are invalid PEP-8.
-# E741, short ambiguous variable names
-# H106 Don’t put vim configuration in source files
-# H203 Use assertIs(Not)None to check for None
-max-line-length = 120
-ignore = E123,E125,E741
-enable-extensions=H106,H203
-show-source = True
-exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,ara/api/migrations
+[testenv:format]
+commands =
+ black --diff --check ara
+ isort --recursive --check-only --diff --virtual-env {envdir} ara