From bb6911ecd1f8ba2b81d616a611e55f273948ad24 Mon Sep 17 00:00:00 2001 From: Jochem Berends Date: Mon, 2 Oct 2017 09:22:26 +0200 Subject: [PATCH 1/3] #207 fixed correct response on the notfound and multiplefounderr --- pykechain/models/part.py | 12 ++++++++++-- tests/test_parts.py | 7 +++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/pykechain/models/part.py b/pykechain/models/part.py index b77013268..85aaf1f2b 100644 --- a/pykechain/models/part.py +++ b/pykechain/models/part.py @@ -152,6 +152,8 @@ def model(self): For instance, you can get the part model of a part instance. But trying to get the model of a part that has no model, like a part model, will raise a NotFoundError. + .. versionadded:: 1.8 + :return: pykechain.models.Part :raises: NotFoundError @@ -175,6 +177,8 @@ def instances(self, **kwargs): moodel. If there are no instances (only possible if the multiplicity is `Multiplicity.ZERO_MANY` than a NotFoundError is returned + .. versionadded:: 1.8 + :param kwargs: Additional search arguments to search for, check `pykechain.Client.parts` for additional info :return: pykechain.models.PartSet :raises: NotFoundError @@ -193,7 +197,7 @@ def instances(self, **kwargs): if self.category == Category.MODEL: return self._client.parts(model=self, category=Category.INSTANCE, **kwargs) else: - raise NotFoundError("Part {} has no instances or is not a model".format(self.name)) + raise NotFoundError("Part {} is not a model".format(self.name)) def instance(self): """ @@ -207,9 +211,11 @@ def instance(self): instances_list = list(self.instances()) if len(instances_list) == 1: return instances_list[0] - else: + elif len(instances_list) > 1: raise MultipleFoundError("Part {} has more than a single instance. " "Use the `Part.instances()` method".format(self.name)) + else: + raise NotFoundError("Part {} has no instance".format(self.name)) def proxy_model(self): """ @@ -508,6 +514,8 @@ def as_dict(self): """ Retrieve the properties of a part inside a dict in this structure: {property_name: property_value}. + .. versionadded:: 1.9 + Example ------- >>> front_wheel = client.scope('Bike Project').part('Front Wheel') diff --git a/tests/test_parts.py b/tests/test_parts.py index 6e6a1294b..76ded6aa9 100644 --- a/tests/test_parts.py +++ b/tests/test_parts.py @@ -451,6 +451,13 @@ def test_get_single_instance_of_a_multiplicity_model_raises_multiplefounderror(s with self.assertRaises(MultipleFoundError): wheel_model.instance() + # test added in 1.12.7 + def test_get_single_instance_of_a_model_without_instances_raises_notfounderror(self): + model_without_instances = self.project.model(name='model_without_instances') + + with self.assertRaises(NotFoundError): + model_without_instances.instance() + # new in 1.10 def test_reorder_properties_using_names(self): # Retrieve the front fork model From f004f0ef49713e8eb733ce20051a8497e20c0d3a Mon Sep 17 00:00:00 2001 From: Jochem Berends Date: Mon, 2 Oct 2017 09:44:41 +0200 Subject: [PATCH 2/3] #207 adding missing cassette --- ...stance_of_a_model_without_instances_raises_notfounderror.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/cassettes/TestPartCreateWithProperties.test_get_single_instance_of_a_model_without_instances_raises_notfounderror.json diff --git a/tests/cassettes/TestPartCreateWithProperties.test_get_single_instance_of_a_model_without_instances_raises_notfounderror.json b/tests/cassettes/TestPartCreateWithProperties.test_get_single_instance_of_a_model_without_instances_raises_notfounderror.json new file mode 100644 index 000000000..fb8358d45 --- /dev/null +++ b/tests/cassettes/TestPartCreateWithProperties.test_get_single_instance_of_a_model_without_instances_raises_notfounderror.json @@ -0,0 +1 @@ +{"http_interactions": [{"request": {"uri": "/api/scopes.json?status=ACTIVE&name=Bike+Project+%28pykechain+testing%29", "headers": {"Accept": "*/*", "X-Requested-With": "XMLHttpRequest", "Authorization": "Token ", "User-Agent": "python-requests/2.18.4", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate", "PyKechain-Version": "1.12.6"}, "body": {"string": "", "encoding": "utf-8"}, "method": "GET"}, "response": {"headers": {"X-Content-Type-Options": "nosniff", "Transfer-Encoding": "chunked", "Content-Encoding": "gzip", "X-XSS-Protection": "1; mode=block", "Date": "Mon, 02 Oct 2017 07:12:27 GMT", "Allow": "GET, POST, HEAD, OPTIONS", "X-Frame-Options": "SAMEORIGIN", "Content-Type": "application/json", "Vary": "Accept-Encoding", "Strict-Transport-Security": "max-age=518400; includeSubDomains", "Connection": "keep-alive", "Server": "nginx/1.10.2"}, "body": {"base64_string": "H4sIAAAAAAAAA6VT227bMAz9lUJPGxAlsuSb8tSt68OAARuwYg8bikIXOlFjy4YkbyuC/PvoXNr0oeiwwTIg0jw8JH24JQHi2KZIlj+2ZAwtWZJ1SkNcLhYbMFwNbr4BatbK+bnpuwU6FtH0A8RF2VTayIZRzmuguRWKSmsYBVOoqrCVgMzO72PvyYw4i4n/BoCxXnWA0e/dBi6+hP4eTLp4MzxgOVMVFwlicn71FiMT/E4YibeYVBqxCfLu6ubjt+vpW1A+uuR6f+ht7VbrFt8EWEoKI5yBrj59/nr94Yl6b5Pd7YyoGN3KAzr92LYz0kGnIRwyQqdce6A/4vA2RghH67Hkqf94d4CeuCeH8mr1zKNMcj/h0YGFVrvZE5G+1HPfvkQ3zeWU8t8J+TmhepVwMl9ja1QbX6IT53T3vVlDN8c04G28RN396sMmTrp7qYbnkP/ou5z+NgoipDur0pSas6yiLKO8vOFiyRie70hgR3glQo9mA6jLLel6C+1d6PtJpZXkShgNlImiRPXLnNZ53VBtjG604KwxYmrAYxXewAnWFDwTQgBVGViaQ1lQnZUllVI2MlOiNk12WrCcMUzOK5rh5tK8KhWteYULpqui4lBKAEZ2MzKE3kCclM+sgkIKSWshDM3rSlEty5yywuZGgGzASLIHrMIeweZ5XZfi7ClmBKxLSrePAx0gdA43Z797W2IC7Ad2FMI4HOZ3iLWootA/nEwMPe7nbne7+wNSaYc1nwQAAA==", "string": "", "encoding": null}, "status": {"message": "OK", "code": 200}, "url": "/api/scopes.json?status=ACTIVE&name=Bike+Project+%28pykechain+testing%29"}, "recorded_at": "2017-10-02T07:12:27"}, {"request": {"uri": "/api/parts.json?limit=100&bucket=40003527-1c2a-476a-8270-eb7572e69ee0&name=model_without_instances&category=MODEL", "headers": {"Accept": "*/*", "X-Requested-With": "XMLHttpRequest", "Authorization": "Token ", "User-Agent": "python-requests/2.18.4", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate", "PyKechain-Version": "1.12.6"}, "body": {"string": "", "encoding": "utf-8"}, "method": "GET"}, "response": {"headers": {"X-Content-Type-Options": "nosniff", "Transfer-Encoding": "chunked", "Content-Encoding": "gzip", "X-XSS-Protection": "1; mode=block", "Date": "Mon, 02 Oct 2017 07:12:28 GMT", "Allow": "GET, POST, HEAD, OPTIONS", "X-Frame-Options": "SAMEORIGIN", "Content-Type": "application/json", "Vary": "Accept-Encoding", "Strict-Transport-Security": "max-age=518400; includeSubDomains", "Connection": "keep-alive", "Server": "nginx/1.10.2"}, "body": {"base64_string": "H4sIAAAAAAAAA41RwU7jMBT8FeRz3aRtWpLcKkB7ge1qxWVBKHLsF2Jwbct+3qWq+u/7EjZluXGKx543eTNzZNIli6xezJiFNzrYZMyM+QC/tUtxwgFiMkjw8ci0YjWT0F62pSh4V67WvFhDxUXVVnzRCbkSsFmWZcdmLAVD5B7RxzrLXkEuhdfzV+CyF9rOpdtndJF5ETBmX9Gcv0RnSdiKPZDy3ikwzR+NvUvYaBtRWAmRCAqiDNqjJnrN6EL22qhmHDjbGtGHZ+choIbB5hMNCIRnFw40fre7vrkdNIyIUXeant51r7b329vdt/F/BlC0hrbCkGDGQOlPmBb0CScU6SMxBWjw4AcnPygCkqEkYOjjODm8EiiMe76QziJFBoFIYwMFiGKd5xVf5esNL9qq4uUiB65yuSyrvFL5ZsNO5JGK095oqXGw8nDzc9fcbb//GuycNetOmAhjBm+HKZBexCam9rxqPNP+vYy1fcxC2GuKx9k47C8DUICT3+TVf4jKweAOEySmej+fTk+nv1Bo9OeUAgAA", "string": "", "encoding": null}, "status": {"message": "OK", "code": 200}, "url": "/api/parts.json?limit=100&bucket=40003527-1c2a-476a-8270-eb7572e69ee0&name=model_without_instances&category=MODEL"}, "recorded_at": "2017-10-02T07:12:28"}, {"request": {"uri": "/api/parts.json?limit=100&category=INSTANCE&model=ceb7b8a4-f835-45e9-a9b9-1fac3ae6288f", "headers": {"Accept": "*/*", "X-Requested-With": "XMLHttpRequest", "Authorization": "Token ", "User-Agent": "python-requests/2.18.4", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate", "PyKechain-Version": "1.12.6"}, "body": {"string": "", "encoding": "utf-8"}, "method": "GET"}, "response": {"headers": {"X-Content-Type-Options": "nosniff", "Transfer-Encoding": "chunked", "Content-Encoding": "gzip", "X-XSS-Protection": "1; mode=block", "Date": "Mon, 02 Oct 2017 07:12:28 GMT", "Allow": "GET, POST, HEAD, OPTIONS", "X-Frame-Options": "SAMEORIGIN", "Content-Type": "application/json", "Vary": "Accept-Encoding", "Strict-Transport-Security": "max-age=518400; includeSubDomains", "Connection": "keep-alive", "Server": "nginx/1.10.2"}, "body": {"base64_string": "H4sIAAAAAAAAA6tWSs4vzStRsjLQUcpLrQAy8kpzcnSUCopSyzLzS4th/KLU4tKcEiA3OrYWAHDt3lM0AAAA", "string": "", "encoding": null}, "status": {"message": "OK", "code": 200}, "url": "/api/parts.json?limit=100&category=INSTANCE&model=ceb7b8a4-f835-45e9-a9b9-1fac3ae6288f"}, "recorded_at": "2017-10-02T07:12:28"}], "recorded_with": "betamax/0.8.0"} \ No newline at end of file From 3dc4a8a976a81762a3b479a85a08a3ae0cae7495 Mon Sep 17 00:00:00 2001 From: Jochem Berends Date: Mon, 2 Oct 2017 09:55:33 +0200 Subject: [PATCH 3/3] #207 updated versions and changelog --- CHANGELOG.rst | 26 +++++++++++++++----------- pykechain/__about__.py | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ff28d2496..9fa00967d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,32 +3,36 @@ Change Log pykechain changelog +1.12.7 (2OKT17) +--------------- + * Fixed a bug where a model without an instance raises an incorrect Error. Now it will raise a `NotFoundError` (#207). + 1.12.6 (28SEP17) ---------------- - * fixed a bug in the `models.customisation`. After a succesfull save of a customisation to an activity, the activity could not be retrieved from KE-chain if the activity was part of a closed scope (#205) + * Fixed a bug in the `models.customisation`. After a succesfull save of a customisation to an activity, the activity could not be retrieved from KE-chain if the activity was part of a closed scope (#205). 1.12.5 (28SEP17) ---------------- - * the `get_project()` helper method will now retrieve a scope a status other than 'ACTIVE' only (#203) - * updated the documentation to fix wrongly formatted examples. + * The `get_project()` helper method will now retrieve a scope a status other than 'ACTIVE' only (#203). + * Updated the documentation to fix wrongly formatted examples. 1.12.4 (26SEP17) ---------------- - * Fixed a bug in the customization code by which the activity was incorrectly updated after a correctly saved customization to the KE-chain server. In some cases the incorrect customisation was retrieved on name basis, which may resulted in an error raised. Thansk to @raduiordache for finding it (#200) - * Added `**kwargs` to the `Part.children()`, `Part.siblings()`, `Part.instances()`, `Activity.children()`, and `Activity.siblings()` methods. This will enable more comprehensive searches, eg. by the name of children using `Activity.children(name='Some childs name')` (#199) + * Fixed a bug in the customization code by which the activity was incorrectly updated after a correctly saved customization to the KE-chain server. In some cases the incorrect customisation was retrieved on name basis, which may resulted in an error raised. Thanks to @raduiordache for finding it (#200). + * Added `**kwargs` to the `Part.children()`, `Part.siblings()`, `Part.instances()`, `Activity.children()`, and `Activity.siblings()` methods. This will enable more comprehensive searches, eg. by the name of children using `Activity.children(name='Some childs name')` (#199). 1.12.3 (21SEP17) ---------------- - * Fixing the warning: 'could not any envfile' from envparse. Which is suppressed for cosmetics. It is advised to provide a pathname for the envfile when you want to load the environment variables from an envfile. (#195) + * Fixing the warning: 'could not any envfile' from envparse. Which is suppressed for cosmetics. It is advised to provide a pathname for the envfile when you want to load the environment variables from an envfile (#195). * Fixed tests for the envparse warning and refactored the tests to better deal with in-test settings of the environment. 1.12.2 (15SEP17) ---------------- - * Removed a logical error in the checking of the existing of the environment variables + * Removed a logical error in the checking of the existing of the environment variables. 1.12.1 (15SEP17) ---------------- - * Added the ability to enforce the use of environment variables when the KECHAIN_FORCE_ENV_USE is set to a true value in the environment. Altered documentation and altered tests for that (#193) + * Added the ability to enforce the use of environment variables when the KECHAIN_FORCE_ENV_USE is set to a true value in the environment. Altered documentation and altered tests for that (#193). 1.12 (14SEP17) -------------- @@ -38,9 +42,9 @@ pykechain changelog >>> project = get_project(url='http://localhost:8000', username='foo', password='bar', scope='Bike Project') >>> print(project.name) - * Added additional checks for the `Client` to check if the url provided is correct (#185) - * Improved the state of the project on codacy, a nice code quality monitor, from B to A grade. Removed over 100 insecure code elements, according to codacy. See: https://www.codacy.com/app/KE-works/pykechain/dashboard (#187) - * Updated dependent versions of pyopenssl to 1.1.2 (#188), pytest to 3.2.2 (#183) and tox to 2.8.2 (#184) + * Added additional checks for the `Client` to check if the url provided is correct (#185). + * Improved the state of the project on codacy, a nice code quality monitor, from B to A grade. Removed over 100 insecure code elements, according to codacy. See: https://www.codacy.com/app/KE-works/pykechain/dashboard (#187). + * Updated dependent versions of pyopenssl to 1.1.2 (#188), pytest to 3.2.2 (#183) and tox to 2.8.2 (#184). * Updated coverage of the files to internal standards. The critical models are now 100% tested such as the `Client`, `Activity` and `Part`. (#190) see: https://coveralls.io/github/KE-works/pykechain. 1.11.1 (4SEP17) diff --git a/pykechain/__about__.py b/pykechain/__about__.py index 992afd39a..6480985e7 100644 --- a/pykechain/__about__.py +++ b/pykechain/__about__.py @@ -2,7 +2,7 @@ name = 'pykechain' description = 'KE-chain Python SDK' -version = '1.12.6' +version = '1.12.7' author = 'KE-works BV' email = 'support+pykechain@ke-works.com'