Browse Source

Merge branch 'develop' into feature/cloudUpload

pull/1779/head
Hironsan 3 years ago
parent
commit
7b9f1ac4fa
19 changed files with 442 additions and 72 deletions
  1. 2
      backend/data_export/celery_tasks.py
  2. 4
      backend/data_export/pipeline/factories.py
  3. 32
      backend/data_export/pipeline/repositories.py
  4. 2
      backend/data_export/pipeline/writers.py
  5. 375
      backend/data_export/tests/test_repositories.py
  6. 4
      backend/examples/serializers.py
  7. 35
      backend/metrics/tests.py
  8. 9
      backend/metrics/views.py
  9. 2
      tools/azure.sh
  10. 5
      tools/create-admin.sh
  11. 4
      tools/create-package.sh
  12. 2
      tools/dev-celery.sh
  13. 9
      tools/dev-django.sh
  14. 1
      tools/dev-nuxt.sh
  15. 6
      tools/heroku.sh
  16. 3
      tools/install-mssql.sh
  17. 2
      tools/prod-celery.sh
  18. 8
      tools/prod-django.sh
  19. 9
      tools/run.sh

2
backend/data_export/celery_tasks.py

@ -13,7 +13,7 @@ logger = get_task_logger(__name__)
@shared_task @shared_task
def export_dataset(project_id, file_format: str, export_approved=False): def export_dataset(project_id, file_format: str, export_approved=False):
project = get_object_or_404(Project, pk=project_id) project = get_object_or_404(Project, pk=project_id)
repository = create_repository(project)
repository = create_repository(project, file_format)
writer = create_writer(file_format)(settings.MEDIA_ROOT) writer = create_writer(file_format)(settings.MEDIA_ROOT)
service = ExportApplicationService(repository, writer) service = ExportApplicationService(repository, writer)
filepath = service.export(export_approved) filepath = service.export(export_approved)

4
backend/data_export/pipeline/factories.py

