Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose api execution options timeout ii #516

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ ndarray.workspace = true
num = { version = "0.4.0", features = ["serde"] }
opentelemetry = { version = "0.23.0" }
opentelemetry_sdk = { version = "0.23.0" }
pbjson-types = "0.7.0"
qcs-api-client-common.workspace = true
qcs-api-client-openapi.workspace = true
qcs-api-client-grpc.workspace = true
Expand Down
5 changes: 2 additions & 3 deletions crates/lib/src/executable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,10 +344,9 @@ impl Executable<'_, '_> {
}

fn get_readouts(&self) -> &[Cow<'_, str>] {
return self
.readout_memory_region_names
self.readout_memory_region_names
.as_ref()
.map_or(&[Cow::Borrowed("ro")], Vec::as_slice);
.map_or(&[Cow::Borrowed("ro")], Vec::as_slice)
}

/// Execute on a QVM which must be available at the configured URL (default <http://localhost:5000>).
Expand Down
25 changes: 25 additions & 0 deletions crates/lib/src/qpu/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

use std::{convert::TryFrom, fmt, time::Duration};

#[deny(clippy::module_name_repetitions)]
pub use ::pbjson_types::Duration as QpuApiDuration;
use async_trait::async_trait;
use cached::proc_macro::cached;
use derive_builder::Builder;
Expand Down Expand Up @@ -363,7 +365,7 @@
/// to build a custom set of options.
#[derive(Builder, Clone, Debug, Default, PartialEq)]
#[allow(clippy::module_name_repetitions)]
pub struct ApiExecutionOptions {

Check warning on line 368 in crates/lib/src/qpu/api.rs

View workflow job for this annotation

GitHub Actions / publish-docs

type could implement `Copy`; consider adding `impl Copy`

Check warning on line 368 in crates/lib/src/qpu/api.rs

View workflow job for this annotation

GitHub Actions / Run Checks

type could implement `Copy`; consider adding `impl Copy`

Check warning on line 368 in crates/lib/src/qpu/api.rs

View workflow job for this annotation

GitHub Actions / publish-docs

type could implement `Copy`; consider adding `impl Copy`
/// the inner proto representation
inner: InnerApiExecutionOptions,
}
Expand All @@ -382,6 +384,21 @@
pub fn bypass_settings_protection(&self) -> bool {
self.inner.bypass_settings_protection
}

/// Get the configured `timeout` value.
///
/// Note, this is the timeout while running a job; the job will be evicted from
/// the hardware once this time has elapsed.
///
/// If unset, the job's estimated duration will be used;
/// if the job does not have an estimated duration, the default
/// timeout is selected by the service.
///
/// The service may also enforce a maximum value for this field.
#[must_use]
pub fn timeout(&self) -> Option<::pbjson_types::Duration> {
self.inner.timeout
}
}

impl From<ApiExecutionOptions> for InnerApiExecutionOptions {
Expand All @@ -404,6 +421,14 @@
.bypass_settings_protection = bypass_settings_protection;
self
}

/// Set the `timeout` value. See [`ApiExecutionOptions::timeout`] for more information.
pub fn timeout(&mut self, timeout: Option<::pbjson_types::Duration>) -> &mut Self {
self.inner
.get_or_insert(InnerApiExecutionOptions::default())
.timeout = timeout;
self
}
}

impl ExecutionOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@

__doc__ = common.__doc__
__all__ = getattr(common, "__all__", [])

6 changes: 4 additions & 2 deletions crates/python/qcs_sdk/_tracing_subscriber/common/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@

from typing import Dict, Optional, final


