Skip to content

Commit

Permalink
rename get_XXXX methods as XXXX and fix local_client types
Browse files Browse the repository at this point in the history
  • Loading branch information
korgan00 committed Oct 16, 2024
1 parent 9ae1121 commit 45c24bb
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 80 deletions.
29 changes: 22 additions & 7 deletions client/qiskit_serverless/core/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,15 @@ def __repr__(self):
####### JOBS #######
####################
@abstractmethod
def get_jobs(self, **kwargs) -> List[Job]:
def jobs(self, **kwargs) -> List[Job]:
"""Return list of jobs.
Returns:
list of jobs.
"""

@abstractmethod
def get_job(self, job_id: str) -> Optional[Job]:
def job(self, job_id: str) -> Optional[Job]:
"""Returns job by job id.
Args:
Expand All @@ -123,7 +123,22 @@ def get_job_by_id(self, job_id: str) -> Optional[Job]:
"Please, use `get_job` instead.",
DeprecationWarning,
)
return self.get_job(job_id)
return self.job(job_id)

def get_jobs(self, **kwargs) -> List[Job]:
# pylint: disable=duplicate-code
"""Return list of jobs.
Returns:
list of jobs.
"""
warnings.warn(
"`get_jobs` method has been deprecated. "
"And will be removed in future releases. "
"Please, use `jobs` instead.",
DeprecationWarning,
)
return self.jobs(**kwargs)

@abstractmethod
def run(
Expand Down Expand Up @@ -183,11 +198,11 @@ def upload(self, program: QiskitFunction) -> Optional[QiskitFunction]:
"""Uploads program."""

@abstractmethod
def get_functions(self, **kwargs) -> List[QiskitFunction]:
def functions(self, **kwargs) -> List[QiskitFunction]:
"""Returns list of available programs."""

@abstractmethod
def get_function(
def function(
self, title: str, provider: Optional[str] = None
) -> Optional[QiskitFunction]:
"""Returns program based on parameters."""
Expand All @@ -202,7 +217,7 @@ def get(
"Please, use `get_function` instead.",
DeprecationWarning,
)
return self.get_function(title, provider=provider)
return self.function(title, provider=provider)

def list(self, **kwargs) -> List[QiskitFunction]:
"""Returns list of available programs."""
Expand All @@ -212,7 +227,7 @@ def list(self, **kwargs) -> List[QiskitFunction]:
"Please, use `get_functions` instead.",
DeprecationWarning,
)
return self.get_functions(**kwargs)
return self.functions(**kwargs)

######################
####### Widget #######
Expand Down
117 changes: 61 additions & 56 deletions client/qiskit_serverless/core/clients/local_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@
import os
import re
import sys
from typing import Optional, List, Dict, Any, Union
from typing import Optional, List, Dict, Any, Union, cast
from uuid import uuid4

import subprocess
from subprocess import Popen
from xml.dom import NotFoundErr

from attr import dataclass
from qiskit_ibm_runtime import QiskitRuntimeService

from qiskit_serverless.core.constants import (
Expand All @@ -55,6 +57,14 @@
)


@dataclass
class _LocalClientJob:
status: str
logs: str
result: str | Any
job: Job


class LocalClient(BaseClient):
"""LocalClient."""

Expand All @@ -68,8 +78,8 @@ def __init__(self):
"""
super().__init__("local-client")
self.in_test = os.getenv("IN_TEST")
self._jobs = {}
self._patterns = []
self._jobs = cast(Dict[str, _LocalClientJob], {})
self._patterns = cast(List[QiskitFunction], [])

@classmethod
def from_dict(cls, dictionary: dict):
Expand All @@ -79,11 +89,11 @@ def from_dict(cls, dictionary: dict):
####### JOBS #######
####################

def get_job(self, job_id: str) -> Optional[Job]:
return self._jobs[job_id]["job"]
def job(self, job_id: str) -> Optional[Job]:
return self._jobs[job_id].job

def get_jobs(self, **kwargs) -> List[Job]:
return [job["job"] for job in list(self._jobs.values())]
def jobs(self, **kwargs) -> List[Job]:
return [job.job for job in self._jobs.values()]

