qpi-driver 0.0.6__tar.gz

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.
Files changed (34) hide show
  1. qpi_driver-0.0.6/LICENSE +21 -0
  2. qpi_driver-0.0.6/PKG-INFO +33 -0
  3. qpi_driver-0.0.6/pyproject.toml +63 -0
  4. qpi_driver-0.0.6/qpi_driver/__init__.py +25 -0
  5. qpi_driver-0.0.6/qpi_driver/cli.py +138 -0
  6. qpi_driver-0.0.6/qpi_driver/compat/__init__.py +0 -0
  7. qpi_driver-0.0.6/qpi_driver/compat/qblox.py +120 -0
  8. qpi_driver-0.0.6/qpi_driver/compat/qiskit_aer.py +12 -0
  9. qpi_driver-0.0.6/qpi_driver/compat/quantify.py +131 -0
  10. qpi_driver-0.0.6/qpi_driver/compat/shared.py +6 -0
  11. qpi_driver-0.0.6/qpi_driver/compat/typer.py +19 -0
  12. qpi_driver-0.0.6/qpi_driver/driver.py +373 -0
  13. qpi_driver-0.0.6/qpi_driver/executors/__init__.py +74 -0
  14. qpi_driver-0.0.6/qpi_driver/executors/base.py +157 -0
  15. qpi_driver-0.0.6/qpi_driver/executors/mock.py +169 -0
  16. qpi_driver-0.0.6/qpi_driver/executors/presto.py +36 -0
  17. qpi_driver-0.0.6/qpi_driver/executors/qblox.py +740 -0
  18. qpi_driver-0.0.6/qpi_driver/executors/qiskit_aer.py +178 -0
  19. qpi_driver-0.0.6/qpi_driver/executors/quantify.py +796 -0
  20. qpi_driver-0.0.6/qpi_driver/executors/utils/__init__.py +0 -0
  21. qpi_driver-0.0.6/qpi_driver/executors/utils/qiskit.py +86 -0
  22. qpi_driver-0.0.6/qpi_driver/executors/utils/result.py +114 -0
  23. qpi_driver-0.0.6/qpi_driver.egg-info/PKG-INFO +33 -0
  24. qpi_driver-0.0.6/qpi_driver.egg-info/SOURCES.txt +32 -0
  25. qpi_driver-0.0.6/qpi_driver.egg-info/dependency_links.txt +1 -0
  26. qpi_driver-0.0.6/qpi_driver.egg-info/entry_points.txt +2 -0
  27. qpi_driver-0.0.6/qpi_driver.egg-info/requires.txt +22 -0
  28. qpi_driver-0.0.6/qpi_driver.egg-info/top_level.txt +1 -0
  29. qpi_driver-0.0.6/setup.cfg +4 -0
  30. qpi_driver-0.0.6/tests/test_cli.py +41 -0
  31. qpi_driver-0.0.6/tests/test_executors.py +127 -0
  32. qpi_driver-0.0.6/tests/test_qblox.py +166 -0
  33. qpi_driver-0.0.6/tests/test_qiskit_aer.py +53 -0
  34. qpi_driver-0.0.6/tests/test_quantify.py +170 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Martin Ahindura
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,33 @@
1
+ Metadata-Version: 2.4
2
+ Name: qpi-driver
3
+ Version: 0.0.6
4
+ Summary: Quantum Processing Interface (QPI) Hardware Driver
5
+ Author-email: Martin Ahindura <team.sopherapps@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/sopherapps/qpi
8
+ Project-URL: Repository, https://github.com/sopherapps/qpi
9
+ Project-URL: Documentation, https://github.com/sopherapps/qpi
10
+ Project-URL: Issues, https://github.com/sopherapps/qpi/issues
11
+ Project-URL: Changelog, https://github.com/sopherapps/qpi/blob/main/CHANGELOG.md
12
+ Requires-Python: <3.13,>=3.12
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: numpy>=2.0.0
16
+ Requires-Dist: xarray>=2024.1.0
17
+ Requires-Dist: pynng>=0.8.0
18
+ Requires-Dist: requests>=2.31.0
19
+ Requires-Dist: qiskit>=1.0.0
20
+ Requires-Dist: scipy>=1.10.0
21
+ Requires-Dist: pyyaml>=6.0
22
+ Requires-Dist: qiskit_qasm3_import
23
+ Provides-Extra: cli
24
+ Requires-Dist: typer>=0.9.0; extra == "cli"
25
+ Provides-Extra: aer
26
+ Requires-Dist: qiskit-aer>=0.14.0; extra == "aer"
27
+ Provides-Extra: quantify
28
+ Requires-Dist: quantify-scheduler; extra == "quantify"
29
+ Requires-Dist: qblox-instruments; extra == "quantify"
30
+ Provides-Extra: qblox
31
+ Requires-Dist: qblox-scheduler>=1.0.0b1; extra == "qblox"
32
+ Requires-Dist: qblox-instruments; extra == "qblox"
33
+ Dynamic: license-file
@@ -0,0 +1,63 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "qpi-driver"
7
+ version = "0.0.6"
8
+ description = "Quantum Processing Interface (QPI) Hardware Driver"
9
+ readme = "README.md"
10
+ requires-python = ">=3.12,<3.13"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "Martin Ahindura", email = "team.sopherapps@gmail.com" },
14
+ ]
15
+ dependencies = [
16
+ "numpy>=2.0.0",
17
+ "xarray>=2024.1.0",
18
+ "pynng>=0.8.0",
19
+ "requests>=2.31.0",
20
+ "qiskit>=1.0.0",
21
+ "scipy>=1.10.0",
22
+ "pyyaml>=6.0",
23
+ "qiskit_qasm3_import"
24
+ ]
25
+
26
+ [project.optional-dependencies]
27
+ cli = ["typer>=0.9.0"]
28
+ aer = ["qiskit-aer>=0.14.0"]
29
+ quantify = [
30
+ "quantify-scheduler",
31
+ "qblox-instruments"
32
+ ]
33
+ qblox = [
34
+ "qblox-scheduler>=1.0.0b1",
35
+ "qblox-instruments"
36
+ ]
37
+
38
+ [dependency-groups]
39
+ dev = [
40
+ "pytest>=8.0.0",
41
+ "ruff>=0.3.0"
42
+ ]
43
+
44
+ [project.urls]
45
+ Homepage = "https://github.com/sopherapps/qpi"
46
+ Repository = "https://github.com/sopherapps/qpi"
47
+ Documentation = "https://github.com/sopherapps/qpi"
48
+ Issues = "https://github.com/sopherapps/qpi/issues"
49
+ Changelog = "https://github.com/sopherapps/qpi/blob/main/CHANGELOG.md"
50
+
51
+ [project.scripts]
52
+ qpi-driver = "qpi_driver.cli:app"
53
+
54
+ [tool.setuptools.packages.find]
55
+ where = ["."]
56
+ include = ["qpi_driver*"]
57
+
58
+ [tool.uv]
59
+ override-dependencies = [
60
+ "pyqt5-qt5>=5.15.10",
61
+ "pyqt5>=5.15.10",
62
+ "qcodes<0.57"
63
+ ]
@@ -0,0 +1,25 @@
1
+ import importlib.metadata
2
+
3
+ try:
4
+ __version__ = importlib.metadata.version("qpi-driver")
5
+ except importlib.metadata.PackageNotFoundError:
6
+ __version__ = "0.0.6"
7
+
8
+ from qpi_driver.driver import run_driver
9
+ from qpi_driver.executors.base import Executor
10
+ from qpi_driver.executors.mock import MockExecutor
11
+ from qpi_driver.executors.presto import PrestoExecutor
12
+ from qpi_driver.executors.qblox import QbloxExecutor
13
+ from qpi_driver.executors.qiskit_aer import QiskitAerExecutor
14
+ from qpi_driver.executors.quantify import QuantifyExecutor
15
+
16
+ __all__ = [
17
+ "__version__",
18
+ "run_driver",
19
+ "Executor",
20
+ "MockExecutor",
21
+ "QiskitAerExecutor",
22
+ "QuantifyExecutor",
23
+ "QbloxExecutor",
24
+ "PrestoExecutor",
25
+ ]
@@ -0,0 +1,138 @@
1
+ import importlib.metadata
2
+ from pathlib import Path
3
+ from typing import Annotated
4
+
5
+ from qpi_driver.compat import typer
6
+ from qpi_driver.driver import run_driver
7
+
8
+ app = None
9
+ if typer.IS_TYPER_INSTALLED:
10
+ app = typer.Typer(help="Quantum Processing Interface (QPI) Hardware Driver CLI")
11
+
12
+ @app.command()
13
+ def start(
14
+ qpi_addr: Annotated[
15
+ str,
16
+ typer.Option(
17
+ "--qpi-addr",
18
+ "-a",
19
+ envvar="QPI_ADDR",
20
+ help="Full URL of the QPI orchestrator (e.g. http://localhost:8090 or https://qpi.example.com)",
21
+ ),
22
+ ] = "http://127.0.0.1:8090",
23
+ token: Annotated[
24
+ str,
25
+ typer.Option(
26
+ "--token",
27
+ "-t",
28
+ envvar="QPI_ACCESS_TOKEN",
29
+ help="QPU access token matching a qpus.access_token record",
30
+ ),
31
+ ] = "",
32
+ name: Annotated[
33
+ str,
34
+ typer.Option(
35
+ "--name",
36
+ "-n",
37
+ envvar="QPU_NAME",
38
+ help="Human-readable name for this QPU",
39
+ ),
40
+ ] = "qpu_sim_01",
41
+ executor: Annotated[
42
+ str,
43
+ typer.Option(
44
+ "--executor",
45
+ "-e",
46
+ envvar="DRIVER_BACKEND",
47
+ help="Which executor backend to use (mock, qiskit_aer, quantify, qblox, presto)",
48
+ ),
49
+ ] = "mock",
50
+ data_dir: Annotated[
51
+ Path,
52
+ typer.Option(
53
+ "--data-dir",
54
+ "-d",
55
+ envvar="QPI_DATA_DIR",
56
+ help="Directory where intermediate pickled datasets are written",
57
+ writable=True,
58
+ readable=True,
59
+ dir_okay=True,
60
+ file_okay=False,
61
+ resolve_path=True,
62
+ ),
63
+ ] = Path("./bin/data"),
64
+ is_dummy: Annotated[
65
+ bool,
66
+ typer.Option(
67
+ "--is-dummy",
68
+ help="Whether to run the executor in dummy/simulation mode",
69
+ ),
70
+ ] = False,
71
+ quantify_hardware_config: Annotated[
72
+ Path,
73
+ typer.Option(
74
+ envvar="QPI_QUANTIFY_HARDWARE_CONFIG",
75
+ help="Path to the quantify hardware-layer configuration file containing specifications about the RF control instruments",
76
+ readable=True,
77
+ dir_okay=False,
78
+ file_okay=True,
79
+ resolve_path=True,
80
+ ),
81
+ ] = Path("./quantify.hardware.json"),
82
+ quantify_device_config: Annotated[
83
+ Path,
84
+ typer.Option(
85
+ envvar="QPI_QUANTIFY_DEVICE_CONFIG",
86
+ help="Path to the quantify device-layer configuration file containing specifications about the chip",
87
+ readable=True,
88
+ dir_okay=False,
89
+ file_okay=True,
90
+ resolve_path=True,
91
+ ),
92
+ ] = Path("./quantify.device.yml"),
93
+ job_timeout: Annotated[
94
+ int,
95
+ typer.Option(
96
+ envvar="QPI_JOB_TIMEOUT",
97
+ help="The number of seconds to wait for a job to complete.",
98
+ ),
99
+ ] = 10,
100
+ ):
101
+ """
102
+ Start the QPI driver.
103
+ """
104
+ if not token:
105
+ typer.echo(
106
+ "Error: access token is required. "
107
+ "Set it via --token / -t or the QPI_ACCESS_TOKEN environment variable.",
108
+ err=True,
109
+ )
110
+ raise typer.Exit(code=1)
111
+
112
+ run_driver(
113
+ qpi_addr=qpi_addr,
114
+ token=token,
115
+ name=name,
116
+ executor=executor,
117
+ data_dir=data_dir,
118
+ is_dummy=is_dummy,
119
+ quantify_hardware_config=quantify_hardware_config,
120
+ quantify_device_config=quantify_device_config,
121
+ job_timeout=job_timeout,
122
+ )
123
+
124
+ @app.command()
125
+ def version():
126
+ """
127
+ Show the version of the QPI driver.
128
+ """
129
+
130
+ try:
131
+ ver = importlib.metadata.version("qpi-driver")
132
+ except importlib.metadata.PackageNotFoundError:
133
+ ver = "0.0.6"
134
+
135
+ typer.echo(ver)
136
+
137
+ if __name__ == "__main__":
138
+ app()
File without changes
@@ -0,0 +1,120 @@
1
+ """Module containing compatibility imports for qblox-scheduler-related libraries"""
2
+
3
+ import logging
4
+ from enum import Enum
5
+ from typing import Any, TypeAlias
6
+
7
+ from qpi_driver.compat.shared import BasicCompatClass
8
+
9
+ try:
10
+ from pydantic import BaseModel, ImportString, field_validator
11
+ from qblox_instruments import Cluster, ClusterType, InstrumentType # noqa: F401
12
+ from qblox_scheduler import HardwareAgent, Schedule # noqa: F401
13
+ from qblox_scheduler.device_under_test.quantum_device import (
14
+ DeviceElement,
15
+ Edge,
16
+ QuantumDevice, # noqa: F401
17
+ )
18
+ from qblox_scheduler.device_under_test.transmon_element import (
19
+ BasicTransmonElement, # noqa: F401
20
+ )
21
+ from qblox_scheduler.operations import (
22
+ CNOT,
23
+ CZ,
24
+ H,
25
+ IdlePulse,
26
+ Measure,
27
+ Operation,
28
+ Reset,
29
+ Rxy,
30
+ Rz,
31
+ S,
32
+ SDagger,
33
+ T,
34
+ TDagger,
35
+ X,
36
+ Y,
37
+ Z,
38
+ )
39
+ from qblox_scheduler.qblox.hardware_agent import (
40
+ QbloxHardwareCompilationConfig, # noqa: F401
41
+ )
42
+ from qblox_scheduler.schedules import Schedulable
43
+ from qcodes.instrument import InstrumentModule # noqa: F401
44
+ from qcodes.instrument.base import Instrument # noqa: F401
45
+ from qcodes.parameters import ParameterBase # noqa: F401
46
+
47
+ IS_QBLOX_SCHEDULER_INSTALLED: bool = True
48
+
49
+ except ImportError as exp:
50
+ logging.debug(f"failed importing from qblox.compat {exp}")
51
+ IS_QBLOX_SCHEDULER_INSTALLED: bool = False
52
+
53
+ HardwareAgent: TypeAlias = Any
54
+ QbloxHardwareCompilationConfig: TypeAlias = Any
55
+ QuantumDevice: TypeAlias = Any
56
+ BasicTransmonElement: TypeAlias = Any
57
+ Cluster: TypeAlias = Any
58
+ ImportString: TypeAlias = Any
59
+ Schedulable: TypeAlias = Any
60
+
61
+ class DeviceElement(BasicCompatClass): ...
62
+
63
+ class Edge(BasicCompatClass): ...
64
+
65
+ class BaseModel(BasicCompatClass): ...
66
+
67
+ class CNOT(BasicCompatClass): ...
68
+
69
+ class CZ(BasicCompatClass): ...
70
+
71
+ class H(BasicCompatClass): ...
72
+
73
+ class Measure(BasicCompatClass): ...
74
+
75
+ class Reset(BasicCompatClass): ...
76
+
77
+ class Rxy(BasicCompatClass): ...
78
+
79
+ class Rz(BasicCompatClass): ...
80
+
81
+ class X(BasicCompatClass): ...
82
+
83
+ class Y(BasicCompatClass): ...
84
+
85
+ class Z(BasicCompatClass): ...
86
+
87
+ class S(BasicCompatClass): ...
88
+
89
+ class T(BasicCompatClass): ...
90
+
91
+ class SDagger(BasicCompatClass): ...
92
+
93
+ class TDagger(BasicCompatClass): ...
94
+
95
+ class IdlePulse(BasicCompatClass): ...
96
+
97
+ class InstrumentModule(BasicCompatClass): ...
98
+
99
+ class ParameterBase(BasicCompatClass): ...
100
+
101
+ class InstrumentType(Enum): ...
102
+
103
+ class ClusterType(Enum): ...
104
+
105
+ class Operation(BasicCompatClass): ...
106
+
107
+ class Schedule(BasicCompatClass):
108
+ def add(self, *args, **kwargs):
109
+ pass
110
+
111
+ class Instrument(BasicCompatClass):
112
+ @classmethod
113
+ def close_all(cls):
114
+ pass
115
+
116
+ def field_validator(*args, **kwargs):
117
+ def decor(*args, **kwargs):
118
+ return args
119
+
120
+ return decor
@@ -0,0 +1,12 @@
1
+ """Module containing compatibility helpers for Qiskit aer."""
2
+
3
+ from qpi_driver.compat.shared import BasicCompatClass
4
+
5
+ try:
6
+ from qiskit_aer import AerSimulator
7
+
8
+ IS_AER_INSTALLED: bool = True
9
+ except ImportError:
10
+ IS_AER_INSTALLED: bool = False
11
+
12
+ class AerSimulator(BasicCompatClass): ...
@@ -0,0 +1,131 @@
1
+ """Module containing compatibility imports for quantify-related libraries"""
2
+
3
+ import logging
4
+ from enum import Enum
5
+ from typing import Any, TypeAlias
6
+
7
+ from qpi_driver.compat.shared import BasicCompatClass
8
+
9
+ try:
10
+ from pydantic import BaseModel, ImportString, field_validator
11
+ from qblox_instruments import Cluster, ClusterType, InstrumentType
12
+ from qcodes.instrument import InstrumentModule
13
+ from qcodes.instrument.base import Instrument
14
+ from qcodes.parameters import ParameterBase
15
+ from quantify_core.data.handling import set_datadir
16
+ from quantify_scheduler import Operation, Schedule
17
+ from quantify_scheduler.backends.graph_compilation import SerialCompiler
18
+ from quantify_scheduler.backends.qblox_backend import (
19
+ QbloxHardwareCompilationConfig,
20
+ )
21
+ from quantify_scheduler.backends.types.qblox import ClusterDescription
22
+ from quantify_scheduler.device_under_test.quantum_device import (
23
+ DeviceElement,
24
+ Edge,
25
+ QuantumDevice,
26
+ )
27
+ from quantify_scheduler.device_under_test.transmon_element import (
28
+ BasicTransmonElement,
29
+ )
30
+ from quantify_scheduler.instrument_coordinator import InstrumentCoordinator
31
+ from quantify_scheduler.operations.gate_library import (
32
+ CNOT,
33
+ CZ,
34
+ H,
35
+ Measure,
36
+ Reset,
37
+ Rxy,
38
+ Rz,
39
+ S,
40
+ SDagger,
41
+ T,
42
+ TDagger,
43
+ X,
44
+ Y,
45
+ Z,
46
+ )
47
+ from quantify_scheduler.operations.pulse_library import IdlePulse
48
+ from quantify_scheduler.qblox import ClusterComponent
49
+ from quantify_scheduler.schedules import Schedulable
50
+
51
+ IS_QUANTIFY_INSTALLED: bool = True
52
+
53
+ except ImportError as exp:
54
+ logging.debug(f"failed importing from quantify.compat {exp}")
55
+ IS_QUANTIFY_INSTALLED: bool = False
56
+
57
+ def set_datadir(*args, **kwargs):
58
+ pass
59
+
60
+ def field_validator(*args, **kwargs):
61
+ def decor(*args, **kwargs):
62
+ return args
63
+
64
+ return decor
65
+
66
+ QbloxHardwareCompilationConfig: TypeAlias = Any
67
+ ClusterComponent: TypeAlias = Any
68
+ InstrumentCoordinator: TypeAlias = Any
69
+ BasicTransmonElement: TypeAlias = Any
70
+ QuantumDevice: TypeAlias = Any
71
+ SerialCompiler: TypeAlias = Any
72
+ Cluster: TypeAlias = Any
73
+ ImportString: TypeAlias = Any
74
+ Schedulable: TypeAlias = Any
75
+
76
+ class DeviceElement(BasicCompatClass): ...
77
+
78
+ class Edge(BasicCompatClass): ...
79
+
80
+ class BaseModel(BasicCompatClass): ...
81
+
82
+ class CNOT(BasicCompatClass): ...
83
+
84
+ class CZ(BasicCompatClass): ...
85
+
86
+ class H(BasicCompatClass): ...
87
+
88
+ class Measure(BasicCompatClass): ...
89
+
90
+ class Reset(BasicCompatClass): ...
91
+
92
+ class Rxy(BasicCompatClass): ...
93
+
94
+ class Rz(BasicCompatClass): ...
95
+
96
+ class X(BasicCompatClass): ...
97
+
98
+ class Y(BasicCompatClass): ...
99
+
100
+ class Z(BasicCompatClass): ...
101
+
102
+ class S(BasicCompatClass): ...
103
+
104
+ class T(BasicCompatClass): ...
105
+
106
+ class SDagger(BasicCompatClass): ...
107
+
108
+ class TDagger(BasicCompatClass): ...
109
+
110
+ class IdlePulse(BasicCompatClass): ...
111
+
112
+ class InstrumentModule(BasicCompatClass): ...
113
+
114
+ class ParameterBase(BasicCompatClass): ...
115
+
116
+ class ClusterDescription(BasicCompatClass): ...
117
+
118
+ class InstrumentType(Enum): ...
119
+
120
+ class ClusterType(Enum): ...
121
+
122
+ class Operation(BasicCompatClass): ...
123
+
124
+ class Schedule(BasicCompatClass):
125
+ def add(self, *args, **kwargs):
126
+ pass
127
+
128
+ class Instrument(BasicCompatClass):
129
+ @classmethod
130
+ def close_all(cls):
131
+ pass
@@ -0,0 +1,6 @@
1
+ """Common compatibility utils"""
2
+
3
+
4
+ class BasicCompatClass:
5
+ def __init__(self, *args, **kwargs):
6
+ pass
@@ -0,0 +1,19 @@
1
+ """Module containing compatibility imports for typer-related libraries"""
2
+
3
+ from qpi_driver.compat.shared import BasicCompatClass
4
+
5
+ try:
6
+ from typer import Exit, Option, Typer, echo
7
+
8
+ IS_TYPER_INSTALLED: bool = True
9
+ except ImportError:
10
+ IS_TYPER_INSTALLED: bool = False
11
+
12
+ class Option(BasicCompatClass): ...
13
+
14
+ class Typer(BasicCompatClass): ...
15
+
16
+ class Exit(BasicCompatClass): ...
17
+
18
+ def echo(*args, **kwargs):
19
+ pass