@final
class InstrumentationLibrary:
"""
Information about a library or crate providing instrumentation.

An instrumentation library should be named to follow any naming conventions
of the instrumented library (e.g. 'middleware' for a web framework).

See the `instrumentation libraries <https://github.com/open-telemetry/opentelemetry-specification/blob/v1.9.0/specification/overview.md#instrumentation-libraries>`_
spec for more information.
"""
Expand All @@ -41,3 +42,4 @@ class InstrumentationLibrary:
:param attributes: The attributes of the instrumentation library.
"""
...

Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@

__doc__ = layers.__doc__
__all__ = getattr(layers, "__all__", [])

16 changes: 8 additions & 8 deletions crates/python/qcs_sdk/_tracing_subscriber/layers/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@
from __future__ import annotations
from typing import TYPE_CHECKING

from . import file as file
from . import file as file
from . import otel_otlp_file as otel_otlp_file
from . import otel_otlp as otel_otlp

if TYPE_CHECKING:
from typing import Union
from typing import Union

Config = Union[
file.Config,
otel_otlp_file.Config,
otel_otlp.Config,
]
"""
Config = Union[
file.Config,
otel_otlp_file.Config,
otel_otlp.Config,
]
"""
One of the supported layer configurations that may be set on the subscriber configuration.
"""
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@

__doc__ = file.__doc__
__all__ = getattr(file, "__all__", [])


Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ class Config:
:param json: Whether or not to format the output as JSON. Defaults to `True`.
"""
...

Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@

__doc__ = otel_otlp.__doc__
__all__ = getattr(otel_otlp, "__all__", [])

Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class Resource:
schema_url: Optional[str] = None,
) -> "Resource": ...



@final
class Config:
"""
Expand Down Expand Up @@ -99,14 +101,14 @@ class Config:
...

if TYPE_CHECKING:
from typing import List, Union
from typing import List, Union

ResourceValueArray = Union[List[bool], List[int], List[float], List[str]]
"""
An array of `ResourceValue`s. This array is homogenous, so all values must be of the same type.
"""

ResourceValue = Union[bool, int, float, str, ResourceValueArray]
ResourceValue= Union[bool, int, float, str, ResourceValueArray]
"""
A value that can be added to a `Resource`.
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@

__doc__ = otel_otlp_file.__doc__
__all__ = getattr(otel_otlp_file, "__all__", [])

Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,15 @@
from typing import Optional, final
from qcs_sdk._tracing_subscriber.common import InstrumentationLibrary


@final
class Config:
"""
A configuration for `opentelemetry-stdout <https://docs.rs/opentelemetry-stdout/latest/opentelemetry_stdout/>`_
layer.
"""

def __new__(
cls,
*,
file_path: Optional[str] = None,
filter: Optional[str] = None,
instrumentation_library: Optional[InstrumentationLibrary] = None,
) -> "Config":
def __new__(cls, *, file_path: Optional[str] = None, filter: Optional[str] = None, instrumentation_library: Optional[InstrumentationLibrary] = None) -> "Config":
"""
:param file_path: The path to the file to write to. If not specified, defaults to stdout.
:param filter: A filter string to use for this layer. This uses the same format as the
Expand All @@ -40,3 +35,4 @@ class Config:
:param instrumentation_library: Information about the library providing the tracing instrumentation.
"""
...

Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@

__doc__ = subscriber.__doc__
__all__ = getattr(subscriber, "__all__", [])

Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ class Config:
"""

def __new__(cls, *, layer: layers.Config) -> "Config": ...

44 changes: 44 additions & 0 deletions crates/python/qcs_sdk/qpu/api.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,26 @@ class ExecutionOptionsBuilder:
def build(self) -> ExecutionOptions:
"""Build the ``ExecutionOptions`` using the options set in this builder."""


@final
class QpuApiDuration:
def __new__(cls, seconds: int, nanos: int) -> "QpuApiDuration":
"""
Create a new QpuApiDuration with the given number of seconds and nanoseconds.
"""
...

@property
def seconds(self) -> int:
"""The number of seconds in the duration."""
...

@property
def nanos(self) -> int:
"""The number of nanoseconds in the duration."""
...


@final
class APIExecutionOptions:
@staticmethod
Expand All @@ -408,6 +428,23 @@ class APIExecutionOptions:
def bypass_settings_protection(self) -> bool:
"""Whether or not to force managed settings to change, if applicable. Subject to additional authorization requirements."""

@property
def timeout(self) -> QpuApiDuration:
"""
The job timeout.

Note, this is the timeout while running a job; the job will be evicted from
the hardware once this time has elapsed.

If unset, the job's estimated duration will be used;
if the job does not have an estimated duration, the default
timeout is selected by the service.

The service may also enforce a maximum value for this field
The time in seconds to wait before timing out a request, if any.
"""
...

