Skip to content

Commit

Permalink
Discover collections in doc_maker.py (#41)
Browse files Browse the repository at this point in the history
* remove hardcoding of Collection keyword

Remove hardcoding of "Collection" keyword for checking if
a class is a collection. Check either using 'collection'
property defined in 'EntryPoint' or 'manages' property defined
in that class

* Fix tests

Use get_endpoint_and_path function instead of class_in_endpoint
or collection_in_endpoint as they are changed to get_endpoint_and_path
function
  • Loading branch information
sameshl authored Jul 31, 2020
1 parent 59506a6 commit 104bf96
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 115 deletions.
63 changes: 15 additions & 48 deletions hydra_python_core/doc_maker.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ def create_doc(doc: Dict[str, Any], HYDRUS_SERVER_URL: str = None,
# EntryPoint object
# getEntrypoint checks if all classes have @id
entrypoint_obj = get_entrypoint(doc)

# get the list of all collections if they are defined in entrypoint under 'hydra:collection'
collections = entrypoint_obj.get('collections')
# Main doc object
if HYDRUS_SERVER_URL is not None and API_NAME is not None:
apidoc = HydraDoc(
Expand All @@ -105,7 +106,9 @@ def create_doc(doc: Dict[str, Any], HYDRUS_SERVER_URL: str = None,
class_obj, collection, collection_path = create_class(
entrypoint_obj, class_)
if class_obj:
if "manages" in class_:
if (collections is not None and
class_ in collections or
"manages" in class_):
apidoc.add_supported_class(
class_obj, collection=collection, collection_path=collection_path,
collection_manages=class_["manages"])
Expand Down Expand Up @@ -150,18 +153,18 @@ def create_class(
for k, literal in doc_keys.items():
result[k] = input_key_check(class_dict, k, "class_dict", literal)

collection = False
# See if class_dict is a Collection Class
# type: Union[Match[Any], bool]
collection = re.match(r'(.*)Collection(.*)', result["title"], re.M | re.I)
if collection:
return None, None, None
# get the list of all collections if they are defined in entrypoint under 'hydra:collection'
collections = entrypoint.get('collections')
if (collections is not None and
class_dict in collections or
"manages" in class_dict):
collection = True

# Check if class has it's own endpoint
endpoint, path = class_in_endpoint(class_dict, entrypoint)

# Check if class has a Collection
collection, collection_path = collection_in_endpoint(
class_dict, entrypoint)
endpoint, path = get_endpoint_and_path(class_dict, entrypoint)

# Create the HydraClass object
class_ = HydraClass(
Expand All @@ -177,7 +180,7 @@ def create_class(
op_obj = create_operation(op)
class_.add_supported_op(op_obj)

return class_, collection, collection_path
return class_, collection, path


def get_entrypoint(doc: Dict[str, Any]) -> Dict[str, Any]:
Expand Down Expand Up @@ -286,7 +289,7 @@ def create_link_property(
return link


def class_in_endpoint(
def get_endpoint_and_path(
class_: Dict[str, Any], entrypoint: Dict[str, Any]) -> Tuple[bool, bool]:
"""Check if a given class is in the EntryPoint object as a class.
Expand Down Expand Up @@ -323,42 +326,6 @@ def class_in_endpoint(
return False, None


def collection_in_endpoint(
class_: Dict[str, Any], entrypoint: Dict[str, Any]) -> Tuple[bool, bool]:
"""Check if a given class is in the EntryPoint object as a collection.
Raises:
SyntaxError: If the `entrypoint` dictionary does not include the key
`supportedProperty`.
SyntaxError: If any dictionary in `supportedProperty` list does not include
the key `property`.
SyntaxError: If any property dictionary does not include the key `label`.
"""
# Check supportedProperty for the EntryPoint
try:
supported_property = entrypoint["supportedProperty"]
except KeyError:
raise SyntaxError("EntryPoint must have [supportedProperty]")

# Check all endpoints in supportedProperty
for prop in supported_property:
# Syntax checks
try:
property_ = prop["property"]
except KeyError:
raise SyntaxError("supportedProperty must have [property]")
try:
label = property_["label"]
except KeyError:
raise SyntaxError("property must have [label]")
# Match the title with regular expression
if label == "{}Collection".format(class_["title"]):
path = "/".join(property_['@id'].split("/")[1:])
return True, path
return False, None


def create_operation(supported_op: Dict[str, Any]) -> HydraClassOp:
"""Create a HyraClassOp object from the supportedOperation."""
# Syntax checks
Expand Down
73 changes: 6 additions & 67 deletions tests/test_doc_maker.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def test_output(self, mock_class):

class TestClassInEndPoint(unittest.TestCase):
"""
Test Class for class_in_endpoint method
Test Class for get_endpoint_and_path method
"""

def setUp(self):
Expand All @@ -149,19 +149,19 @@ def test_validations(self):
# check if exception raised is proper when supportedProperty key is not in entrypoint
properties = entrypoint.pop("supportedProperty")
self.assertRaises(
SyntaxError, doc_maker.class_in_endpoint, class_dict, entrypoint)
SyntaxError, doc_maker.get_endpoint_and_path, class_dict, entrypoint)

# check if proper exception is raised when property key is not present
property_ = properties[0].pop("property")
entrypoint["supportedProperty"] = properties
self.assertRaises(
SyntaxError, doc_maker.class_in_endpoint, class_dict, entrypoint)
SyntaxError, doc_maker.get_endpoint_and_path, class_dict, entrypoint)

# check if exception is raised when no label key is found in property
properties[0]["property"] = property_
label = property_.pop("label")
self.assertRaises(
SyntaxError, doc_maker.collection_in_endpoint, class_dict, entrypoint)
SyntaxError, doc_maker.get_endpoint_and_path, class_dict, entrypoint)
property_["label"] = label

def test_output(self):
Expand All @@ -180,74 +180,13 @@ def test_output(self):
}

expected_output = (False, None)
self.assertEqual(doc_maker.class_in_endpoint(
self.assertEqual(doc_maker.get_endpoint_and_path(
class_dict, entrypoint), expected_output)

# Only the title of the class is needed in the method
class_dict["title"] = "Order"
expected_output = (True, '/store/order')
self.assertEqual(doc_maker.class_in_endpoint(
class_dict, entrypoint), expected_output)


class TestCollectionInEndpoint(unittest.TestCase):
"""
Test Class for collection_in_endpoint method
"""

def setUp(self):
self.doc = hydra_doc_sample.doc

def test_validations(self):
"""
Test method to check if proper exceptions are raised when entrypoint has missing keys or
contains syntax errors
"""

class_dict = self.doc["supportedClass"][0]
entrypoint = doc_maker.get_entrypoint(self.doc)

# check if exception raised is proper when supportedProperty key is not in entrypoint
properties = entrypoint.pop("supportedProperty")
self.assertRaises(
SyntaxError, doc_maker.collection_in_endpoint, class_dict, entrypoint)

# check if proper exception is raised when property key is not present
property_ = properties[0].pop("property")
entrypoint["supportedProperty"] = properties
self.assertRaises(
SyntaxError, doc_maker.collection_in_endpoint, class_dict, entrypoint)

# check if exception is raised when no label key is found in property
properties[0]["property"] = property_
label = property_.pop("label")
self.assertRaises(
SyntaxError, doc_maker.collection_in_endpoint, class_dict, entrypoint)
property_["label"] = label

def test_output(self):
"""
Test method to check if proper output is obtained when class title is manipulated
"""

entrypoint = doc_maker.get_entrypoint(self.doc)
class_dict = {
"@id": "vocab:Pet",
"@type": "hydra:Class",
"title": "Pet",
"description": "Pet",
"supportedProperty": [],
"supportedOperation": [],
}

expected_output = (True, '/pet')
self.assertEqual(doc_maker.collection_in_endpoint(
class_dict, entrypoint), expected_output)

# Only the title of the class is needed in the method
class_dict["title"] = "Order"
expected_output = (False, None)
self.assertEqual(doc_maker.collection_in_endpoint(
self.assertEqual(doc_maker.get_endpoint_and_path(
class_dict, entrypoint), expected_output)


Expand Down

0 comments on commit 104bf96

Please sign in to comment.