forked from ReproNim/reproschema-py
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request ReproNim#10 from satra/enh-schema-support
Enh schema support
- Loading branch information
Showing
9 changed files
with
422 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -129,4 +129,4 @@ dmypy.json | |
.pyre/ | ||
|
||
# Pycharm | ||
.idea | ||
.idea/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .protocol import Protocol | ||
from .activity import Activity | ||
from .item import Item |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
from .base import SchemaBase | ||
|
||
|
||
class Activity(SchemaBase): | ||
""" | ||
class to deal with reproschema activities | ||
""" | ||
|
||
schema_type = "reproschema:Activity" | ||
|
||
def __init__(self, version=None): | ||
super().__init__(version) | ||
self.schema["ui"] = {"shuffle": [], "order": [], "addProperties": []} | ||
|
||
def set_ui_shuffle(self, shuffle=False): | ||
self.schema["ui"]["shuffle"] = shuffle | ||
|
||
def set_URI(self, URI): | ||
self.URI = URI | ||
|
||
def get_URI(self): | ||
return self.URI | ||
|
||
# TODO | ||
# preamble | ||
# compute | ||
# citation | ||
# image | ||
|
||
def set_defaults(self, name): | ||
self._ReproschemaSchema__set_defaults(name) # this looks wrong | ||
self.set_ui_shuffle(False) | ||
|
||
def update_activity(self, item_info): | ||
|
||
# TODO | ||
# - remove the hard coding on visibility and valueRequired | ||
|
||
# update the content of the activity schema with new item | ||
|
||
item_info["URI"] = "items/" + item_info["name"] | ||
|
||
append_to_activity = { | ||
"variableName": item_info["name"], | ||
"isAbout": item_info["URI"], | ||
"isVis": item_info["visibility"], | ||
"valueRequired": False, | ||
} | ||
|
||
self.schema["ui"]["order"].append(item_info["URI"]) | ||
self.schema["ui"]["addProperties"].append(append_to_activity) | ||
|
||
def sort(self): | ||
schema_order = [ | ||
"@context", | ||
"@type", | ||
"@id", | ||
"prefLabel", | ||
"description", | ||
"schemaVersion", | ||
"version", | ||
"ui", | ||
] | ||
self.sort_schema(schema_order) | ||
|
||
ui_order = ["shuffle", "order", "addProperties"] | ||
self.sort_ui(ui_order) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import json | ||
import os | ||
|
||
|
||
class SchemaBase: | ||
""" | ||
class to deal with reproschema schemas | ||
""" | ||
|
||
schema_type = None | ||
|
||
def __init__(self, version): | ||
|
||
URL = "https://raw.githubusercontent.com/ReproNim/reproschema/" | ||
VERSION = version or "1.0.0-rc2" | ||
|
||
self.schema = { | ||
"@context": URL + VERSION + "/contexts/generic", | ||
"@type": self.schema_type, | ||
"schemaVersion": VERSION, | ||
"version": "0.0.1", | ||
} | ||
|
||
def set_filename(self, name): | ||
self.schema_file = name + "_schema" | ||
self.schema["@id"] = name + "_schema" | ||
|
||
def get_name(self): | ||
return self.schema_file.replace("_schema", "") | ||
|
||
def get_filename(self): | ||
return self.schema_file | ||
|
||
def set_pref_label(self, pref_label): | ||
self.schema["prefLabel"] = pref_label | ||
|
||
def set_description(self, description): | ||
self.schema["description"] = description | ||
|
||
def set_directory(self, output_directory): | ||
self.dir = output_directory | ||
|
||
def __set_defaults(self, name): | ||
self.set_filename(name) | ||
self.set_directory(name) | ||
self.set_pref_label(name.replace("_", " ")) | ||
self.set_description(name.replace("_", " ")) | ||
|
||
def sort_schema(self, schema_order): | ||
|
||
reordered_dict = {k: self.schema[k] for k in schema_order} | ||
self.schema = reordered_dict | ||
|
||
def sort_ui(self, ui_order): | ||
|
||
reordered_dict = {k: self.schema["ui"][k] for k in ui_order} | ||
self.schema["ui"] = reordered_dict | ||
|
||
def write(self, output_dir): | ||
with open(os.path.join(output_dir, self.schema_file), "w") as ff: | ||
json.dump(self.schema, ff, sort_keys=False, indent=4) | ||
|
||
@classmethod | ||
def from_data(cls, data): | ||
if cls.schema_type is None: | ||
raise ValueError("SchemaBase cannot be used to instantiate class") | ||
if cls.schema_type != data["@type"]: | ||
raise ValueError(f"Mismatch in type {data['@type']} != {cls.schema_type}") | ||
klass = cls() | ||
klass.schema = data | ||
return klass | ||
|
||
@classmethod | ||
def from_file(cls, filepath): | ||
with open(filepath) as fp: | ||
data = json.load(fp) | ||
if "@type" not in data: | ||
raise ValueError("Missing @type key") | ||
return cls.from_data(data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
from .base import SchemaBase | ||
|
||
|
||
class Item(SchemaBase): | ||
""" | ||
class to deal with reproschema activities | ||
""" | ||
|
||
schema_type = "reproschema:Field" | ||
|
||
def __init__(self, version=None): | ||
super().__init__(version) | ||
self.schema["ui"] = {"inputType": []} | ||
self.schema["question"] = {} | ||
self.schema["responseOptions"] = {} | ||
# default input type is "char" | ||
self.set_input_type_as_char() | ||
|
||
def set_URI(self, URI): | ||
self.URI = URI | ||
|
||
# TODO | ||
# image | ||
# readonlyValue | ||
|
||
def set_defaults(self, name): | ||
self._ReproschemaSchema__set_defaults(name) # this looks wrong | ||
self.schema_file = name | ||
self.schema["@id"] = name | ||
self.set_input_type_as_char() | ||
|
||
def set_question(self, question, lang="en"): | ||
self.schema["question"][lang] = question | ||
|
||
def set_input_type(self, input_type): | ||
self.schema["ui"]["inputType"] = input_type | ||
|
||
def set_response_options(self, response_options): | ||
self.schema["responseOptions"] = response_options | ||
|
||
""" | ||
input types with different response choices | ||
""" | ||
|
||
def set_input_type_as_radio(self, response_options): | ||
self.set_input_type("radio") | ||
self.set_response_options(response_options) | ||
|
||
def set_input_type_as_select(self, response_options): | ||
self.set_input_type("select") | ||
self.set_response_options(response_options) | ||
|
||
def set_input_type_as_slider(self): | ||
self.set_input_type_as_char() # until the slide item of the ui is fixed | ||
# self.set_input_type("slider") | ||
# self.set_response_options({"valueType": "xsd:string"}) | ||
|
||
def set_input_type_as_language(self): | ||
|
||
URL = "https://raw.githubusercontent.com/ReproNim/reproschema/" | ||
|
||
self.set_input_type("selectLanguage") | ||
|
||
response_options = { | ||
"valueType": "xsd:string", | ||
"multipleChoice": True, | ||
"choices": URL + "master/resources/languages.json", | ||
} | ||
self.set_response_options(response_options) | ||
|
||
""" | ||
input types with no response choice | ||
""" | ||
|
||
def set_input_type_as_char(self): | ||
self.set_input_type("text") | ||
self.set_response_options({"valueType": "xsd:string"}) | ||
|
||
def set_input_type_as_int(self): | ||
self.set_input_type("number") | ||
self.set_response_options({"valueType": "xsd:integer"}) | ||
|
||
def set_input_type_as_float(self): | ||
self.set_input_type("float") | ||
self.set_response_options({"valueType": "xsd:float"}) | ||
|
||
def set_input_type_as_time_range(self): | ||
self.set_input_type("timeRange") | ||
self.set_response_options({"valueType": "datetime"}) | ||
|
||
def set_input_type_as_date(self): | ||
self.set_input_type("date") | ||
self.set_response_options({"valueType": "xsd:date"}) | ||
|
||
""" | ||
input types with no response choice but with some parameters | ||
""" | ||
|
||
def set_input_type_as_multitext(self, max_length=300): | ||
self.set_input_type("text") | ||
self.set_response_options({"valueType": "xsd:string", "maxLength": max_length}) | ||
|
||
# TODO | ||
# email: EmailInput/EmailInput.vue | ||
# audioCheck: AudioCheck/AudioCheck.vue | ||
# audioRecord: WebAudioRecord/Audio.vue | ||
# audioPassageRecord: WebAudioRecord/Audio.vue | ||
# audioImageRecord: WebAudioRecord/Audio.vue | ||
# audioRecordNumberTask: WebAudioRecord/Audio.vue | ||
# audioAutoRecord: AudioCheckRecord/AudioCheckRecord.vue | ||
# year: YearInput/YearInput.vue | ||
# selectCountry: SelectInput/SelectInput.vue | ||
# selectState: SelectInput/SelectInput.vue | ||
# documentUpload: DocumentUpload/DocumentUpload.vue | ||
# save: SaveData/SaveData.vue | ||
# static: Static/Static.vue | ||
# StaticReadOnly: Static/Static.vue | ||
|
||
def set_basic_response_type(self, response_type): | ||
|
||
# default (also valid for "char" input type) | ||
self.set_input_type_as_char() | ||
|
||
if response_type == "int": | ||
self.set_input_type_as_int() | ||
|
||
elif response_type == "float": | ||
self.set_input_type_as_float() | ||
|
||
elif response_type == "date": | ||
self.set_input_type_as_date() | ||
|
||
elif response_type == "time range": | ||
self.set_input_type_as_time_range() | ||
|
||
elif response_type == "language": | ||
self.set_input_type_as_language() | ||
|
||
def sort(self): | ||
schema_order = [ | ||
"@context", | ||
"@type", | ||
"@id", | ||
"prefLabel", | ||
"description", | ||
"schemaVersion", | ||
"version", | ||
"ui", | ||
"question", | ||
"responseOptions", | ||
] | ||
self.sort_schema(schema_order) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
from .base import SchemaBase | ||
|
||
|
||
class Protocol(SchemaBase): | ||
""" | ||
class to deal with reproschema protocols | ||
""" | ||
|
||
schema_type = "reproschema:Protocol" | ||
|
||
def __init__(self, version=None): | ||
super().__init__(version) | ||
self.schema["ui"] = { | ||
"allow": [], | ||
"shuffle": [], | ||
"order": [], | ||
"addProperties": [], | ||
} | ||
|
||
def set_landing_page(self, landing_page_url, lang="en"): | ||
self.schema["landingPage"] = {"@id": landing_page_url, "@language": lang} | ||
|
||
# TODO | ||
# def add_landing_page(self, landing_page_url, lang="en"): | ||
# preamble | ||
# compute | ||
|
||
def set_image(self, image_url): | ||
self.schema["image"] = image_url | ||
|
||
def set_ui_allow(self): | ||
self.schema["ui"]["allow"] = [ | ||
"reproschema:AutoAdvance", | ||
"reproschema:AllowExport", | ||
] | ||
|
||
def set_ui_shuffle(self, shuffle=False): | ||
self.schema["ui"]["shuffle"] = shuffle | ||
|
||
def set_defaults(self, name): | ||
self._ReproschemaSchema__set_defaults(name) # this looks wrong | ||
self.set_landing_page("../../README-en.md") | ||
self.set_ui_allow() | ||
self.set_ui_shuffle(False) | ||
|
||
def append_activity(self, activity): | ||
|
||
# TODO | ||
# - remove the hard coding on visibility and valueRequired | ||
|
||
# update the content of the protocol with this new activity | ||
append_to_protocol = { | ||
"variableName": activity.get_name(), | ||
"isAbout": activity.get_URI(), | ||
"prefLabel": {"en": activity.schema["prefLabel"]}, | ||
"isVis": True, | ||
"valueRequired": False, | ||
} | ||
|
||
self.schema["ui"]["order"].append(activity.URI) | ||
self.schema["ui"]["addProperties"].append(append_to_protocol) | ||
|
||
def sort(self): | ||
schema_order = [ | ||
"@context", | ||
"@type", | ||
"@id", | ||
"prefLabel", | ||
"description", | ||
"schemaVersion", | ||
"version", | ||
"landingPage", | ||
"ui", | ||
] | ||
self.sort_schema(schema_order) | ||
|
||
ui_order = ["allow", "shuffle", "order", "addProperties"] | ||
self.sort_ui(ui_order) |
Empty file.
Oops, something went wrong.