@final
class APIExecutionOptionsBuilder:
def __new__(cls) -> APIExecutionOptionsBuilder: ...
Expand All @@ -421,6 +458,13 @@ class APIExecutionOptionsBuilder:
@bypass_settings_protection.setter
def bypass_settings_protection(self, bypass_settings_protection: bool):
"""Whether or not to force managed settings to change, if applicable. Subject to additional authorization requirements."""
@property
def timeout(self) -> QpuApiDuration:
raise AttributeError("timeout is not readable")
@timeout.setter
def timeout(self, timeout: QpuApiDuration):
"""Set the job timeout. See ``APIExecutionOptions.timeout`` for details."""

def build(self) -> APIExecutionOptions:
"""Build the ``APIExecutionOptions`` using the options set in this builder."""

Expand Down
51 changes: 48 additions & 3 deletions crates/python/src/qpu/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use pyo3::{
};
use qcs::qpu::api::{
ApiExecutionOptions, ApiExecutionOptionsBuilder, ConnectionStrategy, ExecutionOptions,
ExecutionOptionsBuilder,
ExecutionOptionsBuilder, QpuApiDuration,
};
use qcs_api_client_grpc::models::controller::{
data_value, readout_values, ControllerJobExecutionResult,
Expand All @@ -36,7 +36,8 @@ create_init_submodule! {
PyExecutionOptions,
PyExecutionOptionsBuilder,
PyApiExecutionOptions,
PyApiExecutionOptionsBuilder
PyApiExecutionOptionsBuilder,
PyQpuApiDuration
],
errors: [
SubmissionError,
Expand Down Expand Up @@ -421,7 +422,7 @@ impl PyExecutionOptions {
fn api_options(&self) -> Option<PyApiExecutionOptions> {
self.as_inner()
.api_options()
.map(|x| PyApiExecutionOptions(x.clone().into()))
.map(|x| PyApiExecutionOptions((*x).into()))
BatmanAoD marked this conversation as resolved.
Show resolved Hide resolved
}

fn __richcmp__(&self, py: Python<'_>, other: &Self, op: CompareOp) -> PyObject {
Expand Down Expand Up @@ -479,6 +480,13 @@ impl PyApiExecutionOptions {
fn bypass_settings_protection(&self) -> bool {
self.as_inner().bypass_settings_protection()
}

#[getter]
fn timeout(&self) -> Option<PyQpuApiDuration> {
self.as_inner()
.timeout()
.map(|inner| PyQpuApiDuration { inner })
}
}

py_wrap_type! {
Expand Down Expand Up @@ -539,6 +547,32 @@ py_wrap_type! {
PyApiExecutionOptionsBuilder(ApiExecutionOptionsBuilder) as "APIExecutionOptionsBuilder"
}

#[pyclass(name = "QpuApiDuration")]
#[derive(Debug, Clone)]
pub struct PyQpuApiDuration {
inner: QpuApiDuration,
}

#[pymethods]
impl PyQpuApiDuration {
#[new]
fn new(seconds: i64, nanos: i32) -> Self {
BatmanAoD marked this conversation as resolved.
Show resolved Hide resolved
Self {
inner: QpuApiDuration { seconds, nanos },
}
}

#[getter]
fn seconds(&self) -> i64 {
self.inner.seconds
}

#[getter]
fn nanos(&self) -> i32 {
self.inner.nanos
}
}

#[pymethods]
impl PyApiExecutionOptionsBuilder {
#[new]
Expand All @@ -564,6 +598,17 @@ impl PyApiExecutionOptionsBuilder {
);
}

#[setter]
fn timeout(&mut self, timeout: Option<PyQpuApiDuration>) -> PyResult<()> {
*self = Self::from(
self.as_inner()
.clone()
.timeout(timeout.map(|timeout| timeout.inner))
.clone(),
);
Ok(())
}

fn build(&self) -> PyResult<PyApiExecutionOptions> {
Ok(PyApiExecutionOptions::from(
self.as_inner()
Expand Down
Loading