swbt-python 0.5.3__tar.gz → 0.6.0__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.
- {swbt_python-0.5.3 → swbt_python-0.6.0}/PKG-INFO +4 -4
- {swbt_python-0.5.3 → swbt_python-0.6.0}/README.md +1 -1
- {swbt_python-0.5.3 → swbt_python-0.6.0}/pyproject.toml +5 -5
- swbt_python-0.6.0/spec/complete/unit_086/NORMAL_INPUT_READINESS.md +297 -0
- swbt_python-0.6.0/spec/complete/unit_087/PYTHON_313_RUNTIME_FLOOR.md +187 -0
- swbt_python-0.6.0/spec/dev-journal.md +17 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/hardware-test-log.md +142 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/initial/api.md +12 -3
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/initial/architecture.md +4 -4
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/initial/lifecycle.md +13 -9
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/initial/protocol.md +1 -1
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/initial/testing.md +8 -4
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/gamepad/interface.py +18 -14
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/gamepad/runtime.py +93 -23
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/report_loop.py +11 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/gamepad_factory.py +21 -1
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/hardware/test_reply_holdoff.py +74 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/integration/test_examples.py +3 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/integration/test_switch_gamepad_fake_transport.py +374 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_ci_workflow.py +1 -1
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_package_metadata.py +13 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_report_loop.py +78 -0
- swbt_python-0.5.3/spec/dev-journal.md +0 -3
- {swbt_python-0.5.3 → swbt_python-0.6.0}/AGENTS.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/LICENSE +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/examples/hardware_bringup.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/examples/pairing_probe.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/examples/tap_a.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_001/M0_PROTOCOL_CORE.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_002/M1_SWITCH_GAMEPAD_FAKE_TRANSPORT.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_003/M2_BUMBLE_HID_TRANSPORT.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_004/M3_PAIRING_L2CAP.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_005/M4_SUBCOMMAND_RESPONDER_HARDWARE.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_006/M5_INPUT_OPERATION_API.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_007/M6_RECONNECT_KEYSTORE_DIAGNOSTICS.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_008/M7_PACKAGING_EXAMPLES_CLI.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_009/PORTING_SOURCE_AUDIT.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_010/DIAGNOSTICS_TRACE_SCHEMA.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_011/HARDWARE_TEST_LOG_MATRIX.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_012/INITIAL_RELEASE_GATE.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_013/POST_M5_INPUT_SEMANTIC_CHARACTERIZATION.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_014/DEVICE_CLOSE_GRACEFUL_DISCONNECT.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_015/CONTEXT_MANAGER_RESOURCE_SCOPE.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_016/JSON_KEY_STORE_CURRENT_PREVIOUS.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_017/SWITCH_GAMEPAD_API_HARDENING.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_018/KEY_STORE_TRANSPORT_BOUNDARY.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_019/TRANSPORT_RECONNECT_CONTRACT.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_020/STRUCTURAL_REFACTOR_BOUNDARIES.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_021/SWITCH_GAMEPAD_INPUT_API_CONTRACT.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_022/PUBLIC_API_USAGE_HARDWARE_DOCS.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_023/MKDOCS_DOCUMENTATION_SITE.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_024/STICK_INPUT_SHORTHAND_API.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_025/IMU_INPUT_SHORTHAND_API.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_026/LINUX_MACOS_ADAPTER_EXPERIMENTAL.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_027/ADAPTER_DISCOVERY_API.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_028/CONTROLLER_PROFILE_CUSTOMIZATION.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_029/CONTROLLER_PROFILE_INJECTION.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_030/JOYCON_PROFILE_IDENTITY_SPI.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_031/JOYCON_INPUT_REPORT_MAPPING.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_032/PROFILE_AWARE_SUBCOMMAND_STATE.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_033/PROFILE_AWARE_BUMBLE_SDP.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_034/JOYCON_CONVENIENCE_API_DOCS.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_035/JOYCON_DEVICE_INFO_ADDRESS_WIRING.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_036/JOYCON_SDP_IDENTITY_POLICY.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_037/JOYCON_DEFAULT_CONTROLLER_COLORS.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_038/REARCHITECTURE_DECISION_BOUNDARY_TESTS.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_039/CONTROLLER_RUNTIME_EXTRACTION.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_040/PUBLIC_CONTROLLER_API_MODEL.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_041/CONTROLLER_CONFIG_PROFILE_OWNERSHIP.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_042/INTERNAL_TRANSPORT_FACTORY.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_043/PROTOCOL_PROFILE_MODULE_SPLIT.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_044/REARCHITECTURE_DOCS_RELEASE_MATRIX.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_045/INTERNAL_API_BOUNDARY_CLEANUP.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_046/HARDWARE_PROFILE_TEST_SCENARIOS.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_047/VIRTUAL_GYRO_CALIBRATION.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_048/VIRTUAL_ACCELEROMETER_CALIBRATION.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_049/IMU_SESSION_AND_ENCODING_REDESIGN.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_050/DIRECT_REPORTING_TYPES.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_051/CSR_BD_ADDR_REWRITE_EXPERIMENT.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_052/EXP_LOCAL_ADDRESS_PROFILE.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_053/EXP_LOCAL_ADDRESS_PROFILE_JOYCON.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_054/EXP_LOCAL_ADDRESS_PROFILE_DIRECT.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_055/REMOVE_NATIVE_KEY_STORE_API.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_056/PAIRING_PROFILE_NAMING.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_057/PAIRING_PROFILE_CONTROLLER_KIND.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_058/MULTI_ADDRESS_RECONNECT.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_059/EXPERIMENTAL_DIRECT_SEND_TIMING_PROBE.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_060/HCI_ACL_COMPLETION_CORRELATION.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_061/EXPERIMENTAL_CLASSIC_LINK_POLICY_AB.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_062/PERIODIC_ACL_DRAIN_CHARACTERIZATION.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_063/PERIODIC_NO_DRAIN_CHARACTERIZATION.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_064/BUMBLE_ENQUEUE_COMPLETION_CONTRACT.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_065/PERIODIC_DEADLINE_SCHEDULER.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_066/PAIRING_PROFILE_DEFAULT_ADDRESS.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_067/DEFAULT_BATTERY_STATUS.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_068/DIRECT_PRE_CLOSE_INPUT_REFLECTION.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_069/CONTROLLER_HANDSHAKE_READINESS.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_070/DIAGNOSTICS_AND_UNUSED_PATHS_CLEANUP.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_071/CONTROLLER_CONSTRUCTION_PATH.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_072/CONNECTION_RUNTIME_INTEGRATION.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_073/TEST_CONTRACT_BOUNDARY_CLEANUP.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_074/PUBLIC_GAMEPAD_IMPLEMENTATION_OWNERSHIP.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_075/CONCRETE_CONTROLLER_MODULE.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_076/HARDWARE_HAPPY_CASE_VALIDATION.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_077/RUNTIME_INPUT_UPDATE_DISPATCH.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_078/TEST_RUNTIME_FIXTURES.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_079/PAIRING_PROFILE_KEY_STORE.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_080/TRANSPORT_PROTOCOL_CONTRACT.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_081/PROTOCOL_HANDSHAKE.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_082/REPLY_HOLDOFF_VALIDATION.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/complete/unit_083/PROFILE_SCHEMA_V2_CURRENT_KEY_ONLY.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/initial/README.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/initial/naming.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/initial/risks.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/initial/roadmap.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/initial/transport-bumble.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/rearchitecture/01-design-change-overview.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/rearchitecture/02-as-is-to-be.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/rearchitecture/03-public-api-config-profile.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/rearchitecture/04-runtime-profile-transport-details.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/rearchitecture/05-milestones-implementation.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/rearchitecture/README.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/rearchitecture/mkdocs-nav-snippet.yml +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/spec/wip/unit_084/BUMBLE_0_0_233.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/__init__.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/adapter_discovery.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/diagnostics.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/errors.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/gamepad/__init__.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/gamepad/_config.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/gamepad/connection.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/gamepad/constants.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/gamepad/controllers.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/gamepad/output.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/gamepad/protocol_handshake.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/gamepad/transport_factory.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/imu.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/input.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/probe.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/__init__.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/buttons.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/descriptors.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/imu_report.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/input_report.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/output_report.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/profiles/__init__.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/profiles/base.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/profiles/joycon.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/profiles/pro_controller.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/rumble.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/session.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/spi.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/protocol/subcommand.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/py.typed +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/state_store.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/__init__.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/_adapter_identity.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/_bumble_acl.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/_bumble_hidp.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/_bumble_key_store.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/_bumble_lifecycle.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/_bumble_sdp.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/_bumble_usb_devices.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/_csr_bd_addr.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/_csr_bd_addr_harness.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/_pairing_profile.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/base.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/bumble.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/src/swbt/transport/fake.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/__init__.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/conftest.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/hardware/README.md +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/hardware/test_battery_status.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/hardware/test_bumble_transport.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/hardware/test_close_disconnect.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/hardware/test_context_manager_resource_scope.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/hardware/test_controller_colors.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/hardware/test_multi_address_reconnect.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/hardware/test_pairing_l2cap.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/hardware/test_pairing_profile.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/integration/__init__.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/integration/test_pairing_profile.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/__init__.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/fixtures/source_audit/switch_protocol_values.toml +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_adapter_discovery.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_adapter_identity.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_bumble_acl.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_bumble_hidp.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_bumble_lifecycle.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_bumble_sdp.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_bumble_transport.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_csr_bd_addr_experiment.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_csr_bd_addr_harness.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_diagnostics.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_gamepad_config.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_gamepad_connection_workflow.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_gamepad_output_dispatcher.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_gamepad_transport_factory.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_imu_report.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_input_report.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_input_state.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_output_report.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_package_import.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_pairing_profile.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_pairing_profile_runtime.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_probe_cli.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_protocol_boundary.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_protocol_handshake.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_protocol_profile.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_protocol_session.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_public_api_boundary.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_publish_workflow.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_rumble_state.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_source_audit_fixtures.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_subcommand_responder.py +0 -0
- {swbt_python-0.5.3 → swbt_python-0.6.0}/tests/unit/test_virtual_spi_flash.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: swbt-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Python library for presenting an NX-compatible virtual Bluetooth HID input device.
|
|
5
5
|
Keywords: bluetooth,bluetooth-hid,controller,gamepad,hid,nx
|
|
6
6
|
Author: niart120
|
|
@@ -14,14 +14,14 @@ Classifier: Operating System :: MacOS
|
|
|
14
14
|
Classifier: Operating System :: Microsoft :: Windows
|
|
15
15
|
Classifier: Operating System :: POSIX :: Linux
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
19
|
Classifier: Topic :: Software Development :: Libraries
|
|
20
20
|
Classifier: Typing :: Typed
|
|
21
21
|
Requires-Dist: bumble==0.0.233
|
|
22
22
|
Maintainer: niart120
|
|
23
23
|
Maintainer-email: niart120 <38847256+niart120@users.noreply.github.com>
|
|
24
|
-
Requires-Python: >=3.
|
|
24
|
+
Requires-Python: >=3.13
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
26
26
|
|
|
27
27
|
# swbt-python
|
|
@@ -32,7 +32,7 @@ NX 向けの仮想 Bluetooth HID 入力デバイスを Python から扱うため
|
|
|
32
32
|
|
|
33
33
|
## 必要なもの
|
|
34
34
|
|
|
35
|
-
- Python 3.
|
|
35
|
+
- Python 3.13 以降
|
|
36
36
|
- uv
|
|
37
37
|
- Bumble が利用可能な専用 USB Bluetooth ドングル
|
|
38
38
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "swbt-python"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.6.0"
|
|
4
4
|
description = "Python library for presenting an NX-compatible virtual Bluetooth HID input device."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -9,7 +9,7 @@ authors = [
|
|
|
9
9
|
maintainers = [
|
|
10
10
|
{ name = "niart120", email = "38847256+niart120@users.noreply.github.com" }
|
|
11
11
|
]
|
|
12
|
-
requires-python = ">=3.
|
|
12
|
+
requires-python = ">=3.13"
|
|
13
13
|
license = "MIT"
|
|
14
14
|
license-files = ["LICENSE"]
|
|
15
15
|
keywords = [
|
|
@@ -28,8 +28,8 @@ classifiers = [
|
|
|
28
28
|
"Operating System :: Microsoft :: Windows",
|
|
29
29
|
"Operating System :: POSIX :: Linux",
|
|
30
30
|
"Programming Language :: Python :: 3",
|
|
31
|
-
"Programming Language :: Python :: 3.12",
|
|
32
31
|
"Programming Language :: Python :: 3.13",
|
|
32
|
+
"Programming Language :: Python :: 3.14",
|
|
33
33
|
"Topic :: Software Development :: Libraries",
|
|
34
34
|
"Typing :: Typed",
|
|
35
35
|
]
|
|
@@ -75,7 +75,7 @@ source-exclude = [
|
|
|
75
75
|
line-length = 100
|
|
76
76
|
required-version = ">=0.15.16"
|
|
77
77
|
src = ["src", "tests"]
|
|
78
|
-
target-version = "
|
|
78
|
+
target-version = "py313"
|
|
79
79
|
|
|
80
80
|
[tool.ruff.format]
|
|
81
81
|
docstring-code-format = true
|
|
@@ -130,7 +130,7 @@ strict = true
|
|
|
130
130
|
known-first-party = ["swbt"]
|
|
131
131
|
|
|
132
132
|
[tool.ty.environment]
|
|
133
|
-
python-version = "3.
|
|
133
|
+
python-version = "3.13"
|
|
134
134
|
root = ["./src"]
|
|
135
135
|
|
|
136
136
|
[tool.ty.src]
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# 通常入力 readiness 仕様書
|
|
2
|
+
|
|
3
|
+
## 1. 概要
|
|
4
|
+
|
|
5
|
+
### 1.1 目的
|
|
6
|
+
|
|
7
|
+
GitHub Issue #149 に従い、`pair()` / `reconnect()` などの接続 API が正常終了した時点で、
|
|
8
|
+
controller の通常入力経路が接続初期化中の automatic input holdoff によって抑止されない
|
|
9
|
+
契約を定義する。
|
|
10
|
+
|
|
11
|
+
Periodic / Direct は同じ公開契約を共有する。ただし、通常入力の送信主体は異なる。
|
|
12
|
+
Periodic は library の `ReportLoop`、Direct は呼び出し側の明示 input operation が送信を
|
|
13
|
+
所有する。このため、共通の完了条件を特定の periodic report の送信有無では定義しない。
|
|
14
|
+
|
|
15
|
+
### 1.2 起点 / source
|
|
16
|
+
|
|
17
|
+
| source | 内容 | path |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| GitHub Issue | Pair / active reconnect 完了直後の 50 ms press / release が、300 ms holdoff 中に local state 上で上書きされ、wire へ出ない | https://github.com/niart120/swbt-python/issues/149 |
|
|
20
|
+
| user decision | 「短時間入力を一度も欠落させない」キュー型契約には強めず、接続初期化由来の抑止だけを除く | conversation |
|
|
21
|
+
| current implementation | `ReportSender` は全 `0x21` reply 受理後に automatic input を 300 ms 抑止し、明示 input は抑止しない | `src/swbt/report_loop.py` |
|
|
22
|
+
| pre-change lifecycle | protocol ready で接続 waiter を起こした後、Periodic の `ReportLoop` を開始していた | 変更前の `src/swbt/gamepad/runtime.py` |
|
|
23
|
+
| prior validation | 300 ms は fake / hardware 比較後に維持され、ready 後の新規 subcommand は未観測 | `spec/complete/unit_082/REPLY_HOLDOFF_VALIDATION.md` |
|
|
24
|
+
| prior readiness contract | Periodic / Direct は supported report mode と nonzero player lights による protocol ready を共有する | `spec/complete/unit_069/CONTROLLER_HANDSHAKE_READINESS.md` |
|
|
25
|
+
|
|
26
|
+
### 1.3 use case
|
|
27
|
+
|
|
28
|
+
| actor / boundary | 入力または状態 | 期待する観測結果 | 制約 |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| Periodic controller 利用者 | `await pair()` / `await reconnect()` の直後に `apply()` し、既定 8 ms 周期より長い 50 ms 後に neutral へ戻す | 接続初期化で設定された holdoff に全送信機会を奪われず、通常 cadence の `0x30` に入力が現れる | 1周期未満の全 state 遷移配送は保証しない |
|
|
31
|
+
| Direct controller 利用者 | 接続 API 完了直後に `send()` または意味的入力操作を呼ぶ | protocol ready 後の明示 input が従来どおり transport へ送られる | Direct に automatic report や待機用 neutral probe を追加しない |
|
|
32
|
+
| diagnostics 利用者 | protocol ready から通常入力 readiness までを trace する | protocol handshake 完了と public 接続 API の完了境界を区別できる | report counter のポーリングを利用者へ要求しない |
|
|
33
|
+
| timeout / cancellation 利用者 | Periodic が protocol ready 後の holdoff 終了を待っている間に timeout、cancel、disconnect が起きる | 接続成功を返さず、既存の cleanup と失敗 semantics を維持する | 接続 timeout budget を新たに加算しない |
|
|
34
|
+
|
|
35
|
+
## 2. 対象範囲
|
|
36
|
+
|
|
37
|
+
- `pair()`、`reconnect()`、`connect()` と対応する `try_*` API の正常終了条件。
|
|
38
|
+
- これらへ委譲する `create_profile()` の object return 条件。
|
|
39
|
+
- protocol ready と通常入力 readiness の内部境界。
|
|
40
|
+
- Periodic の automatic input holdoff と接続完了の同期。
|
|
41
|
+
- Direct の明示 input 経路が同じ公開契約を満たすことの回帰確認。
|
|
42
|
+
- timeout、cancellation、disconnect、close、session reset。
|
|
43
|
+
- diagnostics、公開 API docstring、利用者向け docs、初期設計文書の整合。
|
|
44
|
+
- fake transport による Pair / active reconnect と全 controller profile の検証。
|
|
45
|
+
- Pro Controller の代表的な実機確認。
|
|
46
|
+
|
|
47
|
+
## 3. 対象外
|
|
48
|
+
|
|
49
|
+
- `apply()` の各 state 遷移をキューに保存し、必ず1回以上配送する機能。
|
|
50
|
+
- report period より短い press / release を含む全 transient input の配送保証。
|
|
51
|
+
- Periodic の latest-state coalescing semantics の変更。
|
|
52
|
+
- Direct に automatic `0x30`、待機用 neutral probe、`ReportLoop` を追加すること。
|
|
53
|
+
- 300 ms holdoff の値、開始条件、ready 後 subcommand への適用範囲の変更。
|
|
54
|
+
- steady-state report cadence、deadline scheduler、Bluetooth transport の変更。
|
|
55
|
+
- HID report ID、byte layout、timer、IMU encoding の変更。
|
|
56
|
+
- Joy-Con 実機確認。共通 runtime / sender 以外へ変更が及ぶ場合は実機要否を再評価する。
|
|
57
|
+
|
|
58
|
+
## 4. 関連 docs
|
|
59
|
+
|
|
60
|
+
- `spec/initial/api.md`
|
|
61
|
+
- `spec/initial/architecture.md`
|
|
62
|
+
- `spec/initial/lifecycle.md`
|
|
63
|
+
- `spec/initial/protocol.md`
|
|
64
|
+
- `spec/initial/testing.md`
|
|
65
|
+
- `spec/initial/risks.md`
|
|
66
|
+
- `spec/complete/unit_069/CONTROLLER_HANDSHAKE_READINESS.md`
|
|
67
|
+
- `spec/complete/unit_081/PROTOCOL_HANDSHAKE.md`
|
|
68
|
+
- `spec/complete/unit_082/REPLY_HOLDOFF_VALIDATION.md`
|
|
69
|
+
- `spec/hardware-test-log.md`
|
|
70
|
+
|
|
71
|
+
## 5. 根拠監査
|
|
72
|
+
|
|
73
|
+
| 項目 | 要否 | 状態 | 根拠 / 理由 |
|
|
74
|
+
|---|---|---|---|
|
|
75
|
+
| 300 ms automatic input holdoff | required | done | unit_082 で implementation fact と実機比較を記録済み。値と適用範囲は変更しない |
|
|
76
|
+
| Switch HID / report bytes | not applicable | not applicable | `0x21` / `0x30` の ID、layout、payload を変更しない |
|
|
77
|
+
| Bumble / transport | not applicable | not applicable | transport の受理契約と実装を変更しない |
|
|
78
|
+
| OS / driver / adapter | required | done | no-open列挙とPnP driver情報で、Windows 11、`usb:0`、CSR8510 A10 `0A12:0001`、WinUSB / libwdiを実行直前に確認 |
|
|
79
|
+
|
|
80
|
+
### 5.1 事実
|
|
81
|
+
|
|
82
|
+
- `send_subcommand_reply()` は transport の受理後に holdoff deadline を更新する。
|
|
83
|
+
- `send_automatic_input()` は同じ sender lock 内で deadline を検査し、期限前は送信しない。
|
|
84
|
+
- Direct の `send_input()` は automatic input ではなく、holdoff を検査しない。
|
|
85
|
+
- protocol ready を成立させる最後の reply 自身が holdoff deadline を更新する。
|
|
86
|
+
- 変更前の runtime は接続 waiter を起こしてから Periodic の `ReportLoop` を開始していた。
|
|
87
|
+
|
|
88
|
+
### 5.2 推論
|
|
89
|
+
|
|
90
|
+
- public 接続 API の完了条件を「最初の periodic `0x30` 送信」にすると、automatic report を
|
|
91
|
+
持たない Direct では成立しない。
|
|
92
|
+
- 共通契約は report の有無ではなく、「その reporting mode の通常入力経路が接続初期化由来の
|
|
93
|
+
抑止を受けない状態」として定義できる。
|
|
94
|
+
- Periodic では protocol ready 時点の holdoff deadline だけを snapshot して待つと、待機中に
|
|
95
|
+
受理した追加 reply が deadline を延長する競合を見落とす。readiness 公開前に受理された
|
|
96
|
+
最新 reply の deadline を反映する必要がある。
|
|
97
|
+
|
|
98
|
+
### 5.3 未検証
|
|
99
|
+
|
|
100
|
+
- protocol ready 後に Switch が新しい subcommand を送る条件と頻度は未確認である。
|
|
101
|
+
- 接続完了後に届いた新しい reply が automatic input を再び一時抑止する挙動は、本仕様で変更しない。
|
|
102
|
+
- active reconnect、Joy-Con、別adapter、別OS、別firmwareでの修正後50 ms inputは未検証である。
|
|
103
|
+
|
|
104
|
+
## 6. 振る舞い仕様
|
|
105
|
+
|
|
106
|
+
| 振る舞い | 入力・状態 | 期待結果 | 備考 |
|
|
107
|
+
|---|---|---|---|
|
|
108
|
+
| protocol ready | supported report mode と nonzero player lights が揃い、成立させた reply が transport に受理される | protocol handshake を停止・回収し、通常入力 readiness の評価へ進む | protocol ready 自体の predicate は変更しない |
|
|
109
|
+
| Periodic readiness 待機 | protocol ready だが最新 reply の automatic input holdoff 中 | public 接続成功を返さず、connection state は接続処理中のままとする | 外部の固定 sleep や report counter polling は不要 |
|
|
110
|
+
| Periodic readiness 成立 | readiness 公開前に受理された最新 reply の holdoff deadline に到達する | `ReportLoop` を開始してから接続成功を公開する | probe report の成功を条件にしない |
|
|
111
|
+
| Periodic 最初の通常 cadence | 接続 API 完了後に local state が更新される | 次の通常 cadence から latest state を送信対象にできる | 各 state の配送保証ではない |
|
|
112
|
+
| Direct readiness 成立 | protocol ready に到達する | 明示 input 経路が holdoff 対象外であるため、同じ接続成功契約を直ちに満たす | automatic deadline の経過を待たない |
|
|
113
|
+
| Direct 無送信 | Direct の接続 API が完了する | 待機確認のための `0x30` を自動送信しない | lifecycle 全体で ReportLoop を持たない |
|
|
114
|
+
| 追加 reply | Periodic が readiness 待機中に新しい reply を transport が受理する | 待機 deadline を最新値へ延長し、古い deadline では成功を公開しない | holdoff 更新と readiness 公開を競合させない |
|
|
115
|
+
| readiness 公開後の reply | 接続 API 完了後に新しい reply を受理する | 既存方針どおり automatic input holdoff を適用できる | 永続的な「無抑止」は保証しない |
|
|
116
|
+
| timeout | Periodic が readiness 待機中に接続操作の既存 deadline を超える | timeout として失敗し、cleanup する | 300 msを別 budget として加算しない |
|
|
117
|
+
| cancellation | readiness 待機中の接続 task を cancel する | readiness waiter と接続処理を停止し、既存 cancellation / cleanup semantics を維持する | background waiter を残さない |
|
|
118
|
+
| disconnect | readiness 公開前に link が切れる | 接続成功を返さず、失敗として待機 API を起こす | stale deadline を次 session へ持ち越さない |
|
|
119
|
+
| session reset | close 後に再度 open / pair / reconnect する | 前 session の holdoff deadline と readiness を再利用しない | sender は session 単位 |
|
|
120
|
+
| 50 ms入力 | 既定 8 ms Periodic の接続 API 完了直後に press、50 ms後に release | 初期化 holdoff に全 cadence を抑止されず、press state の periodic `0x30` が1件以上観測できる | 50 msという検証条件であり、任意の短時間入力保証ではない |
|
|
121
|
+
|
|
122
|
+
## 7. TDD Test List
|
|
123
|
+
|
|
124
|
+
| status | item | type | layer | hardware | notes |
|
|
125
|
+
|---|---|---|---|---|---|
|
|
126
|
+
| green | reply 受理直後の Periodic 通常入力 readiness は holdoff 期限前に成立せず、境界時刻で成立する | new | unit | no | 注入時計で wall clock 非依存に確認 |
|
|
127
|
+
| green | readiness 待機中に追加 reply を受理すると、古い期限では成立せず最新期限まで待つ | edge | unit | no | deadline snapshot ではなく最新値を再評価 |
|
|
128
|
+
| green | protocol ready 後も holdoff 中の Periodic `pair()` は完了せず、期限到達後に完了する | regression | integration | no | controlled readiness gate で Pair 経路を確認 |
|
|
129
|
+
| green | Periodic active reconnect は protocol ready 後の holdoff 終了まで `status="connected"` を返さない | regression | integration | no | controlled readiness gate で `try_reconnect()` を確認 |
|
|
130
|
+
| green | Direct の Pair / active reconnect は protocol ready で完了し、holdoff 経過や automatic `0x30` を要求しない | regression | integration | no | Pro / Joy-Con L/R を parameterize |
|
|
131
|
+
| green | `connect()`、`try_connect()`、`create_profile()` は選択した Pair / reconnect と同じ通常入力 readiness を使う | regression | integration | no | connect 2入口と6具象create_profileのpair委譲を確認 |
|
|
132
|
+
| green | Periodic の接続完了直後に50 ms保持した stateが通常 cadence の `0x30` に現れる | regression | integration | no | 既定8 msのButton Aとneutralを確認。全transient配送へ一般化しない |
|
|
133
|
+
| green | readiness 待機中の timeout は成功を返さず既存 cleanup を完了する | edge | integration | no | timeout 後close、`stage=input_readiness`、次回Pairのfresh readinessを確認 |
|
|
134
|
+
| green | readiness 待機中の cancellation / disconnect は waiter を残さず、次 session が stale readiness を再利用しない | edge | integration | no | cancellation red後にwaiter回収を追加。disconnect失敗の`stage=input_readiness`も確認 |
|
|
135
|
+
| green | Pro Controller の Pair または active reconnect 完了直後の50 ms Button Aがperiodic `0x30`とSwitch UIに反映される | characterization | hardware | yes | fresh PairでA付き周期`0x30`を7件記録し、利用者が対象機器側の反映を確認 |
|
|
136
|
+
|
|
137
|
+
## 8. 文書検証計画
|
|
138
|
+
|
|
139
|
+
| document | audience / task | source of truth | mechanical check | review result | unresolved |
|
|
140
|
+
|---|---|---|---|---|---|
|
|
141
|
+
| `spec/initial/api.md` | 接続 API 完了後に入力を開始する利用者 | 本仕様 §6 | `uv run --group docs mkdocs build --strict` | pass | Periodic / Direct 共通契約と方式差を反映。未解決なし |
|
|
142
|
+
| `spec/initial/architecture.md` | runtime と report loop の所有境界を確認する maintainer | 本仕様 §6 / §9 | `uv run --group docs mkdocs build --strict` | pass | report loop の開始時点を通常入力 readiness と一致。未解決なし |
|
|
143
|
+
| `spec/initial/lifecycle.md` | maintainer が protocol ready と通常入力 readiness の順序を追う | 本仕様 §6 / §9 | `uv run --group docs mkdocs build --strict` | pass | timeout / disconnect を含む状態遷移を反映。未解決なし |
|
|
144
|
+
| `spec/initial/testing.md` | fake / hardware test の分担を確認する maintainer | 本仕様 §7 | `uv run --group docs mkdocs build --strict` | pass | 50 ms は代表条件であり全 transient 保証ではないと明記。未解決なし |
|
|
145
|
+
| public API docstring / `docs/api.md` / `docs/usage.md` / `docs/release-notes.md` / `docs/hardware.md` | 接続後に入力する利用者と実機確認担当者 | 本仕様 §6 / §7、`spec/hardware-test-log.md` | docs build + `docs-quality-review` | pass | 契約、非保証、50 ms実機観測、未確認範囲を照合。must-fix なし |
|
|
146
|
+
|
|
147
|
+
自然言語の意味要件を固定語句の存在・不在 assertion に置き換えない。公開文書の事実性、
|
|
148
|
+
操作順、未保証範囲は正本との照合と `docs-quality-review` で確認する。
|
|
149
|
+
|
|
150
|
+
## 9. 設計メモ
|
|
151
|
+
|
|
152
|
+
### 9.1 共通契約
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
connection API success
|
|
156
|
+
implies
|
|
157
|
+
the reporting mode's normal input path is not blocked
|
|
158
|
+
by a holdoff already created during connection initialization
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
「通常入力経路」は reporting mode ごとに次を指す。
|
|
162
|
+
|
|
163
|
+
| reporting mode | 通常入力経路 | readiness の具体条件 |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| Periodic | local latest stateを通常 cadence で送る `ReportLoop` | readiness 公開前に受理された最新 reply の automatic input holdoff が終了済み |
|
|
166
|
+
| Direct | `send()` と意味的 input operation による明示送信 | protocol ready で明示 input sender が利用可能 |
|
|
167
|
+
|
|
168
|
+
この違いは公開契約の差ではなく、送信所有者の違いである。
|
|
169
|
+
|
|
170
|
+
### 9.2 `connected` の意味
|
|
171
|
+
|
|
172
|
+
`connected` と接続 API の正常終了は、protocol ready だけでなく通常入力 readiness も満たす。
|
|
173
|
+
diagnostics では次を分ける。
|
|
174
|
+
|
|
175
|
+
- `protocol_ready`: handshake predicate を成立させた reply が受理され、handshake task を
|
|
176
|
+
停止・回収した時点。
|
|
177
|
+
- `input_ready`: reporting mode ごとの通常入力 readiness が成立した時点。
|
|
178
|
+
- `active_reconnect_result(status="connected")`: `input_ready` 後。
|
|
179
|
+
|
|
180
|
+
Direct では `protocol_ready` と `input_ready` が連続して記録される。Periodic では通常、
|
|
181
|
+
最後の初期化 reply が設定した holdoff の残り時間だけ間隔が空く。
|
|
182
|
+
|
|
183
|
+
`input_ready` を接続成功の linearization point とする。sender の同期境界でこれより前に
|
|
184
|
+
受理された reply は readiness 待機へ反映し、これより後に受理された reply は接続後の
|
|
185
|
+
通常処理として扱う。coroutine を再開する wall-clock 上の瞬間と Bluetooth event の到着を
|
|
186
|
+
完全に排他する保証は置かない。
|
|
187
|
+
|
|
188
|
+
### 9.3 holdoff と readiness の同期
|
|
189
|
+
|
|
190
|
+
readiness 判定は、holdoff deadline の単発 snapshot や `sleep(0.3)` で実装しない。
|
|
191
|
+
subcommand reply の transport 受理、deadline 更新、readiness の再評価を同じ sender の
|
|
192
|
+
同期境界で順序付ける。
|
|
193
|
+
|
|
194
|
+
readiness 公開前に追加 reply が受理された場合、その reply が更新した deadline を待つ。
|
|
195
|
+
readiness 公開後に受理された reply は既存の automatic input holdoff として扱う。本仕様は
|
|
196
|
+
ready 後 holdoff の廃止や initializing 限定化を行わない。
|
|
197
|
+
|
|
198
|
+
### 9.4 ReportLoop の開始
|
|
199
|
+
|
|
200
|
+
Periodic の `ReportLoop` は通常入力 readiness 成立後に開始する。接続完了確認のための
|
|
201
|
+
neutral probe は送らない。loop の最初の deadline は開始時刻から `report_period_us` 後とし、
|
|
202
|
+
接続完了直後の `apply()` はその時点の latest state を次回 cadence の候補にする。
|
|
203
|
+
|
|
204
|
+
Direct は lifecycle 全体で通常 `ReportLoop` を持たない。handshake 中の
|
|
205
|
+
`handshake_bootstrap` / `handshake_report_mode` は `ProtocolHandshake` が所有する内部
|
|
206
|
+
automatic neutral であり、Direct の通常入力には数えない。
|
|
207
|
+
|
|
208
|
+
### 9.5 transient input の境界
|
|
209
|
+
|
|
210
|
+
Periodic は latest-state model を維持する。複数の `apply()` が同じ通常 cadence より前に
|
|
211
|
+
完了した場合、中間 state は後続 state に統合され得る。これを欠落防止 queue へ変更しない。
|
|
212
|
+
|
|
213
|
+
Issue #149 の 50 ms / 8 ms は通常なら複数 cadence を含むため、接続初期化 holdoff による
|
|
214
|
+
全機会の抑止を検出する代表条件として使う。50 msを任意の環境、任意の period に対する
|
|
215
|
+
最小配送時間として公開しない。
|
|
216
|
+
|
|
217
|
+
## 10. 対象ファイル
|
|
218
|
+
|
|
219
|
+
| path | change | 内容 |
|
|
220
|
+
|---|---|---|
|
|
221
|
+
| `src/swbt/report_loop.py` | modify | automatic input readiness の待機と reply deadline 更新の同期 |
|
|
222
|
+
| `src/swbt/gamepad/runtime.py` | modify | protocol ready 後の mode 別 readiness、event、timeout、cleanup、diagnostics |
|
|
223
|
+
| `src/swbt/gamepad/interface.py` | modify | 公開接続 API docstring の readiness 契約 |
|
|
224
|
+
| `tests/unit/test_report_loop.py` | modify | deadline 境界と追加 reply の決定的 unit test |
|
|
225
|
+
| `tests/integration/test_switch_gamepad_fake_transport.py` | modify | Pair / reconnect / Direct / Periodic / failure lifecycle |
|
|
226
|
+
| `tests/hardware/test_reply_holdoff.py` | modify | fresh Pair 完了直後50 ms入力の実機 gate |
|
|
227
|
+
| `spec/initial/api.md` | modify | 接続成功後の通常入力契約 |
|
|
228
|
+
| `spec/initial/architecture.md` | modify | ReportLoop の生成時点と runtime の wait 所有 |
|
|
229
|
+
| `spec/initial/lifecycle.md` | modify | protocol ready と input ready の状態遷移 |
|
|
230
|
+
| `spec/initial/protocol.md` | modify | holdoff 対象となる ReportLoop の開始境界を明確化 |
|
|
231
|
+
| `spec/initial/testing.md` | modify | fake / hardware completion gate |
|
|
232
|
+
| `docs/api.md` | modify | 利用者向け接続 API 説明 |
|
|
233
|
+
| `docs/usage.md` | modify | 接続後の入力開始手順と latest-state の非保証 |
|
|
234
|
+
| `docs/release-notes.md` | modify | 修正内容、互換境界、実機未確認範囲 |
|
|
235
|
+
| `docs/hardware.md` | modify | `protocol_ready` と `input_ready` の診断手順 |
|
|
236
|
+
| `spec/hardware-test-log.md` | modify | 承認後の実機条件と結果 |
|
|
237
|
+
|
|
238
|
+
実装時に実ファイル構成を再確認し、内部 helper 名をこの表へ合わせるためだけの変更は行わない。
|
|
239
|
+
|
|
240
|
+
## 11. 検証
|
|
241
|
+
|
|
242
|
+
| command | result | notes |
|
|
243
|
+
|---|---|---|
|
|
244
|
+
| `git diff --no-index --check -- NUL spec/complete/unit_086/NORMAL_INPUT_READINESS.md` | pass | 新規 untracked spec に whitespace error なし。差分ありを表す exit 1、error output なし |
|
|
245
|
+
| `uv run pytest tests/unit/test_report_loop.py::test_automatic_input_readiness_waits_until_reply_holdoff_boundary -q` | pass | red は `_sleep` 未対応の `TypeError`、green は `1 passed` |
|
|
246
|
+
| `uv run pytest tests/unit/test_report_loop.py -q` | pass | first cycle 後 `11 passed` |
|
|
247
|
+
| `uv run pytest tests/unit/test_report_loop.py::test_additional_reply_extends_automatic_input_readiness_wait -q` | pass | first cycle の再評価 loop で green、`1 passed` |
|
|
248
|
+
| targeted Pair / Direct readiness integration | pass | Periodic red は waiter 未呼び出しで timeout。runtime 分離後、既存境界を含め `9 passed` |
|
|
249
|
+
| targeted active reconnect readiness integration | pass | Periodic `1 passed`、Direct Pro / Joy-Con L/R `3 passed` |
|
|
250
|
+
| `uv run pytest tests/integration/test_switch_gamepad_fake_transport.py::test_periodic_input_after_pair_is_not_blocked_by_initialization_holdoff -q` | pass | 接続完了後50 msのButton Aと後続neutralをperiodic `0x30`で確認 |
|
|
251
|
+
| targeted timeout / cancellation / disconnect readiness integration | pass | timeout後の再Pair、task cancellation、disconnect、既存reconnect cancellationを含む `4 passed` |
|
|
252
|
+
| targeted connect / create_profile delegation integration | pass | connect 2入口と6具象create_profileのpair委譲、計 `8 passed` |
|
|
253
|
+
| `uv run ruff format --check .` | pass | `106 files already formatted` |
|
|
254
|
+
| `uv run ruff check .` | pass | `All checks passed!` |
|
|
255
|
+
| `uv run ty check --no-progress` | pass | `All checks passed!` |
|
|
256
|
+
| `uv run pytest tests/unit` | pass | final gateは`450 passed in 2.09s` |
|
|
257
|
+
| `uv run pytest tests/integration` | pass | final gateは`165 passed in 3.05s` |
|
|
258
|
+
| `uv run --group docs mkdocs build --strict` | pass | strict build 成功 |
|
|
259
|
+
| `uv run pytest --collect-only tests/hardware/test_reply_holdoff.py -q` | pass | 修正後harnessを含む10件を収集。adapter / Switch は開いていない |
|
|
260
|
+
| approved Pro Controller fresh Pair hardware gate | observed-pass | commandはdiagnostics reasonのtest bugで`1 failed in 5.58s`。artifactはA付き周期`0x30`を7件、neutral、cleanupを記録し、利用者がUI反映を確認。test bugは`reason=periodic`へ修正 |
|
|
261
|
+
| hardware artifact review | pass | debug PDUのtimer `0x15`–`0x1B`でButton A bitを7件、次のtimer `0x1C`でneutralを確認 |
|
|
262
|
+
|
|
263
|
+
## 12. 実機実行条件
|
|
264
|
+
|
|
265
|
+
| 項目 | 内容 |
|
|
266
|
+
|---|---|
|
|
267
|
+
| 実機要否 | required for completion |
|
|
268
|
+
| 承認範囲 | Pro Controller の Pair または active reconnect、HID advertising、subcommand handling、通常 periodic report、50 ms Button A press / release、neutral close、adapter release |
|
|
269
|
+
| adapter | 実行直前に対象 adapter、identity、driver を確認する。過去の `usb:0` / CSR8510 A10 / WinUSB を現在値として仮定しない |
|
|
270
|
+
| 実行遮断 | 環境変数による遮断は採用しない。明示承認、対象 adapter、command、Switch-facing 動作、cleanup plan で管理する |
|
|
271
|
+
| log / artifact | OS、Python / Bumble / swbt-python version、Switch model / firmware、profile / route、`protocol_ready`、`input_ready`、reply、periodic `0x30`、UI 観測を保存する |
|
|
272
|
+
| cleanup | neutral、ReportLoop停止、disconnect、transport close、adapter release。失敗時も同じ項目を確認する |
|
|
273
|
+
| 実行結果 | fresh Pairでobserved-pass。詳細は`spec/hardware-test-log.md`の2026-07-26 unit_086記録 |
|
|
274
|
+
|
|
275
|
+
実機 test は自動 trace の periodic `0x30` と利用者による Switch UI 観測を分けて記録する。
|
|
276
|
+
明示承認なしに `bumble` / `hardware` marker を実行しない。
|
|
277
|
+
|
|
278
|
+
## 13. 先送り事項
|
|
279
|
+
|
|
280
|
+
- ready 後 subcommand の発生条件と、steady-state holdoff の必要性。観測できた場合は unit_082
|
|
281
|
+
の後続として別 work unit / Issue に分ける。
|
|
282
|
+
- 各 Periodic state 遷移を配送する queue。latest-state API の別契約になるため本仕様には含めない。
|
|
283
|
+
- report period に対する最小 transient input duration の公開保証。OS / scheduler / transport を
|
|
284
|
+
含む保証設計が必要なため本仕様には含めない。
|
|
285
|
+
|
|
286
|
+
## 14. チェックリスト
|
|
287
|
+
|
|
288
|
+
- [x] 対象範囲と対象外を確認した
|
|
289
|
+
- [x] Periodic / Direct に等価な公開契約を定義した
|
|
290
|
+
- [x] 「最初の periodic `0x30`」を共通 completion gate から除外した
|
|
291
|
+
- [x] transient input の全配送を対象外として明記した
|
|
292
|
+
- [x] TDD Test List を作成した
|
|
293
|
+
- [x] 必要な根拠監査を記録した
|
|
294
|
+
- [x] 実機実行条件を記録した
|
|
295
|
+
- [x] 実装と local gate を完了した
|
|
296
|
+
- [x] 公開文書を更新し `docs-quality-review` を完了した
|
|
297
|
+
- [x] 明示承認付き実機 gate を完了した
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Python 3.13 最低実行バージョン仕様書
|
|
2
|
+
|
|
3
|
+
## 1. 概要
|
|
4
|
+
|
|
5
|
+
### 1.1 目的
|
|
6
|
+
|
|
7
|
+
Windows上のPython 3.12では、`time.monotonic_ns()`と`asyncio` event loopが
|
|
8
|
+
`GetTickCount64()`の15.625 ms分解能に制約され、8 ms周期のquaternion IMU入力に
|
|
9
|
+
カクつきが発生した。report生成やevent loopへ個別の時計補正を入れず、最低実行
|
|
10
|
+
バージョンをPython 3.13へ引き上げる。CIでは最低バージョンの3.13と次の安定版
|
|
11
|
+
3.14を検証する。
|
|
12
|
+
|
|
13
|
+
### 1.2 起点 / source
|
|
14
|
+
|
|
15
|
+
| source | 内容 | path |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| GitHub Issue | 8 ms送信時の周期的なカクつきとHCI credit仮説 | `https://github.com/niart120/swbt-python/issues/152` |
|
|
18
|
+
| hardware observation | Python 3.12.10では8 ms区間がカクつき、Python 3.13.5では同条件でカクつきなし | `spec/hardware-test-log.md` |
|
|
19
|
+
| local characterization | Python 3.12.10の`monotonic_ns()`は15.625 ms分解能、Python 3.13.5は100 ns分解能 | 2026-07-27のruntime比較 |
|
|
20
|
+
| user decision | clock実装を変更せず、最低Pythonを3.13へ引き上げ、CIへ3.14を追加する | 2026-07-27 |
|
|
21
|
+
|
|
22
|
+
### 1.3 use case
|
|
23
|
+
|
|
24
|
+
| actor / boundary | 入力または状態 | 期待する観測結果 | 制約 |
|
|
25
|
+
|---|---|---|---|
|
|
26
|
+
| package利用者 | Python 3.13以上でinstallする | package metadataが対応runtimeを明示する | Python 3.12は対応対象外 |
|
|
27
|
+
| contributor | CIを実行する | Python 3.13 / 3.14のunit、integration、buildを検証する | hardware gateは含めない |
|
|
28
|
+
| Direct / Periodic利用者 | 8 ms周期の入力を扱う | CPython 3.13以降の高分解能なmonotonic clockを利用する | OS負荷による起床遅延までは保証しない |
|
|
29
|
+
|
|
30
|
+
## 2. 対象範囲
|
|
31
|
+
|
|
32
|
+
- `requires-python`を`>=3.13`へ変更する。
|
|
33
|
+
- Python classifierを3.13 / 3.14へ揃える。
|
|
34
|
+
- RuffとtyのPython対象バージョンを3.13へ変更する。
|
|
35
|
+
- CI matrixをPython 3.13 / 3.14へ変更する。
|
|
36
|
+
- Bumble canaryを最低対応バージョンのPython 3.13で実行する。
|
|
37
|
+
- READMEと実機準備文書の必要Pythonバージョンを3.13へ変更する。
|
|
38
|
+
- lockfileのPython要件を更新する。
|
|
39
|
+
- package versionを0.6.0へ更新し、互換性変更と実機確認範囲をrelease notesへ記載する。
|
|
40
|
+
- Issue #152の実験用HCI / USB probeと実機観測を記録する。
|
|
41
|
+
|
|
42
|
+
## 3. 対象外
|
|
43
|
+
|
|
44
|
+
- `ReportSender`、`ReportLoop`、Bumble、`asyncio` event loopのclock変更。
|
|
45
|
+
- Python 3.12互換性の維持。
|
|
46
|
+
- 8 ms周期やOS scheduler精度の保証。
|
|
47
|
+
- HID report layout、IMU packing、既定report周期の変更。
|
|
48
|
+
- Bluetooth air capture、別adapter、別OS、別Switch firmwareへの一般化。
|
|
49
|
+
- TestPyPI / PyPI publish、tag、GitHub Release作成。
|
|
50
|
+
|
|
51
|
+
## 4. 関連 docs
|
|
52
|
+
|
|
53
|
+
- `README.md`
|
|
54
|
+
- `spec/initial/testing.md`
|
|
55
|
+
- `spec/initial/risks.md`
|
|
56
|
+
- `spec/complete/unit_049/IMU_SESSION_AND_ENCODING_REDESIGN.md`
|
|
57
|
+
- `spec/complete/unit_065/PERIODIC_DEADLINE_SCHEDULER.md`
|
|
58
|
+
|
|
59
|
+
## 5. 根拠監査
|
|
60
|
+
|
|
61
|
+
| 項目 | 要否 | 状態 | 根拠 / 理由 |
|
|
62
|
+
|---|---|---|---|
|
|
63
|
+
| Switch HID / report bytes | not required | done | report生成実装とbyte layoutは変更しない |
|
|
64
|
+
| Bumble / transport | required | done | Bumble 0.0.230 / 0.0.233差では症状が変わらず、credit待ち最大0を実測した |
|
|
65
|
+
| Python clock | required | done | 対象Windows環境で3.12.10と3.13.5のclock implementationと分解能を取得した |
|
|
66
|
+
| OS / driver / adapter | required for observation | done | Windows 11 / CSR8510 A10 / WinUSB / `usb:0`で比較した。別環境へ一般化しない |
|
|
67
|
+
|
|
68
|
+
### 根拠監査の結果
|
|
69
|
+
|
|
70
|
+
| 項目 | 値 / 判断 | 根拠分類 | source | status |
|
|
71
|
+
|---|---|---|---|---|
|
|
72
|
+
| Python 3.12.10 Windows monotonic | `GetTickCount64()`、分解能15.625 ms | runtime fact | `time.get_clock_info("monotonic")` | done |
|
|
73
|
+
| Python 3.13.5 Windows monotonic | `QueryPerformanceCounter()`、分解能100 ns | runtime fact | `time.get_clock_info("monotonic")` | done |
|
|
74
|
+
| Python / Bumble比較 | 3.12.10ではBumble 0.0.230 / 0.0.233の両方でカクつき、3.13.5 / 0.0.230ではカクつきなし | hardware observation | 実機matrix | done |
|
|
75
|
+
| HCI credit | 対象runのBumble queue待機packet最大0 | hardware observation | HCI credit probe | done |
|
|
76
|
+
| clock修正案 | `ReportSender`と`ReportLoop`の`perf_counter_ns()`化でPeriodicは滑らかになったが、Directはcaller schedulerの補正も必要だった | experimental observation | 修正後route比較 | done |
|
|
77
|
+
| final disposition | clock修正を製品へ採用せず、Python 3.13を最低対応runtimeとする | decision | user decision | done |
|
|
78
|
+
|
|
79
|
+
## 6. 振る舞い仕様
|
|
80
|
+
|
|
81
|
+
| 振る舞い | 入力・状態 | 期待結果 | 備考 |
|
|
82
|
+
|---|---|---|---|
|
|
83
|
+
| package runtime floor | package metadataを読む | `requires-python`が`>=3.13` | Python 3.12へのinstallを拒否する |
|
|
84
|
+
| supported classifiers | PyPI metadataを読む | Python 3.13 / 3.14を列挙し、3.12を列挙しない | 実機互換性の保証ではない |
|
|
85
|
+
| CI matrix | GitHub Actions CIを実行する | Ubuntu / macOSの各OSで3.13 / 3.14を検証する | Bumble / hardware testは実行しない |
|
|
86
|
+
| static target | Ruff / tyを実行する | 最低対応バージョン3.13を基準に解析する | 新しい構文の採用を要求しない |
|
|
87
|
+
| clock implementation | controllerを利用する | 既存の`monotonic_ns()`とclock注入境界を維持する | clockのglobal差し替えを行わない |
|
|
88
|
+
|
|
89
|
+
## 7. TDD Test List
|
|
90
|
+
|
|
91
|
+
| status | item | type | layer | hardware | notes |
|
|
92
|
+
|---|---|---|---|---|---|
|
|
93
|
+
| refactor-skipped | package metadataとstatic targetがPython 3.13以上を表す | regression | unit | no | REDは`requires-python >=3.12`で失敗。metadata変更後GREEN |
|
|
94
|
+
| refactor-skipped | CIがPython 3.13 / 3.14を実行する | regression | unit | no | REDはmatrix 3.12 / 3.13で失敗。workflow変更後GREEN |
|
|
95
|
+
| green | Python 3.13で標準gateが成功する | compatibility | gate | no | Python 3.13.5でstatic、451 unit、165 integration、buildがpass |
|
|
96
|
+
| green | Python 3.14でunit / integration / buildが成功する | compatibility | gate | no | Python 3.14.6を明示し、static、451 unit、165 integration、buildがpass |
|
|
97
|
+
|
|
98
|
+
## 8. 文書検証計画
|
|
99
|
+
|
|
100
|
+
READMEの対象読者はpackage利用者であり、install前に必要なPythonバージョンを判断できる
|
|
101
|
+
ことを確認する。正本は`pyproject.toml`の`requires-python`とする。README以外の公開
|
|
102
|
+
文書にはPython 3.12要件がないことを検索し、`docs-quality-review`で正本との一致を
|
|
103
|
+
確認する。
|
|
104
|
+
|
|
105
|
+
## 9. 設計メモ
|
|
106
|
+
|
|
107
|
+
- Python 3.13の採用理由は、今回のWindows実機で確認したclock分解能と画面観測である。
|
|
108
|
+
- Python 3.13でも`asyncio.sleep(0.008)`の正確な起床や125 Hzを保証しない。
|
|
109
|
+
- 3.14のCI追加は互換性検査であり、3.14固有機能の採用を意味しない。
|
|
110
|
+
- clock注入引数は決定的test用の内部境界として維持する。
|
|
111
|
+
|
|
112
|
+
## 10. 対象ファイル
|
|
113
|
+
|
|
114
|
+
| path | change | 内容 |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| `pyproject.toml` | modify | version 0.6.0、runtime floor、classifier、Ruff / ty target |
|
|
117
|
+
| `uv.lock` | modify | version 0.6.0、runtime floor |
|
|
118
|
+
| `.github/workflows/ci.yml` | modify | Python 3.13 / 3.14 matrix |
|
|
119
|
+
| `.github/workflows/bumble-canary.yml` | modify | Python 3.13 |
|
|
120
|
+
| `tests/unit/test_ci_workflow.py` | modify | CI matrix契約 |
|
|
121
|
+
| `tests/unit/test_package_metadata.py` | modify | package / static target契約 |
|
|
122
|
+
| `README.md` | modify | 必要Pythonバージョン |
|
|
123
|
+
| `docs/hardware.md` | modify | 実機準備の必要Pythonバージョン |
|
|
124
|
+
| `docs/release-notes.md` | modify | v0.6.0の互換性変更と実機確認範囲 |
|
|
125
|
+
| `tools/hci_credit_gyro_probe.py` | new | Issue #152実験用probe |
|
|
126
|
+
| `spec/hardware-test-log.md` | modify | 実験結果と不採用判断 |
|
|
127
|
+
| `spec/complete/unit_087/PYTHON_313_RUNTIME_FLOOR.md` | new | 完了した作業仕様 |
|
|
128
|
+
|
|
129
|
+
## 11. 検証
|
|
130
|
+
|
|
131
|
+
| command | result | notes |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| `uv run pytest tests/unit/test_ci_workflow.py tests/unit/test_package_metadata.py -q` | red, expected | CI matrixと`requires-python`が旧3.12境界のため2 failed、4 passed |
|
|
134
|
+
| 同focused testのGREEN再実行 | passed | 6 passed |
|
|
135
|
+
| `uv lock` | passed | 52 packages resolved |
|
|
136
|
+
| `uv sync --dev --python 3.13` | passed | Python 3.13.5、40 packages checked |
|
|
137
|
+
| Python 3.13.5 `ruff format --check` / `ruff check` / `ty check` | passed | 107 files formatted、lint / type errorなし |
|
|
138
|
+
| Python 3.13.5 `pytest tests/unit` | passed | 451 passed |
|
|
139
|
+
| Python 3.13.5 `pytest tests/integration` | passed | 165 passed |
|
|
140
|
+
| Python 3.13.5 `uv build` | passed | sdist / wheel生成 |
|
|
141
|
+
| `uv sync --dev --python 3.14` | passed | CPython 3.14.6を取得し、40 packages installed |
|
|
142
|
+
| `uv run --python 3.14 ruff format --check .` / `ruff check .` / `ty check --no-progress` | passed | runtimeを明示し、format / lint / type errorなし |
|
|
143
|
+
| `uv run --python 3.14 pytest tests/unit` | passed | Python 3.14.6、451 passed |
|
|
144
|
+
| `uv run --python 3.14 pytest tests/integration` | passed | Python 3.14.6、165 passed |
|
|
145
|
+
| `uv build --python 3.14` | passed | sdist / wheel生成。0.5.4 wheel metadataは`Requires-Python: >=3.13` |
|
|
146
|
+
| runtime指定なしの並列`uv run`による3.14検証 | invalid, rerun | `.python-version`の3.13を再選択したため判定に使用せず、全commandへ`--python 3.14`を明示して再実行 |
|
|
147
|
+
| `uv lock --check` | passed | 52 packages resolved |
|
|
148
|
+
| `git diff --check` | passed | whitespace errorなし |
|
|
149
|
+
| `uv run --python 3.13 --group docs mkdocs build --strict` | passed | 公開docsをstrict modeで生成 |
|
|
150
|
+
| v0.6.0 release gate: `uv sync --dev --group docs --python 3.13` | passed | local packageを0.6.0へ更新 |
|
|
151
|
+
| v0.6.0 release gate: Ruff / ty / unit / integration / MkDocs | passed | 451 unit、165 integration、static、docs strict build |
|
|
152
|
+
| `uv build` | passed | `swbt_python-0.6.0` wheel / sdistを生成 |
|
|
153
|
+
| `uvx --from twine twine check --strict dist\swbt_python-0.6.0-py3-none-any.whl dist\swbt_python-0.6.0.tar.gz` | passed | wheel / sdistともにPASSED |
|
|
154
|
+
|
|
155
|
+
### Docs Quality Review
|
|
156
|
+
|
|
157
|
+
- audience / task: package利用者がinstallまたは実機準備前に最低Pythonバージョンを判断する。
|
|
158
|
+
- documents: `README.md`、`docs/hardware.md`、`docs/release-notes.md`
|
|
159
|
+
- sources checked: `pyproject.toml`のversion / `requires-python`、classifiers、CI matrix、`v0.5.4..HEAD`と未コミット差分、`spec/hardware-test-log.md`
|
|
160
|
+
- must-fix: なし
|
|
161
|
+
- disposition: 利用要件をPython 3.13へ揃え、v0.6.0 release notesの先頭に破壊的変更、移行操作、実装非変更、CI範囲、実機確認と未確認範囲を記載した。
|
|
162
|
+
- verification: `uv run --python 3.13 --group docs mkdocs build --strict`がpass。
|
|
163
|
+
- remaining risk: Python 3.14の実機互換性は未検証であり、READMEでは保証していない。
|
|
164
|
+
|
|
165
|
+
## 12. 実機実行条件
|
|
166
|
+
|
|
167
|
+
| 項目 | 内容 |
|
|
168
|
+
|---|---|
|
|
169
|
+
| 今回の設定変更後実機検証 | not required |
|
|
170
|
+
| 理由 | 製品report / transport実装を変更せず、採用判断の根拠となる実機比較は完了済み |
|
|
171
|
+
| 過去の承認範囲 | dedicated `usb:0`、既存profile active reconnect、Direct / Periodic正Z yaw、neutral close、adapter release |
|
|
172
|
+
| artifact | `tmp/hardware/issue_152/credit-gyro-20260727/` |
|
|
173
|
+
|
|
174
|
+
## 13. 先送り事項
|
|
175
|
+
|
|
176
|
+
- Python 3.14でのSwitch実機検証は未実行。今回のCI追加は実機なしの互換性gateに限る。
|
|
177
|
+
- versionを0.6.0へ更新し、release notesを追加した。tag、PyPI / TestPyPI publish、GitHub Releaseはrelease実行時に扱う。
|
|
178
|
+
- 別OSにおける8 ms周期の実機表示は未検証。
|
|
179
|
+
|
|
180
|
+
## 14. チェックリスト
|
|
181
|
+
|
|
182
|
+
- [x] 対象範囲と対象外を確認した
|
|
183
|
+
- [x] TDD Test Listを更新した
|
|
184
|
+
- [x] 必要な根拠監査を記録した
|
|
185
|
+
- [x] 実機実行条件を記録した
|
|
186
|
+
- [x] 検証結果または未実行理由を記録した
|
|
187
|
+
- [x] docs-quality-reviewを完了した
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Dev Journal
|
|
2
|
+
|
|
3
|
+
swbt-python の設計観測、未解決事項、先送り判断の記録。
|
|
4
|
+
|
|
5
|
+
## 2026-07-26: VID:PID 33FA:0010 の HCI extended-features 応答
|
|
6
|
+
|
|
7
|
+
### 現状
|
|
8
|
+
|
|
9
|
+
Windows 11 / WinUSB / libwdi / Bumble 0.0.233 で検出した `33FA:0010` は、Bumble の `Read Local Extended Features` (`0x1004`) に対する応答を event length `0x01` として返し、通常の `power_on()` を停止させた。
|
|
10
|
+
|
|
11
|
+
### 観察
|
|
12
|
+
|
|
13
|
+
実験用に `0x1004` の対応判定を抑止すると、Bumble は既存の `0x1003` 代替経路を使い、HID advertising、fresh pairing、protocol ready、Button A の Switch UI 反映、neutral close まで成功した。active reconnect は同条件で2回、`host_connection` 後かつ L2CAP 前に Switch reason `19` で切断された。実験用コードは main に取り込まない。
|
|
14
|
+
|
|
15
|
+
### 方針
|
|
16
|
+
|
|
17
|
+
この adapter を正式対応にしない。再検討する場合は、Bumble の upstream driver / quirk として扱える根拠、または複数個体・別 OS/driver での再現を先に集める。観測 artifact と実行条件は `spec/hardware-test-log.md` を正本とする。
|