diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 8921d7f..384762d 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -1,9 +1,29 @@ ## Release 0.3.0 (development release) +### New features since last release + +* Job lists can now be filtered by status. + [(#30)](https://github.com/XanaduAI/xanadu-cloud-client/pull/30) + + Using the CLI: + + ```bash + xcc job list --status '' + ``` + + Using the Python API: + + ```python + xcc.Job.list(connection, status="") + ``` + + ### Contributors This release contains contributions from (in alphabetical order): +[Hudhayfa Zaheem](https://github.com/HudZah). + ## Release 0.2.1 (current release) ### New features since last release @@ -38,8 +58,6 @@ This release contains contributions from (in alphabetical order): ## Release 0.2.0 -### New features since last release - * The Connection class can now load a Connection from a Settings instance. [(#22)](https://github.com/XanaduAI/xanadu-cloud-client/pull/22) diff --git a/docs/conf.py b/docs/conf.py index 38edfbd..08bd623 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -85,6 +85,7 @@ # # The full version, including alpha/beta/rc tags. import xcc + release = xcc.__version__ # The short X.Y version. @@ -253,7 +254,6 @@ html_theme_options = { "navbar_name": "Xanadu Cloud Client", "navbar_logo_colour": "#78909c", - "navbar_right_links": [ { "name": "GitHub", @@ -261,14 +261,12 @@ "icon": "fab fa-github", } ], - "border_colour": "#78909c", "prev_next_button_colour": "#607d8b", "prev_next_button_hover_colour": "#34515e", "toc_marker_colour": "#78909c", "table_header_background_colour": "#78909c", "text_accent_colour": "#78909c", - } edit_on_github_project = "XanaduAI/xanadu-cloud-client" diff --git a/docs/requirements.txt b/docs/requirements.txt index 63ed2bf..c1379c5 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -2,5 +2,6 @@ docutils m2r2 nbsphinx sphinx-copybutton -sphinx>=3.1.0 +Jinja2<3.1 +sphinx==4.5.0 xanadu-sphinx-theme==0.1.0 diff --git a/tests/test_commands.py b/tests/test_commands.py index 3a15b1b..a182f67 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -47,7 +47,7 @@ class MockJob(xcc.Job): """ @staticmethod - def list(connection, limit=10, ids=None): + def list(connection, limit=10, ids=None, status=None): connection = xcc.commands.load_connection() return [MockJob(id_, connection) for id_ in ("foo", "bar", "baz")][:limit] diff --git a/tests/test_job.py b/tests/test_job.py index 82e229a..395a1e4 100644 --- a/tests/test_job.py +++ b/tests/test_job.py @@ -123,6 +123,27 @@ def test_list(self, connection, add_response, limit, ids, want_params, want_name have_params = responses.calls[0].request.params # pyright: reportGeneralTypeIssues=false assert have_params == want_params + @pytest.mark.parametrize( + "limit, status, want_status_param", + [ + (1, "queued", "queued"), + (2, None, None), + (2, "invalid", "invalid"), + (2, "complete", "complete"), + ], + ) + @responses.activate + def test_list_status(self, connection, add_response, limit, status, want_status_param): + """Tests that the correct status parameter is encoded in the HTTP + request to the Xanadu Cloud platform when listing jobs. + """ + add_response(body={"data": []}, path="/jobs") + xcc.Job.list(connection, limit=limit, status=status) + + have_params = responses.calls[0].request.params # pyright: reportGeneralTypeIssues=false + have_status_param = have_params.get("status") + assert have_status_param == want_status_param + @pytest.mark.parametrize("name", [None, "foo"]) @responses.activate def test_submit(self, job_id, connection, name): @@ -167,7 +188,13 @@ def test_result(self, connection, job): with io.BytesIO() as buffer: # The public savez() function does not allow pickling to be disabled. savez = numpy.lib.npyio._savez # pylint: disable=protected-access - savez(file=buffer, args=output, kwds=metadata, compress=False, allow_pickle=False) + savez( + file=buffer, + args=output, + kwds=metadata, + compress=False, + allow_pickle=False, + ) buffer.seek(0) body = buffer.read() diff --git a/xcc/commands.py b/xcc/commands.py index 200f0ef..94cc708 100644 --- a/xcc/commands.py +++ b/xcc/commands.py @@ -257,18 +257,19 @@ def get_job( @beautify -def list_jobs(limit: int = 5, ids: List[str] = None) -> Sequence[Mapping]: +def list_jobs(limit: int = 5, ids: List[str] = None, status: str = None) -> Sequence[Mapping]: """Lists jobs submitted to the Xanadu Cloud. Args: limit (int): Maximum number of jobs to display. ids (List[str], optional): IDs of the jobs to display. If at least one ID is specified, the limit flag will be set to the number of IDs. + status (str, optional): If specificed, filter returned jobs by the given status. Returns: Sequence[Mapping]: Overview of each job submitted to the Xanadu Cloud. """ - jobs = Job.list(connection=load_connection(), limit=limit, ids=ids) + jobs = Job.list(connection=load_connection(), limit=limit, ids=ids, status=status) return [job.overview for job in jobs] diff --git a/xcc/job.py b/xcc/job.py index a7a125a..a2ca946 100644 --- a/xcc/job.py +++ b/xcc/job.py @@ -93,23 +93,30 @@ class Job: @staticmethod def list( - connection: Connection, limit: int = 5, ids: Optional[Collection[str]] = None + connection: Connection, + limit: int = 5, + ids: Optional[Collection[str]] = None, + status: Optional[str] = None, ) -> Sequence[Job]: """Returns jobs submitted to the Xanadu Cloud. + Args: connection (Connection): connection to the Xanadu Cloud limit (int): maximum number of jobs to retrieve ids (Collection[str], optional): IDs of the jobs to retrieve; if at least one ID is specified, ``limit`` will be set to the length of the ID collection + status (str, optional): filter jobs by the given status (if not ``None``) Returns: Sequence[Job]: jobs which were submitted on the Xanadu Cloud by the user associated with the Xanadu Cloud connection """ size = len(ids) if ids else limit - response = connection.request("GET", "/jobs", params={"size": size, "id": ids}) + + params = {"size": size, "id": ids, "status": status} + response = connection.request("GET", "/jobs", params=params) jobs = [] @@ -122,7 +129,11 @@ def list( @staticmethod def submit( - connection: Connection, name: Optional[str], target: str, circuit: str, language: str + connection: Connection, + name: Optional[str], + target: str, + circuit: str, + language: str, ) -> Job: """Submits a job to the Xanadu Cloud. @@ -136,7 +147,12 @@ def submit( Returns: Job: job submitted to the Xanadu Cloud """ - payload = {"name": name, "target": target, "circuit": circuit, "language": language} + payload = { + "name": name, + "target": target, + "circuit": circuit, + "language": language, + } response = connection.request("POST", "/jobs", json=payload) details = response.json()