def multiple(parameters): """TODO: add documentation""" commit = jsonapi.deduce("v1/commits", parameters) if commit is None: raise jsonapi.UsageError( "commit must be specified, ex. &commit=<sha1>") file_obj = jsonapi.deduce("v1/files", parameters) blob_sha1 = commit.getFileInformation(file_obj).sha1 return api.filecontent.fetch( parameters.critic, commit.repository, blob_sha1, file_obj)
def multiple(parameters): """TODO: add documentation""" changeset = jsonapi.deduce("v1/changesets", parameters) if changeset is None: raise jsonapi.UsageError( "changeset needs to be specified, ex. &changeset=<id>") repository = jsonapi.deduce("v1/repositories", parameters) if repository is None: raise jsonapi.UsageError( "repository needs to be specified, " "ex. &repository=<id or name>") return api.filediff.fetchAll(parameters.critic, changeset)
def multiple(parameters): """Retrieve all reviews in this system. repository : REPOSITORY : - Include only reviews in one repository, identified by the repository's unique numeric id or short-name. state : STATE[,STATE,...] : - Include only reviews in the specified state. Valid values are: <code>open</code>, <code>closed</code>, <code>dropped</code>.""" repository = jsonapi.deduce("v1/repositories", parameters) state_parameter = parameters.getQueryParameter("state") if state_parameter: state = set(state_parameter.split(",")) invalid = state - api.review.Review.STATE_VALUES if invalid: raise jsonapi.UsageError("Invalid review state values: %s" % ", ".join(map(repr, sorted(invalid)))) else: state = None return api.review.fetchAll(parameters.critic, repository=repository, state=state)
def multiple(parameters): """Retrieve all branches in the Git repositories. repository : REPOSITORY : - Include only branches in one repository, identified by the repository's unique numeric id or short-name. name : NAME : string Retrieve only the branch with the specified name. The name should <em>not</em> include the "refs/heads/" prefix. When this parameter is specified a repository must be specified as well, either in the resource path or using the <code>repository</code> parameter.""" repository = jsonapi.deduce("v1/repositories", parameters) name_parameter = parameters.getQueryParameter("name") if name_parameter: if repository is None: raise jsonapi.UsageError( "Named branch access must have repository specified.") return api.branch.fetch(parameters.critic, repository=repository, name=name_parameter) return api.branch.fetchAll(parameters.critic, repository=repository)
def multiple(parameters): """Retrieve a single extension by key or all extensions. key : KEY : string Retrieve only the extension with the given key. This is equivalent to accessing /api/v1/extensions/EXTENSION_ID with that extension's numeric id. When used, other parameters are ignored. installed_by : INSTALLED_BY : integer or string Retrieve only extensions installed by the specified user. The user can be identified by numeric id or username.""" key_parameter = parameters.getQueryParameter("key") if key_parameter: return api.extension.fetch(parameters.critic, key=key_parameter) installed_by = jsonapi.from_parameter( "v1/users", "installed_by", parameters) return api.extension.fetchAll( parameters.critic, publisher=jsonapi.deduce("v1/users", parameters), installed_by=installed_by)
def multiple(parameters): """Retrieve all reviews in this system. repository : REPOSITORY : - Include only reviews in one repository, identified by the repository's unique numeric id or short-name. state : STATE[,STATE,...] : - Include only reviews in the specified state. Valid values are: <code>open</code>, <code>closed</code>, <code>dropped</code>.""" repository = jsonapi.deduce("v1/repositories", parameters) state_parameter = parameters.getQueryParameter("state") if state_parameter: state = set(state_parameter.split(",")) invalid = state - api.review.Review.STATE_VALUES if invalid: raise jsonapi.UsageError( "Invalid review state values: %s" % ", ".join(map(repr, sorted(invalid)))) else: state = None return api.review.fetchAll( parameters.critic, repository=repository, state=state)
def multiple(parameters): """Retrieve a single commit identified by its SHA-1 sum. sha1 : COMMIT_SHA1 : string Retrieve a commit identified by its SHA-1 sum. The SHA-1 sum can be abbreviated, but must be at least 4 characters long, and must be unambigious in the repository. repository : REPOSITORY : - Specify repository to access, identified by its unique numeric id or short-name. Required unless a repository is specified in the resource path.""" sha1_parameter = parameters.getQueryParameter("sha1") if sha1_parameter is None: raise jsonapi.UsageError("Missing required SHA-1 parameter.") if not re.match("[0-9A-Fa-f]{4,40}$", sha1_parameter): raise jsonapi.UsageError("Invalid SHA-1 parameter: %r" % sha1_parameter) repository = jsonapi.deduce("v1/repositories", parameters) if repository is None: raise jsonapi.UsageError( "Commit reference must have repository specified.") return api.commit.fetch(repository, sha1=sha1_parameter)
def multiple(parameters): """Retrieve a single extension by key or all extensions. key : KEY : string Retrieve only the extension with the given key. This is equivalent to accessing /api/v1/extensions/EXTENSION_ID with that extension's numeric id. When used, other parameters are ignored. installed_by : INSTALLED_BY : integer or string Retrieve only extensions installed by the specified user. The user can be identified by numeric id or username.""" key_parameter = parameters.getQueryParameter("key") if key_parameter: return api.extension.fetch(parameters.critic, key=key_parameter) installed_by = jsonapi.from_parameter("v1/users", "installed_by", parameters) return api.extension.fetchAll(parameters.critic, publisher=jsonapi.deduce( "v1/users", parameters), installed_by=installed_by)
def multiple(parameters): """Retrieve a single commit identified by its SHA-1 sum. sha1 : COMMIT_SHA1 : string Retrieve a commit identified by its SHA-1 sum. The SHA-1 sum can be abbreviated, but must be at least 4 characters long, and must be unambigious in the repository. repository : REPOSITORY : - Specify repository to access, identified by its unique numeric id or short-name. Required unless a repository is specified in the resource path.""" sha1_parameter = parameters.getQueryParameter("sha1") if sha1_parameter is None: raise jsonapi.UsageError("Missing required SHA-1 parameter.") if not re.match("[0-9A-Fa-f]{4,40}$", sha1_parameter): raise jsonapi.UsageError( "Invalid SHA-1 parameter: %r" % sha1_parameter) repository = jsonapi.deduce("v1/repositories", parameters) if repository is None: raise jsonapi.UsageError( "Commit reference must have repository specified.") return api.commit.fetch(repository, sha1=sha1_parameter)
def multiple(parameters): """Retrieve all reviewable file changes in a review. review : REVIEW_ID : - Retrieve the reviewable changes in the specified review. changeset : CHANGESET_ID : - Retrieve the reviewable changes in the specified changeset. file : FILE : - Retrieve the reviewable changes in the specified file only. assignee : USER : - Retrieve reviewable changes assigned to the specified user only. state : STATE : "pending" or "reviewed" Retrieve reviewable changes in the specified state only.""" review = jsonapi.deduce("v1/reviews", parameters) changeset = jsonapi.deduce("v1/changesets", parameters) if not review: raise jsonapi.UsageError("Missing required parameter: review") file = jsonapi.from_parameter("v1/files", "file", parameters) assignee = jsonapi.from_parameter("v1/users", "assignee", parameters) state_parameter = parameters.getQueryParameter("state") if state_parameter is None: is_reviewed = None else: if state_parameter not in ("pending", "reviewed"): raise jsonapi.UsageError( "Invalid parameter value: state=%r " "(value values are 'pending' and 'reviewed')" % state_parameter) is_reviewed = state_parameter == "reviewed" return api.reviewablefilechange.fetchAll(parameters.critic, review, changeset, file, assignee, is_reviewed)
def multiple(parameters): """Retrieve all reviewable file changes in a review. review : REVIEW_ID : - Retrieve the reviewable changes in the specified review. changeset : CHANGESET_ID : - Retrieve the reviewable changes in the specified changeset. file : FILE : - Retrieve the reviewable changes in the specified file only. assignee : USER : - Retrieve reviewable changes assigned to the specified user only. state : STATE : "pending" or "reviewed" Retrieve reviewable changes in the specified state only.""" review = jsonapi.deduce("v1/reviews", parameters) changeset = jsonapi.deduce("v1/changesets", parameters) if not review: raise jsonapi.UsageError("Missing required parameter: review") file = jsonapi.from_parameter("v1/files", "file", parameters) assignee = jsonapi.from_parameter("v1/users", "assignee", parameters) state_parameter = parameters.getQueryParameter("state") if state_parameter is None: is_reviewed = None else: if state_parameter not in ("pending", "reviewed"): raise jsonapi.UsageError( "Invalid parameter value: state=%r " "(value values are 'pending' and 'reviewed')" % state_parameter) is_reviewed = state_parameter == "reviewed" return api.reviewablefilechange.fetchAll( parameters.critic, review, changeset, file, assignee, is_reviewed)
def single(parameters, argument): """TODO: add documentation""" changeset = jsonapi.deduce("v1/changesets", parameters) if changeset is None: raise jsonapi.UsageError( "changeset needs to be specified, ex. &changeset=<id>") repository = jsonapi.deduce("v1/repositories", parameters) if repository is None: raise jsonapi.UsageError( "repository needs to be specified, " "ex. &repository=<id or name>") file = api.file.fetch(parameters.critic, jsonapi.numeric_id(argument)) filechange = api.filechange.fetch(parameters.critic, changeset, file) return api.filediff.fetch(parameters.critic, filechange)
def multiple(parameters): """Retrieve all labeled access control profile selectors in the system. profile : PROFILE_ID : integer Include only selectors selecting the given profile, identified by its unique numeric id.""" profile = jsonapi.deduce("v1/accesscontrolprofiles", parameters) return api.labeledaccesscontrolprofile.fetchAll( parameters.critic, profile=profile)
def multiple(parameters): """Retrieve all rebases in this system. review : REVIEW_ID : - Include only rebases of one review, identified by the review's unique numeric id.""" review = jsonapi.deduce("v1/reviews", parameters) return api.log.rebase.fetchAll(parameters.critic, review=review)
def multiple(parameters): """Retrieve all labeled access control profile selectors in the system. profile : PROFILE_ID : integer Include only selectors selecting the given profile, identified by its unique numeric id.""" profile = jsonapi.deduce("v1/accesscontrolprofiles", parameters) return api.labeledaccesscontrolprofile.fetchAll(parameters.critic, profile=profile)
def location_json(location): if not location: return None if location.type == "file-version": changeset = jsonapi.deduce("v1/changesets", parameters) if not changeset: # FileVersionLocation.translateTo() only allows one, so let # a deduced changeset win over a deduced commit. commit = jsonapi.deduce("v1/commits", parameters) else: commit = None if changeset or commit: location = location.translateTo(changeset=changeset, commit=commit) if not location: raise jsonapi.ResourceSkipped( "Comment not present in changeset/commit") result = { "type": location.type, "first_line": location.first_line, "last_line": location.last_line } if location.type == "commit-message": result.update({ "commit": location.commit }) else: result.update({ "file": location.file, "changeset": location.changeset, "side": location.side, "commit": location.commit, "is_translated": location.is_translated }) return result
def multiple(parameters): """All access tokens.""" user = jsonapi.deduce("v1/users", parameters) # Only administrators are allowed to access all access tokens in the # system. if user is None: api.PermissionDenied.raiseUnlessAdministrator(parameters.critic) return api.accesstoken.fetchAll(parameters.critic, user=user)
def location_json(location): if not location: return None if location.type == "file-version": changeset = jsonapi.deduce("v1/changesets", parameters) if not changeset: # FileVersionLocation.translateTo() only allows one, so let # a deduced changeset win over a deduced commit. commit = jsonapi.deduce("v1/commits", parameters) else: commit = None if changeset or commit: location = location.translateTo(changeset=changeset, commit=commit) if not location: raise jsonapi.ResourceSkipped( "Comment not present in changeset/commit") result = { "type": location.type, "first_line": location.first_line, "last_line": location.last_line } if location.type == "commit-message": result.update({"commit": location.commit}) else: result.update({ "file": location.file, "changeset": location.changeset, "side": location.side, "commit": location.commit, "is_translated": location.is_translated }) return result
def multiple(parameters): """Retrieve replies to a comment. comment : COMMENT_ID : integer Retrieve all replies to the specified comment.""" comment = jsonapi.deduce("v1/comments", parameters) if not comment: raise jsonapi.UsageError("A comment must be identified.") return comment.replies
def multiple(parameters): """Retrieve all filechanges (changed files) from a changeset. changeset : CHANGESET : - Retrieve the changed from a changeset indentified by its unique numeric id. reposititory : REPOSITORY : - The repository in which the files exist.""" changeset = jsonapi.deduce("v1/changesets", parameters) return api.filechange.fetchAll(parameters.critic, changeset)
def create(parameters, value, values, data): critic = parameters.critic user = parameters.context.get("users", critic.actual_user) if value or values: raise jsonapi.UsageError("Invalid POST request") converted = jsonapi.convert( parameters, { "review?": api.review.Review, "comment?": 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 "comment" in converted: comment_text = converted["comment"].strip() if not comment_text: raise jsonapi.UsageError("Empty comment specified") else: comment_text = None result = [] def collectBatch(batch): assert isinstance(batch, api.batch.Batch) result.append(batch) with api.transaction.Transaction(critic) as transaction: modifier = transaction.modifyReview(review) if comment_text: note = modifier.createComment(comment_type="note", author=critic.actual_user, text=comment_text) else: note = None modifier.submitChanges(note, callback=collectBatch) assert len(result) == 1 return result[0], None
def json(value, parameters): """Changeset { "id": integer, // the changeset's id "type": string, // the changeset type (direct, custom, merge, conflict) "from_commit": integer, // commit id for changesets from_commit "to_commit": integer, // commit id for changesets to_commit "files": integer[], // a list of all files changed in this changeset "review_state": ReviewState or null, } ReviewState { "review": integer, "comments": integer[], }""" def review_state(review): if not review: return None comments = api.comment.fetchAll( parameters.critic, review=review, changeset=value) try: reviewablefilechanges = api.reviewablefilechange.fetchAll( parameters.critic, review=review, changeset=value) except api.reviewablefilechange.InvalidChangeset: reviewablefilechanges = None return { "review": review, "commments": comments, "reviewablefilechanges": reviewablefilechanges, } review = jsonapi.deduce("v1/reviews", parameters) contributing_commits = value.contributing_commits if contributing_commits: contributing_commits = list(contributing_commits.topo_ordered) return parameters.filtered( "changesets", { "id": value.id, "type": value.type, "from_commit": value.from_commit, "to_commit": value.to_commit, "files": value.files, "contributing_commits": contributing_commits, "review_state": review_state(review) })
def create(parameters, value, values, data): critic = parameters.critic user = critic.actual_user converted = jsonapi.convert( parameters, { "new_upstream?": str, "history_rewrite?": bool }, data) new_upstream = converted.get("new_upstream") history_rewrite = converted.get("history_rewrite") if (new_upstream is None) == (history_rewrite is None): raise jsonapi.UsageError( "Exactly one of the arguments new_upstream and history_rewrite " "must be specified.") if history_rewrite == False: raise jsonapi.UsageError( "history_rewrite must be true, or omitted.") review = jsonapi.deduce("v1/reviews", parameters) if review is None: raise jsonapi.UsageError( "review must be specified when preparing a rebase") if history_rewrite is not None: expected_type = api.log.rebase.HistoryRewrite else: expected_type = api.log.rebase.MoveRebase result = [] def collectRebase(rebase): assert isinstance(rebase, expected_type), repr(rebase) result.append(rebase) with api.transaction.Transaction(critic) as transaction: transaction \ .modifyReview(review) \ .prepareRebase( user, new_upstream, history_rewrite, callback=collectRebase) assert len(result) == 1, repr(result) return result[0], None
def create(parameters, value, values, data): critic = parameters.critic user = parameters.context.get("users", critic.actual_user) if value or values: raise jsonapi.UsageError("Invalid POST request") converted = jsonapi.convert( parameters, { "comment?": api.comment.Comment, "author?": api.user.User, "text": str }, data) comment = jsonapi.deduce("v1/comments", parameters) if not comment: if "comment" not in converted: raise jsonapi.UsageError("No comment specified") comment = converted["comment"] elif "comment" in converted and comment != converted["comment"]: raise jsonapi.UsageError("Conflicting comments specified") if "author" in converted: author = converted["author"] else: author = critic.actual_user if not converted["text"].strip(): raise jsonapi.UsageError("Empty reply") result = [] def collectReply(reply): assert isinstance(reply, api.reply.Reply) result.append(reply) with api.transaction.Transaction(critic) as transaction: transaction \ .modifyReview(comment.review) \ .modifyComment(comment) \ .addReply( author=author, text=converted["text"], callback=collectReply) assert len(result) == 1 return result[0], None
def deduce(parameters): repository = parameters.context.get("repositories") repository_parameter = parameters.getQueryParameter("repository") if repository_parameter is not None: if repository is not None: raise jsonapi.UsageError( "Redundant query parameter: repository=%s" % repository_parameter) repository = from_argument(parameters, repository_parameter) if repository is not None: return repository review = jsonapi.deduce("v1/reviews", parameters) if review is not None: return review.repository
def deduce(parameters): repository = jsonapi.deduce("v1/repositories", parameters) changeset = parameters.context.get(Changesets.name) changeset_parameter = parameters.getQueryParameter("changeset") if changeset_parameter is not None: if changeset is not None: raise jsonapi.UsageError( "Redundant query parameter: changeset=%s" % changeset_parameter) if repository is None: raise jsonapi.UsageError( "repository needs to be specified, ex. &repository=<id>") changeset_id = jsonapi.numeric_id(changeset_parameter) changeset = api.changeset.fetch( parameters.critic, repository, changeset_id=changeset_id) return changeset
def single(parameters, argument): """Retrieve one (or more) replies to comments. REPLY_ID : integer Retrieve a reply identified by its unique numeric id.""" reply = api.reply.fetch( parameters.critic, reply_id=jsonapi.numeric_id(argument)) comment = jsonapi.deduce("v1/comments", parameters) if comment and comment != reply.comment: raise jsonapi.PathError( "Reply does not belong to specified comment") return reply
def multiple(parameters): """All repository filters. repository : REPOSITORY : - Include only filters for the specified repository, identified by its unique numeric id or short-name.""" user = parameters.context["users"] repository = jsonapi.deduce("v1/repositories", parameters) if repository: repository_filters = user.repository_filters.get(repository, []) else: repository_filters = itertools.chain( *user.repository_filters.values()) return jsonapi.sorted_by_id(repository_filters)
def deduce(parameters): changeset = jsonapi.deduce("v1/changesets", parameters) if changeset is None: raise jsonapi.UsageError( "changeset needs to be specified, ex. &changeset=<id>") filechange = parameters.context.get(FileChanges.name) filechange_parameter = parameters.getQueryParameter("filechange") if filechange_parameter is not None: if filechange is not None: raise jsonapi.UsageError( "Redundant query parameter: filechange=%s" % filechange_parameter) filechange_id = jsonapi.numeric_id(filechange_parameter) filechange = api.filechange.fetch(parameters.critic, changeset, filechange_id) return filechange
def single(parameters, argument): """Retrieve one (or more) comments in reviews. COMMENT_ID : integer Retrieve a comment identified by its unique numeric id.""" comment = api.comment.fetch(parameters.critic, comment_id=jsonapi.numeric_id(argument)) review = jsonapi.deduce("v1/reviews", parameters) if review and review != comment.review: raise jsonapi.PathError( "Comment does not belong to specified review") return Comments.setAsContext(parameters, comment)
def single(parameters, argument): """Retrieve one (or more) batches in reviews. BATCH_ID : integer Retrieve a batch identified by its unique numeric id.""" batch = api.batch.fetch( parameters.critic, batch_id=jsonapi.numeric_id(argument)) review = jsonapi.deduce("v1/reviews", parameters) if review and review != batch.review: raise jsonapi.PathError( "Batch does not belong to specified review") return Batches.setAsContext(parameters, batch)
def deduce(parameters): changeset = jsonapi.deduce("v1/changesets", parameters) if changeset is None: raise jsonapi.UsageError( "changeset needs to be specified, ex. &changeset=<id>") filechange = parameters.context.get(FileChanges.name) filechange_parameter = parameters.getQueryParameter("filechange") if filechange_parameter is not None: if filechange is not None: raise jsonapi.UsageError( "Redundant query parameter: filechange=%s" % filechange_parameter) filechange_id = jsonapi.numeric_id(filechange_parameter) filechange = api.filechange.fetch( parameters.critic, changeset, filechange_id) return filechange
def single(parameters, argument): """Retrieve one (or more) comments in reviews. COMMENT_ID : integer Retrieve a comment identified by its unique numeric id.""" comment = api.comment.fetch( parameters.critic, comment_id=jsonapi.numeric_id(argument)) review = jsonapi.deduce("v1/reviews", parameters) if review and review != comment.review: raise jsonapi.PathError( "Comment does not belong to specified review") return Comments.setAsContext(parameters, comment)
def single(parameters, argument): """Retrieve one (or more) replies to comments. REPLY_ID : integer Retrieve a reply identified by its unique numeric id.""" reply = api.reply.fetch(parameters.critic, reply_id=jsonapi.numeric_id(argument)) comment = jsonapi.deduce("v1/comments", parameters) if comment and comment != reply.comment: raise jsonapi.PathError( "Reply does not belong to specified comment") return reply
def create(parameters, value, values, data): critic = parameters.critic user = parameters.context.get("users", critic.actual_user) if value or values: raise jsonapi.UsageError("Invalid POST request") converted = jsonapi.convert(parameters, { "comment?": api.comment.Comment, "author?": api.user.User, "text": str }, data) comment = jsonapi.deduce("v1/comments", parameters) if not comment: if "comment" not in converted: raise jsonapi.UsageError("No comment specified") comment = converted["comment"] elif "comment" in converted and comment != converted["comment"]: raise jsonapi.UsageError("Conflicting comments specified") if "author" in converted: author = converted["author"] else: author = critic.actual_user if not converted["text"].strip(): raise jsonapi.UsageError("Empty reply") result = [] def collectReply(reply): assert isinstance(reply, api.reply.Reply) result.append(reply) with api.transaction.Transaction(critic) as transaction: transaction \ .modifyReview(comment.review) \ .modifyComment(comment) \ .addReply( author=author, text=converted["text"], callback=collectReply) assert len(result) == 1 return result[0], None
def create(parameters, value, values, data): critic = parameters.critic user = critic.actual_user converted = jsonapi.convert(parameters, { "new_upstream?": str, "history_rewrite?": bool }, data) new_upstream = converted.get("new_upstream") history_rewrite = converted.get("history_rewrite") if (new_upstream is None) == (history_rewrite is None): raise jsonapi.UsageError( "Exactly one of the arguments new_upstream and history_rewrite " "must be specified.") if history_rewrite == False: raise jsonapi.UsageError( "history_rewrite must be true, or omitted.") review = jsonapi.deduce("v1/reviews", parameters) if review is None: raise jsonapi.UsageError( "review must be specified when preparing a rebase") if history_rewrite is not None: expected_type = api.log.rebase.HistoryRewrite else: expected_type = api.log.rebase.MoveRebase result = [] def collectRebase(rebase): assert isinstance(rebase, expected_type), repr(rebase) result.append(rebase) with api.transaction.Transaction(critic) as transaction: transaction \ .modifyReview(review) \ .prepareRebase( user, new_upstream, history_rewrite, callback=collectRebase) assert len(result) == 1, repr(result) return result[0], None
def multiple(parameters): """All repository filters. repository : REPOSITORY : - Include only filters for the specified repository, identified by its unique numeric id or short-name.""" user = parameters.context["users"] repository = jsonapi.deduce("v1/repositories", parameters) if repository: repository_filters = user.repository_filters.get( repository, []) else: repository_filters = itertools.chain( *user.repository_filters.values()) return jsonapi.sorted_by_id(repository_filters)
def single(parameters, argument): """Retrieve one (or more) commits from a Git repository. COMMIT_ID : integer Retrieve a commit identified by its unique numeric id. repository : REPOSITORY : - Specify repository to access, identified by its unique numeric id or short-name. Required unless a repository is specified in the resource path.""" repository = jsonapi.deduce("v1/repositories", parameters) if repository is None: raise jsonapi.UsageError( "Commit reference must have repository specified.") return Commits.setAsContext(parameters, api.commit.fetch( repository, commit_id=jsonapi.numeric_id(argument)))
def single(parameters, argument): """Retrieve one (or more) filechanges (changed files). FILE_ID : integer Retrieve the changes to a file identified by its unique numeric id. changeset : CHANGESET : - Retrieve the changes from a changeset identified by its unique numeric id. reposititory : REPOSITORY : - The repository in which the files exist.""" changeset = jsonapi.deduce("v1/changesets", parameters) file = api.file.fetch(parameters.critic, jsonapi.numeric_id(argument)) return FileChanges.setAsContext( parameters, api.filechange.fetch(parameters.critic, changeset, file))
def single(parameters, argument): """Retrieve one (or more) filechanges (changed files). FILE_ID : integer Retrieve the changes to a file identified by its unique numeric id. changeset : CHANGESET : - Retrieve the changes from a changeset identified by its unique numeric id. reposititory : REPOSITORY : - The repository in which the files exist.""" changeset = jsonapi.deduce("v1/changesets", parameters) file = api.file.fetch(parameters.critic, jsonapi.numeric_id(argument)) return FileChanges.setAsContext( parameters, api.filechange.fetch( parameters.critic, changeset, file))
def single(parameters, argument): """Retrieve one (or more) commits from a Git repository. COMMIT_ID : integer Retrieve a commit identified by its unique numeric id. repository : REPOSITORY : - Specify repository to access, identified by its unique numeric id or short-name. Required unless a repository is specified in the resource path.""" repository = jsonapi.deduce("v1/repositories", parameters) if repository is None: raise jsonapi.UsageError( "Commit reference must have repository specified.") return Commits.setAsContext( parameters, api.commit.fetch(repository, commit_id=jsonapi.numeric_id(argument)))
def single(parameters, argument): """Retrieve one (or more) changesets. CHANGESET_ID : integer Retrieve a changeset identified by its unique numeric id. repository : REPOSITORY : - Specify repository to access, identified by its unique numeric id or short-name. Required unless a repository is specified in the resource path.""" repository = jsonapi.deduce("v1/repositories", parameters) if repository is None: raise jsonapi.UsageError( "repository needs to be specified, ex. &repository=<id>") return Changesets.setAsContext(parameters, api.changeset.fetch( parameters.critic, repository, jsonapi.numeric_id(argument)))
def multiple(parameters): """Retrieve all batches in the system (or review.) review : REVIEW_ID : integer Retrieve only batches in the specified review. Can only be used if a review is not specified in the resource path. author : AUTHOR : integer or string Retrieve only batches authored by the specified user, identified by the user's unique numeric id or user name. unpublished : UNPUBLISHED : 'yes' Retrieve a single batch representing the current user's unpublished changes to a review. Must be combined with `review` and cannot be combined with `author`.""" critic = parameters.critic review = jsonapi.deduce("v1/reviews", parameters) author = jsonapi.from_parameter("v1/users", "author", parameters) unpublished_parameter = parameters.getQueryParameter("unpublished") if unpublished_parameter is not None: if unpublished_parameter == "yes": if author is not None: raise jsonapi.UsageError( "Parameters 'author' and 'unpublished' cannot be " "combined") return api.batch.fetchUnpublished(critic, review) else: raise jsonapi.UsageError( "Invalid 'unpublished' parameter: %r (must be 'yes')" % unpublished_parameter) return api.batch.fetchAll(critic, review=review, author=author)
def multiple(parameters): """Retrieve all branches in the Git repositories. repository : REPOSITORY : - Include only branches in one repository, identified by the repository's unique numeric id or short-name. name : NAME : string Retrieve only the branch with the specified name. The name should <em>not</em> include the "refs/heads/" prefix. When this parameter is specified a repository must be specified as well, either in the resource path or using the <code>repository</code> parameter.""" repository = jsonapi.deduce("v1/repositories", parameters) name_parameter = parameters.getQueryParameter("name") if name_parameter: if repository is None: raise jsonapi.UsageError( "Named branch access must have repository specified.") return api.branch.fetch( parameters.critic, repository=repository, name=name_parameter) return api.branch.fetchAll(parameters.critic, repository=repository)
def fromParameter(value, parameters): repository = jsonapi.deduce("v1/repositories", parameters) commit_id, ref = jsonapi.id_or_name(value) return api.commit.fetch(repository, commit_id, ref=ref)
def multiple(parameters): """Retrieve all comments in the system (or review.) with_reply : REPLY_ID : integer Retrieve only the comment to which the specified reply is a reply. This is equivalent to accessing /api/v1/comments/COMMENT_ID with that comment's numeric id. When used, any other parameters are ignored. review : REVIEW_ID : integer Retrieve only comments in the specified review. Can only be used if a review is not specified in the resource path. author : AUTHOR : integer or string Retrieve only comments authored by the specified user, identified by the user's unique numeric id or user name. comment_type : TYPE : - Retrieve only comments of the specified type. Valid values are: <code>issue</code> and <code>note</code>. state : STATE : - Retrieve only issues in the specified state. Valid values are: <code>open</code>, <code>addressed</code> and <code>resolved</code>. location_type : LOCATION : - Retrieve only comments in the specified type of location. Valid values are: <code>general</code>, <code>commit-message</code> and <code>file-version</code>. changeset : CHANGESET_ID : integer Retrieve only comments visible in the specified changeset. Can not be combined with the <code>commit</code> parameter. commit : COMMIT : integer or string Retrieve only comments visible in the specified commit, either in its commit message or in the commit's version of a file. Combine with the <code>location_type</code> parameter to select only one of those possibilities. Can not be combined with the <code>changeset</code> parameter.""" critic = parameters.critic reply = jsonapi.from_parameter("v1/replies", "with_reply", parameters) if reply: return reply.comment review = jsonapi.deduce("v1/reviews", parameters) author = jsonapi.from_parameter("v1/users", "author", parameters) comment_type_parameter = parameters.getQueryParameter("comment_type") if comment_type_parameter: if comment_type_parameter not in api.comment.Comment.TYPE_VALUES: raise jsonapi.UsageError("Invalid comment-type parameter: %r" % comment_type_parameter) comment_type = comment_type_parameter else: comment_type = None state_parameter = parameters.getQueryParameter("state") if state_parameter: if state_parameter not in api.comment.Issue.STATE_VALUES: raise jsonapi.UsageError( "Invalid state parameter: %r" % state_parameter) state = state_parameter else: state = None location_type_parameter = parameters.getQueryParameter("location_type") if location_type_parameter: if location_type_parameter not in api.comment.Location.TYPE_VALUES: raise jsonapi.UsageError("Invalid location-type parameter: %r" % location_type_parameter) location_type = location_type_parameter else: location_type = None changeset = jsonapi.deduce("v1/changesets", parameters) commit = jsonapi.deduce("v1/commits", parameters) if changeset and commit: raise jsonapi.UsageError( "Incompatible parameters: changeset and commit") return api.comment.fetchAll(critic, review=review, author=author, comment_type=comment_type, state=state, location_type=location_type, changeset=changeset, commit=commit)
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
def json(value, parameters): """TODO: add documentation""" def part_as_dict(part): if not part.type and not part.state: return part.content dict_part = { "content": part.content } if part.type: dict_part["type"] = part.type if part.state: dict_part["state"] = part.state return dict_part def line_as_dict(line): dict_line = { "type": line.type_string, "old_offset": line.old_offset, "new_offset": line.new_offset, } dict_line["content"] = [part_as_dict(part) for part in line.content] return dict_line def chunk_as_dict(chunk): return { "content": [line_as_dict(line) for line in chunk.lines], "old_offset": chunk.old_offset, "old_count": chunk.old_count, "new_offset": chunk.new_offset, "new_count": chunk.new_count } context_lines = parameters.getQueryParameter( "context_lines", int, ValueError) if context_lines is not None: if context_lines < 0: raise jsonapi.UsageError( "Negative number of context lines not supported") else: # TODO: load this from the user's config (or make it mandatory and # let the client handle config loading). context_lines = 3 comment = jsonapi.deduce("v1/comments", parameters) if comment is not None: comments = [comment] ignore_chunks = True else: review = jsonapi.deduce("v1/reviews", parameters) if review is not None: comments = api.comment.fetchAll( parameters.critic, review=review, changeset=value.filechange.changeset) else: comments = None ignore_chunks = False macro_chunks = value.getMacroChunks( context_lines, comments, ignore_chunks) dict_chunks = [chunk_as_dict(chunk) for chunk in macro_chunks] return parameters.filtered( "filediffs", { "file": value.filechange, "changeset": value.filechange.changeset, "macro_chunks": dict_chunks, "old_count": value.old_count, "new_count": value.new_count })