class ClientRuntimeContext(object): def __init__(self, url, auth_context=None): """ Client runtime context for services :type url: str :type auth_context: AuthenticationContext or None """ self.__service_root_url = url self.__auth_context = auth_context self.afterExecuteOnce = EventHandler(True) @abc.abstractmethod def get_pending_request(self): """ :rtype: ClientRequest """ pass @property def has_pending_request(self): return len(self.get_pending_request().queries) > 0 def authenticate_request(self, request): self.__auth_context.authenticate_request(request) def load(self, client_object, properties_to_retrieve=None): """Prepare query :type properties_to_retrieve: list[str] or None :type client_object: office365.runtime.client_object.ClientObject """ qry = ReadEntityQuery(client_object, properties_to_retrieve) self.get_pending_request().add_query(qry) def execute_request_direct(self, request): """ :type request: RequestOptions """ return self.get_pending_request().execute_request_direct(request) def execute_query(self): while self.has_pending_request: self.get_pending_request().execute_query() query = self.get_pending_request().current_query self.afterExecuteOnce.notify(query.return_type) def add_query(self, query): """ Adds query to internal queue :type query: ClientQuery """ self.get_pending_request().add_query(query) @property def service_root_url(self): return self.__service_root_url
class ClientRequest(object): def __init__(self, context): """ Base request for OData/REST service :type context: office365.runtime.client_runtime_context.ClientRuntimeContext """ self.context = context self._queries = [] self.beforeExecute = EventHandler() self.afterExecute = EventHandler() @property def queries(self): return self._queries @abstractmethod def build_request(self): pass @abstractmethod def process_response(self, response): pass def execute_query(self): """Submit a pending request to the server""" try: request = self.build_request() self.beforeExecute.notify(request) response = self.execute_request_direct(request) response.raise_for_status() self.process_response(response) self.afterExecute.notify(response) except HTTPError as e: raise ClientRequestException(*e.args, response=e.response) def execute_request_direct(self, request_options): """Execute client request :type request_options: RequestOptions """ self.context.authenticate_request(request_options) if request_options.method == HttpMethod.Post: if request_options.is_bytes or request_options.is_file: result = requests.post(url=request_options.url, headers=request_options.headers, data=request_options.data, auth=request_options.auth, verify=request_options.verify) else: result = requests.post(url=request_options.url, headers=request_options.headers, json=request_options.data, auth=request_options.auth, verify=request_options.verify) elif request_options.method == HttpMethod.Patch: result = requests.patch(url=request_options.url, headers=request_options.headers, json=request_options.data, auth=request_options.auth, verify=request_options.verify) elif request_options.method == HttpMethod.Delete: result = requests.delete(url=request_options.url, headers=request_options.headers, auth=request_options.auth, verify=request_options.verify) elif request_options.method == HttpMethod.Put: result = requests.put(url=request_options.url, data=request_options.data, headers=request_options.headers, auth=request_options.auth, verify=request_options.verify) else: result = requests.get(url=request_options.url, headers=request_options.headers, auth=request_options.auth, verify=request_options.verify, stream=request_options.stream, proxies=request_options.proxies) return result def add_query(self, query): """ :type query: ClientQuery """ self._queries.append(query)
class ClientRequest(object): """Base request for OData/REST service""" def __init__(self, context): self.context = context self._queries = [] self.beforeExecute = EventHandler() self.afterExecute = EventHandler() @property def queries(self): return self._queries @abstractmethod def build_request(self): pass @abstractmethod def process_response(self, response): pass def execute_query(self): """Submit a pending request to the server""" try: request = self.build_request() self.beforeExecute.notify(request) response = self.execute_request_direct(request) response.raise_for_status() self.process_response(response) self.afterExecute.notify(response) except HTTPError as e: raise ClientRequestException(*e.args, response=e.response) def execute_request_direct(self, request_options): """Execute client request""" self.context.authenticate_request(request_options) if request_options.method == HttpMethod.Post: if hasattr(request_options.data, 'decode') and callable( request_options.data.decode): result = requests.post(url=request_options.url, headers=request_options.headers, data=request_options.data, auth=request_options.auth, verify=request_options.verify) elif hasattr(request_options.data, 'read') and callable( request_options.data.read): result = requests.post(url=request_options.url, headers=request_options.headers, data=request_options.data, auth=request_options.auth, verify=request_options.verify) else: result = requests.post(url=request_options.url, headers=request_options.headers, json=request_options.data, auth=request_options.auth, verify=request_options.verify) elif request_options.method == HttpMethod.Patch: result = requests.patch(url=request_options.url, headers=request_options.headers, json=request_options.data, auth=request_options.auth, verify=request_options.verify) elif request_options.method == HttpMethod.Delete: result = requests.delete(url=request_options.url, headers=request_options.headers, auth=request_options.auth, verify=request_options.verify) elif request_options.method == HttpMethod.Put: result = requests.put(url=request_options.url, data=request_options.data, headers=request_options.headers, auth=request_options.auth, verify=request_options.verify) else: result = requests.get(url=request_options.url, headers=request_options.headers, auth=request_options.auth, verify=request_options.verify) return result def add_query(self, query): self._queries.append(query)
class ClientObjectCollection(ClientObject): def __init__(self, context, item_type, resource_path=None): """Client object collection :type context: ClientRuntimeContext :type item_type: type[ClientObject] :type resource_path: ResourcePath """ super(ClientObjectCollection, self).__init__(context, resource_path) self._data = [] self._item_type = item_type self.page_loaded = EventHandler(False) self._page_size = 100 self._page_index = 0 self.next_request_url = None @property def page_size(self): return self._page_size @page_size.setter def page_size(self, value): self._page_size = value self.top(value) def clear(self): self._data = [] def create_typed_object(self, properties): if self._item_type is None: raise AttributeError("No class for object type '{0}' found".format( self._item_type)) client_object = self._item_type(self.context) client_object._parent_collection = self for k, v in properties.items(): client_object.set_property(k, v, False) return client_object def set_property(self, name, value, persist_changes=False): child_client_object = self.create_typed_object(value) self.add_child(child_client_object) def add_child(self, client_object): """ Adds client object into collection :type client_object: ClientObject """ client_object._parent_collection = self self._data.append(client_object) def remove_child(self, client_object): self._data.remove(client_object) def __iter__(self): for cur_item in self._data: yield cur_item while self.next_request_url: self._page_index += 1 next_index = self._page_size * self._page_index self._load_next_items() self.page_loaded.notify(len(self._data)) next_items = self._data[next_index:] for cur_item in next_items: yield cur_item def __len__(self): list(iter(self)) return len(self._data) def __getitem__(self, index): # fetch only as much items as necessary item_iterator = iter(self) while len(self._data) <= index: next(item_iterator) return self._data[index] def filter(self, expression): """ :type expression: str """ self.query_options.filter = expression return self def order_by(self, value): self.query_options.orderBy = value return self def skip(self, value): self.query_options.skip = value return self def top(self, value): self.query_options.top = value return self def _load_next_items(self): request = RequestOptions(self.next_request_url) response = self.context.execute_request_direct(request) json = response.json() self.next_request_url = None self.context.get_pending_request().map_json(json, self)