Ejemplo n.º 1
0
 def __call__(self, context, value):
     if not self.check_compatibility(context, value):
         raise jsonapi.InputError("%s: expected %s" % (context, self))
     message = self.check(context, value)
     if message is not None:
         raise jsonapi.InputError("%s: %s" % (context, message))
     if hasattr(self, "convert"):
         try:
             value = self.convert(context, value)
         except self.convert_exception as error:
             raise jsonapi.InputError("%s: %s" % (context, error.message))
     if hasattr(self, "process"):
         self.process(context, value)
     return value
Ejemplo n.º 2
0
    def convert(self, context, value):
        result = {}

        def convert_attributes(attributes):
            for attribute_name, attribute_value in attributes:
                with context.push(attribute_name):
                    if attribute_name not in self.attributes:
                        raise jsonapi.InputError("%s: unexpected attribute" %
                                                 context)
                    result[attribute_name] = self.attributes[attribute_name][
                        2](context, attribute_value)

        convert_attributes(
            (attribute_name, attribute_value)
            for attribute_name, attribute_value in value.items()
            if attribute_name in self.prioritized)
        convert_attributes(
            (attribute_name, attribute_value)
            for attribute_name, attribute_value in value.items()
            if attribute_name not in self.prioritized)
        for attribute_name, (required, default, _) in self.attributes.items():
            if attribute_name not in result:
                if required:
                    with context.push(attribute_name):
                        raise jsonapi.InputError("%s: missing attribute" %
                                                 context)
                elif default:
                    result[attribute_name] = None
        return result
Ejemplo n.º 3
0
 def convert_attributes(attributes):
     for attribute_name, attribute_value in attributes:
         with context.push(attribute_name):
             if attribute_name not in self.attributes:
                 raise jsonapi.InputError("%s: unexpected attribute" %
                                          context)
             result[attribute_name] = self.attributes[attribute_name][
                 2](context, attribute_value)
Ejemplo n.º 4
0
    def update(parameters, value, values, data):
        if values and len(values) != 1:
            raise UsageError("Updating multiple users not supported")

        critic = parameters.critic

        if values:
            value = values[0]

        converted = jsonapi.convert(parameters, {"fullname?": str}, data)

        with api.transaction.Transaction(critic) as transaction:
            if "fullname" in converted:
                new_fullname = converted["fullname"].strip()
                if not new_fullname:
                    raise jsonapi.InputError("Empty new fullname")
                transaction.modifyUser(value).setFullname(new_fullname)
Ejemplo n.º 5
0
def ensure(data, path, ensured_value):
    if isinstance(path, (tuple, list)):
        for key in path[:-1]:
            data = data[key]
        key = path[-1]
    else:
        key = path

    if key not in data:
        data[key] = ensured_value
    elif data[key] != ensured_value:
        path_string = "data"
        for key in path:
            if isinstance(key, str):
                path_string += "." + key
            else:
                path_string += "[%d]" % key
        raise jsonapi.InputError("%s: must be %r or omitted" %
                                 (path_string, ensured_value))
Ejemplo n.º 6
0
    def create(parameters, value, values, data):
        critic = parameters.critic
        user = parameters.context.get("users", critic.actual_user)
        path = parameters.subresource_path

        if value and path == ["replies"]:
            assert isinstance(value, api.comment.Comment)
            Comments.setAsContext(parameters, value)
            raise jsonapi.InternalRedirect("v1/replies")

        if value or values or path:
            raise jsonapi.UsageError("Invalid POST request")

        converted = jsonapi.convert(
            parameters,
            {
                "type": api.comment.Comment.TYPE_VALUES,
                "review!?": api.review.Review,
                "author?": api.user.User,
                "location?": {
                    # Note: "general" not included here; |location| should be
                    #       omitted instead.
                    "type": frozenset(["commit-message", "file-version"]),
                    "first_line": int,
                    "last_line": int,
                    "commit?": api.commit.Commit,
                    "file?": api.file.File,
                    "changeset?": api.changeset.Changeset,
                    "side?": frozenset(["old", "new"]),
                },
                "text": str
            },
            data)

        review = jsonapi.deduce("v1/reviews", parameters)

        if not review:
            if "review" not in converted:
                raise jsonapi.UsageError("No review specified")
            review = converted["review"]
        elif "review" in converted and review != converted["review"]:
            raise jsonapi.UsageError("Conflicting reviews specified")

        if "author" in converted:
            author = converted["author"]
        else:
            author = critic.actual_user

        if converted["type"] == "issue":
            expected_class = api.comment.Issue
        else:
            expected_class = api.comment.Note

        converted_location = converted.get("location")
        if converted_location:
            location_type = converted_location.pop("type")
            if location_type == "commit-message":
                required_fields = set(("first_line", "last_line", "commit"))
                optional_fields = set()
            else:
                required_fields = set(("first_line", "last_line", "file"))
                optional_fields = set(("commit", "changeset", "side"))
            accepted_fields = required_fields | optional_fields

            for required_field in required_fields:
                if required_field not in converted_location:
                    raise jsonapi.InputError(
                        "data.location.%s: missing attribute" % required_field)
            for actual_field in converted_location.keys():
                if actual_field not in accepted_fields:
                    raise jsonapi.InputError(
                        "data.location.%s: unexpected attribute" %
                        actual_field)

            if location_type == "commit-message":
                max_line = len(
                    converted_location["commit"].message.splitlines())
            else:
                if "commit" in converted_location:
                    if "changeset" in converted_location:
                        raise jsonapi.InputError(
                            "data.location: only one of commit and changeset "
                            "can be specified")
                    changeset = None
                    side = None
                    commit = converted_location["commit"]
                elif "changeset" not in converted_location:
                    raise jsonapi.InputError(
                        "data.location: one of commit and changeset must be "
                        "specified")
                elif "side" not in converted_location:
                    raise jsonapi.InputError(
                        "data.location.side: missing attribute (required when "
                        "changeset is specified)")
                else:
                    changeset = converted_location["changeset"]
                    side = converted_location["side"]
                    commit = None

            first_line = converted_location["first_line"]
            last_line = converted_location["last_line"]

            if location_type == "commit-message":
                location = api.comment.CommitMessageLocation.make(
                    critic, first_line, last_line,
                    converted_location["commit"])
            else:
                location = api.comment.FileVersionLocation.make(
                    critic, first_line, last_line, converted_location["file"],
                    changeset, side, commit)
        else:
            location = None

        result = []

        def collectComment(comment):
            assert isinstance(comment, expected_class), repr(comment)
            result.append(comment)

        with api.transaction.Transaction(critic) as transaction:
            transaction \
                .modifyReview(review) \
                .createComment(
                    comment_type=converted["type"],
                    author=author,
                    text=converted["text"],
                    location=location,
                    callback=collectComment)

        assert len(result) == 1, repr(result)
        return result[0], None