Metadata-Version: 2.4
Name: qubecore-client
Version: 1.0.24
Summary: QubeCore Client SDK
License: MIT License
        
        Copyright (c) 2026 QubeCore Project
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: grpcio>=1.80.0
Requires-Dist: protobuf>=6.0.0
Requires-Dist: python-jose[cryptography]>=3.3.0
Provides-Extra: dev
Requires-Dist: grpcio-tools>=1.80.0; extra == 'dev'
Requires-Dist: mypy>=1.8.0; extra == 'dev'
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
Requires-Dist: pytest-mock>=3.12.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: python-jose[cryptography]>=3.3.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Description-Content-Type: text/markdown

# qubecore-client

Python client SDK for QubeCore — Quantum Computing Operating System.

[![PyPI](https://img.shields.io/pypi/v/qubecore-client)](https://pypi.org/project/qubecore-client/)
[![Python](https://img.shields.io/pypi/pyversions/qubecore-client)](https://pypi.org/project/qubecore-client/)

---

## Installation

```bash
pip install qubecore-client
```

---

## Quick Start

```python
from qubecore_client import login, QubeClient

access_token, refresh_tok = login("localhost:50051", "admin", "Admin1234!")
client = QubeClient(address="localhost:50051", token=access_token)

job_id = client.submit_gate_job(
    gate_circuits=["OPENQASM 2.0; include \"qelib1.inc\"; qreg q[2]; creg c[2]; h q[0]; cx q[0],q[1]; measure q->c;"],
    shots=1000,
)
print(client.get_job_result(job_id))
```

---

## Auth

```python
from qubecore_client import login, logout

# 로그인 — access token + refresh token 반환
access_token, refresh_tok = login(address, username, password)

# 로그아웃
logout(address, access_token)
```

---

## QubeClient

```python
client = QubeClient(address="localhost:50051", token=access_token)
client.set_token(new_token)  # 토큰 교체
client.close()               # 채널 종료
```

컨텍스트 매니저로도 사용 가능:

```python
with QubeClient(address="localhost:50051", token=access_token) as client:
    ...
```

---

## API

### User

| 메서드 | 설명 |
|--------|------|
| `get_me()` | 현재 유저 정보 반환 |
| `get_my_jobs(page, page_size)` | 내 잡 목록 반환 (기본: page=1, page_size=20) |

```python
info = client.get_me()
# {"user_id": "...", "username": "admin", "role": "admin", "created_at": "..."}

result = client.get_my_jobs(page=1, page_size=20)
# {"total": 42, "jobs": [{"job_id": "...", "type": "execute_gate", "status": "COMPLETED", ...}]}
```

---

### Submit

| 메서드 | 필수 파라미터 | 설명 |
|--------|--------------|------|
| `submit_gate_job()` | `gate_circuits`, `shots` | 게이트 회로 실행 |
| `submit_pulse_job()` | `pulse_circuits`, `shots` | 펄스 프로그램 실행 |
| `submit_reset_job()` | `qubits`, `shots` | 큐비트 액티브 리셋 |
| `submit_calibration_job()` | `calibration_type`, `params` | 캘리브레이션 |

모든 submit 메서드는 `job_id: str`을 반환합니다.  
공통 선택 파라미터: `priority: int` (1=CRITICAL 2=HIGH 3=NORMAL 4=LOW)

```python
# gate
job_id = client.submit_gate_job(
    gate_circuits=["OPENQASM 2.0; ..."],
    shots=1000,
    priority=2,
    optimization_level=1,  # 0~3, gate/stream만 해당
)

# pulse
job_id = client.submit_pulse_job(
    pulse_circuits=["..."],
    shots=1000,
)

# reset
job_id = client.submit_reset_job(
    qubits=["qubit_0", "qubit_1"],
    shots=100,
)

# calibration
job_id = client.submit_calibration_job(
    calibration_type="widescan",  # "widescan" | "punchout"
    params={"qubit": "qubit_0", "span": 100_000_000, "n_points": 200, "num_shots": 100},
)
```

---

### Job

| 메서드 | 설명 |
|--------|------|
| `get_job_status(job_id)` | 잡 상태 조회 |
| `get_job_result(job_id)` | 잡 결과 조회 |
| `cancel_job(job_id)` | 잡 취소 (PENDING 상태만 가능) |

```python
status = client.get_job_status(job_id)
# {"job_id": "...", "status": "COMPLETED", "priority": 3, "submitted_at": "...", ...}

result = client.get_job_result(job_id)
# gate/pulse/reset: {"job_id": "...", "status": "COMPLETED", "results": [{"counts": {...}, "s11": {...}, "qubit_mapping": {...}}]}
# calibration:      {"job_id": "...", "status": "COMPLETED", "calibration_result": {...}}

message = client.cancel_job(job_id)  # raises RuntimeError if not PENDING
```

---

### Stream

파라미터 스윕을 스트리밍으로 실행합니다. 각 iteration 결과를 즉시 yield합니다.

```python
for i, result in enumerate(client.stream_gate_job(
    circuit_template="OPENQASM 2.0; ...; rx({theta}) q[0]; ...",
    params_list=[{"theta": 0.0}, {"theta": 1.5707}, {"theta": 3.1415}],
    shots=200,
)):
    print(f"[{i+1}] counts={result['counts']}")
```

| 파라미터 | 필수 | 설명 |
|----------|:----:|------|
| `circuit_template` | ✅ | `{param}` 플레이스홀더가 있는 QASM 문자열 |
| `params_list` | ✅ | `list[dict[str, float]]` — iteration당 파라미터 딕셔너리 |
| `shots` | ✅ | iteration당 shot 수 |
| `priority` | — | 1~4 |
| `optimization_level` | — | 0~3 |

---

### Backend

| 메서드 | 설명 |
|--------|------|
| `get_backend_info()` | 백엔드 정보 조회 (이름, 큐비트 수, 커플링 맵, 게이트 목록) |
| `get_characterization()` | 큐비트 캐릭터라이제이션 조회 (T1, T2, 주파수) |
| `update_characterization(last_calibrated, qubits)` | 캐릭터라이제이션 업데이트 |
| `update_qchip(updates)` | QChip 파라미터 업데이트 |

```python
info = client.get_backend_info()
# {"name": "kreo.sc-20", "num_qubits": 20, "coupling_map": [...], "native_gates": [...], "qasm_supported_gates": [...]}

data = client.get_characterization()
# {"last_calibrated": "2026-05-13T00:00:00Z", "qubits": [{"index": 0, "t1": 1.1e-4, "t2": 9.8e-5, "frequency": 4.85e9}, ...]}

client.update_characterization(
    last_calibrated="2026-05-13T00:00:00Z",
    qubits=[{"index": 0, "t1": 1.1e-4, "t2": 9.8e-5, "frequency": 4.85e9}],
)

client.update_qchip([
    {
        "qubit": "qubit_0",
        "freq": 4.85e9,
        "readfreq": 6.5e9,
        "gates": [{"gate_name": "X90", "amp": 0.5, "twidth": 20e-9}],
    }
])
```

---

## Compatibility

| qubecore-client | qubecore |
|----------------|----------|
| 1.0.18+ | 1.x |

---

## License

MIT
