Skip to content

Commit

Permalink
move request type to global and allow for multi choices in ilmc (#18)
Browse files Browse the repository at this point in the history
* move request type to global and allow for multi choices in ilmc

* small fixes

* more reasonable defaults

* fix lint too

* trickiness

* add yeah we have an image involved
  • Loading branch information
gaieges authored Jun 19, 2019
1 parent b659498 commit 3534080
Show file tree
Hide file tree
Showing 9 changed files with 422 additions and 222 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ ENV LANG C.UTF-8

COPY Pipfile Pipfile.lock /work/
RUN pip3 install pipenv
RUN pipenv install --system --deploy
RUN pipenv install --system --deploy --dev

COPY test.py /work/
COPY yapf.cfg test.py /work/
COPY basemodels /work/basemodels/
COPY bin /work/bin/

Expand Down
4 changes: 2 additions & 2 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]
yapf = "==0.25.0"
mypy = "==0.670"

[packages]
yapf = "*"
schematics = "*"
mypy = "*"

[requires]
python_version = "3.6"
Expand Down
69 changes: 35 additions & 34 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Versioning should follow the [semver](https://semver.org/) versioning methodolog
In root folder
- `virtualenv -p python3 venv`
- `source venv/bin/activate`
- `pipenv install`
- `pipenv install --dev`
- `pip install twine`
- `python3 setup.py sdist bdist_wheel`
- `twine upload dist/*`
Expand Down
118 changes: 51 additions & 67 deletions basemodels/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,41 @@
from schematics.types import StringType, DecimalType, BooleanType, IntType, DictType, ListType, URLType, FloatType, \
UUIDType, ModelType, BooleanType, UnionType


BASE_JOB_TYPES = [
"image_label_binary",
"image_label_multiple_choice",
"image_label_multiple_choice_one_option", # historical
"image_label_multiple_choice_multiple_options", # historical
"text_free_entry",
"text_multiple_choice_one_option",
"text_multiple_choice_multiple_options",
"image_label_area_adjust",
"image_label_area_select",
"image_label_area_select_one_option", # legacy
"image_label_area_select_multiple_options", # legacy
"image_label_single_polygon",
"image_label_multiple_polygons",
"image_label_semantic_segmentation_one_option",
"image_label_semantic_segmentation_multiple_options",
"image_label_text",
]
"image_label_binary",
"image_label_multiple_choice",
"text_free_entry",
"text_multiple_choice_one_option",
"text_multiple_choice_multiple_options",
"image_label_area_adjust",
"image_label_area_select",
"image_label_single_polygon",
"image_label_multiple_polygons",
"image_label_semantic_segmentation_one_option",
"image_label_semantic_segmentation_multiple_options",
"image_label_text",
]


def validate_request_type(self, data, value):
"""
validate request types for all types of challenges
multi_challenge should always have multi_challenge_manifests
"""
# validation runs before other params, so need to handle missing case
if not data.get('request_type'):
raise ValidationError("request_type missing")

if data.get('request_type') == 'multi_challenge':
if not data.get('multi_challenge_manifests'):
raise ValidationError("multi_challenge requires multi_challenge_manifests.")
elif data.get('request_type') in ['image_label_multiple_choice', 'image_label_area_select']:
if data.get('multiple_choice_min_choices', 1) > data.get('multiple_choice_max_choices', 1):
raise ValidationError(
"multiple_choice_min_choices cannot be greater than multiple_choice_max_choices")

return value


class TaskData(Model):
""" objects within taskdata list in Manifest """
Expand All @@ -33,22 +49,15 @@ class TaskData(Model):
class RequestConfig(Model):
""" definition of the request_config object in manifest """
version = IntType(default=0)
shape_type = StringType(
choices=["point", "bounding_box", "polygon"])
shape_type = StringType(choices=["point", "bounding_box", "polygon"])
min_points = IntType()
max_points = IntType()
min_shapes_per_image = IntType()
max_shapes_per_image = IntType()
restrict_to_coords = BooleanType()
minimum_selection_area_per_shape = IntType()
multiple_choice_max_choices = IntType()

def validate_shape_type(self, data, value):
"""shape_type should exist if not multiple_choice"""
if not data.get('shape_type') and not data.get('multiple_choice_max_choices'):
raise ValidationError("shape_type multiple_choice_max_choices required.")
return value

multiple_choice_max_choices = IntType(default=1)
multiple_choice_min_choices = IntType(default=1)


class NestedManifest(Model):
Expand Down Expand Up @@ -82,17 +91,14 @@ def validate_requester_question_example(self, data, value):
if not data.get('request_type'):
raise ValidationError("request_type missing")

if data['request_type'] != 'image_label_binary' and isinstance(
value, list):
raise ValidationError(
"Lists are not allowed in this challenge type")
if data['request_type'] != 'image_label_binary' and isinstance(value, list):
raise ValidationError("Lists are not allowed in this challenge type")
return value

