def _bool_param_handler(input): if isinstance(input, bool): if input: return "true" else: return "false" if isinstance(input, basestring): if input not in ("true", "false"): raise InvalidArgumentException.pyexc( "String for boolean must be " "'true' or 'false'", input) return input try: input + 0 if input: return "true" else: return "false" except TypeError: raise InvalidArgumentException.pyexc( "Boolean value must be boolean, " "numeric, or a string of 'true' " "or 'false'", input)
def __init__(self, id_generator=None, data_converter=lambda x: x, operation=BucketOperators.UPSERT): # type: (IdGenerator, DataConverter, BucketOperator) -> None """ Initialise ingester. :param DataConverter data_converter: Single parameter Callable which takes a JSON input and returns a transformed JSON output. :param IdGenerator id_generator: Callable that takes a JSON input and returns an ID string :param BucketOperator operation: Callable that takes a bucket object, a key and a value and applies the key and value to the bucket (e.g. upsert/insert/replace) """ if not isinstance(operation, BucketOperator): raise InvalidArgumentException("Operation is not a BucketOperator") if operation == BucketOperators.REPLACE and not id_generator: raise InvalidArgumentException( "Replace cannot use default ID generator.") self.id_generator = id_generator or (lambda x: str(uuid.uuid4())) self.data_converter = data_converter self.operation = operation
def upsert_index(self, # type: SearchIndexManager index, # type: SearchIndex *options, # type: UpsertSearchIndexOptions **kwargs # type: Any ): # type: (...) -> None """ Creates or updates an index. :param SearchIndex index: Index to upsert. :param UpsertSearchIndexOptions options: options to upsert index. :param Any kwargs: override corresponding value in options :raise: :exc: `~.InvalidArgumentsException` if the arguments were invalid :exc: `~.CouchbaseException` for various server errors Uri PUT http://localhost:8094/api/index/<index_name>""" if not index: raise InvalidArgumentException("expected index to not be None") else: if not index.is_valid(): raise InvalidArgumentException("Index must have name, source set") try: self._http_request( path="api/index/{}".format(index.name), method="PUT", content=json.dumps(index.as_dict()), **forward_args(kwargs, *options)) except HTTPException as h: error = getattr(getattr(h, 'objextra', None), 'value', {}).get('error', "") if not "index with the same name already exists" in error: raise
def validate_project(project): if not project: return if isinstance(project, str): raise InvalidArgumentException("project must be an array of paths") if hasattr(project, "__getitem__") or hasattr(project, "__iter__"): return raise InvalidArgumentException("project must be an Iterable[str]")
def _num_param_handler(input): # Don't allow booleans: if isinstance(input, bool): raise InvalidArgumentException.pyexc( "Cannot use booleans as numeric values", input) try: return str(int(input)) except Exception as e: raise InvalidArgumentException.pyexc("Expected a numeric argument", input, e)
def _jval_param_handler(input): try: ret = json.dumps(input) return _string_param_handler(ret) except Exception as e: raise InvalidArgumentException.pyexc("Couldn't convert value to JSON", input, e)
def get_index(self, # type: SearchIndexManager index_name, # type: str *options, # type: GetSearchIndexOptions **kwargs # type: Any ): # type: (...)-> SearchIndex """ Fetches an index from the server if it exists. param str index_name: Name of the index to get. param GetSearchIndexOptions: options to use when getting index. param Any kwargs: overrides corresponding value in options :return: a :class:`~.SearchIndex` object. :raise: :exc:`~.SearchIndexNotFoundException` if the index was not found. :exc:`~.InvalidArgumentsException` if the arguments were not understood :exc:`~.CouchbaseException` for various server errors Uri GET http://localhost:8094/api/index/<name>""" if not index_name: raise InvalidArgumentException("expected index_name to not be empty") return SearchIndex.from_server( **self._http_request( path="api/index/{}".format(index_name), method='GET', **forward_args(kwargs, *options)).value["indexDef"] )
def _jarry_param_handler(input): ret = _jval_param_handler(input) if not ret.startswith('['): raise InvalidArgumentException.pyexc( "Value must be converted to JSON array", input) return ret
def unfreeze_plan(self, # type: SearchIndexManager index_name, # type: str *options, # type: UnfreezePlanSearchIndexOptions **kwargs # type: Any ): """ Unfreeze the assignment of index partitions to nodes. :param str index_name: Name of index to freeze. :param UnfreezePlanSearchIndexOptions options: Options for freezing index. :param kwargs Any: Override corresponding value in options. :return: None :raise: :exc: `~.SearchIndexNotFoundException` if the index doesn't exist :exc: `~.InvalidArgumentsException` if the arguments were invalid :exc: `~.CouchbaseException` for various server errors Uri POST http://localhost:8094/api/index/{index_name}/planFreezeControl/unfreeze """ if not index_name: raise InvalidArgumentException("expected an index_name") self._http_request( path='api/index/{}/planFreezeControl/unfreeze'.format(index_name), method='POST', **forward_args(kwargs, *options))
def disallow_querying(self, # type: SearchIndexManager index_name, # type: str *options, # type: DisallowQueryingSearchIndexOptions **kwargs # type: Any ): """ Allow querying against an index. :param str index_name: Name of index to allow querying. :param AllowQueryingSearchIndexOptions options: options for allowing querying. :param Any kwargs: Override corresponding value in options. :return: None :raise: :exc: `~.SearchIndexNotFoundException` if the index doesn't exist :exc: `~.InvalidArgumentsException` if the arguments were invalid :exc: `~.CouchbaseException` for various server errors Uri POST http://localhost:8094/api/index/{index_name}/queryControl/allow """ if not index_name: raise InvalidArgumentException("expected an index_name") self._http_request( path='api/index/{}/queryControl/allow'.format(index_name), method='POST', **forward_args(kwargs, *options))
def _set_common(self, param, value, set_user=True): # Invalidate encoded string self._encoded = None if value is UNSPEC: self._real_options.pop(param, None) if set_user: self._user_options.pop(param, None) return handler = _HANDLER_MAP.get(param) if not handler: if not self.unrecognized_ok: raise InvalidArgumentException.pyexc( "Unrecognized parameter. To use unrecognized parameters, " "set 'unrecognized_ok' to True") if not handler: self._extra_options[param] = _string_param_handler(value) return if self.passthrough: handler = _string_param_handler self._real_options[param] = handler(value) if set_user: self._user_options[param] = value
def resume_ingest(self, # type: SearchIndexManager index_name, # type: str *options, # type: ResumeIngestSearchIndexOptions **kwargs # type: Any ): """ Resume the ingestion of documents for an index. :param str index_name: Name of index to resume. :param ResumeIngestSearchIndexOptions options: Options for resuming ingestion of index. :param Any kwargs: Override corresponding value in options. :return: None :raise: :exc: `~.InvalidArgumentsException` if the arguments were invalid :exc: `~.CouchbaseException` for various server errors Uri POST http://localhost:8094/api/index/{index_name}/ingestControl/resume """ if not index_name: raise InvalidArgumentException("expected an index_name") self._http_request( path="api/index/{}/ingestControl/resume".format(index_name), method="POST", **forward_args(kwargs, *options))
def get_indexed_documents_count(self, # type: SearchIndexManager index_name, # type: str *options, # type: GetSearchIndexedDocumentsCountOptions **kwargs # type: Any ): """ Get a count of the documents indexed by the given index. :param str index_name: Name of index to get indexed document count. :param GetIndexedDocumentsSearchIndexOptions options: Options for geting the indexed document count. :param Any kwargs: Override corresponding value in options. :return: A :class: `int`, the count of documents indexed by the index. :raise: :exc: `~.InvalidArgumentsException` if the arguments were invalid :exc: `~.CouchbaseException` for various server errors Uri GET http://localhost:8094/api/index/{index_name}/count """ if not index_name: raise InvalidArgumentException("expected an index_name") return self._http_request( path="api/index/{}/count".format(index_name), **forward_args(kwargs, *options)).value['count']
def drop_index(self, # type: SearchIndexManager index_name, # type: str *options, # type: DropSearchIndexOptions **kwargs # type: Any ): # type: (...) -> None """ Drop an index. :param str index_name: Name of index to drop. :param DropSearchIndexOptions options: options for dropping index. :param Any kwargs: override corresponding option in options :raise: :exc: `~.InvalidArgumentsException` if the arguments were invalid :exc: `~.CouchbaseException` for various server errors Uri DELETE http://localhost:8094/api/index/{index_name} """ if not index_name: raise InvalidArgumentException("expected an index_name") self._http_request( path="api/index/{}".format(index_name), method='DELETE', **forward_args(kwargs, *options))
def _set_range_common(self, k_sugar, k_start, k_end, value): """ Checks to see if the client-side convenience key is present, and if so converts the sugar convenience key into its real server-side equivalents. :param string k_sugar: The client-side convenience key :param string k_start: The server-side key specifying the beginning of the range :param string k_end: The server-side key specifying the end of the range """ if not isinstance(value, (list, tuple, _Unspec)): raise InvalidArgumentException.pyexc( "Range specification for {0} must be a list, tuple or UNSPEC". format(k_sugar)) if self._user_options.get( k_start, UNSPEC) is not UNSPEC or (self._user_options.get( k_end, UNSPEC) is not UNSPEC): raise InvalidArgumentException.pyexc( "Cannot specify {0} with either {1} or {2}".format( k_sugar, k_start, k_end)) if not value: self._set_common(k_start, UNSPEC, set_user=False) self._set_common(k_end, UNSPEC, set_user=False) self._user_options[k_sugar] = UNSPEC return if len(value) not in (1, 2): raise InvalidArgumentException.pyexc( "Range specification " "must have one or two elements", value) value = value[::] if len(value) == 1: value.append(UNSPEC) for p, ix in ((k_start, 0), (k_end, 1)): self._set_common(p, value[ix], set_user=False) self._user_options[k_sugar] = value
def __call__(self, src: Enum_Type) -> str: if not self._enforce and isinstance(src, str) and src in map( lambda x: x.value, self._type): warnings.warn("Using deprecated string parameter {}".format(src)) return src if not isinstance(src, self._type): raise InvalidArgumentException( "Argument must be of type {} but got {}".format( self._type, src)) return src.value
def __init__(self, # type: DiagnosticsResult source_diagnostics # type: Union[Mapping[str,Any], list[Mapping[str,Any]]] ): self._id = self._version = self._sdk = self._endpoints = None # we could have an array of dicts, or just a single dict if isinstance(source_diagnostics, dict): source_diagnostics = [source_diagnostics] if not isinstance(source_diagnostics, list): raise InvalidArgumentException("DiagnosticsResult expects a dict or list(dict)") for d in source_diagnostics: self.append_endpoints(d)
def convert(mapping: Orig_Mapping, raw_info: Mapping[str, Any]) -> Mapping[str, Any]: converted = {} for k, v in raw_info.items(): entry = mapping.get(k, {k: Identity(object)}) for dest, transform in entry.items(): try: converted[dest] = transform(v) except InvalidArgumentException as e: raise InvalidArgumentException( "Problem processing argument {}: {}".format( k, e.message)) return converted
def _string_param_common(input, do_quote=False): # TODO, if we pass this to urlencode, do we ever need to quote? # For the moment, i'm always forcing non-quote behavior do_quote = False s = None if isinstance(input, basestring): s = input elif isinstance(input, bool): raise InvalidArgumentException.pyexc("Can't use boolean as string", input) elif isinstance(input, (int, long, float)): # Basic numeric types: s = str(input) else: raise InvalidArgumentException.pyexc( "Expected simple numeric type or string ", input) if do_quote: s = ulp.quote(s) return s
def __init__( self, name=None, # type: str bucket=None, # type: str scope=None, # type: str collection=None, # type: str ): if not name: raise InvalidArgumentException('A role must have a name') self._name = name self._bucket = bucket self._scope = scope self._collection = collection
def analyze_document(self, # type: SearchIndexManager index_name, # type: str document, # type: Any *options, # type: AnalyzeDocumentSearchIndexOptions **kwargs # type: Any ): """ Shows how a given document will be analyzed against a specific index :param str index_name: Index to use. :param Any document: Document to analyze. :param AnalyzeDocumentSearchIndexOptions options: Options for analyzing document. :param Any kwargs: Override corresponding value in options. :return: dict :raise: :exc: `~.SearchIndexNotFoundException` if the index doesn't exist :exc: `~.InvalidArgumentsException` if the arguments were invalid :exc: `~.CouchbaseException` for various server errors Uri POST http://localhost:8094/api/index/{index_name}/analyzeDoc """ if not index_name: raise InvalidArgumentException("expected an index_name") if not document: raise InvalidArgumentException("expected a document to analyze") try: jsonDoc = json.dumps(document) except: raise InvalidArgumentException("cannot convert doc to json to analyze") return self._http_request( path="api/index/{}/analyzeDoc".format(index_name), method='POST', content=jsonDoc, **forward_args(kwargs, *options)).value
def _design_poll(self, name, mode, oldres, timeout=5, use_devmode=False): """ Poll for an 'async' action to be complete. :param string name: The name of the design document :param string mode: One of ``add`` or ``del`` to indicate whether we should check for addition or deletion of the document :param oldres: The old result from the document's previous state, if any :param float timeout: How long to poll for. If this is 0 then this function returns immediately :type oldres: :class:`~couchbase_core.result.HttpResult` """ if not timeout: return True if timeout < 0: raise InvalidArgumentException.pyexc( "Interval must not be negative") t_end = time.time() + timeout old_rev = None if oldres: old_rev = self._doc_rev(oldres) while time.time() < t_end: try: cur_resp = self.design_get(name, use_devmode=use_devmode) if old_rev and self._doc_rev(cur_resp) == old_rev: continue try: if not self._poll_vq_single(name, use_devmode, cur_resp.value): continue return True except CouchbaseException: continue except CouchbaseException: if mode == 'del': # Deleted, whopee! return True raise exceptions.TimeoutException.pyexc( "Wait time for design action completion exceeded")
def __init__( self, username=None, # type: str display_name=None, # type: str groups=None, # type: Set[str] roles=None, # type: Set[Role] password=None # type: str ): if not username: raise InvalidArgumentException('A user must have a username') self._username = username self._display_name = display_name self._groups = SetHelper.to_set(groups, str, 'Groups') self._roles = SetHelper.to_set(roles, Role, 'Roles') self._password = password
def __init__( self, name=None, # type: str description=None, # type: str roles=None, # type: Set[Role] ldap_group_reference=None, # type: str **kwargs # type: Any ): if not name: raise InvalidArgumentException('A group must have a name') self._name = name self._description = description self._roles = SetHelper.to_set(roles, Role, 'Roles') self._ldap_group_reference = ldap_group_reference self._raw_data = kwargs.get('raw_data', None)
def to_set(cls, value, valid_type, display_name): if not value: return value elif isinstance(value, set): cls.validate_all_set_types(value, valid_type, display_name) return value elif isinstance(value, list): cls.validate_all_set_types(value, valid_type, display_name) return set(value) elif isinstance(value, tuple): cls.validate_all_set_types(value, valid_type, display_name) return set(value) elif isinstance(value, valid_type): return set([value]) else: raise InvalidArgumentException('{} must be of type {}.'.format( display_name, valid_type.__name__))
def _http_request(self, **kwargs): # TODO: maybe there is a more general way of making this # call? Ponder # the kwargs can override the defaults imeth = None method = kwargs.get('method', 'GET') if not method in METHMAP: raise InvalidArgumentException("Unknown HTTP Method", method) imeth = METHMAP[method] return self._admin_bucket._http_request( type=LCB.LCB_HTTP_TYPE_SEARCH, path=kwargs['path'], method=imeth, content_type=kwargs.get('content_type', 'application/json'), post_data=kwargs.get('content', None), response_format=LCB.FMT_JSON, timeout=kwargs.get('timeout', None))
def from_any(cls, params, **ctor_opts): """ Creates a new Query object from input. :param params: Parameter to convert to query :type params: dict, string, or :class:`Query` If ``params`` is a :class:`Query` object already, a deep copy is made and a new :class:`Query` object is returned. If ``params`` is a string, then a :class:`Query` object is contructed from it. The string itself is not parsed, but rather prepended to any additional parameters (defined via the object's methods) with an additional ``&`` characted. If ``params`` is a dictionary, it is passed to the :class:`Query` constructor. :return: a new :class:`Query` object :raise: :exc:`InvalidArgumentException` if the input is none of the acceptable types mentioned above. Also raises any exceptions possibly thrown by the constructor. """ if isinstance(params, cls): return deepcopy(params) elif isinstance(params, dict): ctor_opts.update(**params) if cls is QueryBase: if ('bbox' in params or 'start_range' in params or 'end_range' in params): return SpatialQuery(**ctor_opts) else: return ViewQuery(**ctor_opts) elif isinstance(params, basestring): ret = cls() ret._base_str = params return ret else: raise InvalidArgumentException.pyexc( "Params must be Query, dict, or string")
def gen_projection_spec(project, with_exp=False): def generate(path): if path is None: return with_expiry() if path: return SD.get(path) return get_full() validate_project(project) # empty string = with_expiry # None = get_full if not project: project = [""] if with_exp: project = [None] + project if len(project) > MAX_SPECS: raise InvalidArgumentException( "Project only accepts {} operations or less".format(MAX_SPECS)) return map(generate, project)
def update(self, copy=False, **params): """ Chained assignment operator. This may be used to quickly assign extra parameters to the :class:`Query` object. Example:: q = Query(reduce=True, full_sec=True) # Someplace later v = View(design, view, query=q.update(mapkey_range=["foo"])) Its primary use is to easily modify the query object (in-place). :param boolean copy: If set to true, the original object is copied before new attributes are added to it :param params: Extra arguments. These must be valid query options. :return: A :class:`Query` object. If ``copy`` was set to true, this will be a new instance, otherwise it is the same instance on which this method was called """ if copy: self = deepcopy(self) for k, v in params.items(): if not hasattr(self, k): if not self.unrecognized_ok: raise InvalidArgumentException.pyexc("Unknown option", k) self._set_common(k, v) else: setattr(self, k, v) return self
def view_query(self, *args, **kwargs): """ Reimplemented from base class. This method does not add additional functionality of the base class' :meth:`~couchbase_v2.bucket.Bucket.query` method (all the functionality is encapsulated in the view class anyway). However it does require one additional keyword argument :param class itercls: A class used for instantiating the view object. This should be a subclass of :class:`~couchbase.asynchronous.view.AsyncViewBase`. """ if not issubclass(kwargs.get('itercls', None), AsyncViewBase): raise InvalidArgumentException.pyexc( "itercls must be defined " "and must be derived from AsyncViewBase") try: return super(AsyncClientMixin, self).view_query(*args, **kwargs) except Exception as e: raise