def query(self, index_name, index_query, includes=None, metadata_only=False, index_entries_only=False, force_read_from_master=False): """ @param index_name: A name of an index to query @param force_read_from_master: If True the reading also will be from the master :type bool :type str @param index_query: A query definition containing all information required to query a specified index. :type IndexQuery @param includes: An array of relative paths that specify related documents ids which should be included in a query result. :type list @param metadata_only: True if returned documents should include only metadata without a document body. :type bool @param index_entries_only: True if query results should contain only index entries. :type bool @return:json :rtype:dict """ if not index_name: raise ValueError("index_name cannot be None or empty") if index_query is None: raise ValueError("None query is invalid") if not isinstance(index_query, IndexQuery): raise ValueError("query must be IndexQuery type") path = "indexes/{0}?".format(Utils.quote_key(index_name)) if index_query.default_operator is QueryOperator.AND: path += "&operator={0}".format(index_query.default_operator.value) if index_query.query: path += "&query={0}".format(Utils.quote_key(index_query.query)) if index_query.sort_hints: for hint in index_query.sort_hints: path += "&{0}".format(hint) if index_query.sort_fields: for field in index_query.sort_fields: path += "&sort={0}".format(field) if index_query.fetch: for item in index_query.fetch: path += "&fetch={0}".format(item) if metadata_only: path += "&metadata-only=true" if index_entries_only: path += "&debug=entries" if includes and len(includes) > 0: path += "".join("&include=" + item for item in includes) if index_query.start: path += "&start={0}".format(index_query.start) path += "&pageSize={0}".format(index_query.page_size) response = self._requests_handler.http_request_handler( path, "GET", force_read_from_master=force_read_from_master).json() if "Error" in response: raise exceptions.ErrorResponseException(response["Error"][:100]) return response
def get(self, key_or_keys, includes=None, metadata_only=False, force_read_from_master=False): """ @param key_or_keys: the key of the documents you want to retrieve (key can be a list of ids) :type str or list @param includes: array of paths in documents in which server should look for a 'referenced' document :type list @param metadata_only: specifies if only document metadata should be returned :type bool @return: A list of the id or ids we looked for (if they exists) :rtype: dict @param force_read_from_master: If True the reading also will be from the master :type bool """ if key_or_keys is None: raise ValueError("None Key is not valid") path = "queries/?" method = "GET" data = None if includes: path += "".join("&include=" + Utils.quote_key(item) for item in includes) # make get method handle a multi document requests in a single request if isinstance(key_or_keys, list): key_or_keys = collections.OrderedDict.fromkeys(key_or_keys) if metadata_only: path += "&metadata-only=True" # If it is too big, we drop to POST (note that means that we can't use the HTTP cache any longer) if (sum(len(x) for x in key_or_keys)) > 1024: method = "POST" data = list(key_or_keys) else: path += "".join("&id=" + Utils.quote_key(item) for item in key_or_keys) else: path += "&id={0}".format(Utils.quote_key(key_or_keys)) response = self._requests_handler.http_request_handler( path, method, data=data, force_read_from_master=force_read_from_master) if response.status_code == 200: response = response.json() return response
def create_database(self, database_document): """ Creates a database @param database_document: has to be DatabaseDocument type """ if "Raven/DataDir" not in database_document.settings: raise exceptions.InvalidOperationException( "The Raven/DataDir setting is mandatory") db_name = database_document.database_id.replace( "Raven/Databases/", "") Utils.name_validation(db_name) path = "databases/{0}".format(Utils.quote_key(db_name)) response = self.requests_handler.http_request_handler( path, "PUT", database_document.to_json(), admin=True) if response.status_code == 502: raise exceptions.ErrorResponseException( "Connection failed please check your connection to {0}". format(self.requests_handler.url)) if response.status_code != 200: raise exceptions.ErrorResponseException( "Database with the name '{0}' already exists".format( database_document.database_id)) return response
def initialize(self): if not self._initialize: self._database_commands = database_commands.DatabaseCommands( self._requests_handler) if self.database is None: raise exceptions.InvalidOperationException( "None database is not valid") if not self.database.lower() == self.conventions.system_database: path = "Raven/Databases/{0}".format(self.database) response = self._requests_handler.check_database_exists( "docs?id=" + Utils.quote_key(path)) # here we unsure database exists if not create new one if response.status_code == 404: try: raise exceptions.ErrorResponseException( "Could not open database named: {0}, database does not exists" .format(self.database)) except exceptions.ErrorResponseException: print(traceback.format_exc()) self._database_commands.admin_commands.create_database( DatabaseDocument(self.database, { "Raven/DataDir": "~\\{0}".format(self.database) })) self._requests_handler.get_replication_topology() self.generator = HiloGenerator(self.conventions.max_ids_to_catch, self._database_commands) self._initialize = True
def query(self, index_name, index_query, includes=None, metadata_only=False, index_entries_only=False, force_read_from_master=False): """ @param index_name: A name of an index to query @param force_read_from_master: If True the reading also will be from the master :type bool :type str @param index_query: A query definition containing all information required to query a specified index. :type IndexQuery @param includes: An array of relative paths that specify related documents ids which should be included in a query result. :type list @param metadata_only: True if returned documents should include only metadata without a document body. :type bool @param index_entries_only: True if query results should contain only index entries. :type bool @return:json :rtype:dict """ if not index_name: raise ValueError("index_name cannot be None or empty") if index_query is None: raise ValueError("None query is invalid") if not isinstance(index_query, IndexQuery): raise ValueError("index_query must be IndexQuery type") path = "indexes/{0}?".format(Utils.quote_key(index_name)) path += self._build_query_request_path(index_query=index_query, includes=includes, metadata_only=metadata_only, index_entries_only=index_entries_only) response = self._requests_handler.http_request_handler(path, "GET", force_read_from_master=force_read_from_master).json() if "Error" in response: raise exceptions.ErrorResponseException(response["Error"][:100]) return response
def delete_database(self, db_name, hard_delete=False): db_name = db_name.replace("Rave/Databases/", "") path = "databases/{0}".format(Utils.quote_key(db_name)) if hard_delete: path += "?hard-delete=true" response = self.requests_handler.http_request_handler(path, "DELETE", admin=True) if response.content != '' and response.content != b'': raise exceptions.ErrorResponseException(response.content) return response
def delete_database(self, db_name, hard_delete=False): db_name = db_name.replace("Rave/Databases/", "") path = "databases/{0}".format(Utils.quote_key(db_name)) if hard_delete: path += "?hard-delete=true" response = self.requests_handler.http_request_handler(path, "DELETE", admin=True) if response.content != '' and response.content != b'': raise exceptions.ErrorResponseException(response.content) return response
def delete_index(self, index_name): """ @param index_name: Name of the index you like to get or delete :type str @return: json or None :rtype: dict """ if not index_name: raise ValueError("None or empty index_name is invalid") path = "indexes/{0}".format(Utils.quote_key(index_name)) self._requests_handler.http_request_handler(path, "DELETE")
def delete_index(self, index_name): """ @param index_name: Name of the index you like to get or delete :type str @return: json or None :rtype: dict """ if not index_name: raise ValueError("None or empty index_name is invalid") path = "indexes/{0}".format(Utils.quote_key(index_name)) self._requests_handler.http_request_handler(path, "DELETE")
def get(self, key_or_keys, includes=None, metadata_only=False, force_read_from_master=False): """ @param key_or_keys: the key of the documents you want to retrieve (key can be a list of ids) :type str or list @param includes: array of paths in documents in which server should look for a 'referenced' document :type list @param metadata_only: specifies if only document metadata should be returned :type bool @return: A list of the id or ids we looked for (if they exists) :rtype: dict @param force_read_from_master: If True the reading also will be from the master :type bool """ if key_or_keys is None: raise ValueError("None Key is not valid") path = "queries/?" method = "GET" data = None if includes: path += "".join("&include=" + Utils.quote_key(item) for item in includes) # make get method handle a multi document requests in a single request if isinstance(key_or_keys, list): key_or_keys = collections.OrderedDict.fromkeys(key_or_keys) if metadata_only: path += "&metadata-only=True" # If it is too big, we drop to POST (note that means that we can't use the HTTP cache any longer) if (sum(len(x) for x in key_or_keys)) > 1024: method = "POST" data = list(key_or_keys) else: path += "".join("&id=" + Utils.quote_key(item) for item in key_or_keys) else: path += "&id={0}".format(Utils.quote_key(key_or_keys)) response = self._requests_handler.http_request_handler(path, method, data=data, force_read_from_master=force_read_from_master) if response.status_code == 200: response = response.json() return response
def open_session(self, database=None, api_key=None, force_read_from_master=False): self._assert_initialize() session_id = uuid.uuid4() database_commands_for_session = self._database_commands if database is not None: requests_handler = HttpRequestsFactory(self.url, database, self.conventions, force_get_topology=True, api_key=api_key) path = "Raven/Databases/{0}".format(database) response = requests_handler.check_database_exists("docs?id=" + Utils.quote_key(path)) if response.status_code != 200: raise exceptions.ErrorResponseException("Could not open database named:{0}".format(database)) database_commands_for_session = database_commands.DatabaseCommands(requests_handler) return documentsession(database, self, database_commands_for_session, session_id, force_read_from_master)
def delete(self, key, etag=None): if key is None: raise ValueError("None Key is not valid") if not isinstance(key, str): raise ValueError("key must be {0}".format(type(""))) headers = {} if etag is not None: headers["If-None-Match"] = etag key = Utils.quote_key(key) path = "docs/{0}".format(key) response = self._requests_handler.http_request_handler(path, "DELETE", headers=headers) if response.status_code != 204: raise exceptions.ErrorResponseException(response.json()["Error"])
def delete(self, key, etag=None): if key is None: raise ValueError("None Key is not valid") if not isinstance(key, str): raise ValueError("key must be {0}".format(type(""))) headers = {} if etag is not None: headers["If-None-Match"] = "\"" + etag + "\"" key = Utils.quote_key(key) path = "docs/{0}".format(key) response = self._requests_handler.http_request_handler(path, "DELETE", headers=headers) if response.status_code != 204: raise exceptions.ErrorResponseException(response.json()["Error"])
def get_index(self, index_name, force_read_from_master=False): """ @param index_name: Name of the index you like to get or delete :type str @return: json or None :rtype: dict @param force_read_from_master: If True the reading also will be from the master :type bool """ path = "indexes/{0}?definition=yes".format(Utils.quote_key(index_name)) response = self._requests_handler.http_request_handler( path, "GET", force_read_from_master=force_read_from_master) if response.status_code != 200: return None return response.json()
def search(self, field_name, search_terms, escape_query_options=EscapeQueryOptions.RawQuery): """ for more complex text searching @param field_name:The field name in the index you want to query. :type str @param search_terms: the terms you want to query :type str @param escape_query_options: the way we should escape special characters :type EscapeQueryOptions """ search_terms = Utils.quote_key(str(search_terms)) search_terms = self._lucene_builder(search_terms, "search", escape_query_options) self.query_builder += "{0}:{1}".format(field_name, search_terms) return self
def get_index(self, index_name, force_read_from_master=False): """ @param index_name: Name of the index you like to get or delete :type str @return: json or None :rtype: dict @param force_read_from_master: If True the reading also will be from the master :type bool """ path = "indexes/{0}?definition=yes".format(Utils.quote_key(index_name)) response = self._requests_handler.http_request_handler(path, "GET", force_read_from_master=force_read_from_master) if response.status_code != 200: return None return response.json()
def put_index(self, index_name, index_def, overwrite=False): """ @param index_name:The name of the index @param index_def: IndexDefinition class a definition of a RavenIndex @param overwrite: if set to True overwrite """ if index_name is None: raise ValueError("None index_name is not valid") if not isinstance(index_def, IndexDefinition): raise ValueError("index_def must be IndexDefinition type") index_name = Utils.quote_key(index_name) path = "indexes/{0}?definition=yes".format(index_name) response = self._requests_handler.http_request_handler(path, "GET") if not overwrite and response.status_code != 404: raise exceptions.InvalidOperationException("Cannot put index:{0},index already exists".format(index_name)) data = index_def.to_json() return self._requests_handler.http_request_handler(path, "PUT", data=data).json()
def put_index(self, index_name, index_def, overwrite=False): """ @param index_name:The name of the index @param index_def: IndexDefinition class a definition of a RavenIndex @param overwrite: if set to True overwrite """ if index_name is None: raise ValueError("None index_name is not valid") if not isinstance(index_def, IndexDefinition): raise ValueError("index_def must be IndexDefinition type") index_name = Utils.quote_key(index_name) path = "indexes/{0}?definition=yes".format(index_name) response = self._requests_handler.http_request_handler(path, "GET") if not overwrite and response.status_code != 404: raise exceptions.InvalidOperationException("Cannot put index:{0},index already exists".format(index_name)) data = index_def.to_json() return self._requests_handler.http_request_handler(path, "PUT", data=data).json()
def _build_query_request_path(index_query, includes=None, metadata_only=False, index_entries_only=False, include_query=True, add_page_size=True): path = "" if index_query.default_operator is QueryOperator.AND: try: operator = index_query.default_operator.value except AttributeError: operator = index_query.default_operator path += "&operator={0}".format(operator) if index_query.query and include_query: path += "&query={0}".format( Utils.quote_key(index_query.query, safe='/')) if index_query.sort_hints: for hint in index_query.sort_hints: path += "&{0}".format(hint) if index_query.sort_fields: for field in index_query.sort_fields: path += "&sort={0}".format(field) if index_query.fetch: for item in index_query.fetch: path += "&fetch={0}".format(item) if metadata_only: path += "&metadata-only=true" if index_entries_only: path += "&debug=entries" if includes and len(includes) > 0: path += "".join("&include=" + item for item in includes) if index_query.start and index_query.start != 0: path += "&start={0}".format(index_query.start) if add_page_size and index_query.page_size: path += "&pageSize={0}".format(index_query.page_size) if index_query.wait_for_non_stale_results: path += "&waitForNonStaleResultsAsOfNow=true" return path
def query(self, index_name, index_query, includes=None, metadata_only=False, index_entries_only=False, force_read_from_master=False): """ @param index_name: A name of an index to query @param force_read_from_master: If True the reading also will be from the master :type bool :type str @param index_query: A query definition containing all information required to query a specified index. :type IndexQuery @param includes: An array of relative paths that specify related documents ids which should be included in a query result. :type list @param metadata_only: True if returned documents should include only metadata without a document body. :type bool @param index_entries_only: True if query results should contain only index entries. :type bool @return:json :rtype:dict """ if not index_name: raise ValueError("index_name cannot be None or empty") if index_query is None: raise ValueError("None query is invalid") if not isinstance(index_query, IndexQuery): raise ValueError("index_query must be IndexQuery type") path = "indexes/{0}?".format(Utils.quote_key(index_name)) path += self._build_query_request_path( index_query=index_query, includes=includes, metadata_only=metadata_only, index_entries_only=index_entries_only) response = self._requests_handler.http_request_handler( path, "GET", force_read_from_master=force_read_from_master).json() if "Error" in response: raise exceptions.ErrorResponseException(response["Error"][:100]) return response
def initialize(self): if not self._initialize: self._operations = Operations(self._requests_handler) self._database_commands = database_commands.DatabaseCommands(self._requests_handler) if self.database is None: raise exceptions.InvalidOperationException("None database is not valid") if not self.database.lower() == self.conventions.system_database: path = "Raven/Databases/{0}".format(self.database) response = self._requests_handler.check_database_exists("docs?id=" + Utils.quote_key(path)) # here we unsure database exists if not create new one if response.status_code == 404: try: raise exceptions.ErrorResponseException( "Could not open database named: {0}, database does not exists".format(self.database)) except exceptions.ErrorResponseException: print(traceback.format_exc()) self._database_commands.admin_commands.create_database( DatabaseDocument(self.database, {"Raven/DataDir": "~\\{0}".format(self.database)})) self._requests_handler.get_replication_topology() self.generator = HiloGenerator(self.conventions.max_ids_to_catch, self._database_commands) self._initialize = True
def create_database(self, database_document): """ Creates a database @param database_document: has to be DatabaseDocument type """ if "Raven/DataDir" not in database_document.settings: raise exceptions.InvalidOperationException("The Raven/DataDir setting is mandatory") db_name = database_document.database_id.replace("Raven/Databases/", "") Utils.name_validation(db_name) path = "databases/{0}".format(Utils.quote_key(db_name)) response = self.requests_handler.http_request_handler(path, "PUT", database_document.to_json(), admin=True) if response.status_code == 502: raise exceptions.ErrorResponseException( "Connection failed please check your connection to {0}".format(self.requests_handler.url)) if response.status_code != 200: raise exceptions.ErrorResponseException( "Database with the name '{0}' already exists".format(database_document.database_id)) return response
def open_session(self, database=None, api_key=None, force_read_from_master=False): self._assert_initialize() session_id = uuid.uuid4() database_commands_for_session = self._database_commands if database is not None: requests_handler = HttpRequestsFactory(self.url, database, self.conventions, force_get_topology=True, api_key=api_key) path = "Raven/Databases/{0}".format(database) response = requests_handler.check_database_exists( "docs?id=" + Utils.quote_key(path)) if response.status_code != 200: raise exceptions.ErrorResponseException( "Could not open database named:{0}".format(database)) database_commands_for_session = database_commands.DatabaseCommands( requests_handler) return documentsession(database, self, database_commands_for_session, session_id, force_read_from_master)
def _build_query_request_path(index_query, includes=None, metadata_only=False, index_entries_only=False, include_query=True, add_page_size=True): path = "" if index_query.default_operator is QueryOperator.AND: try: operator = index_query.default_operator.value except AttributeError: operator = index_query.default_operator path += "&operator={0}".format(operator) if index_query.query and include_query: path += "&query={0}".format(Utils.quote_key(index_query.query, safe='/')) if index_query.sort_hints: for hint in index_query.sort_hints: path += "&{0}".format(hint) if index_query.sort_fields: for field in index_query.sort_fields: path += "&sort={0}".format(field) if index_query.fetch: for item in index_query.fetch: path += "&fetch={0}".format(item) if metadata_only: path += "&metadata-only=true" if index_entries_only: path += "&debug=entries" if includes and len(includes) > 0: path += "".join("&include=" + item for item in includes) if index_query.start and index_query.start != 0: path += "&start={0}".format(index_query.start) if add_page_size and index_query.page_size: path += "&pageSize={0}".format(index_query.page_size) if index_query.wait_for_non_stale_results: path += "&waitForNonStaleResultsAsOfNow=true" return path
def create_request(self, server_node): self.url = "{0}/admin/certificates?thumbprint={1}".format( server_node.url, Utils.quote_key(self._thumbprint))