classiq 0.37.1__py3-none-any.whl → 0.65.3__py3-none-any.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.
- classiq/__init__.py +49 -34
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +3 -2
- classiq/_analyzer_extras/interactive_hardware.py +3 -3
- classiq/_internals/api_wrapper.py +241 -95
- classiq/_internals/async_utils.py +2 -77
- classiq/_internals/authentication/auth0.py +26 -10
- classiq/_internals/authentication/authentication.py +11 -0
- classiq/_internals/authentication/device.py +18 -8
- classiq/_internals/authentication/password_manager.py +40 -13
- classiq/_internals/authentication/token_manager.py +11 -6
- classiq/_internals/client.py +106 -37
- classiq/_internals/config.py +3 -4
- classiq/_internals/host_checker.py +38 -15
- classiq/_internals/jobs.py +56 -50
- classiq/_internals/type_validation.py +9 -9
- classiq/analyzer/__init__.py +1 -3
- classiq/analyzer/analyzer.py +50 -47
- classiq/analyzer/analyzer_utilities.py +15 -15
- classiq/analyzer/rb.py +19 -20
- classiq/analyzer/show_interactive_hack.py +30 -7
- classiq/analyzer/url_utils.py +2 -3
- classiq/applications/__init__.py +3 -12
- classiq/applications/chemistry/__init__.py +14 -10
- classiq/applications/chemistry/ansatz_parameters.py +4 -4
- classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +170 -170
- classiq/applications/chemistry/ground_state_problem.py +1 -1
- classiq/applications/combinatorial_helpers/allowed_constraints.py +23 -0
- classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
- classiq/applications/combinatorial_helpers/arithmetic/isolation.py +42 -0
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +166 -0
- classiq/applications/combinatorial_helpers/encoding_mapping.py +107 -0
- classiq/applications/combinatorial_helpers/encoding_utils.py +124 -0
- classiq/applications/combinatorial_helpers/memory.py +75 -0
- classiq/applications/combinatorial_helpers/optimization_model.py +193 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
- classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
- classiq/applications/combinatorial_helpers/sympy_utils.py +22 -0
- classiq/applications/combinatorial_helpers/transformations/encoding.py +189 -0
- classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +143 -0
- classiq/applications/combinatorial_helpers/transformations/ising_converter.py +120 -0
- classiq/applications/combinatorial_helpers/transformations/penalty.py +31 -0
- classiq/applications/combinatorial_helpers/transformations/penalty_support.py +37 -0
- classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +74 -0
- classiq/applications/combinatorial_helpers/transformations/slack_variables.py +87 -0
- classiq/applications/combinatorial_optimization/__init__.py +24 -5
- classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +137 -0
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +229 -0
- classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
- classiq/applications/finance/__init__.py +4 -5
- classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +50 -57
- classiq/applications/grover/__init__.py +9 -0
- classiq/applications/grover/grover_model_constructor.py +157 -0
- classiq/applications/hamiltonian/__init__.py +0 -0
- classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
- classiq/applications/libraries/__init__.py +0 -0
- classiq/applications/libraries/qmci_library.py +22 -0
- classiq/applications/qnn/__init__.py +2 -4
- classiq/applications/qnn/circuit_utils.py +8 -8
- classiq/applications/qnn/datasets/__init__.py +9 -11
- classiq/applications/qnn/datasets/dataset_base_classes.py +7 -5
- classiq/applications/qnn/datasets/dataset_not.py +2 -1
- classiq/applications/qnn/datasets/dataset_parity.py +2 -2
- classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
- classiq/applications/qnn/qlayer.py +30 -10
- classiq/applications/qnn/torch_utils.py +4 -3
- classiq/applications/qnn/types.py +7 -7
- classiq/applications/qsvm/__init__.py +6 -4
- classiq/applications/qsvm/qsvm.py +4 -10
- classiq/applications/qsvm/qsvm_data_generation.py +5 -8
- classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +30 -28
- classiq/execution/__init__.py +8 -3
- classiq/execution/all_hardware_devices.py +11 -0
- classiq/execution/execution_session.py +400 -0
- classiq/execution/iqcc.py +63 -0
- classiq/execution/jobs.py +197 -25
- classiq/execution/qnn.py +79 -0
- classiq/executor.py +23 -117
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +49 -16
- classiq/interface/analyzer/cytoscape_graph.py +15 -9
- classiq/interface/analyzer/result.py +36 -32
- classiq/interface/applications/qsvm.py +28 -25
- classiq/interface/ast_node.py +16 -0
- classiq/interface/backend/backend_preferences.py +390 -119
- classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
- classiq/interface/backend/pydantic_backend.py +27 -22
- classiq/interface/backend/quantum_backend_providers.py +70 -16
- classiq/interface/chemistry/fermionic_operator.py +43 -32
- classiq/interface/chemistry/ground_state_problem.py +42 -24
- classiq/interface/chemistry/molecule.py +20 -14
- classiq/interface/chemistry/operator.py +75 -236
- classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
- classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +2 -4
- classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
- classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
- classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
- classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
- classiq/interface/combinatorial_optimization/examples/mds.py +2 -1
- classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
- classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
- classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
- classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
- classiq/interface/combinatorial_optimization/examples/set_cover.py +3 -3
- classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
- classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +14 -9
- classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
- classiq/interface/combinatorial_optimization/result.py +1 -3
- classiq/interface/combinatorial_optimization/solver_types.py +1 -1
- classiq/interface/debug_info/__init__.py +0 -0
- classiq/interface/debug_info/debug_info.py +86 -0
- classiq/interface/exceptions.py +201 -0
- classiq/interface/execution/iqcc.py +19 -0
- classiq/interface/execution/jobs.py +15 -12
- classiq/interface/execution/primitives.py +18 -0
- classiq/interface/executor/constants.py +1 -0
- classiq/interface/executor/estimation.py +2 -2
- classiq/interface/executor/execution_preferences.py +26 -143
- classiq/interface/executor/execution_request.py +36 -56
- classiq/interface/executor/execution_result.py +30 -8
- classiq/interface/executor/iqae_result.py +4 -6
- classiq/interface/executor/optimizer_preferences.py +34 -22
- classiq/interface/executor/{quantum_program.py → quantum_code.py} +44 -34
- classiq/interface/executor/quantum_instruction_set.py +3 -2
- classiq/interface/executor/register_initialization.py +12 -17
- classiq/interface/executor/result.py +122 -64
- classiq/interface/executor/vqe_result.py +11 -11
- classiq/interface/finance/function_input.py +42 -19
- classiq/interface/finance/gaussian_model_input.py +7 -5
- classiq/interface/finance/log_normal_model_input.py +6 -4
- classiq/interface/finance/model_input.py +6 -4
- classiq/interface/generator/adjacency.py +1 -3
- classiq/interface/generator/amplitude_loading.py +27 -14
- classiq/interface/generator/ansatz_library.py +5 -5
- classiq/interface/generator/application_apis/__init__.py +1 -0
- classiq/interface/generator/application_apis/arithmetic_declarations.py +17 -0
- classiq/interface/generator/application_apis/chemistry_declarations.py +27 -187
- classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +18 -21
- classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
- classiq/interface/generator/application_apis/finance_declarations.py +48 -69
- classiq/interface/generator/application_apis/qsvm_declarations.py +0 -70
- classiq/interface/generator/arith/argument_utils.py +57 -6
- classiq/interface/generator/arith/arithmetic.py +37 -16
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +15 -17
- classiq/interface/generator/arith/arithmetic_expression_abc.py +70 -26
- classiq/interface/generator/arith/arithmetic_expression_parser.py +18 -12
- classiq/interface/generator/arith/arithmetic_expression_validator.py +61 -43
- classiq/interface/generator/arith/arithmetic_operations.py +19 -16
- classiq/interface/generator/arith/arithmetic_param_getters.py +7 -8
- classiq/interface/generator/arith/arithmetic_result_builder.py +21 -17
- classiq/interface/generator/arith/ast_node_rewrite.py +4 -3
- classiq/interface/generator/arith/binary_ops.py +375 -139
- classiq/interface/generator/arith/endianness.py +1 -1
- classiq/interface/generator/arith/extremum_operations.py +96 -23
- classiq/interface/generator/arith/logical_ops.py +16 -12
- classiq/interface/generator/arith/machine_precision.py +3 -0
- classiq/interface/generator/arith/number_utils.py +44 -48
- classiq/interface/generator/arith/register_user_input.py +70 -27
- classiq/interface/generator/arith/unary_ops.py +57 -46
- classiq/interface/generator/arith/uncomputation_methods.py +1 -1
- classiq/interface/generator/builtin_api_builder.py +2 -9
- classiq/interface/generator/chemistry_function_params.py +5 -5
- classiq/interface/generator/circuit_code/circuit_code.py +7 -7
- classiq/interface/generator/circuit_code/types_and_constants.py +4 -7
- classiq/interface/generator/commuting_pauli_exponentiation.py +8 -6
- classiq/interface/generator/compiler_keywords.py +8 -0
- classiq/interface/generator/complex_type.py +13 -25
- classiq/interface/generator/constant.py +3 -4
- classiq/interface/generator/control_state.py +35 -28
- classiq/interface/generator/copy.py +47 -0
- classiq/interface/generator/custom_ansatz.py +2 -5
- classiq/interface/generator/distance.py +3 -5
- classiq/interface/generator/excitations.py +3 -2
- classiq/interface/generator/expressions/atomic_expression_functions.py +26 -8
- classiq/interface/generator/expressions/enums/__init__.py +0 -10
- classiq/interface/generator/expressions/enums/finance_functions.py +12 -22
- classiq/interface/generator/expressions/evaluated_expression.py +21 -7
- classiq/interface/generator/expressions/expression.py +27 -15
- classiq/interface/generator/expressions/expression_constants.py +9 -3
- classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +99 -0
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +59 -0
- classiq/interface/generator/expressions/qmod_qstruct_proxy.py +36 -0
- classiq/interface/generator/expressions/qmod_sized_proxy.py +30 -2
- classiq/interface/generator/expressions/qmod_struct_instance.py +14 -2
- classiq/interface/generator/expressions/sympy_supported_expressions.py +20 -11
- classiq/interface/generator/finance.py +3 -3
- classiq/interface/generator/function_param_library.py +6 -6
- classiq/interface/generator/function_param_list_without_self_reference.py +2 -10
- classiq/interface/generator/function_params.py +42 -69
- classiq/interface/generator/functions/__init__.py +0 -22
- classiq/interface/generator/functions/builtins/__init__.py +0 -0
- classiq/interface/generator/functions/builtins/internal_operators.py +16 -0
- classiq/interface/generator/functions/classical_function_declaration.py +18 -9
- classiq/interface/generator/functions/classical_type.py +47 -166
- classiq/interface/generator/functions/concrete_types.py +55 -0
- classiq/interface/generator/functions/function_declaration.py +13 -14
- classiq/interface/generator/functions/port_declaration.py +1 -13
- classiq/interface/generator/functions/qmod_python_interface.py +2 -1
- classiq/interface/generator/functions/type_name.py +90 -0
- classiq/interface/generator/generated_circuit_data.py +155 -22
- classiq/interface/generator/grover_diffuser.py +32 -25
- classiq/interface/generator/grover_operator.py +34 -23
- classiq/interface/generator/hamiltonian_evolution/exponentiation.py +4 -6
- classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
- classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +12 -8
- classiq/interface/generator/hardware/hardware_data.py +76 -36
- classiq/interface/generator/hardware_efficient_ansatz.py +38 -17
- classiq/interface/generator/hartree_fock.py +14 -4
- classiq/interface/generator/identity.py +10 -6
- classiq/interface/generator/linear_pauli_rotations.py +33 -19
- classiq/interface/generator/mcmt_method.py +1 -1
- classiq/interface/generator/mcu.py +20 -16
- classiq/interface/generator/mcx.py +29 -20
- classiq/interface/generator/model/__init__.py +2 -5
- classiq/interface/generator/model/constraints.py +27 -8
- classiq/interface/generator/model/model.py +32 -203
- classiq/interface/generator/model/preferences/preferences.py +118 -43
- classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +27 -22
- classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
- classiq/interface/generator/oracles/custom_oracle.py +17 -13
- classiq/interface/generator/oracles/oracle_abc.py +9 -9
- classiq/interface/generator/partitioned_register.py +7 -7
- classiq/interface/generator/piecewise_linear_amplitude_loading.py +45 -29
- classiq/interface/generator/preferences/optimization.py +1 -2
- classiq/interface/generator/qpe.py +47 -34
- classiq/interface/generator/qsvm.py +13 -17
- classiq/interface/generator/quantum_function_call.py +107 -87
- classiq/interface/generator/{generated_circuit.py → quantum_program.py} +50 -37
- classiq/interface/generator/range_types.py +13 -12
- classiq/interface/generator/register_role.py +18 -6
- classiq/interface/generator/slice_parsing_utils.py +11 -6
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +32 -39
- classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
- classiq/interface/generator/standard_gates/standard_gates.py +3 -3
- classiq/interface/generator/standard_gates/u_gate.py +7 -10
- classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
- classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
- classiq/interface/generator/state_preparation/distributions.py +16 -15
- classiq/interface/generator/state_preparation/metrics.py +5 -7
- classiq/interface/generator/state_preparation/state_preparation.py +30 -23
- classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +20 -6
- classiq/interface/generator/transpiler_basis_gates.py +7 -3
- classiq/interface/generator/types/builtin_enum_declarations.py +178 -0
- classiq/interface/generator/types/compilation_metadata.py +6 -0
- classiq/interface/generator/types/enum_declaration.py +54 -0
- classiq/interface/generator/types/qstruct_declaration.py +18 -0
- classiq/interface/generator/types/struct_declaration.py +15 -14
- classiq/interface/generator/ucc.py +9 -6
- classiq/interface/generator/unitary_gate.py +10 -6
- classiq/interface/generator/user_defined_function_params.py +4 -1
- classiq/interface/generator/validations/flow_graph.py +11 -9
- classiq/interface/generator/validations/validator_functions.py +8 -6
- classiq/interface/generator/visitor.py +23 -16
- classiq/interface/hardware.py +31 -10
- classiq/interface/helpers/classproperty.py +8 -0
- classiq/interface/helpers/custom_encoders.py +3 -0
- classiq/interface/helpers/custom_pydantic_types.py +40 -50
- classiq/interface/helpers/datastructures.py +26 -0
- classiq/interface/helpers/hashable_mixin.py +3 -2
- classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
- classiq/interface/helpers/pydantic_model_helpers.py +7 -11
- classiq/interface/helpers/validation_helpers.py +4 -21
- classiq/interface/helpers/versioned_model.py +1 -1
- classiq/interface/ide/ide_data.py +16 -20
- classiq/interface/ide/visual_model.py +130 -0
- classiq/interface/interface_version.py +1 -0
- classiq/interface/jobs.py +35 -6
- classiq/interface/model/allocate.py +16 -0
- classiq/interface/model/bind_operation.py +44 -14
- classiq/interface/model/classical_if.py +15 -0
- classiq/interface/model/classical_parameter_declaration.py +33 -3
- classiq/interface/model/control.py +45 -0
- classiq/interface/model/handle_binding.py +298 -20
- classiq/interface/model/inplace_binary_operation.py +31 -26
- classiq/interface/model/invert.py +12 -0
- classiq/interface/model/model.py +87 -73
- classiq/interface/model/native_function_definition.py +16 -21
- classiq/interface/model/parameter.py +13 -0
- classiq/interface/model/phase_operation.py +11 -0
- classiq/interface/model/port_declaration.py +27 -9
- classiq/interface/model/power.py +14 -0
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +38 -21
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +51 -14
- classiq/interface/model/quantum_expressions/quantum_expression.py +12 -35
- classiq/interface/model/quantum_function_call.py +146 -462
- classiq/interface/model/quantum_function_declaration.py +193 -152
- classiq/interface/model/quantum_lambda_function.py +65 -0
- classiq/interface/model/quantum_statement.py +71 -12
- classiq/interface/model/quantum_type.py +205 -67
- classiq/interface/model/quantum_variable_declaration.py +4 -26
- classiq/interface/model/repeat.py +15 -0
- classiq/interface/model/statement_block.py +58 -0
- classiq/interface/model/validation_handle.py +13 -6
- classiq/interface/model/variable_declaration_statement.py +3 -1
- classiq/interface/model/within_apply_operation.py +13 -0
- classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
- classiq/interface/server/global_versions.py +6 -7
- classiq/interface/server/routes.py +22 -21
- classiq/interface/source_reference.py +59 -0
- classiq/model_expansions/__init__.py +0 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +253 -0
- classiq/model_expansions/capturing/__init__.py +0 -0
- classiq/model_expansions/capturing/captured_vars.py +435 -0
- classiq/model_expansions/capturing/mangling_utils.py +56 -0
- classiq/model_expansions/closure.py +171 -0
- classiq/model_expansions/debug_flag.py +3 -0
- classiq/model_expansions/evaluators/__init__.py +0 -0
- classiq/model_expansions/evaluators/arg_type_match.py +158 -0
- classiq/model_expansions/evaluators/argument_types.py +42 -0
- classiq/model_expansions/evaluators/classical_expression.py +36 -0
- classiq/model_expansions/evaluators/control.py +144 -0
- classiq/model_expansions/evaluators/parameter_types.py +226 -0
- classiq/model_expansions/evaluators/quantum_type_utils.py +239 -0
- classiq/model_expansions/evaluators/type_type_match.py +90 -0
- classiq/model_expansions/expression_evaluator.py +135 -0
- classiq/model_expansions/expression_renamer.py +76 -0
- classiq/model_expansions/function_builder.py +247 -0
- classiq/model_expansions/generative_functions.py +158 -0
- classiq/model_expansions/interpreters/__init__.py +0 -0
- classiq/model_expansions/interpreters/base_interpreter.py +263 -0
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
- classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
- classiq/model_expansions/model_tables.py +18 -0
- classiq/model_expansions/quantum_operations/__init__.py +9 -0
- classiq/model_expansions/quantum_operations/bind.py +60 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +266 -0
- classiq/model_expansions/quantum_operations/classicalif.py +53 -0
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
- classiq/model_expansions/quantum_operations/emitter.py +181 -0
- classiq/model_expansions/quantum_operations/quantum_function_call.py +33 -0
- classiq/model_expansions/quantum_operations/repeat.py +56 -0
- classiq/model_expansions/quantum_operations/shallow_emitter.py +180 -0
- classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
- classiq/model_expansions/scope.py +240 -0
- classiq/model_expansions/scope_initialization.py +150 -0
- classiq/model_expansions/sympy_conversion/__init__.py +0 -0
- classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +179 -0
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +123 -0
- classiq/model_expansions/transformers/__init__.py +0 -0
- classiq/model_expansions/transformers/ast_renamer.py +26 -0
- classiq/model_expansions/transformers/var_splitter.py +299 -0
- classiq/model_expansions/utils/__init__.py +0 -0
- classiq/model_expansions/utils/counted_name_allocator.py +11 -0
- classiq/model_expansions/utils/handles_collector.py +33 -0
- classiq/model_expansions/visitors/__init__.py +0 -0
- classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
- classiq/model_expansions/visitors/variable_references.py +144 -0
- classiq/open_library/__init__.py +4 -0
- classiq/open_library/functions/__init__.py +130 -0
- classiq/open_library/functions/amplitude_estimation.py +30 -0
- classiq/open_library/functions/discrete_sine_cosine_transform.py +181 -0
- classiq/open_library/functions/grover.py +157 -0
- classiq/open_library/functions/hea.py +115 -0
- classiq/open_library/functions/linear_pauli_rotation.py +82 -0
- classiq/open_library/functions/modular_exponentiation.py +201 -0
- classiq/open_library/functions/qaoa_penalty.py +117 -0
- classiq/open_library/functions/qft_functions.py +54 -0
- classiq/open_library/functions/qpe.py +46 -0
- classiq/open_library/functions/qsvt.py +331 -0
- classiq/open_library/functions/state_preparation.py +301 -0
- classiq/open_library/functions/swap_test.py +27 -0
- classiq/open_library/functions/utility_functions.py +81 -0
- classiq/open_library/functions/variational.py +52 -0
- classiq/qmod/__init__.py +17 -10
- classiq/qmod/builtins/__init__.py +19 -2
- classiq/qmod/builtins/classical_execution_primitives.py +60 -47
- classiq/qmod/builtins/classical_functions.py +44 -38
- classiq/qmod/builtins/constants.py +10 -0
- classiq/qmod/builtins/enums.py +208 -0
- classiq/qmod/builtins/functions/__init__.py +137 -0
- classiq/qmod/builtins/functions/allocation.py +150 -0
- classiq/qmod/builtins/functions/arithmetic.py +55 -0
- classiq/qmod/builtins/functions/benchmarking.py +8 -0
- classiq/qmod/builtins/functions/chemistry.py +91 -0
- classiq/qmod/builtins/functions/exponentiation.py +105 -0
- classiq/qmod/builtins/functions/finance.py +34 -0
- classiq/qmod/builtins/functions/operators.py +16 -0
- classiq/qmod/builtins/functions/qsvm.py +24 -0
- classiq/qmod/builtins/functions/standard_gates.py +651 -0
- classiq/qmod/builtins/operations.py +379 -57
- classiq/qmod/builtins/structs.py +103 -80
- classiq/qmod/cfunc.py +42 -0
- classiq/qmod/classical_function.py +8 -20
- classiq/qmod/cparam.py +64 -0
- classiq/qmod/create_model_function.py +56 -0
- classiq/qmod/declaration_inferrer.py +145 -112
- classiq/qmod/expression_query.py +39 -0
- classiq/qmod/generative.py +42 -0
- classiq/qmod/model_state_container.py +19 -5
- classiq/qmod/native/__init__.py +7 -0
- classiq/qmod/native/expression_to_qmod.py +194 -0
- classiq/qmod/native/pretty_printer.py +401 -0
- classiq/qmod/pretty_print/__init__.py +7 -0
- classiq/qmod/pretty_print/expression_to_python.py +222 -0
- classiq/qmod/pretty_print/pretty_printer.py +572 -0
- classiq/qmod/python_classical_type.py +67 -0
- classiq/qmod/qfunc.py +79 -0
- classiq/qmod/qmod_constant.py +143 -0
- classiq/qmod/qmod_parameter.py +84 -53
- classiq/qmod/qmod_variable.py +497 -100
- classiq/qmod/quantum_callable.py +17 -7
- classiq/qmod/quantum_expandable.py +278 -105
- classiq/qmod/quantum_function.py +232 -48
- classiq/qmod/semantics/__init__.py +0 -0
- classiq/qmod/semantics/annotation/__init__.py +0 -0
- classiq/qmod/semantics/annotation/call_annotation.py +92 -0
- classiq/qmod/semantics/annotation/qstruct_annotator.py +23 -0
- classiq/qmod/semantics/error_manager.py +88 -0
- classiq/qmod/semantics/lambdas.py +25 -0
- classiq/qmod/semantics/static_semantics_visitor.py +384 -0
- classiq/qmod/semantics/validation/__init__.py +0 -0
- classiq/qmod/semantics/validation/constants_validation.py +16 -0
- classiq/qmod/semantics/validation/func_call_validation.py +99 -0
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
- classiq/qmod/semantics/validation/handle_validation.py +85 -0
- classiq/qmod/semantics/validation/main_validation.py +33 -0
- classiq/qmod/semantics/validation/types_validation.py +128 -0
- classiq/qmod/symbolic.py +178 -111
- classiq/qmod/symbolic_expr.py +36 -12
- classiq/qmod/symbolic_type.py +2 -5
- classiq/qmod/type_attribute_remover.py +32 -0
- classiq/qmod/utilities.py +108 -1
- classiq/qmod/write_qmod.py +53 -0
- classiq/synthesis.py +210 -22
- {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/METADATA +16 -8
- classiq-0.65.3.dist-info/RECORD +521 -0
- {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/WHEEL +1 -1
- classiq/_internals/_qfunc_ext.py +0 -6
- classiq/applications/benchmarking/__init__.py +0 -9
- classiq/applications/benchmarking/mirror_benchmarking.py +0 -67
- classiq/applications/numpy_utils.py +0 -37
- classiq/applications_model_constructors/__init__.py +0 -17
- classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +0 -178
- classiq/applications_model_constructors/grover_model_constructor.py +0 -227
- classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
- classiq/applications_model_constructors/libraries/qmci_library.py +0 -109
- classiq/builtin_functions/__init__.py +0 -43
- classiq/builtin_functions/amplitude_loading.py +0 -3
- classiq/builtin_functions/binary_ops.py +0 -1
- classiq/builtin_functions/exponentiation.py +0 -5
- classiq/builtin_functions/qpe.py +0 -4
- classiq/builtin_functions/qsvm.py +0 -7
- classiq/builtin_functions/range_types.py +0 -5
- classiq/builtin_functions/standard_gates.py +0 -1
- classiq/builtin_functions/state_preparation.py +0 -6
- classiq/builtin_functions/suzuki_trotter.py +0 -3
- classiq/exceptions.py +0 -131
- classiq/interface/executor/aws_execution_cost.py +0 -72
- classiq/interface/executor/error_mitigation.py +0 -6
- classiq/interface/generator/credit_risk_example/linear_gci.py +0 -115
- classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -59
- classiq/interface/generator/expressions/enums/chemistry.py +0 -28
- classiq/interface/generator/expressions/enums/classical_enum.py +0 -5
- classiq/interface/generator/expressions/enums/ladder_operator.py +0 -16
- classiq/interface/generator/expressions/enums/optimizers.py +0 -9
- classiq/interface/generator/expressions/enums/pauli.py +0 -8
- classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
- classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +0 -641
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/exponentiation_functions.py +0 -89
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +0 -862
- classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -169
- classiq/interface/generator/functions/foreign_function_definition.py +0 -106
- classiq/interface/generator/functions/function_implementation.py +0 -103
- classiq/interface/generator/functions/native_function_definition.py +0 -153
- classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
- classiq/interface/generator/functions/register.py +0 -42
- classiq/interface/generator/functions/register_mapping_data.py +0 -102
- classiq/interface/generator/inequality_mixer.py +0 -51
- classiq/interface/generator/model/classical_main_validator.py +0 -106
- classiq/interface/generator/range_mixer.py +0 -56
- classiq/interface/generator/state_propagator.py +0 -63
- classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -2
- classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
- classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
- classiq/interface/generator/types/combinatorial_problem.py +0 -26
- classiq/interface/ide/show.py +0 -34
- classiq/interface/model/common_model_types.py +0 -23
- classiq/interface/model/numeric_reinterpretation.py +0 -25
- classiq/interface/model/operator_synthesis_data.py +0 -48
- classiq/interface/model/quantum_expressions/control_state.py +0 -38
- classiq/interface/model/quantum_if_operation.py +0 -95
- classiq/interface/model/resolvers/function_call_resolver.py +0 -43
- classiq/interface/model/validations/handle_validation_base.py +0 -55
- classiq/interface/model/validations/handles_validator.py +0 -154
- classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
- classiq/model/__init__.py +0 -14
- classiq/model/composite_function_generator.py +0 -33
- classiq/model/function_handler.py +0 -466
- classiq/model/function_handler.pyi +0 -152
- classiq/model/logic_flow.py +0 -149
- classiq/model/logic_flow_change_handler.py +0 -71
- classiq/model/model.py +0 -246
- classiq/qmod/builtins/functions.py +0 -896
- classiq/qmod/qmod_struct.py +0 -37
- classiq/quantum_functions/__init__.py +0 -17
- classiq/quantum_functions/annotation_parser.py +0 -207
- classiq/quantum_functions/decorators.py +0 -22
- classiq/quantum_functions/function_library.py +0 -181
- classiq/quantum_functions/function_parser.py +0 -74
- classiq/quantum_functions/quantum_function.py +0 -236
- classiq-0.37.1.dist-info/RECORD +0 -418
- /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers}/__init__.py +0 -0
- /classiq/{interface/generator/credit_risk_example → applications/combinatorial_helpers/arithmetic}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations → applications/combinatorial_helpers/pauli_helpers}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → applications/combinatorial_helpers/py.typed} +0 -0
- /classiq/{interface/model/resolvers → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
- /classiq/{interface/model/validations → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
- /classiq/{_internals → interface}/enum_utils.py +0 -0
@@ -1,20 +1,36 @@
|
|
1
1
|
import urllib.parse
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import Any,
|
3
|
+
from typing import Any, Optional, Union
|
4
4
|
|
5
5
|
from httpx import AsyncClient, Response, codes
|
6
|
-
from pydantic import
|
6
|
+
from pydantic import Field
|
7
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
7
8
|
|
8
|
-
from classiq.exceptions import ClassiqAuthenticationError
|
9
|
+
from classiq.interface.exceptions import ClassiqAuthenticationError
|
9
10
|
|
10
11
|
|
11
12
|
class AuthSettings(BaseSettings):
|
12
|
-
domain: str = Field(
|
13
|
-
|
13
|
+
domain: str = Field(
|
14
|
+
default="auth.classiq.io", validation_alias="CLASSIQ_AUTH_DOMAIN"
|
15
|
+
)
|
16
|
+
audience: str = Field(
|
17
|
+
default="https://cadmium-be", validation_alias="CLASSIQ_AUTH_AUDIENCE"
|
18
|
+
)
|
14
19
|
client_id: str = Field(
|
15
|
-
default="f6721qMOVoDAOVkzrv8YaWassRKSFX6Y",
|
20
|
+
default="f6721qMOVoDAOVkzrv8YaWassRKSFX6Y",
|
21
|
+
validation_alias="CLASSIQ_AUTH_CLIENT_ID",
|
16
22
|
)
|
17
23
|
|
24
|
+
model_config = SettingsConfigDict(extra="allow")
|
25
|
+
|
26
|
+
def __init__(self, **data: Any) -> None:
|
27
|
+
initial_data = {
|
28
|
+
field: data[field] for field in data if field in self.model_fields
|
29
|
+
}
|
30
|
+
super().__init__(**data)
|
31
|
+
for field, value in initial_data.items():
|
32
|
+
setattr(self, field, value)
|
33
|
+
|
18
34
|
|
19
35
|
@dataclass
|
20
36
|
class Tokens:
|
@@ -40,9 +56,9 @@ class Auth0:
|
|
40
56
|
async def _make_request(
|
41
57
|
self,
|
42
58
|
url: str,
|
43
|
-
payload:
|
59
|
+
payload: dict[str, str],
|
44
60
|
allow_error: Union[bool, int] = False,
|
45
|
-
) ->
|
61
|
+
) -> dict[str, Any]:
|
46
62
|
encoded_payload = urllib.parse.urlencode(payload)
|
47
63
|
client: AsyncClient
|
48
64
|
async with AsyncClient(
|
@@ -60,7 +76,7 @@ class Auth0:
|
|
60
76
|
f"Request to Auth0 failed with error code {code}: {data.get('error')}"
|
61
77
|
)
|
62
78
|
|
63
|
-
async def get_device_data(self, get_refresh_token: bool = True) ->
|
79
|
+
async def get_device_data(self, get_refresh_token: bool = True) -> dict[str, Any]:
|
64
80
|
payload = {
|
65
81
|
"client_id": self._auth_settings.client_id,
|
66
82
|
"audience": self._auth_settings.audience,
|
@@ -73,7 +89,7 @@ class Auth0:
|
|
73
89
|
payload=payload,
|
74
90
|
)
|
75
91
|
|
76
|
-
async def poll_tokens(self, device_code: str) ->
|
92
|
+
async def poll_tokens(self, device_code: str) -> dict[str, Any]:
|
77
93
|
payload = {
|
78
94
|
"client_id": self._client_id,
|
79
95
|
"device_code": device_code,
|
@@ -3,6 +3,17 @@ from classiq._internals.client import client
|
|
3
3
|
|
4
4
|
|
5
5
|
def authenticate(overwrite: bool = False) -> None:
|
6
|
+
"""
|
7
|
+
|
8
|
+
Authenticate to access the Classiq platform.
|
9
|
+
|
10
|
+
Args:
|
11
|
+
overwrite: A flag indicating whether to overwrite the existing
|
12
|
+
authentication tokens. Defaults to `False`.
|
13
|
+
|
14
|
+
If you are not registered, please visit the Classiq platform
|
15
|
+
to complete registration: https://platform.classiq.io/
|
16
|
+
"""
|
6
17
|
async_utils.run(authenticate_async(overwrite))
|
7
18
|
|
8
19
|
|
@@ -1,11 +1,16 @@
|
|
1
1
|
import asyncio
|
2
2
|
import webbrowser
|
3
|
+
from collections.abc import Iterable
|
3
4
|
from datetime import timedelta
|
4
|
-
from typing import Any,
|
5
|
+
from typing import Any, Optional, TypeVar
|
6
|
+
|
7
|
+
from classiq.interface.exceptions import (
|
8
|
+
ClassiqAuthenticationError,
|
9
|
+
ClassiqExpiredTokenError,
|
10
|
+
)
|
5
11
|
|
6
12
|
from classiq._internals.async_utils import poll_for
|
7
13
|
from classiq._internals.authentication.auth0 import Auth0, Tokens
|
8
|
-
from classiq.exceptions import ClassiqAuthenticationError, ClassiqExpiredTokenError
|
9
14
|
|
10
15
|
T = TypeVar("T")
|
11
16
|
|
@@ -22,13 +27,13 @@ class DeviceRegistrar:
|
|
22
27
|
cls, get_refresh_token: bool = True, text_only: bool = False
|
23
28
|
) -> Tokens:
|
24
29
|
auth0_client = Auth0()
|
25
|
-
data:
|
30
|
+
data: dict[str, Any] = await auth0_client.get_device_data(
|
26
31
|
get_refresh_token=get_refresh_token
|
27
32
|
)
|
28
33
|
|
29
|
-
print(f"Your user code: {data['user_code']}")
|
34
|
+
print(f"Your user code: {data['user_code']}") # noqa: T201
|
30
35
|
verification_url = data["verification_uri_complete"]
|
31
|
-
print(
|
36
|
+
print( # noqa: T201
|
32
37
|
f"If a browser doesn't automatically open, please visit this URL from any trusted device: {verification_url}"
|
33
38
|
)
|
34
39
|
if not text_only:
|
@@ -44,7 +49,7 @@ class DeviceRegistrar:
|
|
44
49
|
|
45
50
|
@classmethod
|
46
51
|
def _handle_ready_data(
|
47
|
-
cls, data:
|
52
|
+
cls, data: dict[str, Any], get_refresh_token: bool
|
48
53
|
) -> Tokens:
|
49
54
|
access_token: Optional[str] = data.get("access_token")
|
50
55
|
# If refresh token was not requested, this would be None
|
@@ -68,7 +73,7 @@ class DeviceRegistrar:
|
|
68
73
|
timeout: float,
|
69
74
|
get_refresh_token: bool = True,
|
70
75
|
) -> Tokens:
|
71
|
-
async def poller():
|
76
|
+
async def poller() -> dict[str, Any]:
|
72
77
|
nonlocal device_code
|
73
78
|
return await auth0_client.poll_tokens(device_code=device_code)
|
74
79
|
|
@@ -92,7 +97,12 @@ class DeviceRegistrar:
|
|
92
97
|
elif error_code == "expired_token":
|
93
98
|
raise ClassiqExpiredTokenError(cls._TIMEOUT_ERROR)
|
94
99
|
elif error_code == "access_denied":
|
95
|
-
error_description
|
100
|
+
error_description = data.get("error_description")
|
101
|
+
if error_description is None:
|
102
|
+
raise ClassiqAuthenticationError(
|
103
|
+
"Failed authenticating to Classiq, missing error description"
|
104
|
+
)
|
105
|
+
|
96
106
|
raise ClassiqAuthenticationError(error_description)
|
97
107
|
else:
|
98
108
|
raise ClassiqAuthenticationError(
|
@@ -5,34 +5,57 @@ import os
|
|
5
5
|
import pathlib
|
6
6
|
import platform
|
7
7
|
import stat
|
8
|
-
from typing import
|
8
|
+
from typing import Any, Optional
|
9
9
|
|
10
10
|
import keyring
|
11
11
|
from keyring.backends import fail
|
12
|
+
from pydantic import Field
|
13
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
12
14
|
|
13
15
|
_logger = logging.getLogger(__name__)
|
14
16
|
|
15
17
|
|
18
|
+
class PasswordManagerSettings(BaseSettings):
|
19
|
+
ACCESS_TOKEN_KEY: str = Field(
|
20
|
+
default="classiqTokenAccount", validation_alias="CLASSIQ_ACCESS_TOKEN_ACCOUNT"
|
21
|
+
)
|
22
|
+
REFRESH_TOKEN_KEY: str = Field(
|
23
|
+
default="classiqRefershTokenAccount",
|
24
|
+
validation_alias="CLASSIQ_REFRESH_TOKEN_ACCOUNT",
|
25
|
+
)
|
26
|
+
|
27
|
+
model_config = SettingsConfigDict(extra="allow")
|
28
|
+
|
29
|
+
def __init__(self, **data: Any) -> None:
|
30
|
+
initial_data = {
|
31
|
+
field: data[field] for field in data if field in self.model_fields
|
32
|
+
}
|
33
|
+
super().__init__(**data)
|
34
|
+
for field, value in initial_data.items():
|
35
|
+
setattr(self, field, value)
|
36
|
+
|
37
|
+
|
16
38
|
class PasswordManager(abc.ABC):
|
17
39
|
_SERVICE_NAME: str = "classiqTokenService"
|
18
|
-
|
19
|
-
|
40
|
+
|
41
|
+
def __init__(self) -> None:
|
42
|
+
self._settings = PasswordManagerSettings()
|
20
43
|
|
21
44
|
@property
|
22
45
|
def access_token(self) -> Optional[str]:
|
23
|
-
return self._get(key=self.
|
46
|
+
return self._get(key=self._settings.ACCESS_TOKEN_KEY)
|
24
47
|
|
25
48
|
@access_token.setter
|
26
49
|
def access_token(self, access_token: Optional[str]) -> None:
|
27
|
-
self._set(key=self.
|
50
|
+
self._set(key=self._settings.ACCESS_TOKEN_KEY, value=access_token)
|
28
51
|
|
29
52
|
@property
|
30
53
|
def refresh_token(self) -> Optional[str]:
|
31
|
-
return self._get(key=self.
|
54
|
+
return self._get(key=self._settings.REFRESH_TOKEN_KEY)
|
32
55
|
|
33
56
|
@refresh_token.setter
|
34
57
|
def refresh_token(self, refresh_token: Optional[str]) -> None:
|
35
|
-
self._set(key=self.
|
58
|
+
self._set(key=self._settings.REFRESH_TOKEN_KEY, value=refresh_token)
|
36
59
|
|
37
60
|
@abc.abstractmethod
|
38
61
|
def _get(self, key: str) -> Optional[str]:
|
@@ -46,8 +69,9 @@ class PasswordManager(abc.ABC):
|
|
46
69
|
def _clear(self, key: str) -> None:
|
47
70
|
pass
|
48
71
|
|
72
|
+
@staticmethod
|
49
73
|
@abc.abstractmethod
|
50
|
-
def is_supported(
|
74
|
+
def is_supported() -> bool:
|
51
75
|
pass
|
52
76
|
|
53
77
|
|
@@ -71,7 +95,8 @@ class KeyringPasswordManager(PasswordManager):
|
|
71
95
|
username=key,
|
72
96
|
)
|
73
97
|
|
74
|
-
|
98
|
+
@staticmethod
|
99
|
+
def is_supported() -> bool:
|
75
100
|
return not isinstance(keyring.get_keyring(), fail.Keyring)
|
76
101
|
|
77
102
|
|
@@ -85,7 +110,8 @@ class DummyPasswordManager(PasswordManager):
|
|
85
110
|
def _clear(self, key: str) -> None:
|
86
111
|
return
|
87
112
|
|
88
|
-
|
113
|
+
@staticmethod
|
114
|
+
def is_supported() -> bool:
|
89
115
|
return True
|
90
116
|
|
91
117
|
|
@@ -98,12 +124,12 @@ class FilePasswordManager(PasswordManager):
|
|
98
124
|
super().__init__()
|
99
125
|
self.credentials_file = pathlib.Path(self._CLASSIQ_CREDENTIALS_FILE_PATH)
|
100
126
|
|
101
|
-
def _update_file(self, token_dict:
|
127
|
+
def _update_file(self, token_dict: dict) -> None:
|
102
128
|
self.credentials_file.touch()
|
103
129
|
self.credentials_file.chmod(stat.S_IRUSR | stat.S_IWUSR)
|
104
130
|
self.credentials_file.write_text(json.dumps(token_dict))
|
105
131
|
|
106
|
-
def _get_token_dict(self) ->
|
132
|
+
def _get_token_dict(self) -> dict:
|
107
133
|
if self.credentials_file.exists():
|
108
134
|
return json.loads(self.credentials_file.read_text())
|
109
135
|
return {}
|
@@ -125,5 +151,6 @@ class FilePasswordManager(PasswordManager):
|
|
125
151
|
token_dict.pop(key)
|
126
152
|
self._update_file(token_dict)
|
127
153
|
|
128
|
-
|
154
|
+
@staticmethod
|
155
|
+
def is_supported() -> bool:
|
129
156
|
return "windows" not in platform.platform().lower()
|
@@ -2,18 +2,23 @@ import argparse
|
|
2
2
|
import logging
|
3
3
|
import threading
|
4
4
|
import warnings
|
5
|
+
from collections.abc import Sequence
|
5
6
|
from typing import Optional
|
6
7
|
|
8
|
+
from classiq.interface.exceptions import (
|
9
|
+
ClassiqAuthenticationError,
|
10
|
+
ClassiqPasswordManagerSelectionError,
|
11
|
+
)
|
12
|
+
|
7
13
|
from classiq._internals.authentication import password_manager as pm
|
8
14
|
from classiq._internals.authentication.auth0 import Auth0
|
9
15
|
from classiq._internals.authentication.device import DeviceRegistrar, Tokens
|
10
16
|
from classiq._internals.config import Configuration
|
11
|
-
from classiq.exceptions import (
|
12
|
-
ClassiqAuthenticationError,
|
13
|
-
ClassiqPasswordManagerSelectionError,
|
14
|
-
)
|
15
17
|
|
16
|
-
PASSWORD_MANAGERS
|
18
|
+
PASSWORD_MANAGERS: Sequence[type[pm.PasswordManager]] = [
|
19
|
+
pm.KeyringPasswordManager,
|
20
|
+
pm.FilePasswordManager,
|
21
|
+
]
|
17
22
|
_logger = logging.getLogger(__name__)
|
18
23
|
|
19
24
|
|
@@ -57,7 +62,7 @@ class TokenManager:
|
|
57
62
|
return pm.FilePasswordManager()
|
58
63
|
for password_manager in PASSWORD_MANAGERS:
|
59
64
|
if password_manager.is_supported():
|
60
|
-
return password_manager
|
65
|
+
return password_manager()
|
61
66
|
raise ClassiqPasswordManagerSelectionError(
|
62
67
|
"Password Manager not found, we could not store your credentials securely. Please contact support@classiq.io"
|
63
68
|
)
|
classiq/_internals/client.py
CHANGED
@@ -1,22 +1,26 @@
|
|
1
1
|
import asyncio
|
2
|
+
import contextlib
|
2
3
|
import functools
|
3
4
|
import inspect
|
4
5
|
import logging
|
5
6
|
import os
|
6
7
|
import platform
|
7
|
-
import ssl
|
8
8
|
import sys
|
9
|
-
|
9
|
+
import time
|
10
|
+
from collections.abc import Awaitable
|
11
|
+
from types import TracebackType
|
12
|
+
from typing import Any, Callable, NoReturn, Optional, TypeVar, Union
|
10
13
|
|
11
14
|
import httpx
|
12
|
-
from
|
15
|
+
from typing_extensions import ParamSpec
|
13
16
|
|
14
17
|
from classiq.interface._version import VERSION as _VERSION
|
18
|
+
from classiq.interface.exceptions import ClassiqAPIError, ClassiqExpiredTokenError
|
19
|
+
from classiq.interface.interface_version import INTERFACE_VERSION
|
15
20
|
|
16
21
|
from classiq._internals import config
|
17
22
|
from classiq._internals.authentication import token_manager
|
18
23
|
from classiq._internals.host_checker import HostChecker
|
19
|
-
from classiq.exceptions import ClassiqAPIError, ClassiqExpiredTokenError
|
20
24
|
|
21
25
|
_FRONTEND_VARIANT: str = "classiq-sdk"
|
22
26
|
_INTERFACE_VARIANT: str = "classiq-interface-sdk"
|
@@ -26,7 +30,7 @@ _logger = logging.getLogger(__name__)
|
|
26
30
|
|
27
31
|
_RETRY_COUNT = 2
|
28
32
|
|
29
|
-
Headers =
|
33
|
+
Headers = dict[str, str]
|
30
34
|
|
31
35
|
APPROVED_API_ERROR_MESSAGES_FOR_RESTART = [
|
32
36
|
"Call to API failed with code 502",
|
@@ -80,9 +84,13 @@ def _get_user_agent_header() -> Headers:
|
|
80
84
|
}
|
81
85
|
|
82
86
|
|
87
|
+
Ret = TypeVar("Ret")
|
88
|
+
P = ParamSpec("P")
|
89
|
+
|
90
|
+
|
83
91
|
def try_again_on_failure(
|
84
|
-
func: Callable[
|
85
|
-
) -> Callable[
|
92
|
+
func: Callable[P, Awaitable[Ret]]
|
93
|
+
) -> Callable[P, Awaitable[Ret]]:
|
86
94
|
def check_approved_api_error(error_message: str) -> bool:
|
87
95
|
for approved_api_error in APPROVED_API_ERROR_MESSAGES_FOR_RESTART:
|
88
96
|
if approved_api_error in error_message:
|
@@ -93,7 +101,7 @@ def try_again_on_failure(
|
|
93
101
|
raise TypeError("Must decorate a coroutine function")
|
94
102
|
|
95
103
|
@functools.wraps(func)
|
96
|
-
async def wrapper(*args, **kwargs):
|
104
|
+
async def wrapper(*args: P.args, **kwargs: P.kwargs) -> Ret:
|
97
105
|
for i in range(_RETRY_COUNT):
|
98
106
|
try:
|
99
107
|
return await func(*args, **kwargs)
|
@@ -123,32 +131,49 @@ def try_again_on_failure(
|
|
123
131
|
"There is problem with the connection to Classiq's server. Trying again"
|
124
132
|
)
|
125
133
|
await asyncio.sleep(API_ERROR_SLEEP_TIME)
|
134
|
+
raise ClassiqAPIError(
|
135
|
+
"Reached max retries when trying to connect to Classiq's server"
|
136
|
+
)
|
126
137
|
|
127
138
|
return wrapper
|
128
139
|
|
129
140
|
|
141
|
+
class _AsyncNullContext(contextlib.AbstractAsyncContextManager):
|
142
|
+
"""
|
143
|
+
This class is meant to replace `contextlib.nullcontext`, which hadn't supported
|
144
|
+
async context manager until python 3.10.
|
145
|
+
"""
|
146
|
+
|
147
|
+
def __init__(self, enter_result: Any = None) -> None:
|
148
|
+
self._enter_result = enter_result
|
149
|
+
|
150
|
+
async def __aenter__(self) -> Any:
|
151
|
+
return self._enter_result
|
152
|
+
|
153
|
+
async def __aexit__(
|
154
|
+
self,
|
155
|
+
exc_type: Optional[type[BaseException]],
|
156
|
+
exc_val: Optional[BaseException],
|
157
|
+
exc_tb: Optional[TracebackType],
|
158
|
+
) -> None:
|
159
|
+
pass
|
160
|
+
|
161
|
+
|
130
162
|
class Client:
|
131
163
|
_UNKNOWN_VERSION = HostChecker._UNKNOWN_VERSION
|
132
164
|
_SESSION_HEADER = "Classiq-Session"
|
133
165
|
_WARNINGS_HEADER = "X-Classiq-Warnings"
|
134
|
-
|
166
|
+
_HTTP_TIMEOUT_SECONDS = 3600 # Needs to be synced with load-balancer timeout
|
135
167
|
|
136
168
|
def __init__(self, conf: config.Configuration) -> None:
|
137
169
|
self._config = conf
|
138
170
|
self._token_manager = token_manager.TokenManager(config=self._config)
|
139
|
-
self._ssl_context = ssl.create_default_context()
|
140
|
-
self._HTTP_TIMEOUT_SECONDS = (
|
141
|
-
3600 # Needs to be synced with load-balancer timeout
|
142
|
-
)
|
143
171
|
self._api_prefix = self._make_api_prefix()
|
144
172
|
self._session_id: Optional[str] = None
|
145
173
|
|
146
|
-
@
|
147
|
-
def _make_api_prefix(
|
148
|
-
|
149
|
-
return cls._LATEST_VERSION_API_PREFIX
|
150
|
-
parsed_version = Version(_VERSION)
|
151
|
-
return f"/api/v{parsed_version.major}-{parsed_version.minor}"
|
174
|
+
@staticmethod
|
175
|
+
def _make_api_prefix() -> str:
|
176
|
+
return f"/api/v{INTERFACE_VERSION}"
|
152
177
|
|
153
178
|
def make_versioned_url(self, url_postfix: str) -> str:
|
154
179
|
return self._api_prefix + url_postfix
|
@@ -186,48 +211,92 @@ class Client:
|
|
186
211
|
try:
|
187
212
|
detail = response.json()["detail"]
|
188
213
|
message += f": {detail}"
|
189
|
-
except Exception: #
|
214
|
+
except Exception: # noqa: S110
|
190
215
|
pass
|
191
|
-
raise ClassiqAPIError(message)
|
216
|
+
raise ClassiqAPIError(message, response.status_code)
|
192
217
|
|
193
|
-
|
218
|
+
@try_again_on_failure
|
219
|
+
async def request(
|
220
|
+
self,
|
221
|
+
http_client: httpx.AsyncClient,
|
222
|
+
method: str,
|
223
|
+
url: str,
|
224
|
+
json: Optional[dict] = None,
|
225
|
+
params: Optional[dict] = None,
|
226
|
+
headers: Optional[dict[str, str]] = None,
|
227
|
+
) -> httpx.Response:
|
228
|
+
http_client.headers.update(self._get_headers())
|
229
|
+
|
230
|
+
_logger.debug("HTTP request: %s %s", method.upper(), url)
|
231
|
+
start_time = time.monotonic()
|
232
|
+
response = await http_client.request(
|
233
|
+
method=method,
|
234
|
+
url=url,
|
235
|
+
json=json,
|
236
|
+
params=params,
|
237
|
+
headers=headers,
|
238
|
+
)
|
239
|
+
_logger.debug(
|
240
|
+
"HTTP response: %s %s %d (%.0fms)",
|
241
|
+
method.upper(),
|
242
|
+
url,
|
243
|
+
response.status_code,
|
244
|
+
(time.monotonic() - start_time) * 1000,
|
245
|
+
)
|
246
|
+
self.handle_response(response)
|
247
|
+
return response
|
248
|
+
|
249
|
+
def _make_client_args(self) -> dict[str, Any]:
|
194
250
|
return {
|
195
|
-
"base_url": self._config.host,
|
251
|
+
"base_url": str(self._config.host),
|
196
252
|
"timeout": self._HTTP_TIMEOUT_SECONDS,
|
197
|
-
"headers": self.
|
253
|
+
"headers": self._get_headers(),
|
198
254
|
}
|
199
255
|
|
200
|
-
@try_again_on_failure
|
201
256
|
async def call_api(
|
202
257
|
self,
|
203
258
|
http_method: str,
|
204
259
|
url: str,
|
205
|
-
body: Optional[
|
206
|
-
params: Optional[
|
260
|
+
body: Optional[dict] = None,
|
261
|
+
params: Optional[dict] = None,
|
207
262
|
use_versioned_url: bool = True,
|
208
|
-
headers: Optional[
|
209
|
-
|
263
|
+
headers: Optional[dict[str, str]] = None,
|
264
|
+
http_client: Optional[httpx.AsyncClient] = None,
|
265
|
+
) -> Union[dict, list, str]:
|
210
266
|
if use_versioned_url:
|
211
267
|
url = self.make_versioned_url(url)
|
212
|
-
async with self.
|
213
|
-
response = await
|
268
|
+
async with self.use_client_or_create(http_client) as async_client:
|
269
|
+
response = await self.request(
|
270
|
+
http_client=async_client,
|
214
271
|
method=http_method,
|
215
272
|
url=url,
|
216
273
|
json=body,
|
217
274
|
params=params,
|
218
275
|
headers=headers,
|
219
276
|
)
|
220
|
-
self.handle_response(response)
|
221
277
|
return response.json()
|
222
278
|
|
279
|
+
def use_client_or_create(
|
280
|
+
self, http_client: Optional[httpx.AsyncClient]
|
281
|
+
) -> contextlib.AbstractAsyncContextManager[httpx.AsyncClient]:
|
282
|
+
if http_client is None:
|
283
|
+
return self.async_client()
|
284
|
+
else:
|
285
|
+
if sys.version_info[0:2] < (3, 10):
|
286
|
+
# remove this `if` and the `_AsyncNullContext` class when we stop
|
287
|
+
# supporting python 3.9
|
288
|
+
return _AsyncNullContext(enter_result=http_client)
|
289
|
+
else:
|
290
|
+
return contextlib.nullcontext(enter_result=http_client)
|
291
|
+
|
223
292
|
def sync_call_api(
|
224
293
|
self,
|
225
294
|
http_method: str,
|
226
295
|
url: str,
|
227
|
-
body: Optional[
|
228
|
-
headers: Optional[
|
296
|
+
body: Optional[dict] = None,
|
297
|
+
headers: Optional[dict] = None,
|
229
298
|
use_versioned_url: bool = True,
|
230
|
-
) -> Union[
|
299
|
+
) -> Union[dict, str]:
|
231
300
|
if use_versioned_url:
|
232
301
|
url = self.make_versioned_url(url)
|
233
302
|
with httpx.Client(**self._make_client_args()) as sync_client:
|
@@ -240,7 +309,7 @@ class Client:
|
|
240
309
|
def async_client(self) -> httpx.AsyncClient:
|
241
310
|
return httpx.AsyncClient(**self._make_client_args())
|
242
311
|
|
243
|
-
def
|
312
|
+
def _get_headers(self) -> Headers:
|
244
313
|
headers = dict()
|
245
314
|
access_token = self._token_manager.get_access_token()
|
246
315
|
if access_token is not None:
|
@@ -254,7 +323,7 @@ class Client:
|
|
254
323
|
await self._token_manager.update_expired_access_token()
|
255
324
|
|
256
325
|
def get_backend_uri(self) -> str:
|
257
|
-
return self._config.host
|
326
|
+
return self._config.host.unicode_string()
|
258
327
|
|
259
328
|
def check_host(self) -> None:
|
260
329
|
# This function is NOT async (despite the fact that it can be) because it's called from a non-async context.
|
classiq/_internals/config.py
CHANGED
@@ -2,16 +2,15 @@
|
|
2
2
|
|
3
3
|
import os
|
4
4
|
import pathlib
|
5
|
-
from typing import
|
5
|
+
from typing import Optional, Union
|
6
6
|
|
7
7
|
import configargparse # type: ignore[import]
|
8
8
|
import pydantic
|
9
9
|
from pydantic import BaseModel
|
10
10
|
|
11
|
+
from classiq.interface.enum_utils import StrEnum
|
11
12
|
from classiq.interface.server.routes import DEFAULT_IDE_FE_APP
|
12
13
|
|
13
|
-
from classiq._internals.enum_utils import StrEnum
|
14
|
-
|
15
14
|
DEFAULT_HOST = "https://api.classiq.io"
|
16
15
|
|
17
16
|
|
@@ -54,7 +53,7 @@ if os.name == "posix":
|
|
54
53
|
] + _DEFAULT_CONFIG_FILES
|
55
54
|
|
56
55
|
|
57
|
-
def init(args: Optional[Union[str,
|
56
|
+
def init(args: Optional[Union[str, list[str]]] = None) -> Configuration:
|
58
57
|
"""Initialize the configuration object.
|
59
58
|
|
60
59
|
Args:
|