Skip to content

Commit

Permalink
Change Provider class name to ServerlessProvider (#1011)
Browse files Browse the repository at this point in the history
* Change Provider class name to ServerlessProvider

* black

* Fix fstring

* Update notebooks with new class name

* Fix notebook error

* Turn BaseProvider into an abstract base class

* Don't turn BaseProvider into an abstract class

* Minor cleanups

* Deprecate Provider

* Call super correctly
  • Loading branch information
caleb-johnson authored Oct 4, 2023
1 parent 8baa46e commit a7d4b0b
Show file tree
Hide file tree
Showing 15 changed files with 94 additions and 51 deletions.
1 change: 1 addition & 0 deletions client/quantum_serverless/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
put,
get_refs_by_status,
Provider,
ServerlessProvider,
IBMServerlessProvider,
save_result,
)
Expand Down
9 changes: 8 additions & 1 deletion client/quantum_serverless/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
:toctree: ../stubs/
Provider
ServerlessProvider
IBMServerlessProvider
BaseProvider
ComputeResource
Expand All @@ -50,7 +51,13 @@
"""

from .provider import BaseProvider, ComputeResource, Provider, IBMServerlessProvider
from .provider import (
BaseProvider,
ComputeResource,
Provider,
ServerlessProvider,
IBMServerlessProvider,
)
from .job import BaseJobClient, RayJobClient, GatewayJobClient, Job, save_result
from .program import (
Program,
Expand Down
6 changes: 3 additions & 3 deletions client/quantum_serverless/core/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ def distribute_program(
"""[Experimental] Program decorator to turn function into remotely executable program.
Example:
>>> @distribute_program(provider=Provider(...), dependencies=[...])
>>> @distribute_program(provider=ServerlessProvider(...), dependencies=[...])
>>> def my_program():
>>> print("Hola!")
>>>
Expand All @@ -357,13 +357,13 @@ def distribute_program(
# pylint: disable=import-outside-toplevel,cyclic-import
from quantum_serverless import QuantumServerlessException
from quantum_serverless.core.program import Program
from quantum_serverless.core.provider import Provider
from quantum_serverless.core.provider import ServerlessProvider

# create provider
if provider is None:
# try to create from env vars
try:
provider = Provider()
provider = ServerlessProvider()
except QuantumServerlessException as qs_error:
raise QuantumServerlessException(
"Set provider in arguments for `distribute_program` "
Expand Down
77 changes: 56 additions & 21 deletions client/quantum_serverless/core/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
:toctree: ../stubs/
ComputeResource
Provider
ServerlessProvider
"""
import logging
import warnings
import os.path
from dataclasses import dataclass
from typing import Optional, List, Dict, Any
Expand Down Expand Up @@ -147,7 +148,20 @@ def __repr__(self):


class BaseProvider(JsonSerializable):
"""Provider."""
"""
A provider class for specifying custom compute resources.
Example:
>>> provider = BaseProvider(
>>> name="<NAME>",
>>> host="<HOST>",
>>> token="<TOKEN>",
>>> compute_resource=ComputeResource(
>>> name="<COMPUTE_RESOURCE_NAME>",
>>> host="<COMPUTE_RESOURCE_HOST>"
>>> ),
>>> )
"""

def __init__(
self,
Expand All @@ -157,18 +171,8 @@ def __init__(
compute_resource: Optional[ComputeResource] = None,
available_compute_resources: Optional[List[ComputeResource]] = None,
):
"""Provider for serverless computation.
Example:
>>> provider = Provider(
>>> name="<NAME>",
>>> host="<HOST>",
>>> token="<TOKEN>",
>>> compute_resource=ComputeResource(
>>> name="<COMPUTE_RESOURCE_NAME>",
>>> host="<COMPUTE_RESOURCE_HOST>"
>>> ),
>>> )
"""
Initialize a BaseProvider instance.
Args:
name: name of provider
Expand Down Expand Up @@ -298,6 +302,7 @@ def download(self, file: str, download_location: str):

def delete(self, file: str):
"""Deletes file uploaded or produced by the programs,"""
raise NotImplementedError

def upload(self, file: str):
"""Upload file."""
Expand All @@ -308,8 +313,17 @@ def widget(self):
return Widget(self).show()


class Provider(BaseProvider):
"""Provider."""
class ServerlessProvider(BaseProvider):
"""
A provider for connecting to a specified host.
Example:
>>> provider = ServerlessProvider(
>>> name="<NAME>",
>>> host="<HOST>",
>>> token="<TOKEN>",
>>> )
"""

def __init__(
self,
Expand All @@ -321,7 +335,8 @@ def __init__(
token: Optional[str] = None,
verbose: bool = False,
):
"""Provider.
"""
Initializes the ServerlessProvider instance.
Args:
name: name of provider
Expand All @@ -332,7 +347,6 @@ def __init__(
token: authorization token
"""
name = name or "gateway-provider"

host = host or os.environ.get(ENV_GATEWAY_PROVIDER_HOST)
if host is None:
raise QuantumServerlessException("Please provide `host` of gateway.")
Expand Down Expand Up @@ -422,11 +436,32 @@ def _verify_token(self, token: str):
raise QuantumServerlessException("Cannot verify token.") from reason


class IBMServerlessProvider(Provider):
"""IBMServerlessProvider."""
class Provider(ServerlessProvider):
"""
[Deprecated since version 0.6.4] Use :class:`.ServerlessProvider` instead.
A provider for connecting to a specified host. This class has been
renamed to :class:`.ServerlessProvider`.
"""

def __init__(self, *args, **kwargs):
warnings.warn(
"The Provider class is deprecated. Use the identical ServerlessProvider class instead."
)
super().__init__(*args, **kwargs)


class IBMServerlessProvider(ServerlessProvider):
"""
A provider for connecting to the IBM serverless host.
Example:
>>> provider = IBMServerlessProvider(token="<TOKEN>")
"""

def __init__(self, token: str):
"""Constructor for IBMServerlessProvider
"""
Initialize a provider with access to an IBMQ-provided remote cluster.
Args:
token: IBM quantum token
Expand Down
6 changes: 3 additions & 3 deletions docs/deployment/client_configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ To install the client library, run:
Next, we need to configure the client to communicate with the provider.
This is done through the `Provider` configuration.
This can be done through the `BaseProvider` configuration.

Before we can configure the client and provider,
we need to know two things: the `username/password`
Expand All @@ -33,9 +33,9 @@ you can start configuring the client:

.. code-block::
from quantum_serverless import QuantumServerless, Provider
from quantum_serverless import QuantumServerless, ServerlessProvider
provider = Provider(
provider = ServerlessProvider(
username="<USERNAME>",
password="<PASSWORD>",
host="<HOST>",
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/01_vqe.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@
"metadata": {},
"outputs": [],
"source": [
"from quantum_serverless import QuantumServerless, Provider\n",
"from quantum_serverless import QuantumServerless, ServerlessProvider\n",
"import os"
]
},
Expand All @@ -189,7 +189,7 @@
"metadata": {},
"outputs": [],
"source": [
"provider = Provider(\n",
"provider = ServerlessProvider(\n",
" username=os.environ.get(\"GATEWAY_USER\", \"user\"),\n",
" password=os.environ.get(\"GATEWAY_PASSWORD\", \"password123\"),\n",
" # token=os.environ.get(\"GATEWAY_TOKEN\", \"<TOKEN>\"), # token can be used instead of user/password combination\n",
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/02_qaoa.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@
"metadata": {},
"outputs": [],
"source": [
"from quantum_serverless import QuantumServerless, Provider\n",
"from quantum_serverless import QuantumServerless, ServerlessProvider\n",
"import os"
]
},
Expand All @@ -221,7 +221,7 @@
}
],
"source": [
"provider = Provider(\n",
"provider = ServerlessProvider(\n",
" username=os.environ.get(\"GATEWAY_USER\", \"user\"),\n",
" password=os.environ.get(\"GATEWAY_PASSWORD\", \"password123\"),\n",
" # token=os.environ.get(\"GATEWAY_TOKEN\", \"<TOKEN>\"), # token can be used instead of user/password combination\n",
Expand Down
6 changes: 3 additions & 3 deletions docs/getting_started/basic/01_running_program.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"\n",
"To run the program, we need to import the necessary classes and configure them. One of these classes is QuantumServerless, which is a client class for interacting with compute resources.\n",
"\n",
"QuantumServerless takes a Provider object as a constructor argument. The Provider object stores configuration information about our compute resources, such as where they are located and how to connect to them. In this example, we will use a provider that is connected to a local Docker Compose setup. In this case, it allows us to run the program locally on our machine. If you want to run the program elsewhere, you will need to provide the corresponding host and authentication details."
"QuantumServerless takes a [BaseProvider](https://qiskit-extensions.github.io/quantum-serverless/stubs/quantum_serverless.core.BaseProvider.html) instance as a constructor argument. The provider stores configuration information about our compute resources, such as where they are located and how to connect to them. In this example, we will use a provider that is connected to a local Docker Compose setup. In this case, it allows us to run the program locally on our machine. If you want to run the program elsewhere, you will need to provide the corresponding host and authentication details."
]
},
{
Expand All @@ -56,7 +56,7 @@
"metadata": {},
"outputs": [],
"source": [
"from quantum_serverless import QuantumServerless, Provider\n",
"from quantum_serverless import QuantumServerless, ServerlessProvider\n",
"import os"
]
},
Expand Down Expand Up @@ -86,7 +86,7 @@
}
],
"source": [
"provider = Provider(\n",
"provider = ServerlessProvider(\n",
" username=os.environ.get(\"GATEWAY_USER\", \"user\"),\n",
" password=os.environ.get(\"GATEWAY_PASSWORD\", \"password123\"),\n",
" # token=os.environ.get(\"GATEWAY_TOKEN\", \"<TOKEN>\"), # token can be used instead of user/password combination\n",
Expand Down
4 changes: 2 additions & 2 deletions docs/getting_started/basic/02_arguments_and_results.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@
}
],
"source": [
"from quantum_serverless import QuantumServerless, Provider\n",
"from quantum_serverless import QuantumServerless, ServerlessProvider\n",
"import os\n",
"\n",
"provider = Provider(\n",
"provider = ServerlessProvider(\n",
" username=os.environ.get(\"GATEWAY_USER\", \"user\"),\n",
" password=os.environ.get(\"GATEWAY_PASSWORD\", \"password123\"),\n",
" # token=os.environ.get(\"GATEWAY_TOKEN\", \"<TOKEN>\"), # token can be used instead of user/password combination\n",
Expand Down
4 changes: 2 additions & 2 deletions docs/getting_started/basic/03_dependencies.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@
}
],
"source": [
"from quantum_serverless import QuantumServerless, Provider\n",
"from quantum_serverless import QuantumServerless, ServerlessProvider\n",
"import os\n",
"\n",
"provider = Provider(\n",
"provider = ServerlessProvider(\n",
" username=os.environ.get(\"GATEWAY_USER\", \"user\"),\n",
" password=os.environ.get(\"GATEWAY_PASSWORD\", \"password123\"),\n",
" # token=os.environ.get(\"GATEWAY_TOKEN\", \"<TOKEN>\"), # token can be used instead of user/password combination\n",
Expand Down
4 changes: 2 additions & 2 deletions docs/getting_started/basic/04_distributed_workloads.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@
}
],
"source": [
"from quantum_serverless import QuantumServerless, Provider\n",
"from quantum_serverless import QuantumServerless, ServerlessProvider\n",
"import os\n",
"\n",
"provider = Provider(\n",
"provider = ServerlessProvider(\n",
" username=os.environ.get(\"GATEWAY_USER\", \"user\"),\n",
" password=os.environ.get(\"GATEWAY_PASSWORD\", \"password123\"),\n",
" # token=os.environ.get(\"GATEWAY_TOKEN\", \"<TOKEN>\"), # token can be used instead of user/password combination\n",
Expand Down
6 changes: 3 additions & 3 deletions docs/getting_started/basic/05_retrieving_past_results.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"id": "37322958-a029-46bb-bc46-82b7ded329b5",
"metadata": {},
"source": [
"First, create [Provider](https://qiskit-extensions.github.io/quantum-serverless/stubs/quantum_serverless.core.Provider.html#quantum_serverless.core.Provider) and [QuantumServerless](https://qiskit-extensions.github.io/quantum-serverless/stubs/quantum_serverless.QuantumServerless.html#quantum_serverless.QuantumServerless) instances.\n",
"First, create [ServerlessProvider](https://qiskit-extensions.github.io/quantum-serverless/stubs/quantum_serverless.core.Provider.html#quantum_serverless.core.ServerlessProvider) and [QuantumServerless](https://qiskit-extensions.github.io/quantum-serverless/stubs/quantum_serverless.QuantumServerless.html#quantum_serverless.QuantumServerless) instances.\n",
"\n",
"> &#x26A0; This provider is set up with default credentials to a test cluster intended to run on your machine. For information on setting up infrastructure on your local machine, check out the guide on [local infrastructure setup](https://qiskit-extensions.github.io/quantum-serverless/deployment/local.html)."
]
Expand All @@ -27,10 +27,10 @@
"metadata": {},
"outputs": [],
"source": [
"from quantum_serverless import QuantumServerless, Provider\n",
"from quantum_serverless import QuantumServerless, ServerlessProvider\n",
"import os\n",
"\n",
"provider = Provider(\n",
"provider = ServerlessProvider(\n",
" username=os.environ.get(\"GATEWAY_USER\", \"user\"),\n",
" password=os.environ.get(\"GATEWAY_PASSWORD\", \"password123\"),\n",
" # token=os.environ.get(\"GATEWAY_TOKEN\", \"<TOKEN>\"), # token can be used instead of user/password combination\n",
Expand Down
4 changes: 2 additions & 2 deletions docs/getting_started/experimental/file_download.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
],
"source": [
"import os\n",
"from quantum_serverless import QuantumServerless, Provider, Program\n",
"from quantum_serverless import QuantumServerless, ServerlessProvider, Program\n",
"\n",
"provider = Provider(\n",
"provider = ServerlessProvider(\n",
" username=\"user\",\n",
" password=\"password123\",\n",
" host=os.environ.get(\"GATEWAY_HOST\", \"http://localhost:8000\"),\n",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
],
"source": [
"import os\n",
"from quantum_serverless import Provider\n",
"from quantum_serverless import ServerlessProvider\n",
"\n",
"provider = Provider(\n",
"provider = ServerlessProvider(\n",
" username=\"user\",\n",
" password=\"password123\",\n",
" host=os.environ.get(\"GATEWAY_HOST\", \"http://localhost:8000\"),\n",
Expand All @@ -61,7 +61,7 @@
"## Hello, Qiskit!\n",
"\n",
"Let's create simpliest program by writing a funtion `hello_qiskit` and annotating it with `@distribute_program` decorator. \n",
"Decorator accepts `Provider` as one of the arguments. Other arguments are `dependencies` to specify extra packages to install during execution and `working_dir` to specify working directory that will be shiped for remote execution if needed."
"The ``distribute_program`` decorator accepts a [BaseProvider](https://qiskit-extensions.github.io/quantum-serverless/stubs/quantum_serverless.core.BaseProvider.html) instance for the ``provider`` argument. Other arguments are `dependencies` to specify extra packages to install during execution and `working_dir` to specify working directory that will be shiped for remote execution if needed."
]
},
{
Expand Down
4 changes: 2 additions & 2 deletions docs/migration/migration_from_qiskit_runtime_programs.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,10 @@
}
],
"source": [
"from quantum_serverless import QuantumServerless, Provider\n",
"from quantum_serverless import QuantumServerless, ServerlessProvider\n",
"import os\n",
"\n",
"provider = Provider(\n",
"provider = ServerlessProvider(\n",
" username=os.environ.get(\"GATEWAY_USER\", \"user\"),\n",
" password=os.environ.get(\"GATEWAY_PASSWORD\", \"password123\"),\n",
" # token=os.environ.get(\"GATEWAY_TOKEN\", \"<TOKEN>\"), # token can be used instead of user/password combination\n",
Expand Down

0 comments on commit a7d4b0b

Please sign in to comment.