Skip to content

Commit

Permalink
added name_or_id to the property retrieval, updated tests
Browse files Browse the repository at this point in the history
* updated all casettes
* small refactoring in the part tests
* updated all tests
* added tests for getting the property by id and name
  • Loading branch information
Jochem Berends committed Jan 24, 2018
1 parent 0afd4c7 commit 94730dc
Show file tree
Hide file tree
Showing 36 changed files with 88 additions and 38 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ pykechain changelog

1.14.2 (24JAN18)
----------------
* enabled to use of property model UUID in the `Part.add_with_properties()` next to using property names. (#258)
* enabled to search for properties using UUID next to using property names. This is provided for you in `Part.property()`.
* updated dependent versions for development: pytest (3.3.2), sphinx (1.6.6), nbsphinx (0.3.1), matplotlib (2.1.2), mypy (0.560)

1.14.1 (24JAN18)
Expand Down
32 changes: 22 additions & 10 deletions pykechain/models/part.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,11 @@ def __init__(self, json, **kwargs):
self.properties = [Property.create(p, client=self._client) for p in json['properties']]
self.multiplicity = json.get('multiplicity', None)

def property(self, name):
def property(self, name_or_id):
# type: (str) -> Property
"""Retrieve the property with name belonging to this part.
If you need to retrieve the property using eg. the id, use :meth:`pykechain.Client.properties`.
:param name: property name to search for
:param name_or_id: property name or property UUID to search for
:return: a single :class:`pykechain.models.Property`
:raises: NotFoundError
Expand All @@ -79,11 +77,19 @@ def property(self, name):
>>> gears = part.property('Gears')
>>> gears.value
6
>>> gears = part.property('123e4567-e89b-12d3-a456-426655440000')
>>> gears.value
6
"""
found = find(self.properties, lambda p: name == p.name)
if is_uuid(name_or_id):
found = find(self.properties, lambda p: name_or_id == p.id)
else:
found = find(self.properties, lambda p: name_or_id == p.name)

if not found:
raise NotFoundError("Could not find property with name {}".format(name))
raise NotFoundError("Could not find property with name {}".format(name_or_id))

return found

Expand Down Expand Up @@ -473,7 +479,8 @@ def add_with_properties(self, model, name=None, update_dict=None, bulk=True, **k
:param model: model of the part which to add a new instance, should follow the model tree in KE-chain
:param name: (optional) name provided for the new instance as string otherwise use the name of the model
:param update_dict: dictionary with keys being property names (str) and values being property values
:param update_dict: dictionary with keys being property names (str) or property_id (from the property models)
and values being property values
:param bulk: True to use the bulk_update_properties API endpoint for KE-chain versions later then 2.1.0b
:param kwargs: (optional) additional keyword arguments that will be passed inside the update request
:return: :class:`pykechain.models.Part`
Expand All @@ -492,8 +499,13 @@ def add_with_properties(self, model, name=None, update_dict=None, bulk=True, **k
name = name or model.name
action = 'new_instance_with_properties'

properties_update_dict = dict([(model.property(property_name).id, property_value)
for property_name, property_value in update_dict.items()])
properties_update_dict = dict()
for prop_name_or_id, property_value in update_dict.items():
if is_uuid(prop_name_or_id):
properties_update_dict[prop_name_or_id] = property_value
else:
properties_update_dict[model.property(prop_name_or_id).id] = property_value

# TODO: add bulk = False flags such that is used the old API (sequential)
if bulk:
r = self._client._request('POST', self._client._build_url('parts'),
Expand Down Expand Up @@ -561,7 +573,7 @@ def order_properties(self, property_list=None):

for prop in property_list:
if isinstance(prop, (str, text_type)):
order_dict[self.property(name=prop).id] = property_list.index(prop)
order_dict[self.property(name_or_id=prop).id] = property_list.index(prop)
else:
order_dict[prop.id] = property_list.index(prop)

Expand Down
2 changes: 1 addition & 1 deletion pykechain/models/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def edit(self, name=None, description=None, unit=None):
Example
-------
>>> front_fork = project.part('Front Fork')
>>> color_property = front_fork.property(name='Color')
>>> color_property = front_fork.property(name_or_id='Color')
>>> color_property.edit(name='Shade', description='Could also be called tint, depending on mixture',
>>> unit='RGB')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"recorded_with": "betamax/0.8.0", "http_interactions": [{"response": {"status": {"message": "OK", "code": 200}, "body": {"base64_string": "H4sIAAAAAAAAA61TTYvbMBD9K4tOLUSJLPlLOW277aFQaKFLDy1LkKVx4o0tB0nedgn57x0l9pLNHlrogm0s6b03o5k3e+LAD23wZPlzTwbXkiXZhLDzy8ViC5qrXTPfAtUb1di57rsFbiy87nfgF3ldVFrWjHJeAk2NUFQazSjoTBWZKQQkZn7ve0tmpDEo/C8ExFrVAaLfN1u4+ur6e9Dh6s3uEdOJWVwF8KGx67eIDPA7IBL/fFBhwEuQdze3n75/jGdOWd+Eprenu42qN5+/fIvHm2a9afENgJkFN8CZxhHzgRzuZkR536wtINMObTsjHXQVuLFaHtyoGnPqlFVrcPGyfqV0aB5gUsaNE3HaGGkn7EQcz6BTTWxDdV3NbTvWjh9mLwLG5X9Eq1Xrz8Kp83DiItxT9V/tdmOg4iLQfa830M1RDKzxrxbtuew1OvpX77Y+OnpMJI/dRge4sDIqREHOkoKyhPL8loslY/j8QLAZ4C+IatBbQF/uSdcbaFeu76NLC8mV0BVQJrIc3S9TWqZlTSutq7oSnNVaxGQsZmE1TLQ644kQAqhKwNAU8oxWSZ5TKWUtEyVKXSfTgKWMoTgvaIKTS9MiV7TkBQ5YVWQFh1wCMHKYkZ3rNfhodWYUZFJIWgqhaVoWilYyTynLTKoFyBq0JEfC2h0ZbJ5louCMi5LJDL8Cq2yaoKr2qUU7cF2Dg3McvT3RDo71Gg037GL5Vg66/gEuenmCrnTb2xcEZcwFGsFPw3sOeu6B08m0Mjg4rn+8oE3JnDMPh7vDH6N+rtwfBQAA", "string": "", "encoding": null}, "url": "<API_URL>/api/scopes.json?status=ACTIVE&name=Bike+Project+%28pykechain+testing%29", "headers": {"Allow": "GET, POST, HEAD, OPTIONS", "Transfer-Encoding": "chunked", "Vary": "Accept-Encoding", "Connection": "keep-alive", "X-XSS-Protection": "1; mode=block", "Date": "Wed, 24 Jan 2018 12:44:03 GMT", "X-Content-Type-Options": "nosniff", "Content-Type": "application/json", "Content-Encoding": "gzip", "X-Frame-Options": "SAMEORIGIN", "Strict-Transport-Security": "max-age=518400; includeSubDomains", "Server": "nginx/1.12.2"}}, "request": {"method": "GET", "uri": "<API_URL>/api/scopes.json?status=ACTIVE&name=Bike+Project+%28pykechain+testing%29", "body": {"string": "", "encoding": "utf-8"}, "headers": {"Accept": "*/*", "User-Agent": "python-requests/2.18.4", "Authorization": "Token <AUTH_TOKEN>", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate", "PyKechain-Version": "1.14.2", "X-Requested-With": "XMLHttpRequest"}}, "recorded_at": "2018-01-24T12:44:03"}, {"response": {"status": {"message": "OK", "code": 200}, "body": {"base64_string": "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", "string": "", "encoding": null}, "url": "<API_URL>/api/parts.json?name=Bike&limit=100&category=INSTANCE&bucket=40003527-1c2a-476a-8270-eb7572e69ee0", "headers": {"Allow": "GET, POST, HEAD, OPTIONS", "Transfer-Encoding": "chunked", "Vary": "Accept-Encoding", "Connection": "keep-alive", "X-XSS-Protection": "1; mode=block", "Date": "Wed, 24 Jan 2018 12:44:03 GMT", "X-Content-Type-Options": "nosniff", "Content-Type": "application/json", "Content-Encoding": "gzip", "X-Frame-Options": "SAMEORIGIN", "Strict-Transport-Security": "max-age=518400; includeSubDomains", "Server": "nginx/1.12.2"}}, "request": {"method": "GET", "uri": "<API_URL>/api/parts.json?name=Bike&limit=100&category=INSTANCE&bucket=40003527-1c2a-476a-8270-eb7572e69ee0", "body": {"string": "", "encoding": "utf-8"}, "headers": {"Accept": "*/*", "User-Agent": "python-requests/2.18.4", "Authorization": "Token <AUTH_TOKEN>", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate", "PyKechain-Version": "1.14.2", "X-Requested-With": "XMLHttpRequest"}}, "recorded_at": "2018-01-24T12:44:03"}, {"response": {"status": {"message": "OK", "code": 200}, "body": {"base64_string": "H4sIAAAAAAAAA82Uy27bMBBFfyXQ2oytF0V55yYpWiCJA9dp0RaBwMeoZi1LAkW1MQL/e0cvG068SJFNVvJwOHd4D+l5cmRR59aZuiMnh0f8kddZNnJKA390UVdDbKCqM4vhzydHK2fqgJIMBJ+QIJIhCdxQERZ5EaEq9qIw8AF84Yyc2mS4eWVtWU3H4zVIj5f6fA1ErrjOz2WxGePCuOTGVuPXaJ7/roochXO+AVT+tgLIMFRQSaNLqzE5dXBBrnSmkk2hINubaKODw6IEYzV0piS38KswW6y+mV9eXZ/S7HteavxaMM5eZJvYbdmkPl7PZ8vk6+z6/qoxn+s90KK2ZY2RNTVg1Kpi56fdyKlwTdrawKBy16s2DRDM62kfGSyMwjNOJ6PuwlgcCcEUI2msFAmk8IiQoUtowBhEfuCHLEKJPzyroZPYjf4Ly5eyWCPMl1A+374zJG6PJE1TX06oR9LQZyQARomgHiOejCAII9+TQr0JyUJvzm5wu9E8OwHm4tNs8b7IeD0ZLxJSxS4jkzj2SOBxQWLFJkQwKUWcRh4N3/ZYltrA2XKl5TqH6tSjeYf/JL+HA65yuUwpCVKKEpS6hDM3JD6XMfUnykOlZ3AeRqfgyIxXlU41pjo+d4v55f3FsuWWgeUig8EnKH0UH1N4abxx25qGZrr3Qzv0FQ1ACOJOcBAEVDB88DQmknuUcVDUd/3DHX3Qa3CQ6gYnvy4zLbVtTv/jajFPbma33xsHRW5xjjd0Up5V0N7j43YAt+JVUtVif7pqOG+faMf+oRTMRiOQ7jodaQCRJcPnMM8HkbpUTYaXZbZNdF5Znss9H3x41hTbIexUnlU27ZPObLeOm9RxRZLD36T19KJDv2F4uCfqnld0bbtot3vY/QOVEaAvfQcAAA==", "string": "", "encoding": null}, "url": "<API_URL>/api/parts.json?name=Wheel&limit=100&category=MODEL&bucket=40003527-1c2a-476a-8270-eb7572e69ee0", "headers": {"Allow": "GET, POST, HEAD, OPTIONS", "Transfer-Encoding": "chunked", "Vary": "Accept-Encoding", "Connection": "keep-alive", "X-XSS-Protection": "1; mode=block", "Date": "Wed, 24 Jan 2018 12:44:03 GMT", "X-Content-Type-Options": "nosniff", "Content-Type": "application/json", "Content-Encoding": "gzip", "X-Frame-Options": "SAMEORIGIN", "Strict-Transport-Security": "max-age=518400; includeSubDomains", "Server": "nginx/1.12.2"}}, "request": {"method": "GET", "uri": "<API_URL>/api/parts.json?name=Wheel&limit=100&category=MODEL&bucket=40003527-1c2a-476a-8270-eb7572e69ee0", "body": {"string": "", "encoding": "utf-8"}, "headers": {"Accept": "*/*", "User-Agent": "python-requests/2.18.4", "Authorization": "Token <AUTH_TOKEN>", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate", "PyKechain-Version": "1.14.2", "X-Requested-With": "XMLHttpRequest"}}, "recorded_at": "2018-01-24T12:44:03"}, {"response": {"status": {"message": "Created", "code": 201}, "body": {"string": "{\"results\":[{\"id\":\"cc89e8ff-96ae-4656-a9a5-d48b73c4acd0\",\"name\":\"Fresh Wheel\",\"description\":\"\",\"child_models\":[],\"properties\":[{\"options\":{},\"property_type\":\"FLOAT_VALUE\",\"order\":0,\"name\":\"Diameter\",\"model\":\"897bb8d8-f9dd-4cb2-bc51-6488e7343587\",\"description\":\"\",\"output\":true,\"part\":\"cc89e8ff-96ae-4656-a9a5-d48b73c4acd0\",\"id\":\"268a0efa-cfcd-44cc-86c3-4742e3130dcb\",\"value\":42.43,\"structure_type\":\"Property\",\"category\":\"INSTANCE\",\"unit\":null},{\"options\":{},\"property_type\":\"INT_VALUE\",\"order\":1,\"name\":\"Spokes\",\"model\":\"fff3c062-f538-4e86-b628-2c7e45732cbd\",\"description\":\"\",\"output\":true,\"part\":\"cc89e8ff-96ae-4656-a9a5-d48b73c4acd0\",\"id\":\"1ca1b8a8-5f56-4151-9541-9f87d48f543d\",\"value\":42,\"structure_type\":\"Property\",\"category\":\"INSTANCE\",\"unit\":null},{\"options\":{},\"property_type\":\"CHAR_VALUE\",\"order\":2,\"name\":\"Rim Material\",\"model\":\"27bcd918-0992-42ab-9d80-b8ccb9f72657\",\"description\":\"\",\"output\":true,\"part\":\"cc89e8ff-96ae-4656-a9a5-d48b73c4acd0\",\"id\":\"fab03afa-7510-486b-be79-d78e424384e4\",\"value\":\"Unobtanium\",\"structure_type\":\"Property\",\"category\":\"INSTANCE\",\"unit\":null},{\"options\":{},\"property_type\":\"FLOAT_VALUE\",\"order\":3,\"name\":\"Tire Thickness\",\"model\":\"e1d1acf6-4f65-4661-a815-3ac9630d2927\",\"description\":\"\",\"output\":true,\"part\":\"cc89e8ff-96ae-4656-a9a5-d48b73c4acd0\",\"id\":\"b9bac0e7-7b60-4188-baba-1dad50985c78\",\"value\":null,\"structure_type\":\"Property\",\"category\":\"INSTANCE\",\"unit\":null}],\"category\":\"INSTANCE\",\"model\":{\"id\":\"edc8eba0-47c5-415d-8727-6d927543ee3b\",\"name\":\"Wheel\"},\"classification\":\"PRODUCT\",\"deletable\":true,\"editable\":true,\"created_at\":\"2018-01-24T12:44:03.956675Z\",\"updated_at\":\"2018-01-24T12:44:03.956686Z\",\"output\":true,\"structure_type\":\"Part\",\"parent\":{\"id\":\"e5106946-40f7-4b49-ae5e-421450857911\",\"name\":\"Bike\"},\"multiplicity\":\"ZERO_MANY\",\"container\":false,\"proxy\":null,\"permissions\":{\"update_apply_instance\":true,\"create\":true,\"create_new_instance\":true,\"create_property\":false,\"create_new_proxy_instance\":true,\"create_create_child_model\":false,\"update_part_name\":true,\"update\":true,\"destroy\":true,\"read\":true},\"has_subparts\":false}]}", "encoding": null}, "url": "<API_URL>/api/parts.json?select_action=new_instance_with_properties", "headers": {"Allow": "GET, POST, HEAD, OPTIONS", "Transfer-Encoding": "chunked", "Vary": "Accept, Cookie", "Connection": "keep-alive", "X-XSS-Protection": "1; mode=block", "Date": "Wed, 24 Jan 2018 12:44:04 GMT", "X-Content-Type-Options": "nosniff", "Content-Type": "application/json", "X-Frame-Options": "SAMEORIGIN", "Strict-Transport-Security": "max-age=518400; includeSubDomains", "Server": "nginx/1.12.2"}}, "request": {"method": "POST", "uri": "<API_URL>/api/parts.json?select_action=new_instance_with_properties", "body": {"string": "model=edc8eba0-47c5-415d-8727-6d927543ee3b&properties=%7B%22897bb8d8-f9dd-4cb2-bc51-6488e7343587%22%3A+42.43%2C+%22fff3c062-f538-4e86-b628-2c7e45732cbd%22%3A+42%2C+%2227bcd918-0992-42ab-9d80-b8ccb9f72657%22%3A+%22Unobtanium%22%7D&parent=e5106946-40f7-4b49-ae5e-421450857911&name=Fresh+Wheel", "encoding": "utf-8"}, "headers": {"Accept": "*/*", "Content-Length": "290", "User-Agent": "python-requests/2.18.4", "Authorization": "Token <AUTH_TOKEN>", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate", "PyKechain-Version": "1.14.2", "X-Requested-With": "XMLHttpRequest", "Content-Type": "application/x-www-form-urlencoded"}}, "recorded_at": "2018-01-24T12:44:04"}, {"response": {"status": {"message": "No Content", "code": 204}, "body": {"string": "", "encoding": null}, "url": "<API_URL>/api/parts/cc89e8ff-96ae-4656-a9a5-d48b73c4acd0.json", "headers": {"Allow": "GET, PUT, PATCH, DELETE, HEAD, OPTIONS", "Connection": "keep-alive", "Content-Length": "0", "Vary": "Accept, Cookie", "X-Content-Type-Options": "nosniff", "X-XSS-Protection": "1; mode=block", "Date": "Wed, 24 Jan 2018 12:44:04 GMT", "Content-Type": "application/json", "X-Frame-Options": "SAMEORIGIN", "Strict-Transport-Security": "max-age=518400; includeSubDomains", "Server": "nginx/1.12.2"}}, "request": {"method": "DELETE", "uri": "<API_URL>/api/parts/cc89e8ff-96ae-4656-a9a5-d48b73c4acd0.json", "body": {"string": "", "encoding": "utf-8"}, "headers": {"Accept": "*/*", "Content-Length": "0", "User-Agent": "python-requests/2.18.4", "Authorization": "Token <AUTH_TOKEN>", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate", "PyKechain-Version": "1.14.2", "X-Requested-With": "XMLHttpRequest"}}, "recorded_at": "2018-01-24T12:44:04"}]}
Loading

0 comments on commit 94730dc

Please sign in to comment.