@ -11,8 +11,8 @@ from projects.models import (
) )
def create_repository(project):
if getattr(project, "use_relation", False):
def create_repository(project, file_format: str):
if getattr(project, "use_relation", False) and file_format == catalog.JSONLRelation.name:
return repositories.RelationExtractionRepository(project) return repositories.RelationExtractionRepository(project)
mapping = { mapping = {
DOCUMENT_CLASSIFICATION: repositories.TextClassificationRepository, DOCUMENT_CLASSIFICATION: repositories.TextClassificationRepository,

32
backend/data_export/pipeline/repositories.py

@ -1,7 +1,7 @@
import abc import abc
import itertools import itertools
from collections import defaultdict from collections import defaultdict
from typing import Dict, Iterator, List, Tuple, Union
from typing import Any, Dict, Iterator, List, Tuple
from .data import Record from .data import Record
from examples.models import Example from examples.models import Example
@ -10,13 +10,12 @@ from projects.models import Project
SpanType = Tuple[int, int, str] SpanType = Tuple[int, int, str]
class BaseRepository(abc.ABC):
class BaseRepository:
def __init__(self, project: Project): def __init__(self, project: Project):
self.project = project self.project = project
@abc.abstractmethod
def list(self, export_approved=False) -> Iterator[Record]: def list(self, export_approved=False) -> Iterator[Record]:
pass
raisen> <span class="ne">NotImplementedError()
class FileRepository(BaseRepository): class FileRepository(BaseRepository):
@ -54,7 +53,7 @@ class FileRepository(BaseRepository):
label_per_user[a.user.username].append(a.label.text) label_per_user[a.user.username].append(a.label.text)
return label_per_user return label_per_user
def reduce_user(self, label_per_user: Dict[str, List]):
def reduce_user(self, label_per_user: Dict[str, Any]):
value = list(itertools.chain(*label_per_user.values())) value = list(itertools.chain(*label_per_user.values()))
return {"all": value} return {"all": value}
@ -96,7 +95,7 @@ class TextRepository(BaseRepository):
def label_per_user(self, doc) -> Dict: def label_per_user(self, doc) -> Dict:
raise NotImplementedError() raise NotImplementedError()
def reduce_user(self, label_per_user: Dict[str, List]):
def reduce_user(self, label_per_user: Dict[str, Any]):
value = list(itertools.chain(*label_per_user.values())) value = list(itertools.chain(*label_per_user.values()))
return {"all": value} return {"all": value}
@ -161,6 +160,14 @@ class RelationExtractionRepository(TextRepository):
label_per_user[user]["entities"] = span label_per_user[user]["entities"] = span
return label_per_user return label_per_user
def reduce_user(self, label_per_user: Dict[str, Any]):
entities = []
relations = []
for user, label in label_per_user.items():
entities.extend(label.get("entities", []))
relations.extend(label.get("relations", []))
return {"all": {"entities": entities, "relations": relations}}
class Seq2seqRepository(TextRepository): class Seq2seqRepository(TextRepository):
@property @property
@ -184,7 +191,7 @@ class IntentDetectionSlotFillingRepository(TextRepository):
def label_per_user(self, doc) -> Dict: def label_per_user(self, doc) -> Dict:
category_per_user: Dict[str, List[str]] = defaultdict(list) category_per_user: Dict[str, List[str]] = defaultdict(list)
span_per_user: Dict[str, List[SpanType]] = defaultdict(list) span_per_user: Dict[str, List[SpanType]] = defaultdict(list)
label_per_user: Dict[str, Dict[str, Union[List[str], List[SpanType]]]] = defaultdict(dict)
label_per_user: Dict[str, Dict[str, List]] = defaultdict(dict)
for a in doc.categories.all(): for a in doc.categories.all():
category_per_user[a.user.username].append(a.label.text) category_per_user[a.user.username].append(a.label.text)
for a in doc.spans.all(): for a in doc.spans.all():
@ -193,4 +200,15 @@ class IntentDetectionSlotFillingRepository(TextRepository):
label_per_user[user]["cats"] = cats label_per_user[user]["cats"] = cats
for user, span in span_per_user.items(): for user, span in span_per_user.items():
label_per_user[user]["entities"] = span label_per_user[user]["entities"] = span
for label in label_per_user.values():
label.setdefault("cats", [])
label.setdefault("entities", [])
return label_per_user return label_per_user
def reduce_user(self, label_per_user: Dict[str, Any]):
cats = []
entities = []
for user, label in label_per_user.items():
cats.extend(label.get("cats", []))
entities.extend(label.get("entities", []))
return {"all": {"entities": entities, "cats": cats}}

2
backend/data_export/pipeline/writers.py

@ -35,7 +35,7 @@ class LineWriter(BaseWriter):
for record in records: for record in records:
filename = os.path.join(self.tmpdir, f"{record.user}.{self.extension}") filename = os.path.join(self.tmpdir, f"{record.user}.{self.extension}")
if filename not in files: if filename not in files:
f = open(filename, mode="a")
f = open(filename, mode="a", encoding="utf-8")
files[filename] = f files[filename] = f
f = files[filename] f = files[filename]
line = self.create_line(record) line = self.create_line(record)

375
backend/data_export/tests/test_repositories.py

@ -3,72 +3,341 @@ import unittest
from model_mommy import mommy from model_mommy import mommy
from ..pipeline.repositories import ( from ..pipeline.repositories import (
FileRepository,
IntentDetectionSlotFillingRepository, IntentDetectionSlotFillingRepository,
RelationExtractionRepository, RelationExtractionRepository,
Seq2seqRepository,
SequenceLabelingRepository,
Speech2TextRepository,
TextClassificationRepository,
)
from projects.models import (
DOCUMENT_CLASSIFICATION,
IMAGE_CLASSIFICATION,
INTENT_DETECTION_AND_SLOT_FILLING,
SEQ2SEQ,
SEQUENCE_LABELING,
SPEECH2TEXT,
) )
from projects.models import INTENT_DETECTION_AND_SLOT_FILLING, SEQUENCE_LABELING
from projects.tests.utils import prepare_project from projects.tests.utils import prepare_project
class TestCSVWriter(unittest.TestCase):
def setUp(self):
self.project = prepare_project(INTENT_DETECTION_AND_SLOT_FILLING)
class TestRepository(unittest.TestCase):
def assert_records(self, repository, expected):
records = list(repository.list())
self.assertEqual(len(records), len(expected))
for record, expect in zip(records, expected):
self.assertEqual(record.data, expect["data"])
self.assertEqual(record.label, expect["label"])
self.assertEqual(record.user, expect["user"])
class TestTextClassificationRepository(TestRepository):
def prepare_data(self, project):
self.example = mommy.make("Example", project=project.item, text="example")
self.category1 = mommy.make("Category", example=self.example, user=project.admin)
self.category2 = mommy.make("Category", example=self.example, user=project.annotator)
def test_list(self): def test_list(self):
example = mommy.make("Example", project=self.project.item, text="example")
category = mommy.make("Category", example=example, user=self.project.admin)
span = mommy.make("Span", example=example, user=self.project.admin, start_offset=0, end_offset=1)
repository = IntentDetectionSlotFillingRepository(self.project.item)
project = prepare_project(DOCUMENT_CLASSIFICATION)
repository = TextClassificationRepository(project.item)
self.prepare_data(project)
expected = [ expected = [
{ {
"data": example.text,
"data": self.example.text,
"label": [self.category1.label.text],
"user": project.admin.username,
},
{
"data": self.example.text,
"label": [self.category2.label.text],
"user": project.annotator.username,
},
]
self.assert_records(repository, expected)
def test_list_on_collaborative_annotation(self):
project = prepare_project(DOCUMENT_CLASSIFICATION, collaborative_annotation=True)
repository = TextClassificationRepository(project.item)
self.prepare_data(project)
expected = [
{
"data": self.example.text,
"label": [self.category1.label.text, self.category2.label.text],
"user": "all",
}
]
self.assert_records(repository, expected)
class TestSeq2seqRepository(TestRepository):
def prepare_data(self, project):
self.example = mommy.make("Example", project=project.item, text="example")
self.text1 = mommy.make("TextLabel", example=self.example, user=project.admin)
self.text2 = mommy.make("TextLabel", example=self.example, user=project.annotator)
def test_list(self):
project = prepare_project(SEQ2SEQ)
repository = Seq2seqRepository(project.item)
self.prepare_data(project)
expected = [
{
"data": self.example.text,
"label": [self.text1.text],
"user": project.admin.username,
},
{
"data": self.example.text,
"label": [self.text2.text],
"user": project.annotator.username,
},
]
self.assert_records(repository, expected)
def test_list_on_collaborative_annotation(self):
project = prepare_project(SEQ2SEQ, collaborative_annotation=True)
repository = Seq2seqRepository(project.item)
self.prepare_data(project)
expected = [
{
"data": self.example.text,
"label": [self.text1.text, self.text2.text],
"user": "all",
}
]
self.assert_records(repository, expected)
class TestIntentDetectionSlotFillingRepository(TestRepository):
def prepare_data(self, project):
self.example = mommy.make("Example", project=project.item, text="example")
self.category1 = mommy.make("Category", example=self.example, user=project.admin)
self.category2 = mommy.make("Category", example=self.example, user=project.annotator)
self.span = mommy.make("Span", example=self.example, user=project.admin, start_offset=0, end_offset=1)
def test_list(self):
project = prepare_project(INTENT_DETECTION_AND_SLOT_FILLING)
repository = IntentDetectionSlotFillingRepository(project.item)
self.prepare_data(project)
expected = [
{
"data": self.example.text,
"label": {
"cats": [self.category1.label.text],
"entities": [(self.span.start_offset, self.span.end_offset, self.span.label.text)],
},
"user": project.admin.username,
},
{
"data": self.example.text,
"label": {
"cats": [self.category2.label.text],
"entities": [],
},
"user": project.annotator.username,
},
]
self.assert_records(repository, expected)
def test_list_on_collaborative_annotation(self):
project = prepare_project(INTENT_DETECTION_AND_SLOT_FILLING, collaborative_annotation=True)
repository = IntentDetectionSlotFillingRepository(project.item)
self.prepare_data(project)
expected = [
{
"data": self.example.text,
"label": { "label": {
"cats": [category.label.text],
"entities": [(span.start_offset, span.end_offset, span.label.text)],
"cats": [self.category1.label.text, self.category2.label.text],
"entities": [(self.span.start_offset, self.span.end_offset, self.span.label.text)],
}, },
"user": "all",
} }
] ]
records = list(repository.list())
self.assertEqual(len(records), len(expected))
for record, expect in zip(records, expected):
self.assertEqual(record.data, expect["data"])
self.assertEqual(record.label["cats"], expect["label"]["cats"])
self.assertEqual(record.label["entities"], expect["label"]["entities"])
class TestRelationExtractionRepository(unittest.TestCase):
def setUp(self):
self.project = prepare_project(SEQUENCE_LABELING, use_relation=True)
def test_label_per_user(self):
from_entity = mommy.make("Span", start_offset=0, end_offset=1, user=self.project.admin)
to_entity = mommy.make(
"Span", start_offset=1, end_offset=2, example=from_entity.example, user=self.project.admin
)
relation = mommy.make(
"Relation", from_id=from_entity, to_id=to_entity, example=from_entity.example, user=self.project.admin
)
repository = RelationExtractionRepository(self.project.item)
expected = {
"admin": {
"entities": [
{
"id": from_entity.id,
"start_offset": from_entity.start_offset,
"end_offset": from_entity.end_offset,
"label": from_entity.label.text,
},
{
"id": to_entity.id,
"start_offset": to_entity.start_offset,
"end_offset": to_entity.end_offset,
"label": to_entity.label.text,
},
],
"relations": [
{"id": relation.id, "from_id": from_entity.id, "to_id": to_entity.id, "type": relation.type.text}
self.assert_records(repository, expected)
class TestSequenceLabelingRepository(TestRepository):
def prepare_data(self, project):
self.example = mommy.make("Example", project=project.item, text="example")
self.span1 = mommy.make("Span", example=self.example, user=project.admin, start_offset=0, end_offset=1)
self.span2 = mommy.make("Span", example=self.example, user=project.annotator, start_offset=1, end_offset=2)
def test_list(self):
project = prepare_project(SEQUENCE_LABELING)
repository = SequenceLabelingRepository(project.item)
self.prepare_data(project)
expected = [
{
"data": self.example.text,
"label": [(self.span1.start_offset, self.span1.end_offset, self.span1.label.text)],
"user": project.admin.username,
},
{
"data": self.example.text,
"label": [(self.span2.start_offset, self.span2.end_offset, self.span2.label.text)],
"user": project.annotator.username,
},
]
self.assert_records(repository, expected)
def test_list_on_collaborative_annotation(self):
project = prepare_project(SEQUENCE_LABELING, collaborative_annotation=True)
repository = SequenceLabelingRepository(project.item)
self.prepare_data(project)
expected = [
{
"data": self.example.text,
"label": [
(self.span1.start_offset, self.span1.end_offset, self.span1.label.text),
(self.span2.start_offset, self.span2.end_offset, self.span2.label.text),
], ],
"user": "all",
}
]
self.assert_records(repository, expected)
class TestRelationExtractionRepository(TestRepository):
def test_list(self):
project = prepare_project(SEQUENCE_LABELING, use_relation=True)
example = mommy.make("Example", project=project.item, text="example")
span1 = mommy.make("Span", example=example, user=project.admin, start_offset=0, end_offset=1)
span2 = mommy.make("Span", example=example, user=project.admin, start_offset=1, end_offset=2)
relation = mommy.make("Relation", from_id=span1, to_id=span2, example=example, user=project.admin)
repository = RelationExtractionRepository(project.item)
expected = [
{
"data": example.text,
"label": {
"entities": [
{
"id": span1.id,
"start_offset": span1.start_offset,
"end_offset": span1.end_offset,
"label": span1.label.text,
},
{
"id": span2.id,
"start_offset": span2.start_offset,
"end_offset": span2.end_offset,
"label": span2.label.text,
},
],
"relations": [
{"id": relation.id, "from_id": span1.id, "to_id": span2.id, "type": relation.type.text}
],
},
"user": project.admin.username,
}
]
self.assert_records(repository, expected)
def test_list_on_collaborative_annotation(self):
project = prepare_project(SEQUENCE_LABELING, collaborative_annotation=True, use_relation=True)
example = mommy.make("Example", project=project.item, text="example")
span1 = mommy.make("Span", example=example, user=project.admin, start_offset=0, end_offset=1)
span2 = mommy.make("Span", example=example, user=project.annotator, start_offset=1, end_offset=2)
relation = mommy.make("Relation", from_id=span1, to_id=span2, example=example, user=project.admin)
repository = RelationExtractionRepository(project.item)
expected = [
{
"data": example.text,
"label": {
"entities": [
{
"id": span1.id,
"start_offset": span1.start_offset,
"end_offset": span1.end_offset,
"label": span1.label.text,
},
{
"id": span2.id,
"start_offset": span2.start_offset,
"end_offset": span2.end_offset,
"label": span2.label.text,
},
],
"relations": [
{"id": relation.id, "from_id": span1.id, "to_id": span2.id, "type": relation.type.text}
],
},
"user": "all",
}
]
self.assert_records(repository, expected)
class TestSpeech2TextRepository(TestRepository):
def prepare_data(self, project):
self.example = mommy.make("Example", project=project.item, text="example")
self.text1 = mommy.make("TextLabel", example=self.example, user=project.admin)
self.text2 = mommy.make("TextLabel", example=self.example, user=project.annotator)
def test_list(self):
project = prepare_project(SPEECH2TEXT)
repository = Speech2TextRepository(project.item)
self.prepare_data(project)
expected = [
{
"data": self.example.filename,
"label": [self.text1.text],
"user": project.admin.username,
},
{
"data": self.example.filename,
"label": [self.text2.text],
"user": project.annotator.username,
},
]
self.assert_records(repository, expected)
def test_list_on_collaborative_annotation(self):
project = prepare_project(SPEECH2TEXT, collaborative_annotation=True)
repository = Speech2TextRepository(project.item)
self.prepare_data(project)
expected = [
{
"data": self.example.filename,
"label": [self.text1.text, self.text2.text],
"user": "all",
}
]
self.assert_records(repository, expected)
class TestFileRepository(TestRepository):
def prepare_data(self, project):
self.example = mommy.make("Example", project=project.item, text="example")
self.category1 = mommy.make("Category", example=self.example, user=project.admin)
self.category2 = mommy.make("Category", example=self.example, user=project.annotator)
def test_list(self):
project = prepare_project(IMAGE_CLASSIFICATION)
repository = FileRepository(project.item)
self.prepare_data(project)
expected = [
{
"data": self.example.filename,
"label": [self.category1.label.text],
"user": project.admin.username,
},
{
"data": self.example.filename,
"label": [self.category2.label.text],
"user": project.annotator.username,
},
]
self.assert_records(repository, expected)
def test_list_on_collaborative_annotation(self):
project = prepare_project(IMAGE_CLASSIFICATION, collaborative_annotation=True)
repository = FileRepository(project.item)
self.prepare_data(project)
expected = [
{
"data": self.example.filename,
"label": [self.category1.label.text, self.category2.label.text],
"user": "all",
} }
}
actual = repository.label_per_user(from_entity.example)
self.assertDictEqual(actual, expected)
]
self.assert_records(repository, expected)

4
backend/examples/serializers.py

@ -43,5 +43,5 @@ class ExampleSerializer(serializers.ModelSerializer):
class ExampleStateSerializer(serializers.ModelSerializer): class ExampleStateSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = ExampleState model = ExampleState
fields = ("id", "example", "confirmed_by")
read_only_fields = ("id", "example", "confirmed_by")
fields = ("id", "example", "confirmed_by", "confirmed_at")
read_only_fields = ("id", "example", "confirmed_by", "confirmed_at")

35
backend/metrics/tests.py

@ -28,6 +28,41 @@ class TestMemberProgress(CRUDMixin):
self.assertEqual(response.data, {"total": 1, "progress": expected_progress}) self.assertEqual(response.data, {"total": 1, "progress": expected_progress})
class TestProgressHelper(CRUDMixin):
collaborative_annotation = False
def setUp(self):
self.project = prepare_project(DOCUMENT_CLASSIFICATION, collaborative_annotation=self.collaborative_annotation)
self.example = make_doc(self.project.item)
mommy.make("ExampleState", example=self.example, confirmed_by=self.project.admin)
self.url = reverse(viewname="progress", args=[self.project.item.id])
class TestProgress(TestProgressHelper):
collaborative_annotation = False
def test_fetch_progress(self):
response = self.assert_fetch(self.project.admin, status.HTTP_200_OK)
expected = {"total": 1, "remaining": 0, "complete": 1}
self.assertEqual(response.data, expected)
def test_cannot_affect_others_progress(self):
for member in self.project.staffs:
response = self.assert_fetch(member, status.HTTP_200_OK)
expected = {"total": 1, "remaining": 1, "complete": 0}
self.assertEqual(response.data, expected)
class TestProgressOnCollaborativeAnnotation(TestProgressHelper):
collaborative_annotation = True
def test_fetch_progress(self):
for member in self.project.members:
response = self.assert_fetch(member, status.HTTP_200_OK)
expected = {"total": 1, "remaining": 0, "complete": 1}
self.assertEqual(response.data, expected)
class TestCategoryDistribution(CRUDMixin): class TestCategoryDistribution(CRUDMixin):
def setUp(self): def setUp(self):
self.project = prepare_project(DOCUMENT_CLASSIFICATION) self.project = prepare_project(DOCUMENT_CLASSIFICATION)

9
backend/metrics/views.py

@ -1,5 +1,6 @@
import abc import abc
from django.shortcuts import get_object_or_404
from rest_framework import status from rest_framework import status
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response from rest_framework.response import Response
@ -8,7 +9,7 @@ from rest_framework.views import APIView
from examples.models import Example, ExampleState from examples.models import Example, ExampleState
from label_types.models import CategoryType, LabelType, RelationType, SpanType from label_types.models import CategoryType, LabelType, RelationType, SpanType
from labels.models import Category, Label, Relation, Span from labels.models import Category, Label, Relation, Span
from projects.models import Member
from projects.models import Member, Project
from projects.permissions import IsProjectAdmin, IsProjectStaffAndReadOnly from projects.permissions import IsProjectAdmin, IsProjectStaffAndReadOnly
@ -18,7 +19,11 @@ class ProgressAPI(APIView):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
examples = Example.objects.filter(project=self.kwargs["project_id"]).values("id") examples = Example.objects.filter(project=self.kwargs["project_id"]).values("id")
total = examples.count() total = examples.count()
complete = ExampleState.objects.count_done(examples, user=self.request.user)
project = get_object_or_404(Project, pk=self.kwargs["project_id"])
if project.collaborative_annotation:
complete = ExampleState.objects.count_done(examples)
else:
complete = ExampleState.objects.count_done(examples, user=self.request.user)
data = {"total": total, "remaining": total - complete, "complete": complete} data = {"total": total, "remaining": total - complete, "complete": complete}
return Response(data=data, status=status.HTTP_200_OK) return Response(data=data, status=status.HTTP_200_OK)

2
tools/azure.sh

@ -11,6 +11,8 @@ if [[ -z "${DOCCANO_ADMIN_CONTACT_EMAIL}" ]]; then echo "Missing DOCCANO_ADMIN_C
if [[ -z "${DOCCANO_ADMIN_PASSWORD}" ]]; then echo "Missing DOCCANO_ADMIN_PASSWORD environment variable" >&2; exit 1; fi if [[ -z "${DOCCANO_ADMIN_PASSWORD}" ]]; then echo "Missing DOCCANO_ADMIN_PASSWORD environment variable" >&2; exit 1; fi
if ! az account show >/dev/null; then echo "Must be logged into Azure" >&2; exit 2; fi if ! az account show >/dev/null; then echo "Must be logged into Azure" >&2; exit 2; fi
set -o nounset
az group create \ az group create \
--location "${DOCCANO_LOCATION}" \ --location "${DOCCANO_LOCATION}" \
--name "${DOCCANO_RESOURCE_GROUP}" --name "${DOCCANO_RESOURCE_GROUP}"

5
tools/create-admin.sh

@ -1,8 +1,9 @@
#!/usr/bin/env bash #!/usr/bin/env bash
if [[ "$#" -ne 3 ]]; then echo "Usage: $0 <username> <email> <password>" >&2; exit 1; fi
set -o errexit set -o errexit
set -o nounset
if [[ "$#" -ne 3 ]]; then echo "Usage: $0 <username> <email> <password>" >&2; exit 1; fi
python app/manage.py wait_for_db python app/manage.py wait_for_db
python app/manage.py migrate python app/manage.py migrate

4
tools/create-package.sh

@ -1,4 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -o errexit
set -o nounset
mkdir -p backend/client mkdir -p backend/client
cd frontend cd frontend

2
tools/dev-celery.sh

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -o errexit set -o errexit
set -o nounset
cd "/src/backend" cd "/src/backend"

9
tools/dev-django.sh

@ -1,6 +1,13 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -o errexit set -o errexit
if [[ -z "${ADMIN_USERNAME}" ]]; then echo "Missing ADMIN_USERNAME environment variable" >&2; exit 1; fi
if [[ -z "${ADMIN_PASSWORD}" ]]; then echo "Missing ADMIN_PASSWORD environment variable" >&2; exit 1; fi
if [[ -z "${ADMIN_EMAIL}" ]]; then echo "Missing ADMIN_EMAIL environment variable" >&2; exit 1; fi
set -o nounset
app="/src/backend" app="/src/backend"
echo "Initializing database" echo "Initializing database"
@ -18,4 +25,4 @@ if [[ -n "${ADMIN_USERNAME}" ]] && [[ -n "${ADMIN_PASSWORD}" ]] && [[ -n "${ADMI
fi fi
echo "Starting django" echo "Starting django"
python -u "${app}/manage.py" runserver 0.0.0.0:8000
python -u "${app}/manage.py" runserver ${HOST:-0.0.0.0}:${PORT:-8000}

1
tools/dev-nuxt.sh

@ -1,6 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -o errexit set -o errexit
set -o nounset
root="$(dirname "$0")/.." root="$(dirname "$0")/.."
app="${root}/frontend" app="${root}/frontend"

6
tools/heroku.sh

@ -2,6 +2,12 @@
set -o errexit set -o errexit
if [[ -z "${ADMIN_USER_NAME}" ]]; then echo "Missing ADMIN_USER_NAME environment variable" >&2; exit 1; fi
if [[ -z "${ADMIN_PASSWORD}" ]]; then echo "Missing ADMIN_PASSWORD environment variable" >&2; exit 1; fi
if [[ -z "${ADMIN_CONTACT_EMAIL}" ]]; then echo "Missing ADMIN_CONTACT_EMAIL environment variable" >&2; exit 1; fi
set -o nounset
python /doccano/backend/manage.py migrate python /doccano/backend/manage.py migrate
if [ -n "$ADMIN_USER_NAME" ]; then if [ -n "$ADMIN_USER_NAME" ]; then
python /doccano/backend/manage.py create_admin --noinput --username="$ADMIN_USER_NAME" --email="$ADMIN_CONTACT_EMAIL" --password="$ADMIN_PASSWORD" python /doccano/backend/manage.py create_admin --noinput --username="$ADMIN_USER_NAME" --email="$ADMIN_CONTACT_EMAIL" --password="$ADMIN_PASSWORD"

3
tools/install-mssql.sh

@ -1,5 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -o errexit
set -o nounset
# parse arguments # parse arguments
mode="prod" mode="prod"
for opt in "$@"; do for opt in "$@"; do

2
tools/prod-celery.sh

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -o errexit set -o errexit
set -o nounset
cd /backend cd /backend

8
tools/prod-django.sh

@ -2,6 +2,12 @@
set -o errexit set -o errexit
if [[ -z "${ADMIN_USERNAME}" ]]; then echo "Missing ADMIN_USERNAME environment variable" >&2; exit 1; fi
if [[ -z "${ADMIN_PASSWORD}" ]]; then echo "Missing ADMIN_PASSWORD environment variable" >&2; exit 1; fi
if [[ -z "${ADMIN_EMAIL}" ]]; then echo "Missing ADMIN_EMAIL environment variable" >&2; exit 1; fi
set -o nounset
echo "Making staticfiles" echo "Making staticfiles"
static_dir=staticfiles static_dir=staticfiles
if [[ ! -d $static_dir ]] || [[ -z $(ls -A $static_dir) ]]; then if [[ ! -d $static_dir ]] || [[ -z $(ls -A $static_dir) ]]; then
@ -25,4 +31,4 @@ if [[ -n "${ADMIN_USERNAME}" ]] && [[ -n "${ADMIN_PASSWORD}" ]] && [[ -n "${ADMI
fi fi
echo "Starting django" echo "Starting django"
gunicorn --bind="0.0.0.0:${PORT:-8000}" --workers="${WORKERS:-4}" config.wsgi --timeout 300
gunicorn --bind="${HOST:-0.0.0.0}:${PORT:-8000}" --workers="${WORKERS:-4}" config.wsgi --timeout 300

9
tools/run.sh

@ -2,6 +2,15 @@
set -o errexit set -o errexit
if [[ -z "${ADMIN_USERNAME}" ]]; then echo "Missing ADMIN_USERNAME environment variable" >&2; exit 1; fi
if [[ -z "${ADMIN_PASSWORD}" ]]; then echo "Missing ADMIN_PASSWORD environment variable" >&2; exit 1; fi
if [[ -z "${ADMIN_EMAIL}" ]]; then echo "Missing ADMIN_EMAIL environment variable" >&2; exit 1; fi
if [[ -z "${PORT}" ]]; then echo "Missing PORT environment variable" >&2; exit 1; fi
if [[ -z "${WORKERS}" ]]; then echo "Missing WORKERS environment variable" >&2; exit 1; fi
if [[ -z "${CELERY_WORKERS}" ]]; then echo "Missing CELERY_WORKERS environment variable" >&2; exit 1; fi
set -o nounset
echo "Making staticfiles" echo "Making staticfiles"
static_dir=staticfiles static_dir=staticfiles
mkdir -p client/dist/static mkdir -p client/dist/static

Loading…
Cancel
Save