def api_view_issues(repo, username=None, namespace=None): """ List project's issues --------------------- List issues of a project. :: GET /api/0/<repo>/issues GET /api/0/<namespace>/<repo>/issues :: GET /api/0/fork/<username>/<repo>/issues GET /api/0/fork/<username>/<namespace>/<repo>/issues Parameters ^^^^^^^^^^ +---------------+---------+--------------+---------------------------+ | Key | Type | Optionality | Description | +===============+=========+==============+===========================+ | ``status`` | string | Optional | | Filters the status of | | | | | issues. Fetches all the | | | | | issues if status is | | | | | ``all``. Default: | | | | | ``Open`` | +---------------+---------+--------------+---------------------------+ | ``tags`` | string | Optional | | A list of tags you | | | | | wish to filter. If | | | | | you want to filter | | | | | for issues not having | | | | | a tag, add an | | | | | exclamation mark in | | | | | front of it | +---------------+---------+--------------+---------------------------+ | ``assignee`` | string | Optional | | Filter the issues | | | | | by assignee | +---------------+---------+--------------+---------------------------+ | ``author`` | string | Optional | | Filter the issues | | | | | by creator | +---------------+---------+--------------+---------------------------+ | ``milestones``| list of | Optional | | Filter the issues | | | strings | | by milestone | +---------------+---------+--------------+---------------------------+ | ``priority`` | string | Optional | | Filter the issues | | | | | by priority | +---------------+---------+--------------+---------------------------+ | ``no_stones`` | boolean | Optional | | If true returns only the| | | | | issues having no | | | | | milestone, if false | | | | | returns only the issues | | | | | having a milestone | +---------------+---------+--------------+---------------------------+ | ``since`` | string | Optional | | Filter the issues | | | | | updated after this date.| | | | | The date can either be | | | | | provided as an unix date| | | | | or in the format Y-M-D | +---------------+---------+--------------+---------------------------+ | ``order`` | string | Optional | | Set the ordering of the | | | | | issues. This can be | | | | | ``asc`` or ``desc``. | | | | | Default: ``desc`` | +---------------+---------+--------------+---------------------------+ | ``page`` | int | Optional | | Specifies which | | | | | page to return | | | | | (defaults to: 1) | +---------------+----------+-------------+---------------------------+ | ``per_page`` | int | Optional | | The number of projects | | | | | to return per page. | | | | | The maximum is 100. | +---------------+----------+-------------+---------------------------+ Sample response ^^^^^^^^^^^^^^^ :: { "args": { "assignee": null, "author": null, 'milestones': [], 'no_stones': null, 'order': null, 'priority': null, "since": null, "status": "Closed", "tags": [ "0.1" ] }, "total_issues": 1, "issues": [ { "assignee": null, "blocks": ["1"], "close_status": null, "closed_at": null, "closed_by": null, "comments": [], "content": "asd", "custom_fields": [], "date_created": "1427442217", "depends": [], "id": 4, "last_updated": "1533815358", "milestone": null, "priority": null, "private": false, "status": "Fixed", "tags": [ "0.1" ], "title": "bug", "user": { "fullname": "PY.C", "name": "pingou" } } ], 'pagination': { 'first': 'http://localhost/api/0/test/issues?per_page=20&page=1', 'last': 'http://localhost/api/0/test/issues?per_page=20&page=1', 'next': null, 'page': 1, 'pages': 1, 'per_page': 20, 'prev': null }, } """ repo = _get_repo(repo, username, namespace) _check_issue_tracker(repo) _check_token(repo) assignee = flask.request.args.get("assignee", None) author = flask.request.args.get("author", None) milestone = flask.request.args.getlist("milestones", None) no_stones = flask.request.args.get("no_stones", None) if no_stones is not None: no_stones = is_true(no_stones) priority = flask.request.args.get("priority", None) since = flask.request.args.get("since", None) order = flask.request.args.get("order", None) status = flask.request.args.get("status", None) tags = flask.request.args.getlist("tags") tags = [tag.strip() for tag in tags if tag.strip()] search_id = flask.request.args.get("query_id", None) priority_key = None if priority: found = False if priority in repo.priorities: found = True priority_key = int(priority) else: for key, val in repo.priorities.items(): if val.lower() == priority.lower(): priority_key = key found = True break if not found: raise pagure.exceptions.APIError( 400, error_code=APIERROR.EINVALIDPRIORITY ) # Hide private tickets private = False # If user is authenticated, show him/her his/her private tickets if api_authenticated(): private = flask.g.fas_user.username # If user is repo committer, show all tickets included the private ones if is_repo_committer(repo): private = None params = { "session": flask.g.session, "repo": repo, "tags": tags, "assignee": assignee, "author": author, "private": private, "milestones": milestone, "priority": priority_key, "order": order, "no_milestones": no_stones, "search_id": search_id, } if status is not None: if status.lower() == "all": params.update({"status": None}) elif status.lower() == "closed": params.update({"closed": True}) else: params.update({"status": status}) else: params.update({"status": "Open"}) updated_after = None if since: # Validate and convert the time if since.isdigit(): # We assume its a timestamp, so convert it to datetime try: updated_after = arrow.get(int(since)).datetime except ValueError: raise pagure.exceptions.APIError( 400, error_code=APIERROR.ETIMESTAMP ) else: # We assume datetime format, so validate it try: updated_after = datetime.datetime.strptime(since, "%Y-%m-%d") except ValueError: raise pagure.exceptions.APIError( 400, error_code=APIERROR.EDATETIME ) params.update({"updated_after": updated_after}) page = get_page() per_page = get_per_page() params["count"] = True issue_cnt = pagure.lib.query.search_issues(**params) pagination_metadata = pagure.lib.query.get_pagination_metadata( flask.request, page, per_page, issue_cnt ) query_start = (page - 1) * per_page query_limit = per_page params["count"] = False params["limit"] = query_limit params["offset"] = query_start issues = pagure.lib.query.search_issues(**params) jsonout = flask.jsonify( { "total_issues": len(issues), "issues": [issue.to_json(public=True) for issue in issues], "args": { "assignee": assignee, "author": author, "milestones": milestone, "no_stones": no_stones, "order": order, "priority": priority, "since": since, "status": status, "tags": tags, }, "pagination": pagination_metadata, } ) return jsonout
def api_pull_request_views(repo, username=None, namespace=None): """ List project's Pull-Requests ---------------------------- Retrieve pull requests of a project. :: GET /api/0/<repo>/pull-requests GET /api/0/<namespace>/<repo>/pull-requests :: GET /api/0/fork/<username>/<repo>/pull-requests GET /api/0/fork/<username>/<namespace>/<repo>/pull-requests Parameters ^^^^^^^^^^ +---------------+----------+--------------+----------------------------+ | Key | Type | Optionality | Description | +===============+==========+==============+============================+ | ``status`` | string | Optional | | Filter the status of | | | | | pull requests. Default: | | | | | ``True`` (opened pull | | | | | requests), can be ``0`` | | | | | or ``closed`` for closed | | | | | requests or ``Merged`` | | | | | for merged requests. | | | | | ``All`` returns closed, | | | | | merged and open requests.| +---------------+----------+--------------+----------------------------+ | ``assignee`` | string | Optional | | Filter the assignee of | | | | | pull requests | +---------------+----------+--------------+----------------------------+ | ``author`` | string | Optional | | Filter the author of | | | | | pull requests | +---------------+----------+--------------+----------------------------+ Sample response ^^^^^^^^^^^^^^^ :: { "args": { "assignee": null, "author": null, "status": true }, "total_requests": 1, "requests": [ { "assignee": null, "branch": "master", "branch_from": "master", "closed_at": null, "closed_by": null, "comments": [], "commit_start": null, "commit_stop": null, "date_created": "1431414800", "id": 1, "project": { "date_created": "1431414800", "description": "test project #1", "id": 1, "name": "test", "parent": null, "user": { "fullname": "PY C", "name": "pingou" } }, "repo_from": { "date_created": "1431414800", "description": "test project #1", "id": 1, "name": "test", "parent": null, "user": { "fullname": "PY C", "name": "pingou" } }, "status": "Open", "title": "test pull-request", "uid": "1431414800", "updated_on": "1431414800", "user": { "fullname": "PY C", "name": "pingou" } } ] } """ repo = get_authorized_api_project( flask.g.session, repo, user=username, namespace=namespace ) if repo is None: raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT) if not repo.settings.get("pull_requests", True): raise pagure.exceptions.APIError( 404, error_code=APIERROR.EPULLREQUESTSDISABLED ) status = flask.request.args.get("status", True) assignee = flask.request.args.get("assignee", None) author = flask.request.args.get("author", None) status_text = ("%s" % status).lower() requests = [] if status_text in ["0", "false", "closed"]: requests = pagure.lib.query.search_pull_requests( flask.g.session, project_id=repo.id, status=False, assignee=assignee, author=author, ) elif status_text == "all": requests = pagure.lib.query.search_pull_requests( flask.g.session, project_id=repo.id, status=None, assignee=assignee, author=author, ) else: requests = pagure.lib.query.search_pull_requests( flask.g.session, project_id=repo.id, assignee=assignee, author=author, status=status, ) page = get_page() per_page = get_per_page() pagination_metadata = pagure.lib.query.get_pagination_metadata( flask.request, page, per_page, len(requests) ) start = (page - 1) * per_page if start + per_page > len(requests): requests_page = requests[start:] else: requests_page = requests[start : (start + per_page)] jsonout = { "total_requests": len(requests), "requests": [ request.to_json(public=True, api=True) for request in requests_page ], "args": {"status": status, "assignee": assignee, "author": author}, } if pagination_metadata: jsonout["args"]["page"] = page jsonout["args"]["per_page"] = per_page jsonout["pagination"] = pagination_metadata return flask.jsonify(jsonout)
def api_view_user_requests_actionable(username): """ List PRs actionable by user --------------------------- Use this endpoint to retrieve a list of open pull requests a user is able to action (e.g. merge) over the entire pagure instance. :: GET /api/0/user/<username>/requests/actionable :: GET /api/0/user/dudemcpants/requests/actionable Parameters ^^^^^^^^^^ +---------------+----------+--------------+----------------------------+ | Key | Type | Optionality | Description | +===============+==========+==============+============================+ | ``username`` | string | Mandatory | | The username of the user | | | | | whose activity you are | | | | | interested in. | +---------------+----------+--------------+----------------------------+ | ``page`` | integer | Mandatory | | The page requested. | | | | | Defaults to 1. | +---------------+----------+--------------+----------------------------+ | ``status`` | string | Optional | | Filter the status of | | | | | pull requests. Default: | | | | | ``Open`` (open pull | | | | | requests), can be | | | | | ``Closed`` for closed | | | | | requests, ``Merged`` | | | | | for merged requests, or | | | | | ``Open`` for open | | | | | requests. | | | | | ``All`` returns closed, | | | | | merged and open requests.| +---------------+----------+--------------+----------------------------+ Sample response ^^^^^^^^^^^^^^^ :: { "args": { "status": "open", "username": "******", "page": 1, }, "pagination": { "first": "http://localhost:5000/api/0/user/ryanlerch/requests/actionable?per_page=1&page=1", "last": "http://localhost:5000/api/0/user/ryanlerch/requests/actionable?per_page=1&page=61", "next": "http://localhost:5000/api/0/user/ryanlerch/requests/actionable?per_page=1&page=2", "page": 1, "pages": 61, "per_page": 1, "prev": null }, "requests": [ { "assignee": null, "branch": "master", "branch_from": "master", "closed_at": null, "closed_by": null, "comments": [], "commit_start": "3973fae98fc485783ca14f5c3612d85832185065", "commit_stop": "3973fae98fc485783ca14f5c3612d85832185065", "date_created": "1510227832", "id": 2, "initial_comment": null, "last_updated": "1510227833", "project": { "access_groups": { "admin": [], "commit": [], "ticket": [] }, "access_users": { "admin": [], "commit": [], "owner": [ "ryanlerch" ], "ticket": [] }, "close_status": [], "custom_keys": [], "date_created": "1510227638", "date_modified": "1510227638", "description": "this is a quick project", "fullname": "aquickproject", "id": 1, "milestones": {}, "name": "aquickproject", "namespace": null, "parent": null, "priorities": {}, "tags": [], "url_path": "aquickproject", "user": { "fullname": "ryanlerch", "name": "ryanlerch" } }, "remote_git": null, "repo_from": { "access_groups": { "admin": [], "commit": [], "ticket": [] }, "access_users": { "admin": [], "commit": [], "owner": [ "dudemcpants" ], "ticket": [] }, "close_status": [], "custom_keys": [], "date_created": "1510227729", "date_modified": "1510227729", "description": "this is a quick project", "fullname": "forks/dudemcpants/aquickproject", "id": 2, "milestones": {}, "name": "aquickproject", "namespace": null, "parent": { "access_groups": { "admin": [], "commit": [], "ticket": [] }, "access_users": { "admin": [], "commit": [], "owner": [ "ryanlerch" ], "ticket": [] }, "close_status": [], "custom_keys": [], "date_created": "1510227638", "date_modified": "1510227638", "description": "this is a quick project", "fullname": "aquickproject", "id": 1, "milestones": {}, "name": "aquickproject", "namespace": null, "parent": null, "priorities": {}, "tags": [], "url_path": "aquickproject", "user": { "fullname": "ryanlerch", "name": "ryanlerch" } }, "priorities": {}, "tags": [], "url_path": "fork/dudemcpants/aquickproject", "user": { "fullname": "Dude McPants", "name": "dudemcpants" } }, "status": "Open", "title": "Update README.md", "uid": "819e0b1c449e414fa291c914f28d73ec", "updated_on": "1510227832", "user": { "fullname": "Dude McPants", "name": "dudemcpants" } } ], "total_requests": 1 } """ # noqa status = flask.request.args.get("status", "open") page = get_page() per_page = get_per_page() offset = (page - 1) * per_page limit = per_page orig_status = status if status.lower() == "all": status = None else: status = status.capitalize() pullrequests_cnt = pagure.lib.query.get_pull_request_of_user( flask.g.session, username=username, status=status, count=True) pagination = pagure.lib.query.get_pagination_metadata( flask.request, page, per_page, pullrequests_cnt) pullrequests = pagure.lib.query.get_pull_request_of_user( flask.g.session, username=username, status=status, actionable=username, offset=offset, limit=limit, ) pullrequestslist = [ pr.to_json(public=True, api=True) for pr in pullrequests ] return flask.jsonify({ "total_requests": len(pullrequestslist), "requests": pullrequestslist, "args": { "username": username, "status": orig_status, "page": page, }, "pagination": pagination, })
def api_view_user_issues(username): """ List user's issues --------------------- List issues opened by or assigned to a specific user across all projects. :: GET /api/0/user/<username>/issues Parameters ^^^^^^^^^^ +---------------+---------+--------------+---------------------------+ | Key | Type | Optionality | Description | +===============+=========+==============+===========================+ | ``page`` | integer | Mandatory | | The page requested. | | | | | Defaults to 1. | +---------------+---------+--------------+---------------------------+ | ``per_page`` | int | Optional | | The number of items | | | | | to return per page. | | | | | The maximum is 100. | +---------------+---------+--------------+---------------------------+ | ``status`` | string | Optional | | Filters the status of | | | | | issues. Fetches all the | | | | | issues if status is | | | | | ``all``. Default: | | | | | ``Open`` | +---------------+---------+--------------+---------------------------+ | ``tags`` | string | Optional | | A list of tags you | | | | | wish to filter. If | | | | | you want to filter | | | | | for issues not having | | | | | a tag, add an | | | | | exclamation mark in | | | | | front of it | +---------------+---------+--------------+---------------------------+ | ``milestones``| list of | Optional | | Filter the issues | | | strings | | by milestone | +---------------+---------+--------------+---------------------------+ | ``no_stones`` | boolean | Optional | | If true returns only the| | | | | issues having no | | | | | milestone, if false | | | | | returns only the issues | | | | | having a milestone | +---------------+---------+--------------+---------------------------+ | ``since`` | string | Optional | | Filter the issues | | | | | updated after this date.| | | | | The date can either be | | | | | provided as an unix date| | | | | or in the format Y-M-D | +---------------+---------+--------------+---------------------------+ | ``order`` | string | Optional | | Set the ordering of the | | | | | issues. This can be | | | | | ``asc`` or ``desc``. | | | | | Default: ``desc`` | +---------------+---------+--------------+---------------------------+ | ``order_key`` | string | Optional | | Set the ordering key. | | | | | This can be ``assignee``| | | | | , ``last_updated`` or | | | | | name of other column. | | | | | Default: | | | | | ``date_created`` | +---------------+---------+--------------+---------------------------+ | ``assignee`` | boolean | Optional | | A boolean of whether to | | | | | return the issues | | | | | assigned to this user | | | | | or not. Defaults to True| +---------------+---------+--------------+---------------------------+ | ``author`` | boolean | Optional | | A boolean of whether to | | | | | return the issues | | | | | created by this user or | | | | | not. Defaults to True | +---------------+---------+--------------+---------------------------+ Sample response ^^^^^^^^^^^^^^^ :: { "args": { "assignee": true, "author": true, "milestones": [], "no_stones": null, "order": null, "order_key": null, "page": 1, "since": null, "status": null, "tags": [] }, "issues_assigned": [ { "assignee": { "fullname": "Anar Adilova", "name": "anar" }, "blocks": [], "close_status": null, "closed_at": null, "comments": [], "content": "Test Issue", "custom_fields": [], "date_created": "1510124763", "depends": [], "id": 2, "last_updated": "1510124763", "milestone": null, "priority": null, "private": false, "status": "Open", "tags": [], "title": "issue4", "user": { "fullname": "Anar Adilova", "name": "anar" } } ], "issues_created": [ { "assignee": { "fullname": "Anar Adilova", "name": "anar" }, "blocks": [], "close_status": null, "closed_at": null, "comments": [], "content": "Test Issue", "custom_fields": [], "date_created": "1510124763", "depends": [], "id": 2, "last_updated": "1510124763", "milestone": null, "priority": null, "private": false, "status": "Open", "tags": [], "title": "issue4", "user": { "fullname": "Anar Adilova", "name": "anar" } } ], "pagination_issues_assigned": { "first": "http://localhost:5000/api/0/user/anar/issues?per_page=1&page=1", "last": "http://localhost:5000/api/0/user/anar/issues?per_page=1&page=0", "next": null, "page": 1, "pages": 0, "per_page": 1, "prev": null }, "pagination_issues_created": { "first": "http://localhost:5000/api/0/user/anar/issues?per_page=1&page=1", "last": "http://localhost:5000/api/0/user/anar/issues?per_page=1&page=200", "next": "http://localhost:5000/api/0/user/anar/issues?per_page=1&page=2", "page": 1, "pages": 200, "per_page": 1, "prev": null }, "total_issues_assigned": 1, "total_issues_created": 1 } """ # noqa milestone = flask.request.args.getlist("milestones", None) no_stones = flask.request.args.get("no_stones", None) if no_stones is not None: no_stones = is_true(no_stones) since = flask.request.args.get("since", None) order = flask.request.args.get("order", None) order_key = flask.request.args.get("order_key", None) status = flask.request.args.get("status", None) tags = flask.request.args.getlist("tags") tags = [tag.strip() for tag in tags if tag.strip()] page = get_page() per_page = get_per_page() assignee = flask.request.args.get("assignee", "").lower() not in [ "false", "0", "f", ] author = flask.request.args.get("author", "").lower() not in [ "false", "0", "f", ] offset = (page - 1) * per_page limit = per_page params = { "session": flask.g.session, "tags": tags, "milestones": milestone, "order": order, "order_key": order_key, "no_milestones": no_stones, "offset": offset, "limit": limit, } if status is not None: if status.lower() == "all": params.update({"status": None}) elif status.lower() == "closed": params.update({"closed": True}) else: params.update({"status": status}) else: params.update({"status": "Open"}) updated_after = None if since: # Validate and convert the time if since.isdigit(): # We assume its a timestamp, so convert it to datetime try: updated_after = datetime.datetime.fromtimestamp(int(since)) except ValueError: raise pagure.exceptions.APIError( 400, error_code=APIERROR.ETIMESTAMP) else: # We assume datetime format, so validate it try: updated_after = datetime.datetime.strptime(since, "%Y-%m-%d") except ValueError: raise pagure.exceptions.APIError(400, error_code=APIERROR.EDATETIME) params.update({"updated_after": updated_after}) issues_created = [] issues_created_pages = 1 issues_created_cnt = 0 pagination_issues_created = None if author: # Issues authored by this user params_created = params.copy() params_created.update({"author": username}) issues_created = pagure.lib.query.search_issues(**params_created) params_created.update({"offset": None, "limit": None, "count": True}) issues_created_cnt = pagure.lib.query.search_issues(**params_created) pagination_issues_created = pagure.lib.query.get_pagination_metadata( flask.request, page, per_page, issues_created_cnt) issues_assigned = [] issues_assigned_pages = 1 issues_assigned_cnt = 0 pagination_issues_assigned = None if assignee: # Issues assigned to this user params_assigned = params.copy() params_assigned.update({"assignee": username}) issues_assigned = pagure.lib.query.search_issues(**params_assigned) params_assigned.update({"offset": None, "limit": None, "count": True}) issues_assigned_cnt = pagure.lib.query.search_issues(**params_assigned) pagination_issues_assigned = pagure.lib.query.get_pagination_metadata( flask.request, page, per_page, issues_assigned_cnt) jsonout = flask.jsonify({ "pagination_issues_created": pagination_issues_created, "pagination_issues_assigned": pagination_issues_assigned, "total_issues_created_pages": issues_created_pages, "total_issues_assigned_pages": issues_assigned_pages, "total_issues_created": issues_created_cnt, "total_issues_assigned": issues_assigned_cnt, "issues_created": [ issue.to_json(public=True, with_project=True) for issue in issues_created ], "issues_assigned": [ issue.to_json(public=True, with_project=True) for issue in issues_assigned ], "args": { "milestones": milestone, "no_stones": no_stones, "order": order, "order_key": order_key, "since": since, "status": status, "tags": tags, "page": page, "assignee": assignee, "author": author, }, }) return jsonout
def api_groups(): """ List groups ----------- Retrieve groups on this Pagure instance. This can then be used as input for autocompletion in some forms/fields. :: GET /api/0/groups Parameters ^^^^^^^^^^ +---------------+----------+---------------+--------------------------+ | Key | Type | Optionality | Description | +===============+==========+===============+==========================+ | ``pattern`` | string | Optional | | Filters the starting | | | | | letters of the group | | | | | names | +---------------+----------+---------------+--------------------------+ | ``page`` | int | Optional | | Specifies which | | | | | page to return | | | | | (defaults to: 1) | +---------------+----------+---------------+--------------------------+ | ``per_page`` | int | Optional | | The number of projects | | | | | to return per page. | | | | | The maximum is 100. | +---------------+----------+---------------+--------------------------+ Sample response ^^^^^^^^^^^^^^^ :: { "total_groups": 2, u'pagination': { 'first': 'http://localhost/api/0/groups?per_page=20&extended=1&page=1', 'last': 'http://localhost/api/0/groups?per_page=20&extended=1&page=1', 'next': null, 'page': 1, 'pages': 1, 'per_page': 20, 'prev': None }, "groups": ["group1", "group2"] } """ # noqa pattern = flask.request.args.get("pattern", None) extended = is_true(flask.request.args.get("extended", False)) if pattern is not None and not pattern.endswith("*"): pattern += "*" page = get_page() per_page = get_per_page() group_cnt = pagure.lib.query.search_groups(flask.g.session, pattern=pattern, count=True) pagination_metadata = pagure.lib.query.get_pagination_metadata( flask.request, page, per_page, group_cnt) query_start = (page - 1) * per_page query_limit = per_page groups = pagure.lib.query.search_groups(flask.g.session, pattern=pattern, limit=query_limit, offset=query_start) if extended: groups = [{ "name": grp.group_name, "description": grp.description } for grp in groups] else: groups = [group.group_name for group in groups] return flask.jsonify({ "total_groups": group_cnt, "groups": groups, "pagination": pagination_metadata, })
def api_groups(): """ List groups ----------- Retrieve groups on this Pagure instance. This can then be used as input for autocompletion in some forms/fields. :: GET /api/0/groups Parameters ^^^^^^^^^^ +---------------+----------+---------------+--------------------------+ | Key | Type | Optionality | Description | +===============+==========+===============+==========================+ | ``pattern`` | string | Optional | | Filters the starting | | | | | letters of the group | | | | | names | +---------------+----------+---------------+--------------------------+ | ``page`` | int | Optional | | Specifies which | | | | | page to return | | | | | (defaults to: 1) | +---------------+----------+---------------+--------------------------+ | ``per_page`` | int | Optional | | The number of projects | | | | | to return per page. | | | | | The maximum is 100. | +---------------+----------+---------------+--------------------------+ Sample response ^^^^^^^^^^^^^^^ :: { "total_groups": 2, u'pagination': { 'first': 'http://localhost/api/0/groups?per_page=20&extended=1&page=1', 'last': 'http://localhost/api/0/groups?per_page=20&extended=1&page=1', 'next': null, 'page': 1, 'pages': 1, 'per_page': 20, 'prev': None }, "groups": ["group1", "group2"] } """ # noqa pattern = flask.request.args.get("pattern", None) extended = is_true(flask.request.args.get("extended", False)) if pattern is not None and not pattern.endswith("*"): pattern += "*" page = get_page() per_page = get_per_page() group_cnt = pagure.lib.query.search_groups( flask.g.session, pattern=pattern, count=True ) pagination_metadata = pagure.lib.query.get_pagination_metadata( flask.request, page, per_page, group_cnt ) query_start = (page - 1) * per_page query_limit = per_page groups = pagure.lib.query.search_groups( flask.g.session, pattern=pattern, limit=query_limit, offset=query_start ) if extended: groups = [ {"name": grp.group_name, "description": grp.description} for grp in groups ] else: groups = [group.group_name for group in groups] return flask.jsonify( { "total_groups": group_cnt, "groups": groups, "pagination": pagination_metadata, } )
def api_view_issues(repo, username=None, namespace=None): """ List project's issues --------------------- List issues of a project. :: GET /api/0/<repo>/issues GET /api/0/<namespace>/<repo>/issues :: GET /api/0/fork/<username>/<repo>/issues GET /api/0/fork/<username>/<namespace>/<repo>/issues Parameters ^^^^^^^^^^ +---------------+---------+--------------+---------------------------+ | Key | Type | Optionality | Description | +===============+=========+==============+===========================+ | ``status`` | string | Optional | | Filters the status of | | | | | issues. Fetches all the | | | | | issues if status is | | | | | ``all``. Default: | | | | | ``Open`` | +---------------+---------+--------------+---------------------------+ | ``tags`` | string | Optional | | A list of tags you | | | | | wish to filter. If | | | | | you want to filter | | | | | for issues not having | | | | | a tag, add an | | | | | exclamation mark in | | | | | front of it | +---------------+---------+--------------+---------------------------+ | ``assignee`` | string | Optional | | Filter the issues | | | | | by assignee | +---------------+---------+--------------+---------------------------+ | ``author`` | string | Optional | | Filter the issues | | | | | by creator | +---------------+---------+--------------+---------------------------+ | ``milestones``| list of | Optional | | Filter the issues | | | strings | | by milestone | +---------------+---------+--------------+---------------------------+ | ``priority`` | string | Optional | | Filter the issues | | | | | by priority | +---------------+---------+--------------+---------------------------+ | ``no_stones`` | boolean | Optional | | If true returns only the| | | | | issues having no | | | | | milestone, if false | | | | | returns only the issues | | | | | having a milestone | +---------------+---------+--------------+---------------------------+ | ``since`` | string | Optional | | Filter the issues | | | | | updated after this date.| | | | | The date can either be | | | | | provided as an unix date| | | | | or in the format Y-M-D | +---------------+---------+--------------+---------------------------+ | ``order`` | string | Optional | | Set the ordering of the | | | | | issues. This can be | | | | | ``asc`` or ``desc``. | | | | | Default: ``desc`` | +---------------+---------+--------------+---------------------------+ | ``page`` | int | Optional | | Specifies which | | | | | page to return | | | | | (defaults to: 1) | +---------------+----------+-------------+---------------------------+ | ``per_page`` | int | Optional | | The number of projects | | | | | to return per page. | | | | | The maximum is 100. | +---------------+----------+-------------+---------------------------+ Sample response ^^^^^^^^^^^^^^^ :: { "args": { "assignee": null, "author": null, 'milestones': [], 'no_stones': null, 'order': null, 'priority': null, "since": null, "status": "Closed", "tags": [ "0.1" ] }, "total_issues": 1, "issues": [ { "assignee": null, "blocks": ["1"], "close_status": null, "closed_at": null, "closed_by": null, "comments": [], "content": "asd", "custom_fields": [], "date_created": "1427442217", "depends": [], "id": 4, "last_updated": "1533815358", "milestone": null, "priority": null, "private": false, "status": "Fixed", "tags": [ "0.1" ], "title": "bug", "user": { "fullname": "PY.C", "name": "pingou" } } ], 'pagination': { 'first': 'http://localhost/api/0/test/issues?per_page=20&page=1', 'last': 'http://localhost/api/0/test/issues?per_page=20&page=1', 'next': null, 'page': 1, 'pages': 1, 'per_page': 20, 'prev': null }, } """ repo = _get_repo(repo, username, namespace) _check_issue_tracker(repo) _check_token(repo, project_token=False) assignee = flask.request.args.get("assignee", None) author = flask.request.args.get("author", None) milestone = flask.request.args.getlist("milestones", None) no_stones = flask.request.args.get("no_stones", None) if no_stones is not None: no_stones = is_true(no_stones) priority = flask.request.args.get("priority", None) since = flask.request.args.get("since", None) order = flask.request.args.get("order", None) status = flask.request.args.get("status", None) tags = flask.request.args.getlist("tags") tags = [tag.strip() for tag in tags if tag.strip()] search_id = flask.request.args.get("query_id", None) priority_key = None if priority: found = False if priority in repo.priorities: found = True priority_key = int(priority) else: for key, val in repo.priorities.items(): if val.lower() == priority.lower(): priority_key = key found = True break if not found: raise pagure.exceptions.APIError( 400, error_code=APIERROR.EINVALIDPRIORITY) # Hide private tickets private = False # If user is authenticated, show him/her his/her private tickets if api_authenticated(): private = flask.g.fas_user.username # If user is repo committer, show all tickets included the private ones if is_repo_committer(repo): private = None params = { "session": flask.g.session, "repo": repo, "tags": tags, "assignee": assignee, "author": author, "private": private, "milestones": milestone, "priority": priority_key, "order": order, "no_milestones": no_stones, "search_id": search_id, } if status is not None: if status.lower() == "all": params.update({"status": None}) elif status.lower() == "closed": params.update({"closed": True}) else: params.update({"status": status}) else: params.update({"status": "Open"}) updated_after = None if since: # Validate and convert the time if since.isdigit(): # We assume its a timestamp, so convert it to datetime try: updated_after = arrow.get(int(since)).datetime except ValueError: raise pagure.exceptions.APIError( 400, error_code=APIERROR.ETIMESTAMP) else: # We assume datetime format, so validate it try: updated_after = datetime.datetime.strptime(since, "%Y-%m-%d") except ValueError: raise pagure.exceptions.APIError(400, error_code=APIERROR.EDATETIME) params.update({"updated_after": updated_after}) page = get_page() per_page = get_per_page() params["count"] = True issue_cnt = pagure.lib.query.search_issues(**params) pagination_metadata = pagure.lib.query.get_pagination_metadata( flask.request, page, per_page, issue_cnt) query_start = (page - 1) * per_page query_limit = per_page params["count"] = False params["limit"] = query_limit params["offset"] = query_start issues = pagure.lib.query.search_issues(**params) jsonout = flask.jsonify({ "total_issues": len(issues), "issues": [issue.to_json(public=True) for issue in issues], "args": { "assignee": assignee, "author": author, "milestones": milestone, "no_stones": no_stones, "order": order, "priority": priority, "since": since, "status": status, "tags": tags, }, "pagination": pagination_metadata, }) return jsonout