def run(
self,
Expand All @@ -98,27 +108,27 @@ def run(
else:
title = str(program)

for pattern in self._patterns:
if pattern["title"] == title:
saved_program = pattern
if saved_program[ # pylint: disable=possibly-used-before-assignment
"dependencies"
]:
dept = json.loads(saved_program["dependencies"])
saved_program = self.function(title)

if not saved_program:
raise NotFoundErr

if saved_program.dependencies:
dept = json.loads(json.dumps(saved_program.dependencies or []))
for dependency in dept:
subprocess.check_call(
[sys.executable, "-m", "pip", "install", dependency]
)
arguments = arguments or {}
env_vars = {
**(saved_program["env_vars"] or {}),
**{OT_PROGRAM_NAME: saved_program["title"]},
**(saved_program.env_vars or {}),
**{OT_PROGRAM_NAME: saved_program.title},
**{"PATH": os.environ["PATH"]},
**{ENV_JOB_ARGUMENTS: json.dumps(arguments, cls=QiskitObjectsEncoder)},
}

with Popen(
["python", saved_program["working_dir"] + saved_program["entrypoint"]],
["python", saved_program.working_dir + saved_program.entrypoint],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
Expand All @@ -134,69 +144,64 @@ def run(
result = results.group(1)

job = Job(job_id=str(uuid4()), client=self)
self._jobs[job.job_id] = {
"status": status,
"logs": output,
"result": result,
"job": job,
}
self._jobs[job.job_id] = _LocalClientJob(
status=status,
logs=output,
result=result,
job=job,
)
return job

def status(self, job_id: str):
return self._jobs[job_id]["status"]
def status(self, job_id: str) -> str:
return self._jobs[job_id].status

def stop(self, job_id: str, service: Optional[QiskitRuntimeService] = None):
def stop(
self, job_id: str, service: Optional[QiskitRuntimeService] = None
) -> Union[str, bool]:
"""Stops job/program."""
return f"job:{job_id} has already stopped"

def result(self, job_id: str):
return self._jobs[job_id]["result"]
def result(self, job_id: str) -> Any:
return self._jobs[job_id].result

def logs(self, job_id: str):
return self._jobs[job_id]["logs"]
def logs(self, job_id: str) -> str:
return self._jobs[job_id].logs

def filtered_logs(self, job_id: str, **kwargs):
def filtered_logs(self, job_id: str, **kwargs) -> str:
"""Return filtered logs."""
raise NotImplementedError

#########################
####### Functions #######
#########################

def upload(self, program: QiskitFunction):
def upload(self, program: QiskitFunction) -> Optional[QiskitFunction]:
# check if entrypoint exists
if not os.path.exists(os.path.join(program.working_dir, program.entrypoint)):
raise QiskitServerlessException(
f"Entrypoint file [{program.entrypoint}] does not exist "
f"in [{program.working_dir}] working directory."
)
self._patterns.append(
{
"title": program.title,
"provider": program.provider,
"entrypoint": program.entrypoint,
"working_dir": program.working_dir,
"env_vars": program.env_vars,
"arguments": json.dumps({}),
"dependencies": json.dumps(program.dependencies or []),
}
function = QiskitFunction(
title=program.title,
provider=program.provider,
entrypoint=program.entrypoint,
working_dir=program.working_dir,
env_vars=program.env_vars,
dependencies=program.dependencies,
client=self,
)
return program.title
self._patterns.append(function)
return function

def get_functions(self, **kwargs) -> List[QiskitFunction]:
def functions(self, **kwargs) -> List[QiskitFunction]:
"""Returns list of programs."""
return [
QiskitFunction(
program.get("title"),
provider=program.get("provider", None),
raw_data=program,
client=self,
)
for program in self._patterns
]
return list(self._patterns)

def get_function(
def function(
self, title: str, provider: Optional[str] = None
) -> Optional[QiskitFunction]:
functions = {function.title: function for function in self.get_functions()}
return functions.get(title)
f = next(
(function for function in self._patterns if function.title is title), None
)
return f
8 changes: 4 additions & 4 deletions client/qiskit_serverless/core/clients/ray_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def from_dict(cls, dictionary: dict):
####### JOBS #######
####################

def get_jobs(self, **kwargs) -> List[Job]:
def jobs(self, **kwargs) -> List[Job]:
"""Return list of jobs.
Returns:
Expand All @@ -84,7 +84,7 @@ def get_jobs(self, **kwargs) -> List[Job]:
for job in self.job_submission_client.list_jobs()
]

def get_job(self, job_id: str) -> Optional[Job]:
def job(self, job_id: str) -> Optional[Job]:
"""Returns job by job id.
Args:
Expand Down Expand Up @@ -161,11 +161,11 @@ def upload(self, program: QiskitFunction) -> Optional[QiskitFunction]:
"""Uploads program."""
raise NotImplementedError("Upload is not available for RayClient.")

def get_functions(self, **kwargs) -> List[QiskitFunction]:
def functions(self, **kwargs) -> List[QiskitFunction]:
"""Returns list of available programs."""
raise NotImplementedError("get_programs is not available for RayClient.")

def get_function(
def function(
self, title: str, provider: Optional[str] = None
) -> Optional[QiskitFunction]:
"""Returns program based on parameters."""
Expand Down
Loading

0 comments on commit 45c24bb

Please sign in to comment.