soundtouch-zonemaster 0.4.8__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 (579) hide show
  1. soundtouch_zonemaster-0.4.8/.env.example +16 -0
  2. soundtouch_zonemaster-0.4.8/.gitattributes +15 -0
  3. soundtouch_zonemaster-0.4.8/.github/actions/extract-metadata/action.yml +108 -0
  4. soundtouch_zonemaster-0.4.8/.github/dependabot.yml +22 -0
  5. soundtouch_zonemaster-0.4.8/.github/workflows/codeql.yml +39 -0
  6. soundtouch_zonemaster-0.4.8/.github/workflows/default_cicd_public.yml +436 -0
  7. soundtouch_zonemaster-0.4.8/.github/workflows/default_release_public.yml +95 -0
  8. soundtouch_zonemaster-0.4.8/.gitignore +197 -0
  9. soundtouch_zonemaster-0.4.8/CHANGELOG.md +837 -0
  10. soundtouch_zonemaster-0.4.8/LICENSE +21 -0
  11. soundtouch_zonemaster-0.4.8/Makefile +487 -0
  12. soundtouch_zonemaster-0.4.8/PKG-INFO +361 -0
  13. soundtouch_zonemaster-0.4.8/README.md +313 -0
  14. soundtouch_zonemaster-0.4.8/docs/notes/library-gotchas.md +90 -0
  15. soundtouch_zonemaster-0.4.8/docs/systemdesign/module_reference.md +261 -0
  16. soundtouch_zonemaster-0.4.8/keymappings.md +291 -0
  17. soundtouch_zonemaster-0.4.8/notebooks/Quickstart.ipynb +79 -0
  18. soundtouch_zonemaster-0.4.8/pyproject.toml +448 -0
  19. soundtouch_zonemaster-0.4.8/research/_click.py +96 -0
  20. soundtouch_zonemaster-0.4.8/research/_settings.py +153 -0
  21. soundtouch_zonemaster-0.4.8/research/analyze_capture.py +479 -0
  22. soundtouch_zonemaster-0.4.8/research/analyze_late_join.py +464 -0
  23. soundtouch_zonemaster-0.4.8/research/capture_model.py +278 -0
  24. soundtouch_zonemaster-0.4.8/research/capture_zone.py +674 -0
  25. soundtouch_zonemaster-0.4.8/research/defaultconfig.d/10-capture.toml +10 -0
  26. soundtouch_zonemaster-0.4.8/research/defaultconfig.d/20-golden.toml +13 -0
  27. soundtouch_zonemaster-0.4.8/research/defaultconfig.d/30-mpd-ab.toml +7 -0
  28. soundtouch_zonemaster-0.4.8/research/defaultconfig.toml +25 -0
  29. soundtouch_zonemaster-0.4.8/research/extract_protos.py +502 -0
  30. soundtouch_zonemaster-0.4.8/research/generate_pb.py +167 -0
  31. soundtouch_zonemaster-0.4.8/research/golden_check.py +264 -0
  32. soundtouch_zonemaster-0.4.8/research/mpd_seek_ab.py +374 -0
  33. soundtouch_zonemaster-0.4.8/research/observe_keys.py +232 -0
  34. soundtouch_zonemaster-0.4.8/research/proto/APConfigValues.proto +142 -0
  35. soundtouch_zonemaster-0.4.8/research/proto/APDashboardMsgDefinitions.proto +34 -0
  36. soundtouch_zonemaster-0.4.8/research/proto/APSourceParsing.proto +30 -0
  37. soundtouch_zonemaster-0.4.8/research/proto/AVSContext.proto +26 -0
  38. soundtouch_zonemaster-0.4.8/research/proto/AVSHeader.proto +15 -0
  39. soundtouch_zonemaster-0.4.8/research/proto/AirPlay2Introspect.proto +9 -0
  40. soundtouch_zonemaster-0.4.8/research/proto/AirPlay2Persistent.proto +9 -0
  41. soundtouch_zonemaster-0.4.8/research/proto/AirplayControllerMsgDefinitions.proto +18 -0
  42. soundtouch_zonemaster-0.4.8/research/proto/Album.proto +44 -0
  43. soundtouch_zonemaster-0.4.8/research/proto/AlbumInfo.proto +22 -0
  44. soundtouch_zonemaster-0.4.8/research/proto/Albums.proto +13 -0
  45. soundtouch_zonemaster-0.4.8/research/proto/AlexaSeekDirective.proto +15 -0
  46. soundtouch_zonemaster-0.4.8/research/proto/AmazonAccessTokenResponse.proto +9 -0
  47. soundtouch_zonemaster-0.4.8/research/proto/AmazonInternalPlaybackRequest.proto +11 -0
  48. soundtouch_zonemaster-0.4.8/research/proto/AmazonIntrospect.proto +61 -0
  49. soundtouch_zonemaster-0.4.8/research/proto/AmazonPlaybackEvent.proto +21 -0
  50. soundtouch_zonemaster-0.4.8/research/proto/AmazonSecret.proto +10 -0
  51. soundtouch_zonemaster-0.4.8/research/proto/AmazonTrackRating.proto +16 -0
  52. soundtouch_zonemaster-0.4.8/research/proto/AmazonTracks.proto +74 -0
  53. soundtouch_zonemaster-0.4.8/research/proto/Artist.proto +26 -0
  54. soundtouch_zonemaster-0.4.8/research/proto/ArtistInfo.proto +15 -0
  55. soundtouch_zonemaster-0.4.8/research/proto/Artists.proto +13 -0
  56. soundtouch_zonemaster-0.4.8/research/proto/ArtistsByCategory.proto +15 -0
  57. soundtouch_zonemaster-0.4.8/research/proto/AudioNotificationAccountIntrospect.proto +11 -0
  58. soundtouch_zonemaster-0.4.8/research/proto/AudioNotificationProxyPlayInfo.proto +10 -0
  59. soundtouch_zonemaster-0.4.8/research/proto/AudioNotificationServiceIntrospect.proto +11 -0
  60. soundtouch_zonemaster-0.4.8/research/proto/AudioPathControl.proto +64 -0
  61. soundtouch_zonemaster-0.4.8/research/proto/AudioServerMsgAudioData.proto +25 -0
  62. soundtouch_zonemaster-0.4.8/research/proto/AudioServerMsgDefinitions.proto +292 -0
  63. soundtouch_zonemaster-0.4.8/research/proto/AuthServerInfo.proto +14 -0
  64. soundtouch_zonemaster-0.4.8/research/proto/AuthenticationResponse.proto +44 -0
  65. soundtouch_zonemaster-0.4.8/research/proto/BTProxy.proto +18 -0
  66. soundtouch_zonemaster-0.4.8/research/proto/BatteryMonitorMsgDefinitions.proto +83 -0
  67. soundtouch_zonemaster-0.4.8/research/proto/BoseLinkServerMsgDefinitions.proto +384 -0
  68. soundtouch_zonemaster-0.4.8/research/proto/CC2540UpdateMsgDefinitions.proto +11 -0
  69. soundtouch_zonemaster-0.4.8/research/proto/CLIServerMsgDefinitions.proto +30 -0
  70. soundtouch_zonemaster-0.4.8/research/proto/CLIServerMsgIds.proto +9 -0
  71. soundtouch_zonemaster-0.4.8/research/proto/Charts.proto +16 -0
  72. soundtouch_zonemaster-0.4.8/research/proto/ClientConfig.proto +16 -0
  73. soundtouch_zonemaster-0.4.8/research/proto/ClockConfiguration.proto +15 -0
  74. soundtouch_zonemaster-0.4.8/research/proto/ClockSyncMsgDefinitions.proto +58 -0
  75. soundtouch_zonemaster-0.4.8/research/proto/ClockTime.proto +26 -0
  76. soundtouch_zonemaster-0.4.8/research/proto/Common.proto +68 -0
  77. soundtouch_zonemaster-0.4.8/research/proto/ConfigResponse.proto +27 -0
  78. soundtouch_zonemaster-0.4.8/research/proto/Configuration/BoseAppCfg.proto +80 -0
  79. soundtouch_zonemaster-0.4.8/research/proto/Configuration/SoundTouchSdkPrivateCfg.proto +23 -0
  80. soundtouch_zonemaster-0.4.8/research/proto/Countries.proto +17 -0
  81. soundtouch_zonemaster-0.4.8/research/proto/Country.proto +15 -0
  82. soundtouch_zonemaster-0.4.8/research/proto/CustomRadioGetTracks.proto +27 -0
  83. soundtouch_zonemaster-0.4.8/research/proto/DeezerContentType.proto +12 -0
  84. soundtouch_zonemaster-0.4.8/research/proto/DeezerError.proto +11 -0
  85. soundtouch_zonemaster-0.4.8/research/proto/DeezerInternalPlaybackRequest.proto +10 -0
  86. soundtouch_zonemaster-0.4.8/research/proto/DeezerIntrospect.proto +21 -0
  87. soundtouch_zonemaster-0.4.8/research/proto/DeezerLocation.proto +11 -0
  88. soundtouch_zonemaster-0.4.8/research/proto/DeezerLoginResponse.proto +11 -0
  89. soundtouch_zonemaster-0.4.8/research/proto/DeezerPersistent.proto +9 -0
  90. soundtouch_zonemaster-0.4.8/research/proto/DeezerQueuedTrack.proto +14 -0
  91. soundtouch_zonemaster-0.4.8/research/proto/DeezerTrackInfo.proto +25 -0
  92. soundtouch_zonemaster-0.4.8/research/proto/EnterCodeResponse.proto +12 -0
  93. soundtouch_zonemaster-0.4.8/research/proto/EnvDefine.proto +16 -0
  94. soundtouch_zonemaster-0.4.8/research/proto/EnvList.proto +10 -0
  95. soundtouch_zonemaster-0.4.8/research/proto/EnvSwitch.proto +18 -0
  96. soundtouch_zonemaster-0.4.8/research/proto/ExtSourceMsgDefinitions.proto +110 -0
  97. soundtouch_zonemaster-0.4.8/research/proto/ExternalMediaPlayerAvsApi.proto +153 -0
  98. soundtouch_zonemaster-0.4.8/research/proto/Favorites.proto +38 -0
  99. soundtouch_zonemaster-0.4.8/research/proto/ForYou.proto +36 -0
  100. soundtouch_zonemaster-0.4.8/research/proto/FullAccount.proto +22 -0
  101. soundtouch_zonemaster-0.4.8/research/proto/GenreList.proto +16 -0
  102. soundtouch_zonemaster-0.4.8/research/proto/GetCodeResponse.proto +13 -0
  103. soundtouch_zonemaster-0.4.8/research/proto/Hpdt.proto +76 -0
  104. soundtouch_zonemaster-0.4.8/research/proto/IHeartCILocation.proto +36 -0
  105. soundtouch_zonemaster-0.4.8/research/proto/IHeartContentType.proto +13 -0
  106. soundtouch_zonemaster-0.4.8/research/proto/IHeartError.proto +36 -0
  107. soundtouch_zonemaster-0.4.8/research/proto/IHeartIntrospect.proto +41 -0
  108. soundtouch_zonemaster-0.4.8/research/proto/IHeartLoginResponse.proto +19 -0
  109. soundtouch_zonemaster-0.4.8/research/proto/IHeartQueuedTrack.proto +31 -0
  110. soundtouch_zonemaster-0.4.8/research/proto/IPCMessageEnvelopeBase.proto +19 -0
  111. soundtouch_zonemaster-0.4.8/research/proto/IPCProtocolDefinitions.proto +27 -0
  112. soundtouch_zonemaster-0.4.8/research/proto/IpcServices.proto +11 -0
  113. soundtouch_zonemaster-0.4.8/research/proto/ListenHistory.proto +60 -0
  114. soundtouch_zonemaster-0.4.8/research/proto/LiveRadioMetaData.proto +30 -0
  115. soundtouch_zonemaster-0.4.8/research/proto/LiveRadioRecommendations.proto +17 -0
  116. soundtouch_zonemaster-0.4.8/research/proto/LiveRadioRegister.proto +12 -0
  117. soundtouch_zonemaster-0.4.8/research/proto/LiveRadioTemplates.proto +22 -0
  118. soundtouch_zonemaster-0.4.8/research/proto/LiveStations.proto +28 -0
  119. soundtouch_zonemaster-0.4.8/research/proto/LocalMusicAlbumInfo.proto +18 -0
  120. soundtouch_zonemaster-0.4.8/research/proto/LocalMusicArtistInfo.proto +12 -0
  121. soundtouch_zonemaster-0.4.8/research/proto/LocalMusicAuthorInfo.proto +12 -0
  122. soundtouch_zonemaster-0.4.8/research/proto/LocalMusicError.proto +11 -0
  123. soundtouch_zonemaster-0.4.8/research/proto/LocalMusicInternalPlaybackRequest.proto +10 -0
  124. soundtouch_zonemaster-0.4.8/research/proto/LocalMusicIntrospect.proto +21 -0
  125. soundtouch_zonemaster-0.4.8/research/proto/LocalMusicPodcastInfo.proto +13 -0
  126. soundtouch_zonemaster-0.4.8/research/proto/LocalMusicQueuedTrack.proto +11 -0
  127. soundtouch_zonemaster-0.4.8/research/proto/LocalMusicTrackInfo.proto +38 -0
  128. soundtouch_zonemaster-0.4.8/research/proto/LocalMusicTracks.proto +29 -0
  129. soundtouch_zonemaster-0.4.8/research/proto/MargeAddDevice.proto +12 -0
  130. soundtouch_zonemaster-0.4.8/research/proto/MargeAddDeviceResponse.proto +9 -0
  131. soundtouch_zonemaster-0.4.8/research/proto/MargeAddPresetRequest.proto +17 -0
  132. soundtouch_zonemaster-0.4.8/research/proto/MargeAddRecentRequest.proto +14 -0
  133. soundtouch_zonemaster-0.4.8/research/proto/MargeClientIntrospect.proto +23 -0
  134. soundtouch_zonemaster-0.4.8/research/proto/MargeConfiguration.proto +14 -0
  135. soundtouch_zonemaster-0.4.8/research/proto/MargeDevice.proto +15 -0
  136. soundtouch_zonemaster-0.4.8/research/proto/MargeDeviceData.proto +55 -0
  137. soundtouch_zonemaster-0.4.8/research/proto/MargeDevices.proto +12 -0
  138. soundtouch_zonemaster-0.4.8/research/proto/MargeGroup.proto +23 -0
  139. soundtouch_zonemaster-0.4.8/research/proto/MargePreset.proto +19 -0
  140. soundtouch_zonemaster-0.4.8/research/proto/MargePresets.proto +10 -0
  141. soundtouch_zonemaster-0.4.8/research/proto/MargeRecent.proto +18 -0
  142. soundtouch_zonemaster-0.4.8/research/proto/MargeRecents.proto +10 -0
  143. soundtouch_zonemaster-0.4.8/research/proto/MargeSource.proto +24 -0
  144. soundtouch_zonemaster-0.4.8/research/proto/MargeSourceProviders.proto +14 -0
  145. soundtouch_zonemaster-0.4.8/research/proto/MargeSourceSettings.proto +15 -0
  146. soundtouch_zonemaster-0.4.8/research/proto/MargeSources.proto +10 -0
  147. soundtouch_zonemaster-0.4.8/research/proto/MargeStatus.proto +12 -0
  148. soundtouch_zonemaster-0.4.8/research/proto/Market.proto +13 -0
  149. soundtouch_zonemaster-0.4.8/research/proto/MarketList.proto +20 -0
  150. soundtouch_zonemaster-0.4.8/research/proto/NetManager.proto +193 -0
  151. soundtouch_zonemaster-0.4.8/research/proto/NowPlayingSupplement.proto +22 -0
  152. soundtouch_zonemaster-0.4.8/research/proto/OAuthAccessToken.proto +11 -0
  153. soundtouch_zonemaster-0.4.8/research/proto/OAuthTokens.proto +12 -0
  154. soundtouch_zonemaster-0.4.8/research/proto/OAuthUserInfo.proto +29 -0
  155. soundtouch_zonemaster-0.4.8/research/proto/OnDemandEpisodesResponse.proto +21 -0
  156. soundtouch_zonemaster-0.4.8/research/proto/OnDemandMetadata.proto +127 -0
  157. soundtouch_zonemaster-0.4.8/research/proto/PerfectFor.proto +42 -0
  158. soundtouch_zonemaster-0.4.8/research/proto/Persistence/AirplayConfiguration.proto +89 -0
  159. soundtouch_zonemaster-0.4.8/research/proto/Persistence/ExtSource.proto +10 -0
  160. soundtouch_zonemaster-0.4.8/research/proto/Persistence/Lightswitch.proto +25 -0
  161. soundtouch_zonemaster-0.4.8/research/proto/Persistence/Pandora.proto +36 -0
  162. soundtouch_zonemaster-0.4.8/research/proto/Persistence/SourceInfo.proto +9 -0
  163. soundtouch_zonemaster-0.4.8/research/proto/Persistence/SourceRegistry.proto +23 -0
  164. soundtouch_zonemaster-0.4.8/research/proto/Persistence/StatsDataCapture.proto +14 -0
  165. soundtouch_zonemaster-0.4.8/research/proto/Persistence/SystemConfiguration.proto +29 -0
  166. soundtouch_zonemaster-0.4.8/research/proto/Persistence/UPnP.proto +20 -0
  167. soundtouch_zonemaster-0.4.8/research/proto/PresetResponse.proto +15 -0
  168. soundtouch_zonemaster-0.4.8/research/proto/PresetUpdate.proto +12 -0
  169. soundtouch_zonemaster-0.4.8/research/proto/ProtoToMarkup/MarkupOptions.proto +14 -0
  170. soundtouch_zonemaster-0.4.8/research/proto/ProviderSettings.proto +16 -0
  171. soundtouch_zonemaster-0.4.8/research/proto/RalphError.proto +10 -0
  172. soundtouch_zonemaster-0.4.8/research/proto/RegisterClientResponse.proto +11 -0
  173. soundtouch_zonemaster-0.4.8/research/proto/ReportStreamResponse.proto +15 -0
  174. soundtouch_zonemaster-0.4.8/research/proto/SCMHardwareNVRamConfigFileFmt.proto +38 -0
  175. soundtouch_zonemaster-0.4.8/research/proto/STSAsyncError.proto +21 -0
  176. soundtouch_zonemaster-0.4.8/research/proto/STSAudioError.proto +12 -0
  177. soundtouch_zonemaster-0.4.8/research/proto/STSAudioReason.proto +9 -0
  178. soundtouch_zonemaster-0.4.8/research/proto/STSAudioSetURL.proto +27 -0
  179. soundtouch_zonemaster-0.4.8/research/proto/STSAudioState.proto +13 -0
  180. soundtouch_zonemaster-0.4.8/research/proto/STSAudioStatus.proto +22 -0
  181. soundtouch_zonemaster-0.4.8/research/proto/STSAuthServerInfo.proto +12 -0
  182. soundtouch_zonemaster-0.4.8/research/proto/STSAvailability.proto +10 -0
  183. soundtouch_zonemaster-0.4.8/research/proto/STSConnectionStatus.proto +16 -0
  184. soundtouch_zonemaster-0.4.8/research/proto/STSContentItem.proto +11 -0
  185. soundtouch_zonemaster-0.4.8/research/proto/STSContentItemHistory.proto +18 -0
  186. soundtouch_zonemaster-0.4.8/research/proto/STSCreateAccount.proto +24 -0
  187. soundtouch_zonemaster-0.4.8/research/proto/STSCreateAccountProxy.proto +13 -0
  188. soundtouch_zonemaster-0.4.8/research/proto/STSDeactivate.proto +7 -0
  189. soundtouch_zonemaster-0.4.8/research/proto/STSDeployment.proto +11 -0
  190. soundtouch_zonemaster-0.4.8/research/proto/STSDeviceInfo.proto +32 -0
  191. soundtouch_zonemaster-0.4.8/research/proto/STSDeviceStatus.proto +8 -0
  192. soundtouch_zonemaster-0.4.8/research/proto/STSErrorSeverity.proto +9 -0
  193. soundtouch_zonemaster-0.4.8/research/proto/STSFilterType.proto +17 -0
  194. soundtouch_zonemaster-0.4.8/research/proto/STSFlexUI.proto +27 -0
  195. soundtouch_zonemaster-0.4.8/research/proto/STSGroupStatus.proto +9 -0
  196. soundtouch_zonemaster-0.4.8/research/proto/STSIntrospect.proto +7 -0
  197. soundtouch_zonemaster-0.4.8/research/proto/STSItemType.proto +37 -0
  198. soundtouch_zonemaster-0.4.8/research/proto/STSItems.proto +36 -0
  199. soundtouch_zonemaster-0.4.8/research/proto/STSLogAutomation.proto +7 -0
  200. soundtouch_zonemaster-0.4.8/research/proto/STSMenuType.proto +34 -0
  201. soundtouch_zonemaster-0.4.8/research/proto/STSMsgDefinitions.proto +90 -0
  202. soundtouch_zonemaster-0.4.8/research/proto/STSMute.proto +11 -0
  203. soundtouch_zonemaster-0.4.8/research/proto/STSNavigate.proto +26 -0
  204. soundtouch_zonemaster-0.4.8/research/proto/STSNetworkStatus.proto +9 -0
  205. soundtouch_zonemaster-0.4.8/research/proto/STSNowPlaying.proto +71 -0
  206. soundtouch_zonemaster-0.4.8/research/proto/STSOAuthCredentials.proto +20 -0
  207. soundtouch_zonemaster-0.4.8/research/proto/STSPlayQueueIntrospect.proto +22 -0
  208. soundtouch_zonemaster-0.4.8/research/proto/STSPlayStatus.proto +11 -0
  209. soundtouch_zonemaster-0.4.8/research/proto/STSPlaybackRequest.proto +13 -0
  210. soundtouch_zonemaster-0.4.8/research/proto/STSProtocolVersion.proto +8 -0
  211. soundtouch_zonemaster-0.4.8/research/proto/STSRating.proto +9 -0
  212. soundtouch_zonemaster-0.4.8/research/proto/STSRecreateAccount.proto +16 -0
  213. soundtouch_zonemaster-0.4.8/research/proto/STSRegisterService.proto +8 -0
  214. soundtouch_zonemaster-0.4.8/research/proto/STSRemoveAccount.proto +7 -0
  215. soundtouch_zonemaster-0.4.8/research/proto/STSRepeatMode.proto +9 -0
  216. soundtouch_zonemaster-0.4.8/research/proto/STSSSDPDiscoveryService.proto +13 -0
  217. soundtouch_zonemaster-0.4.8/research/proto/STSSSDPDiscoveryStatus.proto +13 -0
  218. soundtouch_zonemaster-0.4.8/research/proto/STSSearch.proto +24 -0
  219. soundtouch_zonemaster-0.4.8/research/proto/STSSections.proto +16 -0
  220. soundtouch_zonemaster-0.4.8/research/proto/STSSeekRelative.proto +14 -0
  221. soundtouch_zonemaster-0.4.8/research/proto/STSSeekToTime.proto +9 -0
  222. soundtouch_zonemaster-0.4.8/research/proto/STSServiceAndAccountSettings.proto +67 -0
  223. soundtouch_zonemaster-0.4.8/research/proto/STSServiceInfo.proto +10 -0
  224. soundtouch_zonemaster-0.4.8/research/proto/STSShuffleMode.proto +8 -0
  225. soundtouch_zonemaster-0.4.8/research/proto/STSSkipList.proto +13 -0
  226. soundtouch_zonemaster-0.4.8/research/proto/STSSortOrder.proto +14 -0
  227. soundtouch_zonemaster-0.4.8/research/proto/STSSourceDeselect.proto +12 -0
  228. soundtouch_zonemaster-0.4.8/research/proto/STSSourceSelect.proto +7 -0
  229. soundtouch_zonemaster-0.4.8/research/proto/STSStationInfo.proto +7 -0
  230. soundtouch_zonemaster-0.4.8/research/proto/STSStatus.proto +12 -0
  231. soundtouch_zonemaster-0.4.8/research/proto/STSStreamType.proto +10 -0
  232. soundtouch_zonemaster-0.4.8/research/proto/STSStreamingQuality.proto +15 -0
  233. soundtouch_zonemaster-0.4.8/research/proto/STSUpdateSecret.proto +8 -0
  234. soundtouch_zonemaster-0.4.8/research/proto/STSVoid.proto +6 -0
  235. soundtouch_zonemaster-0.4.8/research/proto/STSVolumeControl.proto +11 -0
  236. soundtouch_zonemaster-0.4.8/research/proto/STSVolumeStatus.proto +7 -0
  237. soundtouch_zonemaster-0.4.8/research/proto/STSZeroconfRegisterService.proto +12 -0
  238. soundtouch_zonemaster-0.4.8/research/proto/STSZeroconfTxtRecord.proto +8 -0
  239. soundtouch_zonemaster-0.4.8/research/proto/STSZeroconfUnregisterService.proto +9 -0
  240. soundtouch_zonemaster-0.4.8/research/proto/STSZoneStatus.proto +9 -0
  241. soundtouch_zonemaster-0.4.8/research/proto/SWUpdateUrl.proto +10 -0
  242. soundtouch_zonemaster-0.4.8/research/proto/ScmmondClient.proto +37 -0
  243. soundtouch_zonemaster-0.4.8/research/proto/ShelbyKeys.proto +66 -0
  244. soundtouch_zonemaster-0.4.8/research/proto/SoftwareUpdate/SwUpdateCheck.proto +7 -0
  245. soundtouch_zonemaster-0.4.8/research/proto/SoftwareUpdateAPIMsgDefinitions.proto +29 -0
  246. soundtouch_zonemaster-0.4.8/research/proto/SoftwareUpdateIndex/SoftwareUpdateIndex.proto +70 -0
  247. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchAccountId.proto +5 -0
  248. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/AcctMode.proto +11 -0
  249. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/AcctModeType.proto +10 -0
  250. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/AudioService.proto +27 -0
  251. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/ContentItem.proto +42 -0
  252. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/ContentItemList.proto +10 -0
  253. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/ContentSelectionService.proto +45 -0
  254. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/ErrorType.proto +345 -0
  255. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/ErrorUpdate.proto +11 -0
  256. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/GetActiveWirelessProfile.proto +12 -0
  257. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/Group.proto +49 -0
  258. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/Msg.proto +43 -0
  259. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/NetworkService.proto +62 -0
  260. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/PlayerService.proto +210 -0
  261. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/Presets.proto +17 -0
  262. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/Recents.proto +16 -0
  263. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/SSDPDiscoveryUpdate.proto +17 -0
  264. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/STSSettings.proto +56 -0
  265. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/ServiceSettings.proto +13 -0
  266. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/Setup.proto +39 -0
  267. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/SoftwareUpdateService.proto +42 -0
  268. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/SoundTouchSdkInfo.proto +10 -0
  269. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/Status.proto +60 -0
  270. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/SystemService.proto +124 -0
  271. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/Updates.proto +126 -0
  272. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/Zone.proto +25 -0
  273. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/initializationcompleteaction.proto +21 -0
  274. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/userActivityUpdate.proto +9 -0
  275. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchInterface/userInactivityUpdate.proto +9 -0
  276. soundtouch_zonemaster-0.4.8/research/proto/SoundTouchSdkAPI.proto +24 -0
  277. soundtouch_zonemaster-0.4.8/research/proto/SpotifyImages.proto +15 -0
  278. soundtouch_zonemaster-0.4.8/research/proto/SpotifyInternalPlaybackRequest.proto +15 -0
  279. soundtouch_zonemaster-0.4.8/research/proto/SpotifyIntrospect.proto +43 -0
  280. soundtouch_zonemaster-0.4.8/research/proto/SpotifyLocation.proto +15 -0
  281. soundtouch_zonemaster-0.4.8/research/proto/SpotifyPersistent.proto +10 -0
  282. soundtouch_zonemaster-0.4.8/research/proto/SpotifyPreset.proto +11 -0
  283. soundtouch_zonemaster-0.4.8/research/proto/SpotifyTracks.proto +13 -0
  284. soundtouch_zonemaster-0.4.8/research/proto/SpotifyUserSavedTracks.proto +9 -0
  285. soundtouch_zonemaster-0.4.8/research/proto/Startup.proto +42 -0
  286. soundtouch_zonemaster-0.4.8/research/proto/StateList.proto +13 -0
  287. soundtouch_zonemaster-0.4.8/research/proto/Station.proto +28 -0
  288. soundtouch_zonemaster-0.4.8/research/proto/StationDetails.proto +31 -0
  289. soundtouch_zonemaster-0.4.8/research/proto/StationType.proto +18 -0
  290. soundtouch_zonemaster-0.4.8/research/proto/StreamSources/StationTracks.proto +63 -0
  291. soundtouch_zonemaster-0.4.8/research/proto/StreamUrl.proto +24 -0
  292. soundtouch_zonemaster-0.4.8/research/proto/Streams.proto +15 -0
  293. soundtouch_zonemaster-0.4.8/research/proto/SxmIntrospect.proto +38 -0
  294. soundtouch_zonemaster-0.4.8/research/proto/SxmRegistrationInfo.proto +12 -0
  295. soundtouch_zonemaster-0.4.8/research/proto/TPDAEndpoint.proto +19 -0
  296. soundtouch_zonemaster-0.4.8/research/proto/TPDAHeader.proto +18 -0
  297. soundtouch_zonemaster-0.4.8/research/proto/TPDAPlaybackStateReporter.proto +133 -0
  298. soundtouch_zonemaster-0.4.8/research/proto/Talk.proto +60 -0
  299. soundtouch_zonemaster-0.4.8/research/proto/ThumbResponse.proto +12 -0
  300. soundtouch_zonemaster-0.4.8/research/proto/TokenResponse.proto +25 -0
  301. soundtouch_zonemaster-0.4.8/research/proto/Track.proto +15 -0
  302. soundtouch_zonemaster-0.4.8/research/proto/TrackBundle.proto +19 -0
  303. soundtouch_zonemaster-0.4.8/research/proto/TrackEvents.proto +25 -0
  304. soundtouch_zonemaster-0.4.8/research/proto/Tracks.proto +14 -0
  305. soundtouch_zonemaster-0.4.8/research/proto/UpdateGroup.proto +11 -0
  306. soundtouch_zonemaster-0.4.8/research/proto/UpnpIntrospect.proto +15 -0
  307. soundtouch_zonemaster-0.4.8/research/proto/UserBatch.proto +18 -0
  308. soundtouch_zonemaster-0.4.8/research/proto/UserInfo.proto +13 -0
  309. soundtouch_zonemaster-0.4.8/research/proto/UserOptions.proto +11 -0
  310. soundtouch_zonemaster-0.4.8/research/proto/UserProfile.proto +16 -0
  311. soundtouch_zonemaster-0.4.8/research/proto/UserSubscription.proto +15 -0
  312. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/BCOReset.proto +12 -0
  313. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/Balance.proto +23 -0
  314. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/Bass.proto +12 -0
  315. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/BassCapabilities.proto +29 -0
  316. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/BearerToken.proto +7 -0
  317. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/Capabilities.proto +58 -0
  318. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/ClockDisplay.proto +10 -0
  319. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/ControllerUI.proto +10 -0
  320. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/Credentials.proto +13 -0
  321. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/GenreStationsResult.proto +26 -0
  322. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/GroupUIStatusNotification.proto +6 -0
  323. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/GroupVersion.proto +7 -0
  324. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/Info.proto +30 -0
  325. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/Introspect.proto +13 -0
  326. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/Item.proto +74 -0
  327. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/KeyData.proto +60 -0
  328. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/MarconiUI.proto +8 -0
  329. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/MasterMessage.proto +13 -0
  330. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/Mono.proto +14 -0
  331. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/Navigate.proto +79 -0
  332. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/NetStats.proto +63 -0
  333. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/OAuthCredentials.proto +12 -0
  334. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/OledUI.proto +12 -0
  335. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/PairDeviceWithAccount.proto +17 -0
  336. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/PerformWirelessSiteSurvey.proto +34 -0
  337. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/PingRequest.proto +7 -0
  338. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/PlayInfo.proto +15 -0
  339. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/PlaySound.proto +13 -0
  340. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/PlaybackRequest.proto +18 -0
  341. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/Power.proto +18 -0
  342. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/PowerManagementResponse.proto +44 -0
  343. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/Results.proto +30 -0
  344. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/SSDPDiscoveryStatus.proto +14 -0
  345. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/SWUpdateCheckResponse.proto +12 -0
  346. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/SWUpdateQueryResponse.proto +28 -0
  347. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/Search.proto +54 -0
  348. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/SearchSortOrder.proto +12 -0
  349. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/ServiceAvailability.proto +18 -0
  350. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/SlaveMessage.proto +12 -0
  351. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/SourceIcon.proto +8 -0
  352. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/StationInfo.proto +11 -0
  353. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/SupportedUrls.proto +11 -0
  354. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/TrackInfo.proto +8 -0
  355. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/VersionInfo.proto +35 -0
  356. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/WirelessProfile.proto +37 -0
  357. soundtouch_zonemaster-0.4.8/research/proto/WebInterface/ZoneList.proto +9 -0
  358. soundtouch_zonemaster-0.4.8/research/proto/WebServerCfg.proto +9 -0
  359. soundtouch_zonemaster-0.4.8/research/proto/WebServerMsgDefinitions.proto +14 -0
  360. soundtouch_zonemaster-0.4.8/research/proto/ZeroconfRegisterService.proto +10 -0
  361. soundtouch_zonemaster-0.4.8/research/proto/ZeroconfTxtRecord.proto +6 -0
  362. soundtouch_zonemaster-0.4.8/research/proto/ZeroconfUnregisterService.proto +7 -0
  363. soundtouch_zonemaster-0.4.8/research/proto/ZoneState.proto +13 -0
  364. soundtouch_zonemaster-0.4.8/research/sync_report.py +265 -0
  365. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/__init__.py +13 -0
  366. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/__init__conf__.py +99 -0
  367. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/__main__.py +14 -0
  368. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/__init__.py +5 -0
  369. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/aftertouch/__init__.py +10 -0
  370. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/aftertouch/registry.py +144 -0
  371. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/cli/__init__.py +5 -0
  372. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/cli/boundary.py +313 -0
  373. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/cli/context.py +49 -0
  374. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/cli/envelope.py +116 -0
  375. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/cli/main.py +77 -0
  376. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/cli/prototype.py +371 -0
  377. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/cli/py.typed +0 -0
  378. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/cli/safe_console.py +218 -0
  379. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/cli/service/__init__.py +14 -0
  380. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/cli/service/config_cmd.py +84 -0
  381. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/cli/service/deploy_cmd.py +76 -0
  382. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/cli/service/root.py +226 -0
  383. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/cli/typed_click.py +95 -0
  384. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/__init__.py +20 -0
  385. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/defaultconfig.d/10-zone.toml +33 -0
  386. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/defaultconfig.d/20-files.toml +46 -0
  387. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/defaultconfig.d/30-registry.toml +31 -0
  388. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/defaultconfig.d/40-membership.toml +35 -0
  389. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/defaultconfig.d/50-dialling.toml +47 -0
  390. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/defaultconfig.d/60-switch.toml +17 -0
  391. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/defaultconfig.d/70-observer.toml +34 -0
  392. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/defaultconfig.d/80-prototype.toml +31 -0
  393. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/defaultconfig.d/90-mpd.toml +48 -0
  394. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/defaultconfig.toml +47 -0
  395. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/deploy.py +58 -0
  396. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/display.py +113 -0
  397. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/errors.py +26 -0
  398. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/loader.py +154 -0
  399. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/overrides.py +103 -0
  400. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/config/settings_map.py +182 -0
  401. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/files/__init__.py +5 -0
  402. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/files/atomicfile.py +63 -0
  403. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/files/channel_file.py +164 -0
  404. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/files/state_file.py +145 -0
  405. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/files/switch_file.py +77 -0
  406. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/logging/__init__.py +5 -0
  407. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/logging/narration.py +43 -0
  408. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/mpd/__init__.py +23 -0
  409. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/mpd/client.py +292 -0
  410. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/py.typed +0 -0
  411. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/__init__.py +9 -0
  412. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/clock.py +199 -0
  413. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/connections.py +529 -0
  414. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/http_api.py +332 -0
  415. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/ipc.py +175 -0
  416. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/observer.py +200 -0
  417. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/pb/AudioServerMsgAudioData_pb2.py +40 -0
  418. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/pb/AudioServerMsgAudioData_pb2.pyi +48 -0
  419. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/pb/AudioServerMsgDefinitions_pb2.py +133 -0
  420. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/pb/AudioServerMsgDefinitions_pb2.pyi +490 -0
  421. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/pb/IPCMessageEnvelopeBase_pb2.py +40 -0
  422. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/pb/IPCMessageEnvelopeBase_pb2.pyi +36 -0
  423. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/pb/ProtoToMarkup/MarkupOptions_pb2.py +35 -0
  424. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/pb/ProtoToMarkup/MarkupOptions_pb2.pyi +17 -0
  425. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/pb/ProtoToMarkup/__init__.py +0 -0
  426. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/pb/SoundTouchInterface/Zone_pb2.py +41 -0
  427. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/pb/SoundTouchInterface/Zone_pb2.pyi +42 -0
  428. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/pb/SoundTouchInterface/__init__.py +0 -0
  429. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/pb/__init__.py +25 -0
  430. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/placement.py +382 -0
  431. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/reports.py +70 -0
  432. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/source.py +380 -0
  433. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/speaker_http.py +156 -0
  434. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/wire.py +29 -0
  435. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/xmlmodels.py +155 -0
  436. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/xmlread.py +156 -0
  437. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/adapters/soundtouch/zone_master.py +628 -0
  438. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/__init__.py +5 -0
  439. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/errors.py +60 -0
  440. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/options.py +228 -0
  441. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/outcome.py +75 -0
  442. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/ports.py +420 -0
  443. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/prototype.py +114 -0
  444. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/py.typed +0 -0
  445. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/zone_service/__init__.py +16 -0
  446. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/zone_service/channels.py +166 -0
  447. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/zone_service/constants.py +105 -0
  448. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/zone_service/dialling.py +519 -0
  449. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/zone_service/keys.py +205 -0
  450. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/zone_service/service.py +104 -0
  451. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/zone_service/speakers.py +150 -0
  452. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/zone_service/state.py +357 -0
  453. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/zone_service/volume.py +363 -0
  454. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/application/zone_service/zone.py +705 -0
  455. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/composition/__init__.py +135 -0
  456. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/composition/py.typed +0 -0
  457. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/__init__.py +5 -0
  458. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/calibration.py +291 -0
  459. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/channellist.py +407 -0
  460. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/dialling.py +214 -0
  461. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/enums.py +266 -0
  462. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/events.py +83 -0
  463. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/frames.py +211 -0
  464. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/housevolume.py +110 -0
  465. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/logfn.py +28 -0
  466. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/longpress.py +194 -0
  467. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/membership.py +233 -0
  468. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/mpd.py +58 -0
  469. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/playorder.py +112 -0
  470. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/presses.py +392 -0
  471. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/py.typed +0 -0
  472. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/speakers.py +82 -0
  473. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/state.py +145 -0
  474. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/station.py +75 -0
  475. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/switch.py +18 -0
  476. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/timeline.py +185 -0
  477. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/xmlfmt.py +90 -0
  478. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/domain/zonexml.py +137 -0
  479. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/entry.py +34 -0
  480. soundtouch_zonemaster-0.4.8/src/soundtouch_zonemaster/py.typed +0 -0
  481. soundtouch_zonemaster-0.4.8/tests/conftest.py +145 -0
  482. soundtouch_zonemaster-0.4.8/tests/e2e/speaker_probe.py +63 -0
  483. soundtouch_zonemaster-0.4.8/tests/e2e_config.py +111 -0
  484. soundtouch_zonemaster-0.4.8/tests/e2e_defaults.toml +20 -0
  485. soundtouch_zonemaster-0.4.8/tests/fixtures/aftertouch-devices.json +54 -0
  486. soundtouch_zonemaster-0.4.8/tests/fixtures/burst-as-a-slave-frames.json +190 -0
  487. soundtouch_zonemaster-0.4.8/tests/fixtures/golden/channel_file.json +2920 -0
  488. soundtouch_zonemaster-0.4.8/tests/fixtures/golden/dialler.json +989 -0
  489. soundtouch_zonemaster-0.4.8/tests/fixtures/golden/observer.json +12505 -0
  490. soundtouch_zonemaster-0.4.8/tests/fixtures/golden/options.json +2815 -0
  491. soundtouch_zonemaster-0.4.8/tests/fixtures/golden/registry.json +503 -0
  492. soundtouch_zonemaster-0.4.8/tests/fixtures/golden/seeding.json +535 -0
  493. soundtouch_zonemaster-0.4.8/tests/fixtures/golden/slavemsg.json +1368 -0
  494. soundtouch_zonemaster-0.4.8/tests/fixtures/golden/state_file.json +936 -0
  495. soundtouch_zonemaster-0.4.8/tests/fixtures/house-20260921-dialling-frames.json +859 -0
  496. soundtouch_zonemaster-0.4.8/tests/fixtures/live-run-2-frames.json +1560 -0
  497. soundtouch_zonemaster-0.4.8/tests/fixtures/live-run-frames.json +760 -0
  498. soundtouch_zonemaster-0.4.8/tests/fixtures/notification-nowplaying.txt +5 -0
  499. soundtouch_zonemaster-0.4.8/tests/fixtures/notification-volume.txt +4 -0
  500. soundtouch_zonemaster-0.4.8/tests/fixtures/slavemsg-keydata.txt +10 -0
  501. soundtouch_zonemaster-0.4.8/tests/fixtures/superfly-24k.aac +0 -0
  502. soundtouch_zonemaster-0.4.8/tests/fixtures/sync-run.log +25 -0
  503. soundtouch_zonemaster-0.4.8/tests/fixtures/sync-silent.log +14 -0
  504. soundtouch_zonemaster-0.4.8/tests/fixtures/sync-spread.log +12 -0
  505. soundtouch_zonemaster-0.4.8/tests/fixtures/technikumcity-24k.mp3 +0 -0
  506. soundtouch_zonemaster-0.4.8/tests/fixtures/zone_frames.json +127 -0
  507. soundtouch_zonemaster-0.4.8/tests/hang_watchdog.py +254 -0
  508. soundtouch_zonemaster-0.4.8/tests/mpdfake.py +177 -0
  509. soundtouch_zonemaster-0.4.8/tests/registry_double.py +97 -0
  510. soundtouch_zonemaster-0.4.8/tests/speaker_double.py +540 -0
  511. soundtouch_zonemaster-0.4.8/tests/test_boundary_golden.py +1441 -0
  512. soundtouch_zonemaster-0.4.8/tests/test_calibration.py +245 -0
  513. soundtouch_zonemaster-0.4.8/tests/test_capture_model.py +100 -0
  514. soundtouch_zonemaster-0.4.8/tests/test_capture_zone.py +191 -0
  515. soundtouch_zonemaster-0.4.8/tests/test_channel_file.py +292 -0
  516. soundtouch_zonemaster-0.4.8/tests/test_channellist.py +389 -0
  517. soundtouch_zonemaster-0.4.8/tests/test_click_facades.py +103 -0
  518. soundtouch_zonemaster-0.4.8/tests/test_config.py +327 -0
  519. soundtouch_zonemaster-0.4.8/tests/test_config_private_overrides.py +155 -0
  520. soundtouch_zonemaster-0.4.8/tests/test_dialling.py +312 -0
  521. soundtouch_zonemaster-0.4.8/tests/test_domain_is_pure.py +129 -0
  522. soundtouch_zonemaster-0.4.8/tests/test_doubles.py +58 -0
  523. soundtouch_zonemaster-0.4.8/tests/test_e2e_config.py +96 -0
  524. soundtouch_zonemaster-0.4.8/tests/test_e2e_speakers.py +167 -0
  525. soundtouch_zonemaster-0.4.8/tests/test_export_public.py +509 -0
  526. soundtouch_zonemaster-0.4.8/tests/test_extract_protos.py +257 -0
  527. soundtouch_zonemaster-0.4.8/tests/test_golden_check.py +56 -0
  528. soundtouch_zonemaster-0.4.8/tests/test_house_dialling.py +215 -0
  529. soundtouch_zonemaster-0.4.8/tests/test_housevolume.py +127 -0
  530. soundtouch_zonemaster-0.4.8/tests/test_install_service.py +189 -0
  531. soundtouch_zonemaster-0.4.8/tests/test_key_events.py +145 -0
  532. soundtouch_zonemaster-0.4.8/tests/test_longpress.py +336 -0
  533. soundtouch_zonemaster-0.4.8/tests/test_membership.py +441 -0
  534. soundtouch_zonemaster-0.4.8/tests/test_metadata.py +85 -0
  535. soundtouch_zonemaster-0.4.8/tests/test_metadata_sync.py +86 -0
  536. soundtouch_zonemaster-0.4.8/tests/test_module_entry.py +126 -0
  537. soundtouch_zonemaster-0.4.8/tests/test_mpd_seek_ab.py +77 -0
  538. soundtouch_zonemaster-0.4.8/tests/test_mpd_status.py +59 -0
  539. soundtouch_zonemaster-0.4.8/tests/test_mpdclient.py +595 -0
  540. soundtouch_zonemaster-0.4.8/tests/test_never_touch.py +171 -0
  541. soundtouch_zonemaster-0.4.8/tests/test_no_private_names.py +91 -0
  542. soundtouch_zonemaster-0.4.8/tests/test_observe_keys.py +82 -0
  543. soundtouch_zonemaster-0.4.8/tests/test_observer.py +335 -0
  544. soundtouch_zonemaster-0.4.8/tests/test_play_order.py +160 -0
  545. soundtouch_zonemaster-0.4.8/tests/test_ports.py +64 -0
  546. soundtouch_zonemaster-0.4.8/tests/test_press_or_echo.py +690 -0
  547. soundtouch_zonemaster-0.4.8/tests/test_registry.py +178 -0
  548. soundtouch_zonemaster-0.4.8/tests/test_research_config.py +106 -0
  549. soundtouch_zonemaster-0.4.8/tests/test_safe_console.py +172 -0
  550. soundtouch_zonemaster-0.4.8/tests/test_service_cli.py +274 -0
  551. soundtouch_zonemaster-0.4.8/tests/test_service_config.py +627 -0
  552. soundtouch_zonemaster-0.4.8/tests/test_service_loopback.py +4014 -0
  553. soundtouch_zonemaster-0.4.8/tests/test_shutdown_is_quiet.py +170 -0
  554. soundtouch_zonemaster-0.4.8/tests/test_stream_end.py +132 -0
  555. soundtouch_zonemaster-0.4.8/tests/test_switch_and_state.py +404 -0
  556. soundtouch_zonemaster-0.4.8/tests/test_sync_report.py +211 -0
  557. soundtouch_zonemaster-0.4.8/tests/test_usage_error_envelope.py +127 -0
  558. soundtouch_zonemaster-0.4.8/tests/test_wheel_contents.py +95 -0
  559. soundtouch_zonemaster-0.4.8/tests/test_xmlread.py +289 -0
  560. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_bind_retry.py +176 -0
  561. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_cli.py +118 -0
  562. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_cli_machine_mode.py +160 -0
  563. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_frames.py +172 -0
  564. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_http_api.py +136 -0
  565. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_ipc.py +138 -0
  566. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_join_plan.py +347 -0
  567. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_limits.py +296 -0
  568. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_local_e2e.py +1066 -0
  569. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_reports.py +23 -0
  570. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_run_loop.py +191 -0
  571. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_select.py +47 -0
  572. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_source_resolution.py +111 -0
  573. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_speaker_calls.py +302 -0
  574. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_timeline.py +106 -0
  575. soundtouch_zonemaster-0.4.8/tests/test_zonemaster_xml_escaping.py +242 -0
  576. soundtouch_zonemaster-0.4.8/tools/_click.py +91 -0
  577. soundtouch_zonemaster-0.4.8/tools/export_public.py +591 -0
  578. soundtouch_zonemaster-0.4.8/tools/install_service.py +229 -0
  579. soundtouch_zonemaster-0.4.8/tools/public_redactions.example.txt +27 -0
