luna-quantum 1.1.0__cp312-cp312-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- luna_quantum/__init__.py +139 -0
- luna_quantum/__init__.pyi +98 -0
- luna_quantum/_core.cp312-win_amd64.pyd +0 -0
- luna_quantum/_core.pyi +4286 -0
- luna_quantum/_utility.py +148 -0
- luna_quantum/_utility.pyi +20 -0
- luna_quantum/algorithms/__init__.py +1 -0
- luna_quantum/aqm_overwrites/__init__.py +3 -0
- luna_quantum/aqm_overwrites/model.py +184 -0
- luna_quantum/backends/__init__.py +1 -0
- luna_quantum/client/__init__.py +0 -0
- luna_quantum/client/controllers/__init__.py +4 -0
- luna_quantum/client/controllers/luna_http_client.py +37 -0
- luna_quantum/client/controllers/luna_platform_client.py +256 -0
- luna_quantum/client/controllers/luna_q.py +67 -0
- luna_quantum/client/controllers/luna_solve.py +129 -0
- luna_quantum/client/error/__init__.py +0 -0
- luna_quantum/client/error/luna_api_key_invalid_error.py +10 -0
- luna_quantum/client/error/luna_api_key_missing_error.py +10 -0
- luna_quantum/client/error/luna_error.py +2 -0
- luna_quantum/client/error/luna_server_error.py +20 -0
- luna_quantum/client/error/timeout_error.py +12 -0
- luna_quantum/client/error/transformation_error.py +18 -0
- luna_quantum/client/error/utils/__init__.py +0 -0
- luna_quantum/client/error/utils/http_error_utils.py +112 -0
- luna_quantum/client/interfaces/__init__.py +4 -0
- luna_quantum/client/interfaces/clients/__init__.py +25 -0
- luna_quantum/client/interfaces/clients/circuit_rest_client_i.py +68 -0
- luna_quantum/client/interfaces/clients/info_rest_client_i.py +53 -0
- luna_quantum/client/interfaces/clients/model_rest_client_i.py +139 -0
- luna_quantum/client/interfaces/clients/qpu_token_rest_client_i.py +364 -0
- luna_quantum/client/interfaces/clients/rest_client_i.py +21 -0
- luna_quantum/client/interfaces/clients/solve_job_rest_client_i.py +201 -0
- luna_quantum/client/interfaces/clients/users_rest_client_i.py +29 -0
- luna_quantum/client/interfaces/services/__init__.py +0 -0
- luna_quantum/client/interfaces/services/luna_q_i.py +34 -0
- luna_quantum/client/interfaces/services/luna_solve_i.py +72 -0
- luna_quantum/client/interfaces/services/service_i.py +56 -0
- luna_quantum/client/rest_client/__init__.py +15 -0
- luna_quantum/client/rest_client/circuit_rest_client.py +107 -0
- luna_quantum/client/rest_client/info_rest_client.py +74 -0
- luna_quantum/client/rest_client/model_rest_client.py +216 -0
- luna_quantum/client/rest_client/qpu_token_rest_client.py +508 -0
- luna_quantum/client/rest_client/solve_job_rest_client.py +286 -0
- luna_quantum/client/rest_client/users_rest_client.py +35 -0
- luna_quantum/client/schemas/__init__.py +26 -0
- luna_quantum/client/schemas/circuit.py +48 -0
- luna_quantum/client/schemas/create/__init__.py +15 -0
- luna_quantum/client/schemas/create/circuit.py +30 -0
- luna_quantum/client/schemas/create/optimization.py +39 -0
- luna_quantum/client/schemas/create/qpu_token.py +22 -0
- luna_quantum/client/schemas/create/qpu_token_time_quota.py +35 -0
- luna_quantum/client/schemas/create/qpu_token_time_quota_update.py +24 -0
- luna_quantum/client/schemas/create/qubo.py +19 -0
- luna_quantum/client/schemas/create/solve_job_create.py +43 -0
- luna_quantum/client/schemas/enums/__init__.py +0 -0
- luna_quantum/client/schemas/enums/call_style.py +13 -0
- luna_quantum/client/schemas/enums/circuit.py +42 -0
- luna_quantum/client/schemas/enums/model_format.py +11 -0
- luna_quantum/client/schemas/enums/problem.py +50 -0
- luna_quantum/client/schemas/enums/qpu_token_type.py +20 -0
- luna_quantum/client/schemas/enums/sense.py +8 -0
- luna_quantum/client/schemas/enums/status.py +40 -0
- luna_quantum/client/schemas/enums/timeframe.py +11 -0
- luna_quantum/client/schemas/error_message.py +14 -0
- luna_quantum/client/schemas/model_metadata.py +35 -0
- luna_quantum/client/schemas/qpu_token/__init__.py +0 -0
- luna_quantum/client/schemas/qpu_token/qpu_token.py +154 -0
- luna_quantum/client/schemas/qpu_token/qpu_token_source.py +19 -0
- luna_quantum/client/schemas/qpu_token/qpu_token_time_quota.py +30 -0
- luna_quantum/client/schemas/qpu_token/token_provider.py +132 -0
- luna_quantum/client/schemas/representation.py +19 -0
- luna_quantum/client/schemas/solution.py +106 -0
- luna_quantum/client/schemas/solve_job.py +50 -0
- luna_quantum/client/schemas/solver_info.py +11 -0
- luna_quantum/client/schemas/user.py +11 -0
- luna_quantum/client/schemas/wrappers/__init__.py +5 -0
- luna_quantum/client/schemas/wrappers/datetime_wrapper.py +32 -0
- luna_quantum/client/utils/__init__.py +0 -0
- luna_quantum/client/utils/qpu_token_utils.py +147 -0
- luna_quantum/config.py +11 -0
- luna_quantum/decorators.py +248 -0
- luna_quantum/errors.py +34 -0
- luna_quantum/errors.pyi +287 -0
- luna_quantum/exceptions/__init__.py +0 -0
- luna_quantum/exceptions/base_luna_quantum_error.py +2 -0
- luna_quantum/exceptions/luna_quantum_call_type_error.py +9 -0
- luna_quantum/exceptions/patch_class_field_exists_error.py +10 -0
- luna_quantum/factories/__init__.py +4 -0
- luna_quantum/factories/luna_solve_client_factory.py +100 -0
- luna_quantum/factories/usecase_factory.py +489 -0
- luna_quantum/py.typed +0 -0
- luna_quantum/solve/__init__.py +13 -0
- luna_quantum/solve/default_token.py +304 -0
- luna_quantum/solve/domain/__init__.py +0 -0
- luna_quantum/solve/domain/abstract/__init__.py +4 -0
- luna_quantum/solve/domain/abstract/luna_algorithm.py +205 -0
- luna_quantum/solve/domain/abstract/qpu_token_backend.py +34 -0
- luna_quantum/solve/domain/model_metadata.py +56 -0
- luna_quantum/solve/domain/solve_job.py +230 -0
- luna_quantum/solve/errors/__init__.py +0 -0
- luna_quantum/solve/errors/incompatible_backend_error.py +15 -0
- luna_quantum/solve/errors/model_metadata_missing_error.py +11 -0
- luna_quantum/solve/errors/solve_base_error.py +5 -0
- luna_quantum/solve/errors/token_missing_error.py +11 -0
- luna_quantum/solve/interfaces/__init__.py +0 -0
- luna_quantum/solve/interfaces/algorithm_i.py +49 -0
- luna_quantum/solve/interfaces/backend_i.py +28 -0
- luna_quantum/solve/interfaces/usecases/__init__.py +59 -0
- luna_quantum/solve/interfaces/usecases/model_delete_usecase_i.py +27 -0
- luna_quantum/solve/interfaces/usecases/model_fetch_metadata_usecase_i.py +33 -0
- luna_quantum/solve/interfaces/usecases/model_get_solutions_usecase_i.py +33 -0
- luna_quantum/solve/interfaces/usecases/model_get_solve_jobs_usecase_i.py +33 -0
- luna_quantum/solve/interfaces/usecases/model_load_by_id_usecase_i.py +32 -0
- luna_quantum/solve/interfaces/usecases/model_load_by_metadata_usecase_i.py +37 -0
- luna_quantum/solve/interfaces/usecases/model_load_metadata_by_hash_usecase_i.py +38 -0
- luna_quantum/solve/interfaces/usecases/model_save_usecase_i.py +36 -0
- luna_quantum/solve/interfaces/usecases/solve_job_cancel_usecase_i.py +33 -0
- luna_quantum/solve/interfaces/usecases/solve_job_create_usecase_i.py +44 -0
- luna_quantum/solve/interfaces/usecases/solve_job_delete_usecase_i.py +32 -0
- luna_quantum/solve/interfaces/usecases/solve_job_fetch_updates_usecase_i.py +38 -0
- luna_quantum/solve/interfaces/usecases/solve_job_get_by_id_usecase_i.py +27 -0
- luna_quantum/solve/interfaces/usecases/solve_job_get_result_usecase_i.py +63 -0
- luna_quantum/solve/parameters/__init__.py +0 -0
- luna_quantum/solve/parameters/algorithms/__init__.py +51 -0
- luna_quantum/solve/parameters/algorithms/base_params/__init__.py +24 -0
- luna_quantum/solve/parameters/algorithms/base_params/decomposer.py +57 -0
- luna_quantum/solve/parameters/algorithms/base_params/qaoa_circuit_params.py +95 -0
- luna_quantum/solve/parameters/algorithms/base_params/quantum_annealing_params.py +79 -0
- luna_quantum/solve/parameters/algorithms/base_params/scipy_optimizer.py +122 -0
- luna_quantum/solve/parameters/algorithms/base_params/simulated_annealing_params.py +106 -0
- luna_quantum/solve/parameters/algorithms/base_params/tabu_kerberos_params.py +39 -0
- luna_quantum/solve/parameters/algorithms/base_params/tabu_search_params.py +129 -0
- luna_quantum/solve/parameters/algorithms/flexible_parameter_algorithm.py +59 -0
- luna_quantum/solve/parameters/algorithms/genetic_algorithms/__init__.py +4 -0
- luna_quantum/solve/parameters/algorithms/genetic_algorithms/qaga.py +131 -0
- luna_quantum/solve/parameters/algorithms/genetic_algorithms/saga.py +139 -0
- luna_quantum/solve/parameters/algorithms/lq_fda/__init__.py +3 -0
- luna_quantum/solve/parameters/algorithms/lq_fda/fujits_da_base.py +85 -0
- luna_quantum/solve/parameters/algorithms/lq_fda/fujitsu_da_v3c.py +155 -0
- luna_quantum/solve/parameters/algorithms/optimization_solvers/__init__.py +3 -0
- luna_quantum/solve/parameters/algorithms/optimization_solvers/scip.py +51 -0
- luna_quantum/solve/parameters/algorithms/quantum_annealing/__init__.py +19 -0
- luna_quantum/solve/parameters/algorithms/quantum_annealing/kerberos.py +149 -0
- luna_quantum/solve/parameters/algorithms/quantum_annealing/leap_hybrid_bqm.py +75 -0
- luna_quantum/solve/parameters/algorithms/quantum_annealing/leap_hybrid_cqm.py +75 -0
- luna_quantum/solve/parameters/algorithms/quantum_annealing/parallel_tempering_qpu.py +139 -0
- luna_quantum/solve/parameters/algorithms/quantum_annealing/population_annealing_qpu.py +109 -0
- luna_quantum/solve/parameters/algorithms/quantum_annealing/qbsolv_like_qpu.py +111 -0
- luna_quantum/solve/parameters/algorithms/quantum_annealing/quantum_annealing.py +121 -0
- luna_quantum/solve/parameters/algorithms/quantum_annealing/repeated_reverse_quantum_annealing.py +174 -0
- luna_quantum/solve/parameters/algorithms/quantum_gate/__init__.py +6 -0
- luna_quantum/solve/parameters/algorithms/quantum_gate/flex_qaoa/__init__.py +10 -0
- luna_quantum/solve/parameters/algorithms/quantum_gate/flexqaoa/__init__.py +29 -0
- luna_quantum/solve/parameters/algorithms/quantum_gate/flexqaoa/config.py +58 -0
- luna_quantum/solve/parameters/algorithms/quantum_gate/flexqaoa/flexqaoa.py +188 -0
- luna_quantum/solve/parameters/algorithms/quantum_gate/flexqaoa/optimizers.py +53 -0
- luna_quantum/solve/parameters/algorithms/quantum_gate/flexqaoa/pipeline.py +164 -0
- luna_quantum/solve/parameters/algorithms/quantum_gate/qaoa.py +112 -0
- luna_quantum/solve/parameters/algorithms/quantum_gate/qaoa_fo.py +69 -0
- luna_quantum/solve/parameters/algorithms/quantum_gate/vqe.py +108 -0
- luna_quantum/solve/parameters/algorithms/search_algorithms/__init__.py +5 -0
- luna_quantum/solve/parameters/algorithms/search_algorithms/dialectic_search.py +136 -0
- luna_quantum/solve/parameters/algorithms/search_algorithms/qbsolv_like_tabu_search.py +117 -0
- luna_quantum/solve/parameters/algorithms/search_algorithms/tabu_search.py +126 -0
- luna_quantum/solve/parameters/algorithms/simulated_annealing/__init__.py +13 -0
- luna_quantum/solve/parameters/algorithms/simulated_annealing/parallel_tempering.py +131 -0
- luna_quantum/solve/parameters/algorithms/simulated_annealing/population_annealing.py +95 -0
- luna_quantum/solve/parameters/algorithms/simulated_annealing/qbsolv_like_simulated_annealing.py +141 -0
- luna_quantum/solve/parameters/algorithms/simulated_annealing/repeated_reverse_simulated_annealing.py +172 -0
- luna_quantum/solve/parameters/algorithms/simulated_annealing/simulated_annealing.py +126 -0
- luna_quantum/solve/parameters/backends/__init__.py +27 -0
- luna_quantum/solve/parameters/backends/aqarios.py +17 -0
- luna_quantum/solve/parameters/backends/aqarios_gpu.py +17 -0
- luna_quantum/solve/parameters/backends/aws/__init__.py +11 -0
- luna_quantum/solve/parameters/backends/aws/aws.py +36 -0
- luna_quantum/solve/parameters/backends/aws/aws_backend_base.py +74 -0
- luna_quantum/solve/parameters/backends/aws/ionq.py +43 -0
- luna_quantum/solve/parameters/backends/aws/iqm.py +31 -0
- luna_quantum/solve/parameters/backends/aws/rigetti.py +31 -0
- luna_quantum/solve/parameters/backends/cudaq/__init__.py +5 -0
- luna_quantum/solve/parameters/backends/cudaq/cudaq_base.py +16 -0
- luna_quantum/solve/parameters/backends/cudaq/cudaq_cpu.py +30 -0
- luna_quantum/solve/parameters/backends/cudaq/cudaq_gpu.py +32 -0
- luna_quantum/solve/parameters/backends/dwave.py +17 -0
- luna_quantum/solve/parameters/backends/dwave_qpu.py +166 -0
- luna_quantum/solve/parameters/backends/fda.py +17 -0
- luna_quantum/solve/parameters/backends/ibm.py +138 -0
- luna_quantum/solve/parameters/backends/qctrl.py +103 -0
- luna_quantum/solve/parameters/backends/zib.py +17 -0
- luna_quantum/solve/parameters/constants.py +11 -0
- luna_quantum/solve/parameters/errors.py +30 -0
- luna_quantum/solve/parameters/mixins/__init__.py +0 -0
- luna_quantum/solve/parameters/mixins/fujitsu_common_params_mixin.py +239 -0
- luna_quantum/solve/parameters/mixins/fujitsu_v2_mixin.py +70 -0
- luna_quantum/solve/parameters/mixins/qbsolv_like_mixin.py +60 -0
- luna_quantum/solve/use_cases/__init__.py +119 -0
- luna_quantum/solve/use_cases/arbitrage_edge_based.py +50 -0
- luna_quantum/solve/use_cases/arbitrage_node_based.py +55 -0
- luna_quantum/solve/use_cases/base.py +7 -0
- luna_quantum/solve/use_cases/binary_integer_linear_programming.py +54 -0
- luna_quantum/solve/use_cases/binary_paint_shop_problem.py +37 -0
- luna_quantum/solve/use_cases/credit_scoring_feature_selection.py +40 -0
- luna_quantum/solve/use_cases/dynamic_portfolio_optimization.py +64 -0
- luna_quantum/solve/use_cases/exact_cover.py +51 -0
- luna_quantum/solve/use_cases/flight_gate_assignment.py +79 -0
- luna_quantum/solve/use_cases/graph_coloring.py +42 -0
- luna_quantum/solve/use_cases/graph_isomorphism.py +52 -0
- luna_quantum/solve/use_cases/graph_partitioning.py +46 -0
- luna_quantum/solve/use_cases/hamiltonian_cycle.py +49 -0
- luna_quantum/solve/use_cases/induced_subgraph_isomorphism.py +50 -0
- luna_quantum/solve/use_cases/job_shop_scheduling.py +44 -0
- luna_quantum/solve/use_cases/k_medoids_clustering.py +49 -0
- luna_quantum/solve/use_cases/knapsack_integer_weights.py +56 -0
- luna_quantum/solve/use_cases/linear_regression.py +60 -0
- luna_quantum/solve/use_cases/lmwcs.py +84 -0
- luna_quantum/solve/use_cases/longest_path.py +50 -0
- luna_quantum/solve/use_cases/market_graph_clustering.py +61 -0
- luna_quantum/solve/use_cases/max2sat.py +54 -0
- luna_quantum/solve/use_cases/max3sat.py +55 -0
- luna_quantum/solve/use_cases/max_clique.py +60 -0
- luna_quantum/solve/use_cases/max_cut.py +48 -0
- luna_quantum/solve/use_cases/max_independent_set.py +37 -0
- luna_quantum/solve/use_cases/minimal_maximal_matching.py +54 -0
- luna_quantum/solve/use_cases/minimal_spanning_tree.py +90 -0
- luna_quantum/solve/use_cases/minimum_vertex_cover.py +45 -0
- luna_quantum/solve/use_cases/number_partitioning.py +32 -0
- luna_quantum/solve/use_cases/portfolio_optimization.py +46 -0
- luna_quantum/solve/use_cases/portfolio_optimization_ib_tv.py +63 -0
- luna_quantum/solve/use_cases/quadratic_assignment.py +49 -0
- luna_quantum/solve/use_cases/quadratic_knapsack.py +48 -0
- luna_quantum/solve/use_cases/satellite_scheduling.py +73 -0
- luna_quantum/solve/use_cases/sensor_placement.py +58 -0
- luna_quantum/solve/use_cases/set_cover.py +56 -0
- luna_quantum/solve/use_cases/set_packing.py +54 -0
- luna_quantum/solve/use_cases/set_partitioning.py +52 -0
- luna_quantum/solve/use_cases/subgraph_isomorphism.py +55 -0
- luna_quantum/solve/use_cases/subset_sum.py +37 -0
- luna_quantum/solve/use_cases/support_vector_machine.py +64 -0
- luna_quantum/solve/use_cases/traffic_flow.py +35 -0
- luna_quantum/solve/use_cases/travelling_salesman_problem.py +53 -0
- luna_quantum/solve/use_cases/type_aliases.py +9 -0
- luna_quantum/solve/use_cases/weighted_max_cut.py +37 -0
- luna_quantum/solve/usecases/__init__.py +45 -0
- luna_quantum/solve/usecases/model_delete_usecase.py +49 -0
- luna_quantum/solve/usecases/model_fetch_metadata_usecase.py +50 -0
- luna_quantum/solve/usecases/model_get_solution_usecase.py +59 -0
- luna_quantum/solve/usecases/model_get_solve_jobs_usecase.py +62 -0
- luna_quantum/solve/usecases/model_load_by_id_usecase.py +47 -0
- luna_quantum/solve/usecases/model_load_by_metadata_usecase.py +52 -0
- luna_quantum/solve/usecases/model_load_metadata_by_hash_usecase.py +51 -0
- luna_quantum/solve/usecases/model_save_usecase.py +63 -0
- luna_quantum/solve/usecases/solve_job_cancel_usecase.py +51 -0
- luna_quantum/solve/usecases/solve_job_create_usecase.py +112 -0
- luna_quantum/solve/usecases/solve_job_delete_usecase.py +38 -0
- luna_quantum/solve/usecases/solve_job_fetch_updates_usecase.py +49 -0
- luna_quantum/solve/usecases/solve_job_get_by_id_usecase.py +44 -0
- luna_quantum/solve/usecases/solve_job_get_result_usecase.py +105 -0
- luna_quantum/transformations.py +18 -0
- luna_quantum/transformations.pyi +371 -0
- luna_quantum/translator.py +23 -0
- luna_quantum/translator.pyi +869 -0
- luna_quantum/util/__init__.py +0 -0
- luna_quantum/util/active_waiting.py +79 -0
- luna_quantum/util/class_patcher.py +164 -0
- luna_quantum/util/debug_info.py +52 -0
- luna_quantum/util/log_utils.py +187 -0
- luna_quantum/util/pretty_base.py +67 -0
- luna_quantum/util/pydantic_utils.py +38 -0
- luna_quantum/utils.py +3 -0
- luna_quantum/utils.pyi +67 -0
- luna_quantum-1.1.0.dist-info/METADATA +36 -0
- luna_quantum-1.1.0.dist-info/RECORD +276 -0
- luna_quantum-1.1.0.dist-info/WHEEL +4 -0
- luna_quantum-1.1.0.dist-info/licenses/LICENSE +176 -0
- luna_quantum-1.1.0.dist-info/licenses/NOTICE +13 -0
luna_quantum/_utility.py
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""Utility module for internals."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
if sys.version_info < (3, 13):
|
|
6
|
+
from warnings import warn
|
|
7
|
+
|
|
8
|
+
class DeprecationWarning(Warning): ... # noqa: A001
|
|
9
|
+
|
|
10
|
+
class deprecated: # noqa: N801
|
|
11
|
+
"""Indicate that a class, function or overload is deprecated.
|
|
12
|
+
|
|
13
|
+
When this decorator is applied to an object, the type checker
|
|
14
|
+
will generate a diagnostic on usage of the deprecated object.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
|
|
18
|
+
@deprecated("Use B instead")
|
|
19
|
+
class A:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
@deprecated("Use g instead")
|
|
23
|
+
def f():
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
@overload
|
|
27
|
+
@deprecated("int support is deprecated")
|
|
28
|
+
def g(x: int) -> int: ...
|
|
29
|
+
@overload
|
|
30
|
+
def g(x: str) -> int: ...
|
|
31
|
+
|
|
32
|
+
The warning specified by *category* will be emitted at runtime
|
|
33
|
+
on use of deprecated objects. For functions, that happens on calls;
|
|
34
|
+
for classes, on instantiation and on creation of subclasses.
|
|
35
|
+
If the *category* is ``None``, no warning is emitted at runtime.
|
|
36
|
+
The *stacklevel* determines where the
|
|
37
|
+
warning is emitted. If it is ``1`` (the default), the warning
|
|
38
|
+
is emitted at the direct caller of the deprecated object; if it
|
|
39
|
+
is higher, it is emitted further up the stack.
|
|
40
|
+
Static type checker behavior is not affected by the *category*
|
|
41
|
+
and *stacklevel* arguments.
|
|
42
|
+
|
|
43
|
+
The deprecation message passed to the decorator is saved in the
|
|
44
|
+
``__deprecated__`` attribute on the decorated object.
|
|
45
|
+
If applied to an overload, the decorator
|
|
46
|
+
must be after the ``@overload`` decorator for the attribute to
|
|
47
|
+
exist on the overload as returned by ``get_overloads()``.
|
|
48
|
+
|
|
49
|
+
See PEP 702 for details.
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(
|
|
54
|
+
self,
|
|
55
|
+
message: str,
|
|
56
|
+
/,
|
|
57
|
+
*,
|
|
58
|
+
category: type[Warning] | None = DeprecationWarning, # noqa: PYI011,RUF100
|
|
59
|
+
stacklevel: int = 1,
|
|
60
|
+
) -> None:
|
|
61
|
+
if not isinstance(message, str):
|
|
62
|
+
raise TypeError( # noqa: TRY003
|
|
63
|
+
f"Expected an object of type str for 'message', not {type(message).__name__!r}" # noqa: E501
|
|
64
|
+
)
|
|
65
|
+
self.message = message
|
|
66
|
+
self.category = category
|
|
67
|
+
self.stacklevel = stacklevel
|
|
68
|
+
|
|
69
|
+
def __call__(self, arg, /): # noqa: C901,ANN001,ANN204
|
|
70
|
+
# Make sure the inner functions created below don't
|
|
71
|
+
# retain a reference to self.
|
|
72
|
+
msg = self.message
|
|
73
|
+
category = self.category
|
|
74
|
+
stacklevel = self.stacklevel
|
|
75
|
+
if category is None:
|
|
76
|
+
arg.__deprecated__ = msg
|
|
77
|
+
return arg
|
|
78
|
+
elif isinstance(arg, type): # noqa: RET505
|
|
79
|
+
import functools # noqa: PLC0415
|
|
80
|
+
from types import MethodType # noqa: PLC0415
|
|
81
|
+
|
|
82
|
+
original_new = arg.__new__
|
|
83
|
+
|
|
84
|
+
@functools.wraps(original_new)
|
|
85
|
+
def __new__(cls, /, *args, **kwargs): # noqa: N807,ANN001,ANN202,ANN003,ANN002
|
|
86
|
+
if cls is arg:
|
|
87
|
+
warn(msg, category=category, stacklevel=stacklevel + 1)
|
|
88
|
+
if original_new is not object.__new__:
|
|
89
|
+
return original_new(cls, *args, **kwargs)
|
|
90
|
+
# Mirrors a similar check in object.__new__.
|
|
91
|
+
elif cls.__init__ is object.__init__ and (args or kwargs): # noqa: RET505
|
|
92
|
+
raise TypeError(f"{cls.__name__}() takes no arguments") # noqa: TRY003
|
|
93
|
+
else:
|
|
94
|
+
return original_new(cls)
|
|
95
|
+
|
|
96
|
+
arg.__new__ = staticmethod(__new__)
|
|
97
|
+
|
|
98
|
+
original_init_subclass = arg.__init_subclass__
|
|
99
|
+
# We need slightly different behavior if __init_subclass__
|
|
100
|
+
# is a bound method (likely if it was implemented in Python)
|
|
101
|
+
if isinstance(original_init_subclass, MethodType):
|
|
102
|
+
original_init_subclass = original_init_subclass.__func__
|
|
103
|
+
|
|
104
|
+
@functools.wraps(original_init_subclass)
|
|
105
|
+
def __init_subclass__(*args, **kwargs): # noqa: ANN002,ANN202,ANN003,N807
|
|
106
|
+
warn(msg, category=category, stacklevel=stacklevel + 1)
|
|
107
|
+
return original_init_subclass(*args, **kwargs)
|
|
108
|
+
|
|
109
|
+
arg.__init_subclass__ = classmethod(__init_subclass__)
|
|
110
|
+
# Or otherwise, which likely means it's a builtin such as
|
|
111
|
+
# object's implementation of __init_subclass__.
|
|
112
|
+
else:
|
|
113
|
+
|
|
114
|
+
@functools.wraps(original_init_subclass)
|
|
115
|
+
def __init_subclass__(*args, **kwargs): # noqa: ANN202,ANN002,ANN003,N807
|
|
116
|
+
warn(msg, category=category, stacklevel=stacklevel + 1)
|
|
117
|
+
return original_init_subclass(*args, **kwargs)
|
|
118
|
+
|
|
119
|
+
arg.__init_subclass__ = __init_subclass__
|
|
120
|
+
|
|
121
|
+
arg.__deprecated__ = __new__.__deprecated__ = msg
|
|
122
|
+
__init_subclass__.__deprecated__ = msg
|
|
123
|
+
return arg
|
|
124
|
+
elif callable(arg):
|
|
125
|
+
import functools # noqa: PLC0415
|
|
126
|
+
import inspect # noqa: PLC0415
|
|
127
|
+
|
|
128
|
+
@functools.wraps(arg)
|
|
129
|
+
def wrapper(*args, **kwargs): # noqa: ANN002,ANN003,ANN202
|
|
130
|
+
warn(msg, category=category, stacklevel=stacklevel + 1)
|
|
131
|
+
return arg(*args, **kwargs)
|
|
132
|
+
|
|
133
|
+
if inspect.iscoroutinefunction(arg):
|
|
134
|
+
wrapper = inspect.markcoroutinefunction(wrapper)
|
|
135
|
+
|
|
136
|
+
arg.__deprecated__ = wrapper.__deprecated__ = msg
|
|
137
|
+
return wrapper
|
|
138
|
+
else:
|
|
139
|
+
raise TypeError( # noqa: TRY003
|
|
140
|
+
"@deprecated decorator with non-None category must be applied to "
|
|
141
|
+
f"a class or callable, not {arg!r}"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
else:
|
|
145
|
+
from warnings import deprecated
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
__all__ = ["deprecated"]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
if sys.version_info < (3, 13): # noqa: PYI066
|
|
4
|
+
class DeprecationWarning(Warning): ... # noqa: A001
|
|
5
|
+
|
|
6
|
+
class deprecated: # noqa: N801
|
|
7
|
+
def __init__(
|
|
8
|
+
self,
|
|
9
|
+
message: str,
|
|
10
|
+
/,
|
|
11
|
+
*,
|
|
12
|
+
category: type[Warning] | None = ...,
|
|
13
|
+
stacklevel: int = 1,
|
|
14
|
+
) -> None: ...
|
|
15
|
+
def __call__(self, arg, /): ... # noqa: ANN001,ANN204
|
|
16
|
+
|
|
17
|
+
else:
|
|
18
|
+
from warnings import deprecated
|
|
19
|
+
|
|
20
|
+
__all__ = ["deprecated"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from luna_quantum.solve.parameters.algorithms import * # noqa: F403
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
from luna_quantum._core import Model, Solution
|
|
2
|
+
from luna_quantum.client.interfaces.services.luna_solve_i import ILunaSolve
|
|
3
|
+
from luna_quantum.factories.luna_solve_client_factory import LunaSolveClientFactory
|
|
4
|
+
from luna_quantum.factories.usecase_factory import UseCaseFactory
|
|
5
|
+
from luna_quantum.solve.domain.model_metadata import ModelMetadata
|
|
6
|
+
from luna_quantum.solve.domain.solve_job import SolveJob
|
|
7
|
+
from luna_quantum.util.class_patcher import (
|
|
8
|
+
patch_instance,
|
|
9
|
+
patch_property,
|
|
10
|
+
patch_static,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@patch_property(Model)
|
|
15
|
+
def metadata(self: Model) -> ModelMetadata | None:
|
|
16
|
+
"""
|
|
17
|
+
Return metadata for the current Model instance.
|
|
18
|
+
|
|
19
|
+
If metadata is cached and corresponds to the current hash, returns the cached
|
|
20
|
+
metadata. Otherwise, retrieves metadata via a client and updates the cache.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
self
|
|
25
|
+
Instance of Model.
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
Optional[ModelMetadata]
|
|
30
|
+
Metadata for the current Model instance, or None if an error occurs or
|
|
31
|
+
metadata cannot be retrieved.
|
|
32
|
+
"""
|
|
33
|
+
_hash = self.__hash__()
|
|
34
|
+
if (
|
|
35
|
+
"metadata" in self._metadata # type: ignore[attr-defined]
|
|
36
|
+
and "hash" in self._metadata # type: ignore[attr-defined]
|
|
37
|
+
and self._metadata["hash"] == _hash # type: ignore[attr-defined]
|
|
38
|
+
):
|
|
39
|
+
return self._metadata["metadata"] # type: ignore # noqa: PGH003 # Patched Model
|
|
40
|
+
client = LunaSolveClientFactory.get_client(
|
|
41
|
+
None
|
|
42
|
+
) # TODO(Llewellyn): is there a way to let the user overwrite # noqa: FIX002
|
|
43
|
+
# set the client here
|
|
44
|
+
try:
|
|
45
|
+
_metadata = UseCaseFactory.model_load_metadata_by_hash(client=client).__call__(
|
|
46
|
+
model_hash=_hash
|
|
47
|
+
)
|
|
48
|
+
except Exception:
|
|
49
|
+
_metadata = None
|
|
50
|
+
self._metadata["metadata"] = _metadata # type: ignore # noqa: PGH003 # Patched Model
|
|
51
|
+
self._metadata["hash"] = _hash # type: ignore # noqa: PGH003 # Patched Model
|
|
52
|
+
|
|
53
|
+
return _metadata
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@patch_static(Model)
|
|
57
|
+
def load_luna(model_id: str, client: ILunaSolve | str | None = None) -> Model:
|
|
58
|
+
"""
|
|
59
|
+
Load an AQ model using a specific model ID.
|
|
60
|
+
|
|
61
|
+
This function retrieves an AQ model from a client obj. The client can either be
|
|
62
|
+
provided directly or created dynamically if not specified.
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
model_id : str
|
|
67
|
+
The identifier of the model that needs to be loaded.
|
|
68
|
+
client : Optional[Union[ILunaSolve, str]]
|
|
69
|
+
The client to use for loading the model. If not provided, a client
|
|
70
|
+
will be created automatically.
|
|
71
|
+
|
|
72
|
+
Returns
|
|
73
|
+
-------
|
|
74
|
+
Model
|
|
75
|
+
The AQ model that was successfully loaded.
|
|
76
|
+
"""
|
|
77
|
+
client = LunaSolveClientFactory.get_client(client=client)
|
|
78
|
+
return UseCaseFactory.model_load_by_id(client=client).__call__(model_id=model_id)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@patch_instance(Model)
|
|
82
|
+
def save_luna(self: Model, client: ILunaSolve | str | None = None) -> None:
|
|
83
|
+
"""
|
|
84
|
+
Save the model and update its metadata and hash.
|
|
85
|
+
|
|
86
|
+
This function saves the current state of the model using the provided client or
|
|
87
|
+
default client obtained from `ClientFactory`. It also updates the local `metadata`
|
|
88
|
+
attributes of the model after saving.
|
|
89
|
+
|
|
90
|
+
Parameters
|
|
91
|
+
----------
|
|
92
|
+
self : Model
|
|
93
|
+
The instance of the Model class.
|
|
94
|
+
client : Optional[Union[ILunaSolve, str]], default=None
|
|
95
|
+
The client to facilitate saving the model. Can be an instance of `ILunaSolve`,
|
|
96
|
+
a string representing the client, or left as None to use the default client.
|
|
97
|
+
|
|
98
|
+
Returns
|
|
99
|
+
-------
|
|
100
|
+
None
|
|
101
|
+
This function does not return any values.
|
|
102
|
+
|
|
103
|
+
"""
|
|
104
|
+
client = LunaSolveClientFactory.get_client(client=client)
|
|
105
|
+
self._metadata["metadata"] = UseCaseFactory.model_save(client=client).__call__(self) # type: ignore # noqa: PGH003 # Patched Model
|
|
106
|
+
self._metadata["hash"] = self.__hash__() # type: ignore[attr-defined]
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@patch_instance(Model)
|
|
110
|
+
def delete_luna(self: Model, client: ILunaSolve | str | None = None) -> None:
|
|
111
|
+
"""
|
|
112
|
+
Delete the Luna instance of the Model.
|
|
113
|
+
|
|
114
|
+
Ensure the Model instance is removed properly using the provided client or the
|
|
115
|
+
default client.
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
self : Model
|
|
120
|
+
The instance of the model to be deleted.
|
|
121
|
+
client : Optional[Union[ILunaSolve, str]], optional
|
|
122
|
+
The client used to connect to the service. If not provided, the default
|
|
123
|
+
client is used.
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
None
|
|
128
|
+
"""
|
|
129
|
+
client = LunaSolveClientFactory.get_client(client=client)
|
|
130
|
+
UseCaseFactory.model_delete(client=client).__call__(self)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@patch_instance(Model)
|
|
134
|
+
def load_solutions(
|
|
135
|
+
self: Model, client: ILunaSolve | str | None = None
|
|
136
|
+
) -> list[Solution]:
|
|
137
|
+
"""
|
|
138
|
+
Load solutions for an Model.
|
|
139
|
+
|
|
140
|
+
Fetch and return the list of all solutions for the patched Model
|
|
141
|
+
using the provided client or the default client.
|
|
142
|
+
|
|
143
|
+
Parameters
|
|
144
|
+
----------
|
|
145
|
+
self : Model
|
|
146
|
+
The Model for which solutions are to be loaded.
|
|
147
|
+
client : Optional[Union[ILunaSolve, str]], optional
|
|
148
|
+
The client used to interact and retrieve model solutions. If not provided,
|
|
149
|
+
a default client will be created using the `ClientFactory`.
|
|
150
|
+
|
|
151
|
+
Returns
|
|
152
|
+
-------
|
|
153
|
+
List[IAqSolution]
|
|
154
|
+
A list of IAqSolution instances containing the solutions.
|
|
155
|
+
|
|
156
|
+
"""
|
|
157
|
+
client = LunaSolveClientFactory.get_client(client=client)
|
|
158
|
+
return UseCaseFactory.model_get_solution(client=client).__call__(self)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@patch_instance(Model)
|
|
162
|
+
def load_solve_jobs(
|
|
163
|
+
self: Model, client: ILunaSolve | str | None = None
|
|
164
|
+
) -> list[SolveJob]:
|
|
165
|
+
"""
|
|
166
|
+
Load and return a list of SolveJob objects for the Model instance.
|
|
167
|
+
|
|
168
|
+
Parameters
|
|
169
|
+
----------
|
|
170
|
+
self : Model
|
|
171
|
+
The instance of the Model for which solve jobs need to be loaded.
|
|
172
|
+
client : Optional[Union[ILunaSolve, str]], optional
|
|
173
|
+
The client object or client type for fetching solve jobs, by default None.
|
|
174
|
+
|
|
175
|
+
Returns
|
|
176
|
+
-------
|
|
177
|
+
List[SolveJob]
|
|
178
|
+
A list of SolveJob objects related to the Model instance.
|
|
179
|
+
"""
|
|
180
|
+
client = LunaSolveClientFactory.get_client(client=client)
|
|
181
|
+
return UseCaseFactory.model_get_solve_job(client=client).__call__(self)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
__all__ = ["Model"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from luna_quantum.solve.parameters.backends import * # noqa: F403
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import version
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
from httpx import Client, Response
|
|
8
|
+
|
|
9
|
+
from luna_quantum.client.error.timeout_error import LunaTimeoutError
|
|
10
|
+
from luna_quantum.client.error.utils.http_error_utils import HttpErrorUtils
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class LunaHTTPClient(Client):
|
|
14
|
+
"""
|
|
15
|
+
Luna HTTP client.
|
|
16
|
+
|
|
17
|
+
Mainly used to set custom headers.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
_version: str = version("luna-quantum")
|
|
21
|
+
|
|
22
|
+
_user_agent: str = f"LunaSDK/{_version}"
|
|
23
|
+
|
|
24
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
25
|
+
super().__init__(*args, **kwargs)
|
|
26
|
+
|
|
27
|
+
self.headers["User-Agent"] = self._user_agent
|
|
28
|
+
|
|
29
|
+
def request(self, *args: Any, **kwargs: Any) -> Response:
|
|
30
|
+
"""Send request to Luna platform."""
|
|
31
|
+
try:
|
|
32
|
+
response: Response = super().request(*args, **kwargs)
|
|
33
|
+
except httpx.TimeoutException:
|
|
34
|
+
# Handle all possible in httpx timeout exceptions
|
|
35
|
+
raise LunaTimeoutError from None
|
|
36
|
+
HttpErrorUtils.check_for_error(response)
|
|
37
|
+
return response
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from abc import abstractmethod
|
|
5
|
+
from contextlib import suppress
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from http import HTTPStatus
|
|
8
|
+
from typing import TYPE_CHECKING, ClassVar
|
|
9
|
+
|
|
10
|
+
import httpx
|
|
11
|
+
from httpx import HTTPStatusError, Request, Response
|
|
12
|
+
|
|
13
|
+
from luna_quantum.client.controllers.luna_http_client import LunaHTTPClient
|
|
14
|
+
from luna_quantum.client.error.luna_api_key_invalid_error import LunaApiKeyInvalidError
|
|
15
|
+
from luna_quantum.client.error.luna_api_key_missing_error import LunaApiKeyMissingError
|
|
16
|
+
from luna_quantum.client.error.utils.http_error_utils import HttpErrorUtils
|
|
17
|
+
from luna_quantum.client.interfaces.services.service_i import IService
|
|
18
|
+
from luna_quantum.client.rest_client.users_rest_client import UsersRestClient
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from collections.abc import Generator
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class LunaPrefixEnum(str, Enum):
|
|
25
|
+
"""Enumeration of Luna services."""
|
|
26
|
+
|
|
27
|
+
LUNA_SOLVE = "luna-solve"
|
|
28
|
+
LUNA_Q = "luna-q"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def check_httpx_exceptions(response: Response) -> None:
|
|
32
|
+
"""
|
|
33
|
+
Check if response contains errors from the server.
|
|
34
|
+
|
|
35
|
+
This function examines the HTTP response and raises appropriate SDK exceptions
|
|
36
|
+
if error conditions are detected.
|
|
37
|
+
|
|
38
|
+
Parameters
|
|
39
|
+
----------
|
|
40
|
+
response: Response
|
|
41
|
+
The HTTP response object to be examined for error conditions.
|
|
42
|
+
"""
|
|
43
|
+
HttpErrorUtils.check_for_error(response)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class APIKeyAuth(httpx.Auth): # noqa: PLW1641
|
|
47
|
+
"""API key authentication method for luna platform."""
|
|
48
|
+
|
|
49
|
+
def __init__(self, token: str) -> None:
|
|
50
|
+
self.token = token
|
|
51
|
+
|
|
52
|
+
self.dev_header_value = os.getenv("LUNA_DEV_EXTRA_HEADER_VALUE", None)
|
|
53
|
+
self.dev_header_name = os.getenv("LUNA_DEV_EXTRA_HEADER_NAME", None)
|
|
54
|
+
|
|
55
|
+
def auth_flow(self, request: Request) -> Generator[Request, Response]:
|
|
56
|
+
"""
|
|
57
|
+
Authenticate a request to Luna platform.
|
|
58
|
+
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
request: Request
|
|
62
|
+
Request that needs to be authenticated.
|
|
63
|
+
"""
|
|
64
|
+
request.headers["Luna-API-Key"] = self.token
|
|
65
|
+
|
|
66
|
+
if self.dev_header_name and self.dev_header_value:
|
|
67
|
+
request.headers[self.dev_header_name] = self.dev_header_value
|
|
68
|
+
yield request
|
|
69
|
+
|
|
70
|
+
def __eq__(self, other: object) -> bool:
|
|
71
|
+
"""
|
|
72
|
+
Check if the object is equal to the current instance.
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
other: object
|
|
77
|
+
Object to compare with the current instance.
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
bool:
|
|
82
|
+
True if the object is equal to the current instance, False otherwise.
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
if self is other:
|
|
86
|
+
return True
|
|
87
|
+
if not isinstance(other, APIKeyAuth):
|
|
88
|
+
return False
|
|
89
|
+
return (
|
|
90
|
+
self.token == other.token
|
|
91
|
+
and self.dev_header_name == other.dev_header_name
|
|
92
|
+
and self.dev_header_value == other.dev_header_value
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class LunaPlatformClient(IService):
|
|
97
|
+
"""Luna platform REST client."""
|
|
98
|
+
|
|
99
|
+
_base_url: str
|
|
100
|
+
|
|
101
|
+
_httpx_client: httpx.Client
|
|
102
|
+
_api_key: ClassVar[str | None] = None
|
|
103
|
+
_timeout: float | None = None
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def client(self) -> httpx.Client:
|
|
107
|
+
"""
|
|
108
|
+
Return httpx client.
|
|
109
|
+
|
|
110
|
+
Returns
|
|
111
|
+
-------
|
|
112
|
+
httpx.Client
|
|
113
|
+
"""
|
|
114
|
+
return self._httpx_client
|
|
115
|
+
|
|
116
|
+
@classmethod
|
|
117
|
+
@abstractmethod
|
|
118
|
+
def get_api(cls) -> LunaPrefixEnum:
|
|
119
|
+
"""Return the api of the client."""
|
|
120
|
+
|
|
121
|
+
def __init__(
|
|
122
|
+
self,
|
|
123
|
+
api_key: str | None = None,
|
|
124
|
+
base_url: str | None = None,
|
|
125
|
+
timeout: float | None = 240.0,
|
|
126
|
+
) -> None:
|
|
127
|
+
"""
|
|
128
|
+
LunaPlatformClient is a main entrypoint of the SDK.
|
|
129
|
+
|
|
130
|
+
All the operations with entities should be processed using an instance of
|
|
131
|
+
LunaPlatformClient.
|
|
132
|
+
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
135
|
+
api: LunaPrefixEnum
|
|
136
|
+
Current API with which luna client is working. Can be luna-solve or luna-q.
|
|
137
|
+
api_key: Optional[str]
|
|
138
|
+
Api key to be used to authorize. Default none.
|
|
139
|
+
If its none then the key set by the `authorize` method will be used.
|
|
140
|
+
base_url:
|
|
141
|
+
Base API URL.
|
|
142
|
+
If you want to use API not on your local PC then change it.
|
|
143
|
+
You can do that by setting the environment variable LUNA_BASE_URL.
|
|
144
|
+
Default value https://api.aqarios.com.
|
|
145
|
+
timeout:
|
|
146
|
+
Default timeout in seconds for the requests via the LunaQ client. `None`
|
|
147
|
+
means that the SDK uses no timeouts. Note that either way the Luna platform
|
|
148
|
+
itself will time out after 240 seconds.
|
|
149
|
+
Default: 240.0
|
|
150
|
+
"""
|
|
151
|
+
self._base_url = self._get_base_url(base_url)
|
|
152
|
+
self._timeout = timeout
|
|
153
|
+
|
|
154
|
+
api_key = self._get_api_key(api_key)
|
|
155
|
+
|
|
156
|
+
self.dev_header_value = os.getenv("LUNA_DEV_EXTRA_HEADER_VALUE", None)
|
|
157
|
+
self.dev_header_name = os.getenv("LUNA_DEV_EXTRA_HEADER_NAME", None)
|
|
158
|
+
|
|
159
|
+
self._httpx_client = LunaHTTPClient(
|
|
160
|
+
auth=APIKeyAuth(api_key),
|
|
161
|
+
base_url=self._base_url,
|
|
162
|
+
follow_redirects=True,
|
|
163
|
+
timeout=self._timeout,
|
|
164
|
+
event_hooks={"response": [check_httpx_exceptions]},
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
self._authenticate()
|
|
168
|
+
|
|
169
|
+
def _get_api_key(self, api_key: str | None = None) -> str:
|
|
170
|
+
"""
|
|
171
|
+
Retrieve the API key for authentication.
|
|
172
|
+
|
|
173
|
+
Get the API key from provided arguments, class-specific key, or environment
|
|
174
|
+
variables. Raises an error if no API key is available.
|
|
175
|
+
|
|
176
|
+
Parameters
|
|
177
|
+
----------
|
|
178
|
+
api_key : str or None, optional
|
|
179
|
+
An API key string if provided.
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
str
|
|
184
|
+
The API key to be used for authentication.
|
|
185
|
+
|
|
186
|
+
Raises
|
|
187
|
+
------
|
|
188
|
+
LunaApiKeyMissingError
|
|
189
|
+
If no API key is available from any source.
|
|
190
|
+
"""
|
|
191
|
+
if api_key:
|
|
192
|
+
auth_key = api_key
|
|
193
|
+
elif self.__class__._api_key: # noqa: SLF001 Use here self.__class__ so that LunaSolve and LunaQ can have different api keys set
|
|
194
|
+
auth_key = self.__class__._api_key # noqa: SLF001 Use here self.__class__ so that LunaSolve and LunaQ can have different api keys set
|
|
195
|
+
elif key := os.getenv("LUNA_API_KEY", None):
|
|
196
|
+
auth_key = key
|
|
197
|
+
else:
|
|
198
|
+
raise LunaApiKeyMissingError
|
|
199
|
+
return auth_key
|
|
200
|
+
|
|
201
|
+
def _get_base_url(self, base_url: str | None = None) -> str:
|
|
202
|
+
"""
|
|
203
|
+
Get the base url.
|
|
204
|
+
|
|
205
|
+
Parameters
|
|
206
|
+
----------
|
|
207
|
+
base_url: str
|
|
208
|
+
Base API URL.
|
|
209
|
+
If you want to use API not on your local PC then change it.
|
|
210
|
+
You can do that by setting the environment variable LUNA_BASE_URL.
|
|
211
|
+
Default value https://api.aqarios.com.
|
|
212
|
+
|
|
213
|
+
Returns
|
|
214
|
+
-------
|
|
215
|
+
str
|
|
216
|
+
Base url.
|
|
217
|
+
|
|
218
|
+
"""
|
|
219
|
+
if base_url is None:
|
|
220
|
+
base_url = os.getenv("LUNA_BASE_URL", "https://api.aqarios.com")
|
|
221
|
+
if os.getenv("LUNA_DISABLE_SUFFIX", "false").lower() == "true":
|
|
222
|
+
return f"{base_url}/api/v1"
|
|
223
|
+
return f"{base_url}/{self.get_api().value}/api/v1"
|
|
224
|
+
|
|
225
|
+
def __del__(self) -> None: # noqa: D105
|
|
226
|
+
if hasattr(self, "_httpx_client"):
|
|
227
|
+
with suppress(Exception):
|
|
228
|
+
self._httpx_client.close()
|
|
229
|
+
|
|
230
|
+
def _authenticate(self) -> None:
|
|
231
|
+
try:
|
|
232
|
+
UsersRestClient(service=self).get_me()
|
|
233
|
+
except HTTPStatusError as exception:
|
|
234
|
+
if exception.response.status_code == HTTPStatus.UNAUTHORIZED:
|
|
235
|
+
raise LunaApiKeyInvalidError from exception
|
|
236
|
+
raise
|
|
237
|
+
|
|
238
|
+
def is_same(
|
|
239
|
+
self,
|
|
240
|
+
api_key: str | None = None,
|
|
241
|
+
) -> bool:
|
|
242
|
+
"""
|
|
243
|
+
Whether the service is created with the current environment variables.
|
|
244
|
+
|
|
245
|
+
Returns
|
|
246
|
+
-------
|
|
247
|
+
bool:
|
|
248
|
+
True if the service is created with the current environment variables.
|
|
249
|
+
False otherwise.
|
|
250
|
+
"""
|
|
251
|
+
api_key = self._get_api_key(api_key)
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
self._get_base_url() == self._base_url
|
|
255
|
+
and APIKeyAuth(api_key) == self._httpx_client.auth
|
|
256
|
+
)
|