From 61d8cc32acdc6563cc3c1a78acd21dddd9e2384c Mon Sep 17 00:00:00 2001 From: Francesco Siddi Date: Mon, 25 Jan 2016 16:18:51 +0100 Subject: [PATCH] Introducing Project object Project are a new collection, used to group node_types on a per-project basis. --- pillarsdk/__init__.py | 1 + pillarsdk/nodes.py | 4 +- pillarsdk/projects.py | 96 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 pillarsdk/projects.py diff --git a/pillarsdk/__init__.py b/pillarsdk/__init__.py index 64f7de6..2bf930e 100644 --- a/pillarsdk/__init__.py +++ b/pillarsdk/__init__.py @@ -6,6 +6,7 @@ from .files import File from .tokens import Token from .groups import Group from .organizations import Organization +from .projects import Project from .binary_files import binaryFile from .exceptions import ResourceNotFound, UnauthorizedAccess, MissingConfig from .config import __version__, __pypi_packagename__ diff --git a/pillarsdk/nodes.py b/pillarsdk/nodes.py index 3a4f385..6902ee9 100755 --- a/pillarsdk/nodes.py +++ b/pillarsdk/nodes.py @@ -53,7 +53,6 @@ class Node(List, Find, Create, Post, Update, Delete, Replace): else: raise ResourceNotFound(response) - def update(self, attributes=None, api=None): api = api or self.api attributes = attributes or self.to_dict() @@ -64,6 +63,9 @@ class Node(List, Find, Create, Post, Update, Delete, Replace): attributes.pop('_updated') attributes.pop('_links', None) attributes.pop('allowed_methods') + for attr in ['parent', 'picture']: + if attr in attributes and attributes[attr] is None: + attributes.pop(attr, None) url = utils.join_url(self.path, str(self['_id'])) headers = utils.merge_dict( self.http_headers(), diff --git a/pillarsdk/projects.py b/pillarsdk/projects.py new file mode 100644 index 0000000..6d1d6fa --- /dev/null +++ b/pillarsdk/projects.py @@ -0,0 +1,96 @@ +from .resource import List +from .resource import Find +from .resource import Create +from .resource import Post +from .resource import Update +from .resource import Delete +from .resource import Replace +from .exceptions import ResourceNotFound + +from . import utils +from .nodes import Node +from .api import Api + + +class Project(List, Find, Create, Post, Update, Delete, Replace): + """Project class wrapping the REST nodes endpoint + """ + path = "projects" + + @classmethod + def find(cls, resource_id, params=None, api=None): + """Locate resource, usually using ObjectID + + Usage:: + + >>> Project.find("507f1f77bcf86cd799439011") + """ + + api = api or Api.Default() + + url = utils.join_url(cls.path, str(resource_id)) + if params: + url = utils.join_url_params(url, params) + + item = utils.convert_datetime(api.get(url)) + return cls(item) + + @classmethod + def find_one(cls, params, api=None): + """Get one resource starting from parameters different than the resource + id. TODO if more than one match for the query is found, raise exception. + """ + api = api or Api.Default() + + # Force delivery of only 1 result + params['max_results'] = 1 + url = utils.join_url_params(cls.path, params) + + response = api.get(url) + # Keep the response a dictionary, and cast it later into an object. + if response['_items']: + item = utils.convert_datetime(response['_items'][0]) + return cls(item) + else: + raise ResourceNotFound(response) + + def update(self, attributes=None, api=None): + api = api or self.api + attributes = attributes or self.to_dict() + etag = attributes['_etag'] + attributes.pop('_id') + attributes.pop('_etag') + attributes.pop('_created') + attributes.pop('_updated') + attributes.pop('_links', None) + attributes.pop('allowed_methods') + # Remove fields with None value (causes error on validation) + for prop in ['picture_square', 'picture_header']: + if prop in attributes and attributes[prop] is None: + attributes.pop(prop) + url = utils.join_url(self.path, str(self['_id'])) + headers = utils.merge_dict( + self.http_headers(), + {'If-Match': str(etag)}) + new_attributes = api.put(url, attributes, headers) + self.error = None + self.merge(new_attributes) + return self.success() + + def has_method(self, method): + if method in self.allowed_methods: + return True + return False + + def children(self, api=None): + api = api or self.api + children = Node.all({ + 'where': '{"project" : "%s", "parent" : {"$exists": false}}'\ + % self._id, + }, api=api) + return children + + def get_node_type(self, node_type_name): + return next((item for item in self.node_types if item.name \ + and item['name'] == node_type_name), None) +