@@ -0,0 +1,16 @@
1
+ # Optional. The hardware tests read their settings from tests/e2e_defaults.d/90-e2e-rnhome.toml
2
+ # (copy tests/e2e_defaults.d/90-e2e-rnhome.toml.example), which is where they belong: typed, and
3
+ # beside the safe defaults they override. A .env at the repository root (gitignored) is still read
4
+ # ABOVE that file, so a key set here wins over it. Everything in a .env is text: the speakers comma
5
+ # separated, E2E_AUDIBLE a word. Placeholders only below.
6
+
7
+ # The host on the speaker LAN that the probe runs on, and how to reach it.
8
+ E2E_HOST=
9
+ E2E_USER=root
10
+ E2E_KEY=/path/to/ssh/key
11
+
12
+ # The speakers the read-only probe may query, comma separated. List every box in the house.
13
+ E2E_SPEAKERS=192.0.2.11,192.0.2.12
14
+
15
+ # Whether a test may do something AUDIBLE. Leave false unless you know who is at home.
16
+ E2E_AUDIBLE=false
@@ -0,0 +1,15 @@
1
+ # Normalize every text file to LF in the repo AND the working tree, on every OS.
2
+ # `text=auto` auto-detects binary and leaves it untouched; `eol=lf` forces LF checkout
3
+ # so a Windows edit/save cannot reintroduce CRLF churn.
4
+ * text=auto eol=lf
5
+
6
+ # Runtime-critical: CRLF here breaks execution on Linux (^M in shebang / make recipes).
7
+ Makefile text eol=lf
8
+ *.sh text eol=lf
9
+ *.py text eol=lf
10
+ *.ps1 text eol=lf
11
+ *.toml text eol=lf
12
+ *.md text eol=lf
13
+ *.json text eol=lf
14
+ *.yml text eol=lf
15
+ *.yaml text eol=lf
@@ -0,0 +1,108 @@
1
+ name: Extract project metadata
2
+ description: >-
3
+ Parse pyproject.toml and expose project metadata as step outputs.
4
+ Requires Python to be available in the runner environment.
5
+ Auto-installs rtoml if not already present.
6
+
7
+ outputs:
8
+ PACKAGE_MODULE:
9
+ description: Python-importable module name (underscored)
10
+ value: ${{ steps.meta.outputs.PACKAGE_MODULE }}
11
+ PROJECT_NAME:
12
+ description: Project name from pyproject.toml
13
+ value: ${{ steps.meta.outputs.PROJECT_NAME }}
14
+ CLI_BIN:
15
+ description: CLI entry-point binary name
16
+ value: ${{ steps.meta.outputs.CLI_BIN }}
17
+ SRC_PATH:
18
+ description: Source directory path (e.g. "src")
19
+ value: ${{ steps.meta.outputs.SRC_PATH }}
20
+ COV_FAIL_UNDER:
21
+ description: Minimum coverage percentage from tool.coverage.report.fail_under
22
+ value: ${{ steps.meta.outputs.COV_FAIL_UNDER }}
23
+ COV_REPORT_FILE:
24
+ description: Coverage report filename (e.g. "coverage.xml")
25
+ value: ${{ steps.meta.outputs.COV_REPORT_FILE }}
26
+ PYTEST_VERBOSITY:
27
+ description: Pytest verbosity flag (e.g. "-vv")
28
+ value: ${{ steps.meta.outputs.PYTEST_VERBOSITY }}
29
+ BANDIT_SKIP_FLAG:
30
+ description: Bandit skip flag string (e.g. "-s B101,B601") or empty
31
+ value: ${{ steps.meta.outputs.BANDIT_SKIP_FLAG }}
32
+ PYTEST_MARKER_EXPR:
33
+ description: >-
34
+ Marker expression for the CI test run (e.g. "not local_only and not integration"),
35
+ built from tool.ci.pytest-exclude-markers
36
+ value: ${{ steps.meta.outputs.PYTEST_MARKER_EXPR }}
37
+
38
+ runs:
39
+ using: composite
40
+ steps:
41
+ - name: Extract project metadata from pyproject.toml
42
+ id: meta
43
+ shell: python
44
+ run: |
45
+ import os, subprocess, sys
46
+ try:
47
+ import rtoml
48
+ except ModuleNotFoundError:
49
+ subprocess.check_call([sys.executable, "-m", "pip", "install", "rtoml", "-q"])
50
+ import rtoml
51
+
52
+ from pathlib import Path
53
+ data = rtoml.load(Path('pyproject.toml'))
54
+
55
+ # --- [project] section ---
56
+ project = data['project']['name']
57
+ module = project.replace('-', '_')
58
+ dash = project.replace('_', '-')
59
+ scripts = list(data['project'].get('scripts', {}).keys())
60
+ cli_bin = scripts[0] if scripts else dash
61
+
62
+ # --- [tool.scripts.test] section ---
63
+ scripts_test = data.get('tool', {}).get('scripts', {}).get('test', {})
64
+ src_path = scripts_test.get('src-path', 'src')
65
+ pytest_verbosity = scripts_test.get('pytest-verbosity', '-vv')
66
+ cov_report_file = scripts_test.get('coverage-report-file', 'coverage.xml')
67
+
68
+ # --- [tool.coverage.report] section ---
69
+ cov_fail_under = (
70
+ data.get('tool', {}).get('coverage', {}).get('report', {}).get('fail_under', 90)
71
+ )
72
+
73
+ # --- [tool.bandit] section ---
74
+ bandit_skips = data.get('tool', {}).get('bandit', {}).get('skips', [])
75
+ bandit_skip_flag = f"-s {','.join(bandit_skips)}" if bandit_skips else ""
76
+
77
+ # --- [tool.ci] section ---
78
+ # CI always skips local_only (those tests need a dev box). A project whose
79
+ # suite also carries markers CI cannot satisfy - integration tests needing a
80
+ # container that a separate workflow starts - names them here, rather than
81
+ # every such repo forking this workflow to edit one -m expression.
82
+ ci_config = data.get('tool', {}).get('ci', {})
83
+ exclude_markers = ['local_only', *ci_config.get('pytest-exclude-markers', [])]
84
+ pytest_marker_expr = ' and '.join(f'not {m}' for m in exclude_markers)
85
+
86
+ # Write to GITHUB_OUTPUT for composite action outputs
87
+ with open(os.environ['GITHUB_OUTPUT'], 'a', encoding='utf-8') as out:
88
+ out.write(f"PROJECT_NAME={project}\n")
89
+ out.write(f"PACKAGE_MODULE={module}\n")
90
+ out.write(f"CLI_BIN={cli_bin}\n")
91
+ out.write(f"SRC_PATH={src_path}\n")
92
+ out.write(f"PYTEST_VERBOSITY={pytest_verbosity}\n")
93
+ out.write(f"COV_REPORT_FILE={cov_report_file}\n")
94
+ out.write(f"COV_FAIL_UNDER={cov_fail_under}\n")
95
+ out.write(f"BANDIT_SKIP_FLAG={bandit_skip_flag}\n")
96
+ out.write(f"PYTEST_MARKER_EXPR={pytest_marker_expr}\n")
97
+
98
+ # Also write to GITHUB_ENV so subsequent steps can use ${{ env.VAR }}
99
+ with open(os.environ['GITHUB_ENV'], 'a', encoding='utf-8') as env:
100
+ env.write(f"PROJECT_NAME={project}\n")
101
+ env.write(f"PACKAGE_MODULE={module}\n")
102
+ env.write(f"CLI_BIN={cli_bin}\n")
103
+ env.write(f"SRC_PATH={src_path}\n")
104
+ env.write(f"PYTEST_VERBOSITY={pytest_verbosity}\n")
105
+ env.write(f"COV_REPORT_FILE={cov_report_file}\n")
106
+ env.write(f"COV_FAIL_UNDER={cov_fail_under}\n")
107
+ env.write(f"BANDIT_SKIP_FLAG={bandit_skip_flag}\n")
108
+ env.write(f"PYTEST_MARKER_EXPR={pytest_marker_expr}\n")
@@ -0,0 +1,22 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "pip"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ allow:
8
+ - dependency-type: "direct"
9
+ labels:
10
+ - "dependencies"
11
+ commit-message:
12
+ prefix: "deps"
13
+ include: "scope"
14
+ - package-ecosystem: "github-actions"
15
+ directory: "/"
16
+ schedule:
17
+ interval: "weekly"
18
+ labels:
19
+ - "dependencies"
20
+ commit-message:
21
+ prefix: "deps"
22
+ include: "scope"
@@ -0,0 +1,39 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, master ]
6
+ pull_request:
7
+ branches: [ main, master ]
8
+ schedule:
9
+ - cron: '0 8 * * 1'
10
+
11
+ jobs:
12
+ analyze:
13
+ name: CodeQL Analyze
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ actions: read
17
+ contents: read
18
+ security-events: write
19
+ strategy:
20
+ fail-fast: false
21
+ matrix:
22
+ language: [ 'python' ]
23
+
24
+ steps:
25
+ - name: Checkout repository
26
+ uses: actions/checkout@v7
27
+
28
+ - name: Initialize CodeQL
29
+ uses: github/codeql-action/init@v4
30
+ with:
31
+ languages: ${{ matrix.language }}
32
+
33
+ - name: Autobuild
34
+ uses: github/codeql-action/autobuild@v4
35
+
36
+ - name: Perform CodeQL Analysis
37
+ uses: github/codeql-action/analyze@v4
38
+ with:
39
+ category: "/language:${{ matrix.language }}"
@@ -0,0 +1,436 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, master ]
6
+ pull_request:
7
+ branches: [ main, master ]
8
+ schedule:
9
+ # Run daily at 3:17 AM UTC (off-peak hours, odd minute to avoid congestion)
10
+ - cron: '17 3 * * *'
11
+
12
+ jobs:
13
+ setup:
14
+ name: Extract Python versions and OS matrix from pyproject.toml
15
+ runs-on: ubuntu-latest
16
+ outputs:
17
+ python-versions: ${{ steps.metadata.outputs.python-versions }}
18
+ python-latest: ${{ steps.metadata.outputs.python-latest }}
19
+ os-matrix: ${{ steps.metadata.outputs.os-matrix }}
20
+ steps:
21
+ - uses: actions/checkout@v7
22
+ - uses: actions/setup-python@v7
23
+ with:
24
+ python-version: "3.x"
25
+ - name: Parse pyproject.toml for Python versions and OS matrix
26
+ id: metadata
27
+ shell: python
28
+ run: |
29
+ import json, os, tomllib
30
+
31
+ with open("pyproject.toml", "rb") as f:
32
+ data = tomllib.load(f)
33
+
34
+ # Python versions from classifiers
35
+ classifiers = data.get("project", {}).get("classifiers", [])
36
+ prefix = "Programming Language :: Python :: "
37
+ versions = [
38
+ c[len(prefix):]
39
+ for c in classifiers
40
+ if c.startswith(prefix) and "." in c[len(prefix):]
41
+ ]
42
+ if not versions:
43
+ raise SystemExit("No Python X.Y versions found in classifiers")
44
+
45
+ # OS matrix from [tool.ci]
46
+ ci_config = data.get("tool", {}).get("ci", {})
47
+ os_list = ci_config.get("os", ["ubuntu-latest"])
48
+
49
+ with open(os.environ["GITHUB_OUTPUT"], "a") as fh:
50
+ fh.write(f"python-versions={json.dumps(versions)}\n")
51
+ fh.write(f"python-latest={versions[-1]}\n")
52
+ fh.write(f"os-matrix={json.dumps(os_list)}\n")
53
+
54
+ test:
55
+ name: Tests (Python ${{ matrix.python }}, ${{ matrix.os }})
56
+ needs: setup
57
+ runs-on: ${{ matrix.os }}
58
+ strategy:
59
+ fail-fast: false
60
+ matrix:
61
+ os: ${{ fromJSON(needs.setup.outputs.os-matrix) }}
62
+ python: ${{ fromJSON(needs.setup.outputs.python-versions) }}
63
+ env:
64
+ PYO3_USE_ABI3_FORWARD_COMPATIBILITY: "1"
65
+ PYTHONIOENCODING: "utf-8"
66
+ UV_LINK_MODE: "copy"
67
+ UV_BREAK_SYSTEM_PACKAGES: "1"
68
+ steps:
69
+ - uses: actions/checkout@v7
70
+ - uses: actions/setup-python@v7
71
+ with:
72
+ python-version: ${{ matrix.python }}
73
+ - name: Install uv
74
+ uses: astral-sh/setup-uv@v7
75
+ with:
76
+ enable-cache: true
77
+ prune-cache: false
78
+
79
+ - name: Install bash 4+ on macOS
80
+ if: runner.os == 'macOS'
81
+ run: |
82
+ brew install bash
83
+ echo "$(brew --prefix)/bin" >> "$GITHUB_PATH"
84
+
85
+ - name: Extract project metadata
86
+ id: metadata
87
+ uses: ./.github/actions/extract-metadata
88
+
89
+ - name: Install CI system dependencies (Ubuntu)
90
+ if: runner.os == 'Linux'
91
+ shell: python
92
+ run: |
93
+ import subprocess
94
+ try:
95
+ import tomllib
96
+ except ModuleNotFoundError:
97
+ import pip._vendor.tomli as tomllib
98
+ with open("pyproject.toml", "rb") as f:
99
+ data = tomllib.load(f)
100
+ deps = data.get("tool", {}).get("ci", {}).get("system-dependencies-ubuntu", [])
101
+ if deps:
102
+ print(f"Installing system packages: {' '.join(deps)}")
103
+ subprocess.check_call(["sudo", "apt-get", "update"])
104
+ subprocess.check_call(["sudo", "apt-get", "install", "-y", *deps])
105
+ else:
106
+ print("No CI system dependencies configured for Ubuntu.")
107
+
108
+ - name: Install CI system dependencies (macOS)
109
+ if: runner.os == 'macOS'
110
+ shell: python
111
+ run: |
112
+ import subprocess
113
+ try:
114
+ import tomllib
115
+ except ModuleNotFoundError:
116
+ import pip._vendor.tomli as tomllib
117
+ with open("pyproject.toml", "rb") as f:
118
+ data = tomllib.load(f)
119
+ deps = data.get("tool", {}).get("ci", {}).get("system-dependencies-macos", [])
120
+ if deps:
121
+ print(f"Installing system packages: {' '.join(deps)}")
122
+ subprocess.check_call(["brew", "install", *deps])
123
+ else:
124
+ print("No CI system dependencies configured for macOS.")
125
+
126
+ - name: Install dev deps
127
+ shell: bash
128
+ run: |
129
+ uv pip install -e .[dev] --system
130
+
131
+ - name: Install CI system dependencies (Windows/choco)
132
+ if: runner.os == 'Windows'
133
+ shell: python
134
+ run: |
135
+ import subprocess
136
+ try:
137
+ import tomllib
138
+ except ModuleNotFoundError:
139
+ import pip._vendor.tomli as tomllib
140
+ with open("pyproject.toml", "rb") as f:
141
+ data = tomllib.load(f)
142
+ deps = data.get("tool", {}).get("ci", {}).get("system-dependencies-windows-choco", [])
143
+ if deps:
144
+ print(f"Installing choco packages: {' '.join(deps)}")
145
+ subprocess.check_call(["choco", "install", "-y", *deps])
146
+ else:
147
+ print("No CI choco dependencies configured for Windows.")
148
+
149
+ - name: Install CI pip dependencies (Windows)
150
+ if: runner.os == 'Windows'
151
+ shell: python
152
+ run: |
153
+ import subprocess
154
+ try:
155
+ import tomllib
156
+ except ModuleNotFoundError:
157
+ import pip._vendor.tomli as tomllib
158
+ with open("pyproject.toml", "rb") as f:
159
+ data = tomllib.load(f)
160
+ deps = data.get("tool", {}).get("ci", {}).get("system-dependencies-windows-pip", [])
161
+ if deps:
162
+ print(f"Installing pip packages: {' '.join(deps)}")
163
+ subprocess.check_call(["uv", "pip", "install", *deps, "--system"])
164
+ else:
165
+ print("No CI pip dependencies configured for Windows.")
166
+
167
+ # Self-hosted runners persist ruff cache via RUFF_CACHE_DIR volume mount,
168
+ # so actions/cache is only needed on GitHub-hosted runners.
169
+ - name: Restore ruff cache
170
+ if: runner.environment == 'github-hosted'
171
+ id: ruff-cache
172
+ uses: actions/cache/restore@v6
173
+ with:
174
+ path: .ruff_cache
175
+ key: ruff-${{ runner.os }}-py${{ matrix.python }}-${{ github.sha }}
176
+ restore-keys: |
177
+ ruff-${{ runner.os }}-py${{ matrix.python }}-
178
+ ruff-${{ runner.os }}-
179
+
180
+ - name: Run ruff (lint + format)
181
+ id: ruff
182
+ continue-on-error: true
183
+ shell: bash
184
+ run: |
185
+ ruff check .
186
+ ruff format --check .
187
+
188
+ - name: Run pyright (type check)
189
+ id: pyright
190
+ continue-on-error: true
191
+ shell: bash
192
+ run: pyright
193
+
194
+ - name: Run pytest (tests + coverage)
195
+ id: pytest
196
+ continue-on-error: true
197
+ shell: bash
198
+ env:
199
+ TEST_VERBOSE: "1"
200
+ # Write coverage SQLite database to local disk — network mounts
201
+ # and stale journal files cause "database is locked" errors.
202
+ COVERAGE_FILE: "${{ runner.temp }}/.coverage"
203
+ run: >-
204
+ pytest -m "${{ env.PYTEST_MARKER_EXPR }}"
205
+ --cov=${{ env.SRC_PATH }}/${{ env.PACKAGE_MODULE }}
206
+ --cov-report=term-missing
207
+ --cov-report=xml:${{ env.COV_REPORT_FILE }}
208
+ --cov-fail-under=${{ env.COV_FAIL_UNDER }}
209
+ ${{ env.PYTEST_VERBOSITY }}
210
+
211
+ - name: Upload coverage to Codecov
212
+ if: >-
213
+ always()
214
+ && steps.pytest.outcome == 'success'
215
+ && matrix.os == 'ubuntu-latest'
216
+ && matrix.python == needs.setup.outputs.python-latest
217
+ uses: codecov/codecov-action@v7
218
+ with:
219
+ files: ${{ env.COV_REPORT_FILE }}
220
+ fail_ci_if_error: false
221
+
222
+ - name: Run import-linter (architecture)
223
+ id: importlinter
224
+ continue-on-error: true
225
+ shell: bash
226
+ run: lint-imports
227
+
228
+ - name: Run bandit (security scan)
229
+ id: bandit
230
+ continue-on-error: true
231
+ shell: bash
232
+ run: bandit -q -c pyproject.toml -r ${{ env.SRC_PATH }}/${{ env.PACKAGE_MODULE }} ${{ env.BANDIT_SKIP_FLAG }}
233
+
234
+ - name: Run pip-audit (vulnerability scan)
235
+ id: pipaudit
236
+ continue-on-error: true
237
+ shell: python
238
+ run: |
239
+ import subprocess, sys, tempfile
240
+ import rtoml
241
+ from pathlib import Path
242
+
243
+ # Audit the project's OWN resolved dependency tree, not the ambient
244
+ # environment. "Install dev deps" uses --system, so the interpreter
245
+ # being audited is the runner image's, and that image ships packages
246
+ # this project neither declares nor distributes (setuptools, pip,
247
+ # wheel). Auditing those reported CVEs no consumer of this project is
248
+ # exposed to, and a scan that is permanently yellow is a scan everyone
249
+ # learns to ignore. Resolving pyproject.toml here keeps the result
250
+ # identical on every OS/python and dependent only on what we declare.
251
+ data = rtoml.load(Path("pyproject.toml"))
252
+
253
+ # Not every project declares dev dependencies, and those that do may use
254
+ # either an extra or a PEP 735 group. Asking uv for one that does not
255
+ # exist is a hard error ("Requested extra not found"), which would leave
256
+ # the audit permanently broken here rather than merely noisy, so select
257
+ # the flag from what this project actually declares.
258
+ selector = []
259
+ if "dev" in data.get("project", {}).get("optional-dependencies", {}):
260
+ selector = ["--extra", "dev"]
261
+ elif "dev" in data.get("dependency-groups", {}):
262
+ selector = ["--group", "dev"]
263
+
264
+ tmp = Path(tempfile.mkdtemp())
265
+ req = tmp / "compiled-requirements.txt"
266
+ subprocess.check_call(
267
+ ["uv", "pip", "compile", *selector, "pyproject.toml", "-o", str(req), "--quiet"]
268
+ )
269
+
270
+ # Drop direct URL references ("pkg @ git+https://...") before auditing.
271
+ # pip-audit cannot audit those (they are not on PyPI) but, given a
272
+ # requirements file, first tries to `git clone` each one to resolve a
273
+ # version - a slow, credential-dependent fetch. No public project here
274
+ # uses one today, yet "allow-direct-references" is enabled, so this
275
+ # guards the day one appears and keeps this step identical to the
276
+ # default_cicd_private template's.
277
+ audit_req = tmp / "audit-requirements.txt"
278
+ kept, dropped = [], []
279
+ for line in req.read_text(encoding="utf-8").splitlines():
280
+ if " @ " in line and not line.lstrip().startswith("#"):
281
+ dropped.append(line.split(" @ ", 1)[0].strip())
282
+ else:
283
+ kept.append(line)
284
+ audit_req.write_text("\n".join(kept) + "\n", encoding="utf-8")
285
+ if dropped:
286
+ # Never drop coverage silently: name what is not being audited here.
287
+ print(f"::notice::pip-audit: not auditing {len(dropped)} direct-URL dependency/ies "
288
+ f"(audited in their own repo): {', '.join(sorted(dropped))}")
289
+
290
+ req = audit_req
291
+ vulns = data.get("tool", {}).get("pip-audit", {}).get("ignore-vulns", [])
292
+ # --no-deps: the compiled file is already a complete pinned resolution,
293
+ # so pip-audit must audit it verbatim rather than re-resolving it.
294
+ cmd = ["pip-audit", "--no-deps", "-r", str(req)]
295
+ for v in vulns:
296
+ cmd.extend(["--ignore-vuln", v])
297
+ sys.exit(subprocess.call(cmd))
298
+
299
+ - name: Check all steps passed
300
+ shell: bash
301
+ run: |
302
+ if [[ "${{ steps.ruff.outcome }}" != "success" ]]; then
303
+ echo "::error::Ruff check failed"
304
+ exit 1
305
+ fi
306
+ if [[ "${{ steps.pyright.outcome }}" != "success" ]]; then
307
+ echo "::error::Pyright check failed"
308
+ exit 1
309
+ fi
310
+ if [[ "${{ steps.pytest.outcome }}" != "success" ]]; then
311
+ echo "::error::Pytest failed"
312
+ exit 1
313
+ fi
314
+ if [[ "${{ steps.importlinter.outcome }}" != "success" ]]; then
315
+ echo "::error::Import-linter check failed"
316
+ exit 1
317
+ fi
318
+ if [[ "${{ steps.bandit.outcome }}" != "success" ]]; then
319
+ echo "::error::Bandit security scan failed"
320
+ exit 1
321
+ fi
322
+ if [[ "${{ steps.pipaudit.outcome }}" != "success" ]]; then
323
+ echo "::warning::pip-audit vulnerability scan failed"
324
+ fi
325
+ echo "All checks passed!"
326
+
327
+ - name: Build wheel/sdist
328
+ shell: bash
329
+ run: uv build
330
+
331
+ - name: Verify wheel install in clean env
332
+ shell: bash
333
+ run: |
334
+ uv venv .venv_wheel
335
+ . .venv_wheel/bin/activate 2>/dev/null || . .venv_wheel/Scripts/activate 2>/dev/null
336
+ uv pip install dist/*.whl
337
+ "$CLI_BIN" --version 2>/dev/null || python -m "$PACKAGE_MODULE" --version
338
+
339
+ - name: Prune uv cache
340
+ continue-on-error: true
341
+ shell: bash
342
+ run: uv cache prune --ci
343
+
344
+ - name: Save ruff cache
345
+ if: always() && runner.environment == 'github-hosted' && steps.ruff-cache.outputs.cache-hit != 'true'
346
+ uses: actions/cache/save@v6
347
+ with:
348
+ path: .ruff_cache
349
+ key: ruff-${{ runner.os }}-py${{ matrix.python }}-${{ github.sha }}
350
+
351
+ pipx-uv:
352
+ name: pipx/uv verification (ubuntu)
353
+ runs-on: ubuntu-latest
354
+ steps:
355
+ - uses: actions/checkout@v7
356
+ - uses: actions/setup-python@v7
357
+ with:
358
+ python-version: "3.14"
359
+
360
+ - name: Install uv
361
+ uses: astral-sh/setup-uv@v7
362
+ with:
363
+ enable-cache: true
364
+ prune-cache: false
365
+
366
+ - name: Extract project metadata
367
+ id: metadata
368
+ uses: ./.github/actions/extract-metadata
369
+
370
+ - name: Build wheel
371
+ run: uv build
372
+ - name: pipx install from wheel
373
+ run: |
374
+ uv pip install --system pipx
375
+ pipx ensurepath
376
+ export PATH="$HOME/.local/bin:$PATH"
377
+ pipx install dist/*.whl
378
+ "$CLI_BIN" --version
379
+
380
+ - name: uv tool install
381
+ run: |
382
+ export PATH="$HOME/.local/bin:$PATH"
383
+ uv tool install --force .
384
+ "$CLI_BIN" --version
385
+
386
+ - name: Prune uv cache
387
+ continue-on-error: true
388
+ run: uv cache prune --ci
389
+
390
+ notebooks:
391
+ name: Execute notebooks (ubuntu, Python 3.14)
392
+ runs-on: ubuntu-latest
393
+ steps:
394
+ - uses: actions/checkout@v7
395
+ - uses: actions/setup-python@v7
396
+ with:
397
+ python-version: "3.14"
398
+
399
+ - name: Install uv
400
+ uses: astral-sh/setup-uv@v7
401
+ with:
402
+ enable-cache: true
403
+ prune-cache: false
404
+
405
+ - name: Install notebook runner deps
406
+ run: |
407
+ uv pip install --system nbclient nbformat ipykernel jupyter_client
408
+ python -m ipykernel install --user --name python3 --display-name "Python 3"
409
+ - name: Execute Quickstart notebook
410
+ env:
411
+ PIP_DISABLE_PIP_VERSION_CHECK: "1"
412
+ PIP_NO_INPUT: "1"
413
+ run: |
414
+ python - << 'PY'
415
+ from pathlib import Path
416
+
417
+ import nbformat
418
+ from nbclient import NotebookClient
419
+
420
+ nb_path = Path('notebooks/Quickstart.ipynb')
421
+ if not nb_path.exists():
422
+ raise SystemExit(f"Notebook not found: {nb_path}")
423
+
424
+ notebook = nbformat.read(nb_path, as_version=4)
425
+ client = NotebookClient(
426
+ notebook,
427
+ timeout=900,
428
+ kernel_name='python3',
429
+ allow_errors=False,
430
+ )
431
+ client.execute()
432
+
433
+ out_path = Path('notebooks/Quickstart-executed.ipynb')
434
+ nbformat.write(notebook, out_path)
435
+ print(f"Executed notebook written to: {out_path}")
436
+ PY