def __call__(self, value, context): if not type(value) is dict: raise OperationError("invalid input: %s is not a dictionary" % context) specified_names = set(value.keys()) class Missing: pass def read_with_suffixes(name, checker): try: if name in value: specified_names.remove(name) context.push("." + name) return check(checker, value[name], context) for suffix, suffixed_checker in checker.getSuffixedCheckers(): suffixed_name = "%s_%s" % (name, suffix) if suffixed_name in value: specified_names.remove(suffixed_name) context.push("." + suffixed_name) if suffixed_checker is not None: checker = suffixed_checker return check(checker, value.pop(suffixed_name), context) context.push("." + name) return Missing finally: context.pop() for name, checker in self.__implicit: context.push("." + name) if name in value: raise OperationError( "invalid input: %s should not be specified" % context) value[name] = checker(None, context) context.pop() def process_members(items, required): for name, checker in items: converted = read_with_suffixes(name, checker) if not converted is Missing: value[name] = converted elif required: context.push("." + name) raise OperationError("invalid input: %s missing" % context) process_members(self.__prioritized, True) process_members(self.__required, True) process_members(self.__optional, False) if specified_names: context.push("." + specified_names.pop()) raise OperationError("invalid input: %s was not used" % context)
def __call__(self, value, context): if not type(value) is list: raise OperationError("%s is not a list" % context) for index, item in enumerate(value): context.push("[%d]" % index) value[index] = check(self.__checker, item, context) context.pop()
def process_members(items, required): for name, checker in items: converted = read_with_suffixes(name, checker) if not converted is Missing: value[name] = converted elif required: context.push("." + name) raise OperationError("invalid input: %s missing" % context)
def __call__(self, value, context): if not type(value) is dict: raise OperationError("invalid input: %s is not a dictionary" % context) for key in value: context.push("." + key) self.__key_checker(key, context) value[key] = check(self.__value_checker, value[key], context) context.pop()
def __call__(self, value, context): for checker in self.__checkers: try: variant_context = context.clone() value = checker(value, variant_context) context.copy_from(variant_context) return value except (OperationError, OperationFailure): pass raise OperationError("%s is of invalid type" % context)
def basic(): from operation.basictypes import (OperationResult, OperationError, OperationFailure, OperationFailureMustLogin) def convert(value): return json.loads(str(value)) # # OperationResult # # OperationResult has status=ok by default. assert convert(OperationResult()) == {"status": "ok"} # But status can be overridden. assert convert(OperationResult(status="bananas")) == {"status": "bananas"} # Other values can be set as well. assert convert(OperationResult(foo=10)) == {"status": "ok", "foo": 10} # Even to None/null. assert convert(OperationResult(foo=None)) == {"status": "ok", "foo": None} # And test OperationResult.set(). result = OperationResult() result.set("foo", 10) assert convert(result) == {"status": "ok", "foo": 10} result.set("foo", [1, 2, 3]) assert convert(result) == {"status": "ok", "foo": [1, 2, 3]} result.set("foo", None) assert convert(result) == {"status": "ok", "foo": None} # # OperationError # assert convert(OperationError("wrong!")) == { "status": "error", "error": "wrong!" } # # OperationFailure # assert (convert(OperationFailure("the code", "the title", "the message")) == { "status": "failure", "code": "the code", "title": "the title", "message": "the message" }) # Check HTML escaping. assert (convert(OperationFailure("<code>", "<title>", "<message>")) == { "status": "failure", "code": "<code>", "title": "<title>", "message": "<message>" }) # Check HTML escaping with is_html=True (title still escaped, but not the # message.) assert (convert(OperationFailure("<code>", "<title>", "<message>", True)) == { "status": "failure", "code": "<code>", "title": "<title>", "message": "<message>" }) print "basic: ok"
def __call__(self, value, context): if context.repository is None: raise OperationError("missing repository in context") return super(Commit, self).__call__(value, context)
def __call__(self, value, context): import gitutils if context.repository is None: raise OperationError("missing repository in context") super(CommitSHA1, self).__call__(value, context) return gitutils.Commit.fromSHA1(context.db, context.repository, value)
def __call__(self, value, context): self.__checker(value, context) if value not in self.__enumeration: raise OperationError("invalid input: %s is not valid" % context)
def __call__(self, value, context): if not isinstance(value, int) or isinstance(value, bool): raise OperationError("invalid input: %s is not an integer" % context)
def __call__(self, value, context): if not isinstance(value, basestring): raise OperationError("invalid input: %s is not a string" % context)
def __call__(self, req, db, user): from operation.typechecker import TypeCheckerContext if user.isAnonymous() and not self.__accept_anonymous_user: return OperationFailureMustLogin() if req.method == "POST": data = req.read() else: data = req.getParameter("data") if not data: raise OperationError("no input") try: value = json_decode(data) except ValueError as error: raise OperationError("invalid input: %s" % str(error)) try: self.__checker(value, TypeCheckerContext(req, db, user)) return self.process(db, user, **value) except OperationError as error: return error except OperationFailure as failure: return failure except dbutils.NoSuchUser as error: return OperationFailure( code="nosuchuser", title="Who is '%s'?" % error.name, message="There is no user in Critic's database named that.") except dbutils.NoSuchReview as error: return OperationFailure( code="nosuchreview", title="Invalid review ID", message="The review ID r/%d is not valid." % error.id) except dbutils.TransactionRollbackError: return OperationFailure( code="transactionrollback", title="Transaction rolled back", message= "Your database transaction rolled back, probably due to a deadlock. Please try again." ) except extensions.extension.ExtensionError as error: return OperationFailure(code="invalidextension", title="Invalid extension", message=error.message) except: # Decode value again since the type checkers might have modified it. value = json_decode(data) error_message = ("User: %s\nReferrer: %s\nData: %s\n\n%s" % (user.name, req.getReferrer(), json_encode(self.sanitize(value), indent=2), traceback.format_exc())) db.rollback() import mailutils import configuration if not user.hasRole(db, "developer"): mailutils.sendExceptionMessage(db, "wsgi[%s]" % req.path, error_message) if configuration.debug.IS_DEVELOPMENT or user.hasRole( db, "developer"): return OperationError(error_message) else: return OperationError( "An unexpected error occurred. " + "A message has been sent to the system administrator(s) " + "with details about the problem.")
def process(self, *args, **kwargs): raise OperationError("not implemented!?!")