unsafe_content = BooleanType(default=False)
requester_accuracy_target = FloatType(default=.1)
request_type = StringType(
required=True,
choices=BASE_JOB_TYPES)
request_type = StringType(required=True, choices=BASE_JOB_TYPES)
validate_request_type = validate_request_type

request_config = ModelType(RequestConfig, required=False)

Expand All @@ -102,19 +108,16 @@ def validate_requester_question_example(self, data, value):

def validate_groundtruth(self, data, value):
if data.get('groundtruth_uri') and data.get('groundtruth'):
raise ValidationError(
"Specify only groundtruth_uri or groundtruth, not both.")
raise ValidationError("Specify only groundtruth_uri or groundtruth, not both.")
return value

# Configuration id
confcalc_configuration_id = StringType(required=False)



class Manifest(Model):
""" The manifest description. """
job_mode = StringType(
required=True, choices=["batch", "online", "instant_delivery"])
job_mode = StringType(required=True, choices=["batch", "online", "instant_delivery"])
job_api_key = UUIDType(default=uuid.uuid4)
job_id = UUIDType(default=uuid.uuid4)
job_total_tasks = IntType()
Expand Down Expand Up @@ -145,10 +148,8 @@ def validate_requester_question_example(self, data, value):
if not data.get('request_type'):
raise ValidationError("request_type missing")

if data['request_type'] != 'image_label_binary' and isinstance(
value, list):
raise ValidationError(
"Lists are not allowed in this challenge type")
if data['request_type'] != 'image_label_binary' and isinstance(value, list):
raise ValidationError("Lists are not allowed in this challenge type")
return value

unsafe_content = BooleanType(default=False)
Expand All @@ -172,22 +173,8 @@ def validate_requester_question_example(self, data, value):

multi_challenge_manifests = ListType(ModelType(NestedManifest), required=False)

request_type = StringType(
required=True,
choices=BASE_JOB_TYPES + ["multi_challenge"])


def validate_request_type(self, data, value):
"""multi_challenge should always have multi_challenge_manifests"""
# validation runs before other params, so need to handle missing case
if not data.get('request_type'):
raise ValidationError("request_type missing")

if data['request_type'] == 'multi_challenge':
if not data.get('multi_challenge_manifests'):
raise ValidationError(
"multi_challenge requires multi_challenge_manifests.")
return value
request_type = StringType(required=True, choices=BASE_JOB_TYPES + ["multi_challenge"])
validate_request_type = validate_request_type

request_config = ModelType(RequestConfig, required=False)

Expand All @@ -203,8 +190,7 @@ def validate_request_type(self, data, value):

def validate_groundtruth(self, data, value):
if data.get('groundtruth_uri') and data.get('groundtruth'):
raise ValidationError(
"Specify only groundtruth_uri or groundtruth, not both.")
raise ValidationError("Specify only groundtruth_uri or groundtruth, not both.")
return value

# Configuration id
Expand All @@ -213,11 +199,9 @@ def validate_groundtruth(self, data, value):
restricted_audience = DictType(ListType(DictType(DictType(FloatType))))

def validate_taskdata_uri(self, data, value):
if data.get('taskdata') and len(
data.get('taskdata')) > 0 and data.get('taskdata_uri'):
raise ValidationError(
u'Specify only one of taskdata {} or taskdata_uri {}'.format(
data.get('taskdata'), data.get('taskdata_uri')))
if data.get('taskdata') and len(data.get('taskdata')) > 0 and data.get('taskdata_uri'):
raise ValidationError(u'Specify only one of taskdata {} or taskdata_uri {}'.format(
data.get('taskdata'), data.get('taskdata_uri')))
return value

validate_taskdata = validate_taskdata_uri
10 changes: 5 additions & 5 deletions bin/lint
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
set -exu

FILES="*.py basemodels/*.py"
if [ -z ${CI+x} ]
then
yapf --i $FILES

if [ -z ${CI+x} ]; then
yapf -i --style yapf.cfg $FILES
mypy $FILES --ignore-missing-imports
else
yapf --diff $FILES
mypy $FILES --ignore-missing-imports
yapf --diff --style yapf.cfg $FILES
mypy $FILES --ignore-missing-imports
fi
11 changes: 5 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@

setuptools.setup(
name="hmt-basemodels",
version="0.0.8",
version="0.0.9",
author="HUMAN Protocol",
description=
"Common data models shared by various components of the Human Protocol stack",
description="Common data models shared by various components of the Human Protocol stack",
url="https://github.com/hCaptcha/hmt-basemodels",
include_package_data=True,
zip_safe=True,
classifiers=[
"Intended Audience :: Developers",
"Operating System :: OS Independent", "Programming Language :: Python"
"Intended Audience :: Developers", "Operating System :: OS Independent",
"Programming Language :: Python"
],
packages=setuptools.find_packages(),
install_requires=["schematics==2.1.0", "yapf==0.25.0", "mypy==0.670"])
install_requires=["schematics>=2.1.0"])
Loading

0 comments on commit 3534080

Please sign in to comment.