streamlit-nightly 1.52.3.dev20260113__py3-none-any.whl → 1.53.1.dev20260115__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. streamlit/__init__.py +0 -26
  2. streamlit/commands/logo.py +2 -0
  3. streamlit/commands/page_config.py +16 -16
  4. streamlit/components/v2/__init__.py +2 -2
  5. streamlit/config.py +29 -0
  6. streamlit/connections/base_connection.py +16 -4
  7. streamlit/connections/snowflake_connection.py +254 -205
  8. streamlit/elements/form.py +2 -2
  9. streamlit/elements/lib/streamlit_plotly_theme.py +9 -11
  10. streamlit/elements/metric.py +49 -48
  11. streamlit/elements/widgets/button.py +9 -9
  12. streamlit/elements/widgets/chat.py +5 -9
  13. streamlit/elements/widgets/data_editor.py +3 -3
  14. streamlit/elements/widgets/file_uploader.py +10 -11
  15. streamlit/elements/widgets/select_slider.py +4 -0
  16. streamlit/proto/NewSession_pb2.py +18 -18
  17. streamlit/proto/NewSession_pb2.pyi +5 -1
  18. streamlit/runtime/app_session.py +78 -58
  19. streamlit/runtime/caching/cache_data_api.py +25 -21
  20. streamlit/runtime/caching/cache_resource_api.py +69 -41
  21. streamlit/runtime/connection_factory.py +67 -41
  22. streamlit/runtime/scriptrunner_utils/script_run_context.py +0 -21
  23. streamlit/runtime/state/query_params.py +0 -19
  24. streamlit/static/index.html +1 -1
  25. streamlit/static/manifest.json +296 -296
  26. streamlit/static/static/js/{ErrorOutline.esm.BjVqd_6R.js → ErrorOutline.esm.CiSfK8ht.js} +1 -1
  27. streamlit/static/static/js/{FileDownload.esm.DJCSsghl.js → FileDownload.esm.ItNjcEfs.js} +1 -1
  28. streamlit/static/static/js/{FileHelper.C---TH7o.js → FileHelper.xS7f19FE.js} +1 -1
  29. streamlit/static/static/js/{FormClearHelper.C-6BC487.js → FormClearHelper.N8_BCinn.js} +1 -1
  30. streamlit/static/static/js/{InputInstructions.sxc3InCI.js → InputInstructions.CrsdK7CQ.js} +1 -1
  31. streamlit/static/static/js/Particles.BDlTHC3I.js +1 -0
  32. streamlit/static/static/js/{ProgressBar.BiYsyZCC.js → ProgressBar.Bk2qeHfS.js} +2 -2
  33. streamlit/static/static/js/{StreamlitSyntaxHighlighter.9jZF8jX1.js → StreamlitSyntaxHighlighter.BcuPrPcw.js} +1 -1
  34. streamlit/static/static/js/{TableChart.esm.BdA4Q1rZ.js → TableChart.esm.CP7XPz8I.js} +1 -1
  35. streamlit/static/static/js/Toolbar.DCJcLwve.js +1 -0
  36. streamlit/static/static/js/{WidgetLabelHelpIconInline.DxODTLS2.js → WidgetLabelHelpIconInline.BPqxu1b-.js} +1 -1
  37. streamlit/static/static/js/{base-input.Gf1cKuQR.js → base-input.x4muJJ13.js} +4 -4
  38. streamlit/static/static/js/{checkbox.CnoNruf3.js → checkbox.C5r4AIaH.js} +1 -1
  39. streamlit/static/static/js/{createDownloadLinkElement.B48AepiL.js → createDownloadLinkElement.C83kkEeT.js} +1 -1
  40. streamlit/static/static/js/{data-grid-overlay-editor.Cmdq9aqU.js → data-grid-overlay-editor.0sOWm4IB.js} +1 -1
  41. streamlit/static/static/js/{downloader.CQLoQdMX.js → downloader.C_6FfoEv.js} +1 -1
  42. streamlit/static/static/js/{embed.oKwocwU8.js → embed.BnJ6-SK4.js} +14 -14
  43. streamlit/static/static/js/{es6.BRxlY_y5.js → es6.44_BWfFd.js} +2 -2
  44. streamlit/static/static/js/{formatNumber.DaagZyZe.js → formatNumber.DhHZAosz.js} +1 -1
  45. streamlit/static/static/js/{iconPosition.Q3hNvmK4.js → iconPosition.shOoQuRR.js} +1 -1
  46. streamlit/static/static/js/{iframeResizer.contentWindow.B6EBvI9L.js → iframeResizer.contentWindow.savEE5Vs.js} +1 -1
  47. streamlit/static/static/js/{index.BF23fbfs.js → index.AdijUi9Z.js} +1 -1
  48. streamlit/static/static/js/{index.OpATzEaW.js → index.B5HlOnvq.js} +1 -1
  49. streamlit/static/static/js/{index.Ca7MUNWJ.js → index.B6ewTTej.js} +1 -1
  50. streamlit/static/static/js/{index.CP-hoxJM.js → index.B8Of3XXR.js} +1 -1
  51. streamlit/static/static/js/{index.whRT3Vm3.js → index.BCaCSVj6.js} +1 -1
  52. streamlit/static/static/js/index.BE7Rhig1.js +1 -0
  53. streamlit/static/static/js/{index.BkSwGJoh.js → index.BHpLZ7X6.js} +2 -2
  54. streamlit/static/static/js/{index.na9UBuse.js → index.BNvP8E5Q.js} +1 -1
  55. streamlit/static/static/js/{index.CYE7b5Du.js → index.BNzuyXeN.js} +2 -2
  56. streamlit/static/static/js/{index.slgxPafU.js → index.BT7o4A9V.js} +1 -1
  57. streamlit/static/static/js/{index.BXEC4cf3.js → index.BYY3iuVE.js} +1 -1
  58. streamlit/static/static/js/index.BZI7jTDf.js +1 -0
  59. streamlit/static/static/js/{index.19_qtO6t.js → index.BZXk3Qxq.js} +1 -1
  60. streamlit/static/static/js/{index.B03eQZoH.js → index.BhQvq6YD.js} +1 -1
  61. streamlit/static/static/js/{index.WXybx2Xq.js → index.BkIReLGJ.js} +3 -3
  62. streamlit/static/static/js/{index.BoX8d5rK.js → index.Bl7SMZUw.js} +1 -1
  63. streamlit/static/static/js/{index.BGBTkulf.js → index.BqtgAGnG.js} +2 -2
  64. streamlit/static/static/js/{index.KtjGDGY5.js → index.BwnLQnAk.js} +1 -1
  65. streamlit/static/static/js/index.C1coXTgf.js +2 -0
  66. streamlit/static/static/js/{index.CVlg41MB.js → index.C6uOmY9O.js} +1 -1
  67. streamlit/static/static/js/index.CF88nImM.js +1 -0
  68. streamlit/static/static/js/{index.CFCBhOfx.js → index.CFlGfFvq.js} +1 -1
  69. streamlit/static/static/js/{index.Xg-Qttib.js → index.CQgiNpC7.js} +1 -1
  70. streamlit/static/static/js/{index.CCFwVy90.js → index.CZJkiRFm.js} +1 -1
  71. streamlit/static/static/js/index.Ch1TdQMG.js +1 -0
  72. streamlit/static/static/js/{index.CvIqsWy1.js → index.Ck2mQvBi.js} +1 -1
  73. streamlit/static/static/js/{index.BAI9aHCq.js → index.CrD2lwZG.js} +1 -1
  74. streamlit/static/static/js/index.CySNwKoN.js +2 -0
  75. streamlit/static/static/js/index.D3LEkXqN.js +1 -0
  76. streamlit/static/static/js/{index.QTaWooav.js → index.D8BQH06Z.js} +1 -1
  77. streamlit/static/static/js/{index.B9kZB0o1.js → index.DBtWixG1.js} +1 -1
  78. streamlit/static/static/js/{index.BzwlrgZO.js → index.DIsNrJpC.js} +1 -1
  79. streamlit/static/static/js/{index.Fu73QtkD.js → index.DO3HICut.js} +1 -1
  80. streamlit/static/static/js/{index.KN1VmyYN.js → index.D_ziFad8.js} +1 -1
  81. streamlit/static/static/js/{index.pU9mQeVC.js → index.Dblsdn8d.js} +1 -1
  82. streamlit/static/static/js/{index.Boa0Egng.js → index.DcdD0ROn.js} +2 -2
  83. streamlit/static/static/js/{index.CvB9JBqS.js → index.DfHm3P22.js} +51 -51
  84. streamlit/static/static/js/{index.BRfGUOQ-.js → index.DiwhD0Ic.js} +46 -46
  85. streamlit/static/static/js/index.DvZDNiBV.js +11 -0
  86. streamlit/static/static/js/{index.CJ4oJe0V.js → index.HjydQ4bj.js} +1 -1
  87. streamlit/static/static/js/{index.BbSFVZ3p.js → index.HsxzYHNf.js} +1 -1
  88. streamlit/static/static/js/{index.BVT89mQw.js → index.SVJGpnpy.js} +1 -1
  89. streamlit/static/static/js/index.SjKkVSL7.js +1 -0
  90. streamlit/static/static/js/index.hX8_3tMP.js +1 -0
  91. streamlit/static/static/js/{index.CCQ5p_WC.js → index.jZin0w6_.js} +1 -1
  92. streamlit/static/static/js/{index.BnfTPrHb.js → index.pQvPlPcA.js} +4 -4
  93. streamlit/static/static/js/index.pzQTLx9j.js +1 -0
  94. streamlit/static/static/js/{index.D6X2coHR.js → index.s44_OVd6.js} +33 -33
  95. streamlit/static/static/js/{input.CPzINTl-.js → input.jAD-v9D6.js} +2 -2
  96. streamlit/static/static/js/{main.DSPn8dUe.js → main.Cas0fuOs.js} +1 -1
  97. streamlit/static/static/js/{memory.CfD8IGoU.js → memory.ENruL8Qk.js} +1 -1
  98. streamlit/static/static/js/{number-overlay-editor.4Ae0qegV.js → number-overlay-editor.DAOTdulh.js} +2 -2
  99. streamlit/static/static/js/{pandasStylerUtils.D2EjZ7k6.js → pandasStylerUtils.DChYgcPq.js} +1 -1
  100. streamlit/static/static/js/{sandbox.C6vcPIm0.js → sandbox.DWZYRCm0.js} +1 -1
  101. streamlit/static/static/js/{styled-components.BBmp8buj.js → styled-components.3lwVqgRW.js} +1 -1
  102. streamlit/static/static/js/{throttle.BPcPpy-S.js → throttle.DfOW1Cns.js} +1 -1
  103. streamlit/static/static/js/{timepicker.ryzkTs2C.js → timepicker.CXHgL5f9.js} +1 -1
  104. streamlit/static/static/js/{toConsumableArray.Dg1nDaB_.js → toConsumableArray.DiW0GSDV.js} +1 -1
  105. streamlit/static/static/js/uniqueId.Dfi3SGKZ.js +1 -0
  106. streamlit/static/static/js/{useBasicWidgetState.A4U5lzAm.js → useBasicWidgetState.DnPEt_f3.js} +1 -1
  107. streamlit/static/static/js/{useIntlLocale.DWJgLlNz.js → useIntlLocale.BZEGSOVD.js} +8 -8
  108. streamlit/static/static/js/{useTextInputAutoExpand.BrBonw8t.js → useTextInputAutoExpand.MGVZMqyt.js} +1 -1
  109. streamlit/static/static/js/useUpdateUiValue.CPl6CEx3.js +1 -0
  110. streamlit/static/static/js/{useWaveformController.CBlvXlgZ.js → useWaveformController.DOpzDyZu.js} +1 -1
  111. streamlit/static/static/js/{withCalculatedWidth.D4cpOyNe.js → withCalculatedWidth.DgKFTeif.js} +1 -1
  112. streamlit/static/static/js/{withFullScreenWrapper.BMim3w94.js → withFullScreenWrapper.K1jkwhPu.js} +1 -1
  113. streamlit/user_info.py +225 -166
  114. {streamlit_nightly-1.52.3.dev20260113.dist-info → streamlit_nightly-1.53.1.dev20260115.dist-info}/METADATA +1 -1
  115. {streamlit_nightly-1.52.3.dev20260113.dist-info → streamlit_nightly-1.53.1.dev20260115.dist-info}/RECORD +119 -120
  116. streamlit/commands/experimental_query_params.py +0 -169
  117. streamlit/static/static/js/Particles.S8yD7iW-.js +0 -1
  118. streamlit/static/static/js/Toolbar.B9DaaDfN.js +0 -1
  119. streamlit/static/static/js/index.43b777iP.js +0 -1
  120. streamlit/static/static/js/index.C0fSEz-3.js +0 -1
  121. streamlit/static/static/js/index.CIbgt5wY.js +0 -1
  122. streamlit/static/static/js/index.CSfsEKCF.js +0 -2
  123. streamlit/static/static/js/index.CrPjcPY1.js +0 -1
  124. streamlit/static/static/js/index.D1pK_Vw2.js +0 -1
  125. streamlit/static/static/js/index.DGYHxruh.js +0 -1
  126. streamlit/static/static/js/index.DJ7P09eb.js +0 -2
  127. streamlit/static/static/js/index.Dh5SAThV.js +0 -11
  128. streamlit/static/static/js/index.QHnxuesF.js +0 -1
  129. streamlit/static/static/js/index.j4fnjyHo.js +0 -1
  130. streamlit/static/static/js/uniqueId.BFHzT5KQ.js +0 -1
  131. streamlit/static/static/js/useUpdateUiValue.BkOWyNVX.js +0 -1
  132. {streamlit_nightly-1.52.3.dev20260113.data → streamlit_nightly-1.53.1.dev20260115.data}/scripts/streamlit.cmd +0 -0
  133. {streamlit_nightly-1.52.3.dev20260113.dist-info → streamlit_nightly-1.53.1.dev20260115.dist-info}/WHEEL +0 -0
  134. {streamlit_nightly-1.52.3.dev20260113.dist-info → streamlit_nightly-1.53.1.dev20260115.dist-info}/entry_points.txt +0 -0
  135. {streamlit_nightly-1.52.3.dev20260113.dist-info → streamlit_nightly-1.53.1.dev20260115.dist-info}/top_level.txt +0 -0
@@ -1 +1 @@
1
- import{l as Z,r as i,aR as M,ab as $,aS as O}from"./index.BRfGUOQ-.js";async function q(l,e=16e3){if(!l||l.size===0)throw new Error("Invalid or empty blob provided");if(!window.AudioContext)throw new Error("AudioContext not supported in this browser");const o=new AudioContext;try{const n=await l.arrayBuffer(),r=await o.decodeAudioData(n),d=e??r.sampleRate,s=await J(r,d);return K(s,d)}finally{o.close()}}async function J(l,e){const{duration:o,numberOfChannels:n,sampleRate:r}=l,d=Math.ceil(o*e);if(!window.OfflineAudioContext)throw new Error("OfflineAudioContext not supported");const s=new OfflineAudioContext(1,d,e),p=s.createBufferSource();if(p.buffer=l,n>1){const h=s.createChannelSplitter(n),m=s.createChannelMerger(1);p.connect(h);for(let c=0;c<n;c++){const u=s.createGain();u.gain.value=1/n,h.connect(u,c),u.connect(m,0,0)}m.connect(s.destination)}else p.connect(s.destination);p.start(0);try{return await s.startRendering()}catch(h){throw new Error(`Failed to resample audio from ${r}Hz to ${e}Hz: ${h instanceof Error?h.message:String(h)}`)}}function K(l,e){const n=l.length,r=n*2+44,d=new ArrayBuffer(r),s=new DataView(d),p=l.getChannelData(0),h=(c,u)=>{for(let y=0;y<u.length;y++)s.setUint8(c+y,u.charCodeAt(y))};h(0,"RIFF"),s.setUint32(4,r-8,!0),h(8,"WAVE"),h(12,"fmt "),s.setUint32(16,16,!0),s.setUint16(20,1,!0),s.setUint16(22,1,!0),s.setUint32(24,e,!0),s.setUint32(28,e*2,!0),s.setUint16(32,2,!0),s.setUint16(34,16,!0),h(36,"data"),s.setUint32(40,n*2,!0);let m=44;for(let c=0;c<n;c++){const u=Math.max(-1,Math.min(1,p[c]));s.setInt16(m,u*32767,!0),m+=2}return new Blob([d],{type:"audio/wav"})}class W{constructor(){this.wavesurfer=null,this.currentBlobUrl=null,this.events={},this.isPlaying=!1}initialize(e){this.wavesurfer=e,this.setupEventListeners()}setupEventListeners(){this.wavesurfer&&(this.teardownEventListeners(),this.handleTimeUpdate=e=>{this.events.onTimeUpdate?.(e*1e3)},this.handlePause=()=>{this.isPlaying=!1,this.events.onPause?.()},this.handlePlay=()=>{this.isPlaying=!0,this.events.onPlay?.()},this.handleFinish=()=>{this.isPlaying=!1,this.events.onFinish?.()},this.handleReady=()=>{this.events.onReady?.()},this.handleError=e=>{const o=e instanceof Error?e:new Error(String(e));this.events.onError?.(o)},this.wavesurfer.on("timeupdate",this.handleTimeUpdate),this.wavesurfer.on("pause",this.handlePause),this.wavesurfer.on("play",this.handlePlay),this.wavesurfer.on("finish",this.handleFinish),this.wavesurfer.on("ready",this.handleReady),this.wavesurfer.on("error",this.handleError))}setEventHandlers(e){this.events=e}async load(e){if(!this.wavesurfer)throw new Error("WaveSurfer not initialized");this.cleanupPreviousUrl();let o,n=null;try{if(e instanceof Blob)n=URL.createObjectURL(e),o=n;else if(e instanceof ArrayBuffer){const r=new Blob([e]);n=URL.createObjectURL(r),o=n}else o=e;this.currentBlobUrl=n,await this.wavesurfer.load(o)}catch(r){throw this.cleanupPreviousUrl(),r}}async play(){if(!this.wavesurfer)throw new Error("WaveSurfer not initialized");await this.wavesurfer.play()}pause(){this.wavesurfer&&this.wavesurfer.pause()}getDuration(){return this.wavesurfer?this.wavesurfer.getDuration()*1e3:0}getCurrentTime(){return this.wavesurfer?this.wavesurfer.getCurrentTime()*1e3:0}getIsPlaying(){return this.isPlaying}seekToStart(){this.wavesurfer&&this.wavesurfer.seekTo(0)}cleanupPreviousUrl(){this.currentBlobUrl&&(URL.revokeObjectURL(this.currentBlobUrl),this.currentBlobUrl=null)}destroy(){this.pause(),this.cleanupPreviousUrl(),this.wavesurfer&&(this.teardownEventListeners(),this.wavesurfer.empty(),this.wavesurfer=null),this.events={},this.isPlaying=!1,this.handleTimeUpdate=void 0,this.handlePause=void 0,this.handlePlay=void 0,this.handleFinish=void 0,this.handleReady=void 0,this.handleError=void 0}teardownEventListeners(){this.wavesurfer&&(this.handleTimeUpdate&&(this.wavesurfer.un("timeupdate",this.handleTimeUpdate),this.handleTimeUpdate=void 0),this.handlePause&&(this.wavesurfer.un("pause",this.handlePause),this.handlePause=void 0),this.handlePlay&&(this.wavesurfer.un("play",this.handlePlay),this.handlePlay=void 0),this.handleFinish&&(this.wavesurfer.un("finish",this.handleFinish),this.handleFinish=void 0),this.handleReady&&(this.wavesurfer.un("ready",this.handleReady),this.handleReady=void 0),this.handleError&&(this.wavesurfer.un("error",this.handleError),this.handleError=void 0))}}function I(l){return l.name==="NotAllowedError"||l.name==="PermissionDeniedError"||l.message?.toLowerCase().includes("permission denied")}class Q{constructor(e={}){this.wavesurfer=null,this.recordPlugin=null,this.isRecording=!1,this.recordEndResolve=null,this.recordEndReject=null,this.events={},this.options=e}initialize(e,o){this.wavesurfer=e;try{const n={renderRecordedAudio:!1,mimeType:"audio/webm"};this.recordPlugin=e.registerPlugin(o.create(n)),this.setupEventListeners()}catch(n){const r=n instanceof Error?n:new Error(String(n));throw I(r)?(this.events.onPermissionDenied?.(),new Error("Microphone permission denied")):(this.events.onError?.(r),r)}}setupEventListeners(){this.recordPlugin&&(this.recordPlugin.on("record-start",()=>{this.isRecording=!0,this.events.onRecordStart?.()}),this.recordPlugin.on("record-end",e=>{this.isRecording=!1,this.events.onRecordEnd?.(e),this.recordEndResolve&&e&&e.size>0?(this.recordEndResolve(e),this.recordEndResolve=null,this.recordEndReject=null):this.recordEndReject?(this.recordEndReject(new Error("Invalid or empty recording")),this.recordEndResolve=null,this.recordEndReject=null):(this.recordEndResolve=null,this.recordEndReject=null)}),this.recordPlugin.on("record-progress",e=>{this.events.onRecordProgress?.(e)}))}setEventHandlers(e){this.events=e}async startRecording(){if(!this.recordPlugin)throw new Error("Record plugin not initialized");if(this.isRecording)return;const e=typeof this.options.sampleRate=="number"?this.options.sampleRate:void 0,o={};e!==void 0&&(o.sampleRate={ideal:e}),await this.startRecordingWithConstraints(o,e!==void 0)}async startRecordingWithConstraints(e,o){if(!this.recordPlugin)throw new Error("Record plugin not initialized");try{const n=Object.keys(e).length?e:void 0;await this.recordPlugin.startRecording(n)}catch(n){const r=n instanceof Error?n:new Error(String(n));if(I(r))throw this.events.onPermissionDenied?.(),new Error("Microphone permission denied");if(o&&(r.name==="OverconstrainedError"||r.name==="NotReadableError")){this.options.sampleRate=void 0,await this.startRecordingWithConstraints({},!1);return}throw this.events.onError?.(r),r}}async stopRecording(){if(!this.recordPlugin||!this.isRecording)throw new Error("Not currently recording");try{return await new Promise((e,o)=>{this.recordEndResolve=e,this.recordEndReject=o,this.recordPlugin?.stopRecording()})}catch(e){const o=e instanceof Error?e:new Error(String(e));throw this.events.onError?.(o),o}}cancelRecording(){this.recordPlugin&&this.isRecording&&(this.recordPlugin.stopRecording(),this.isRecording=!1,this.recordEndResolve=null,this.recordEndReject=null)}destroy(){this.cancelRecording(),this.recordPlugin&&(this.recordPlugin.destroy(),this.recordPlugin=null),this.wavesurfer=null,this.events={}}}const X=4,Y=4,ee=8,re=0,te=16e3;function se({containerRef:l,sampleRate:e,events:o,waveformPadding:n=0}){const r=Z(),[d,s]=i.useState("idle"),[p,h]=i.useState(null),[m,c]=i.useState(!1),u=i.useRef(null),y=i.useRef(null),a=i.useRef(null),f=i.useRef(o),U=i.useRef(!1),D=i.useRef(!1),E=i.useRef(new Set),P=i.useRef(!1),b=e===void 0?te:e,A=i.useCallback(()=>{E.current.clear(),c(!1),y.current&&(y.current.destroy(),y.current=null),a.current&&(a.current.destroy(),a.current=null),u.current&&(u.current.destroy(),u.current=null),U.current=!1,P.current=!1,s("idle"),h(null)},[]),x=i.useCallback(()=>{const t=Array.from(E.current);E.current.clear(),t.forEach(w=>{w.resolve()})},[]),_=i.useCallback(t=>{c(!1);const w=Array.from(E.current);E.current.clear(),w.forEach(v=>{v.reject(t)})},[]),T=i.useCallback(t=>{const w={onPlay:()=>{c(!0),f.current.onPlaybackPlay?.()},onPause:()=>{c(!1),f.current.onPlaybackPause?.()},onFinish:()=>{c(!1),f.current.onPlaybackFinish?.()},onReady:()=>{x()},onError:v=>{c(!1),_(v),f.current.onError?.(v)}};t.setEventHandlers(w)},[x,_]);i.useEffect(()=>{f.current=o,a.current&&T(a.current)},[o,T]);const S=i.useCallback(async()=>{if(!(U.current||D.current||!l.current)){D.current=!0;try{const[t,w]=await Promise.all([M(()=>import("./wavesurfer.esm.D1Sty35j.js"),[],import.meta.url),M(()=>import("./record.DytFsBUt.js"),[],import.meta.url)]),v=t.default,B=w.default,k=v.create({container:l.current,waveColor:r.colors.primary,progressColor:r.colors.bodyText,height:n>0?$(r.sizes.largestElementHeight)-2*n:"auto",barWidth:X,barGap:Y,barRadius:ee,cursorWidth:re,interact:!0});u.current=k,P.current=!1;const C=new Q({sampleRate:b});C.initialize(k,B),C.setEventHandlers({onRecordProgress:R=>{f.current.onProgressMs?.(R)},onPermissionDenied:()=>{f.current.onPermissionDenied(),s("idle")},onError:R=>{f.current.onError(R),s("idle")}}),y.current=C;const g=new W;g.initialize(k),a.current=g,T(g),U.current=!0}catch(t){const w=t instanceof Error?t:new Error(String(t));f.current.onError?.(w)}finally{D.current=!1}}},[l,r,b,T,n]);i.useEffect(()=>(S(),()=>{A()}),[A,S]),i.useEffect(()=>{const t=u.current;if(t){if(d==="recording"){t.setOptions({waveColor:r.colors.primary,progressColor:r.colors.primary});return}if(P.current){t.setOptions({interact:!0,waveColor:O(r.colors.fadedText40,r.colors.secondaryBg),progressColor:r.colors.bodyText});return}t.setOptions({waveColor:r.colors.primary,progressColor:r.colors.bodyText})}},[d,r.colors.bodyText,r.colors.fadedText40,r.colors.primary,r.colors.secondaryBg]);const F=i.useCallback(async()=>{if(d!=="recording"){if(U.current||await S(),!y.current)throw new Error("Record backend not initialized");u.current&&u.current.setOptions({waveColor:r.colors.primary,progressColor:r.colors.primary}),P.current=!1,await y.current.startRecording(),s("recording"),h(null),c(!1),f.current.onRecordStart?.()}},[d,S,r.colors.primary]),L=i.useCallback(()=>{a.current&&u.current&&(a.current.destroy(),a.current=new W,a.current.initialize(u.current),E.current.clear(),c(!1),T(a.current)),P.current=!1},[T]),z=i.useCallback(()=>{a.current?.seekToStart(),c(!1),P.current=!0,u.current&&u.current.setOptions({interact:!0,waveColor:O(r.colors.fadedText40,r.colors.secondaryBg),progressColor:r.colors.bodyText})},[r.colors.bodyText,r.colors.fadedText40,r.colors.secondaryBg]),H=i.useCallback(async()=>{if(d!=="recording")throw new Error("Not currently recording");if(!y.current||!a.current)throw new Error("Backends not initialized");try{const t=await y.current.stopRecording();h(t),await new Promise((k,C)=>{if(!a.current){C(new Error("Player not initialized"));return}const g={resolve:()=>{E.current.delete(g),k()},reject:R=>{E.current.delete(g),C(R)}};E.current.add(g),a.current.load(t).catch(R=>{E.current.delete(g),C(R instanceof Error?R:new Error(String(R)))})}),s("idle"),c(!1),z();const v={durationMs:a.current?.getDuration()??0,sampleRate:typeof b=="number"?b:null,mimeType:t.type||"audio/webm",size:t.size},B={blob:t,meta:v};return f.current.onRecordReady?.(t),B}catch(t){const w=t instanceof Error?t:new Error(String(t));return c(!1),s("idle"),f.current.onError(w),{blob:new Blob,meta:{durationMs:0,sampleRate:null,mimeType:"audio/webm",size:0}}}},[d,z,b]),j=i.useCallback(async t=>{const w=t??p;if(!w){const v=new Error("No recorded audio to approve");f.current.onError(v);return}try{const v=await q(w,b);await f.current.onApprove?.(v),h(null),s("idle")}catch(v){const B=v instanceof Error?v:new Error(String(v));f.current.onError(B)}},[p,b]),N=i.useCallback(()=>{d==="recording"&&y.current?.cancelRecording(),L(),h(null),s("idle"),c(!1),P.current=!1,f.current.onCancel?.()},[d,L]),V=i.useMemo(()=>({isPlaying:()=>a.current?.getIsPlaying()??!1,play:async()=>{if(!a.current)throw new Error("Player not initialized");await a.current.play()},pause:()=>{a.current?.pause()},load:async t=>{if(U.current||await S(),!a.current)throw new Error("Player not initialized");await a.current.load(t),z()},getCurrentTimeMs:()=>a.current?.getCurrentTime()??0,getDurationMs:()=>a.current?.getDuration()??0}),[z,S]),G=i.useCallback(t=>{f.current=t},[]);return i.useEffect(()=>()=>{A()},[A]),{state:d,isPlaybackPlaying:m,mountRef:l,start:F,stop:H,approve:j,cancel:N,destroy:A,playback:V,setEventHandlers:G}}export{se as u};
1
+ import{l as Z,r as i,aP as M,aa as $,aQ as O}from"./index.DiwhD0Ic.js";async function q(l,e=16e3){if(!l||l.size===0)throw new Error("Invalid or empty blob provided");if(!window.AudioContext)throw new Error("AudioContext not supported in this browser");const o=new AudioContext;try{const n=await l.arrayBuffer(),r=await o.decodeAudioData(n),d=e??r.sampleRate,s=await Q(r,d);return J(s,d)}finally{o.close()}}async function Q(l,e){const{duration:o,numberOfChannels:n,sampleRate:r}=l,d=Math.ceil(o*e);if(!window.OfflineAudioContext)throw new Error("OfflineAudioContext not supported");const s=new OfflineAudioContext(1,d,e),p=s.createBufferSource();if(p.buffer=l,n>1){const h=s.createChannelSplitter(n),m=s.createChannelMerger(1);p.connect(h);for(let c=0;c<n;c++){const u=s.createGain();u.gain.value=1/n,h.connect(u,c),u.connect(m,0,0)}m.connect(s.destination)}else p.connect(s.destination);p.start(0);try{return await s.startRendering()}catch(h){throw new Error(`Failed to resample audio from ${r}Hz to ${e}Hz: ${h instanceof Error?h.message:String(h)}`)}}function J(l,e){const n=l.length,r=n*2+44,d=new ArrayBuffer(r),s=new DataView(d),p=l.getChannelData(0),h=(c,u)=>{for(let y=0;y<u.length;y++)s.setUint8(c+y,u.charCodeAt(y))};h(0,"RIFF"),s.setUint32(4,r-8,!0),h(8,"WAVE"),h(12,"fmt "),s.setUint32(16,16,!0),s.setUint16(20,1,!0),s.setUint16(22,1,!0),s.setUint32(24,e,!0),s.setUint32(28,e*2,!0),s.setUint16(32,2,!0),s.setUint16(34,16,!0),h(36,"data"),s.setUint32(40,n*2,!0);let m=44;for(let c=0;c<n;c++){const u=Math.max(-1,Math.min(1,p[c]));s.setInt16(m,u*32767,!0),m+=2}return new Blob([d],{type:"audio/wav"})}class W{constructor(){this.wavesurfer=null,this.currentBlobUrl=null,this.events={},this.isPlaying=!1}initialize(e){this.wavesurfer=e,this.setupEventListeners()}setupEventListeners(){this.wavesurfer&&(this.teardownEventListeners(),this.handleTimeUpdate=e=>{this.events.onTimeUpdate?.(e*1e3)},this.handlePause=()=>{this.isPlaying=!1,this.events.onPause?.()},this.handlePlay=()=>{this.isPlaying=!0,this.events.onPlay?.()},this.handleFinish=()=>{this.isPlaying=!1,this.events.onFinish?.()},this.handleReady=()=>{this.events.onReady?.()},this.handleError=e=>{const o=e instanceof Error?e:new Error(String(e));this.events.onError?.(o)},this.wavesurfer.on("timeupdate",this.handleTimeUpdate),this.wavesurfer.on("pause",this.handlePause),this.wavesurfer.on("play",this.handlePlay),this.wavesurfer.on("finish",this.handleFinish),this.wavesurfer.on("ready",this.handleReady),this.wavesurfer.on("error",this.handleError))}setEventHandlers(e){this.events=e}async load(e){if(!this.wavesurfer)throw new Error("WaveSurfer not initialized");this.cleanupPreviousUrl();let o,n=null;try{if(e instanceof Blob)n=URL.createObjectURL(e),o=n;else if(e instanceof ArrayBuffer){const r=new Blob([e]);n=URL.createObjectURL(r),o=n}else o=e;this.currentBlobUrl=n,await this.wavesurfer.load(o)}catch(r){throw this.cleanupPreviousUrl(),r}}async play(){if(!this.wavesurfer)throw new Error("WaveSurfer not initialized");await this.wavesurfer.play()}pause(){this.wavesurfer&&this.wavesurfer.pause()}getDuration(){return this.wavesurfer?this.wavesurfer.getDuration()*1e3:0}getCurrentTime(){return this.wavesurfer?this.wavesurfer.getCurrentTime()*1e3:0}getIsPlaying(){return this.isPlaying}seekToStart(){this.wavesurfer&&this.wavesurfer.seekTo(0)}cleanupPreviousUrl(){this.currentBlobUrl&&(URL.revokeObjectURL(this.currentBlobUrl),this.currentBlobUrl=null)}destroy(){this.pause(),this.cleanupPreviousUrl(),this.wavesurfer&&(this.teardownEventListeners(),this.wavesurfer.empty(),this.wavesurfer=null),this.events={},this.isPlaying=!1,this.handleTimeUpdate=void 0,this.handlePause=void 0,this.handlePlay=void 0,this.handleFinish=void 0,this.handleReady=void 0,this.handleError=void 0}teardownEventListeners(){this.wavesurfer&&(this.handleTimeUpdate&&(this.wavesurfer.un("timeupdate",this.handleTimeUpdate),this.handleTimeUpdate=void 0),this.handlePause&&(this.wavesurfer.un("pause",this.handlePause),this.handlePause=void 0),this.handlePlay&&(this.wavesurfer.un("play",this.handlePlay),this.handlePlay=void 0),this.handleFinish&&(this.wavesurfer.un("finish",this.handleFinish),this.handleFinish=void 0),this.handleReady&&(this.wavesurfer.un("ready",this.handleReady),this.handleReady=void 0),this.handleError&&(this.wavesurfer.un("error",this.handleError),this.handleError=void 0))}}function I(l){return l.name==="NotAllowedError"||l.name==="PermissionDeniedError"||l.message?.toLowerCase().includes("permission denied")}class K{constructor(e={}){this.wavesurfer=null,this.recordPlugin=null,this.isRecording=!1,this.recordEndResolve=null,this.recordEndReject=null,this.events={},this.options=e}initialize(e,o){this.wavesurfer=e;try{const n={renderRecordedAudio:!1,mimeType:"audio/webm"};this.recordPlugin=e.registerPlugin(o.create(n)),this.setupEventListeners()}catch(n){const r=n instanceof Error?n:new Error(String(n));throw I(r)?(this.events.onPermissionDenied?.(),new Error("Microphone permission denied")):(this.events.onError?.(r),r)}}setupEventListeners(){this.recordPlugin&&(this.recordPlugin.on("record-start",()=>{this.isRecording=!0,this.events.onRecordStart?.()}),this.recordPlugin.on("record-end",e=>{this.isRecording=!1,this.events.onRecordEnd?.(e),this.recordEndResolve&&e&&e.size>0?(this.recordEndResolve(e),this.recordEndResolve=null,this.recordEndReject=null):this.recordEndReject?(this.recordEndReject(new Error("Invalid or empty recording")),this.recordEndResolve=null,this.recordEndReject=null):(this.recordEndResolve=null,this.recordEndReject=null)}),this.recordPlugin.on("record-progress",e=>{this.events.onRecordProgress?.(e)}))}setEventHandlers(e){this.events=e}async startRecording(){if(!this.recordPlugin)throw new Error("Record plugin not initialized");if(this.isRecording)return;const e=typeof this.options.sampleRate=="number"?this.options.sampleRate:void 0,o={};e!==void 0&&(o.sampleRate={ideal:e}),await this.startRecordingWithConstraints(o,e!==void 0)}async startRecordingWithConstraints(e,o){if(!this.recordPlugin)throw new Error("Record plugin not initialized");try{const n=Object.keys(e).length?e:void 0;await this.recordPlugin.startRecording(n)}catch(n){const r=n instanceof Error?n:new Error(String(n));if(I(r))throw this.events.onPermissionDenied?.(),new Error("Microphone permission denied");if(o&&(r.name==="OverconstrainedError"||r.name==="NotReadableError")){this.options.sampleRate=void 0,await this.startRecordingWithConstraints({},!1);return}throw this.events.onError?.(r),r}}async stopRecording(){if(!this.recordPlugin||!this.isRecording)throw new Error("Not currently recording");try{return await new Promise((e,o)=>{this.recordEndResolve=e,this.recordEndReject=o,this.recordPlugin?.stopRecording()})}catch(e){const o=e instanceof Error?e:new Error(String(e));throw this.events.onError?.(o),o}}cancelRecording(){this.recordPlugin&&this.isRecording&&(this.recordPlugin.stopRecording(),this.isRecording=!1,this.recordEndResolve=null,this.recordEndReject=null)}destroy(){this.cancelRecording(),this.recordPlugin&&(this.recordPlugin.destroy(),this.recordPlugin=null),this.wavesurfer=null,this.events={}}}const X=4,Y=4,ee=8,re=0,te=16e3;function se({containerRef:l,sampleRate:e,events:o,waveformPadding:n=0}){const r=Z(),[d,s]=i.useState("idle"),[p,h]=i.useState(null),[m,c]=i.useState(!1),u=i.useRef(null),y=i.useRef(null),a=i.useRef(null),f=i.useRef(o),S=i.useRef(!1),D=i.useRef(!1),E=i.useRef(new Set),P=i.useRef(!1),b=e===void 0?te:e,A=i.useCallback(()=>{E.current.clear(),c(!1),y.current&&(y.current.destroy(),y.current=null),a.current&&(a.current.destroy(),a.current=null),u.current&&(u.current.destroy(),u.current=null),S.current=!1,P.current=!1,s("idle"),h(null)},[]),x=i.useCallback(()=>{const t=Array.from(E.current);E.current.clear(),t.forEach(w=>{w.resolve()})},[]),_=i.useCallback(t=>{c(!1);const w=Array.from(E.current);E.current.clear(),w.forEach(v=>{v.reject(t)})},[]),T=i.useCallback(t=>{const w={onPlay:()=>{c(!0),f.current.onPlaybackPlay?.()},onPause:()=>{c(!1),f.current.onPlaybackPause?.()},onFinish:()=>{c(!1),f.current.onPlaybackFinish?.()},onReady:()=>{x()},onError:v=>{c(!1),_(v),f.current.onError?.(v)}};t.setEventHandlers(w)},[x,_]);i.useEffect(()=>{f.current=o,a.current&&T(a.current)},[o,T]);const U=i.useCallback(async()=>{if(!(S.current||D.current||!l.current)){D.current=!0;try{const[t,w]=await Promise.all([M(()=>import("./wavesurfer.esm.D1Sty35j.js"),[],import.meta.url),M(()=>import("./record.DytFsBUt.js"),[],import.meta.url)]),v=t.default,B=w.default,k=v.create({container:l.current,waveColor:r.colors.primary,progressColor:r.colors.bodyText,height:n>0?$(r.sizes.largestElementHeight)-2*n:"auto",barWidth:X,barGap:Y,barRadius:ee,cursorWidth:re,interact:!0});u.current=k,P.current=!1;const C=new K({sampleRate:b});C.initialize(k,B),C.setEventHandlers({onRecordProgress:R=>{f.current.onProgressMs?.(R)},onPermissionDenied:()=>{f.current.onPermissionDenied(),s("idle")},onError:R=>{f.current.onError(R),s("idle")}}),y.current=C;const g=new W;g.initialize(k),a.current=g,T(g),S.current=!0}catch(t){const w=t instanceof Error?t:new Error(String(t));f.current.onError?.(w)}finally{D.current=!1}}},[l,r,b,T,n]);i.useEffect(()=>(U(),()=>{A()}),[A,U]),i.useEffect(()=>{const t=u.current;if(t){if(d==="recording"){t.setOptions({waveColor:r.colors.primary,progressColor:r.colors.primary});return}if(P.current){t.setOptions({interact:!0,waveColor:O(r.colors.fadedText40,r.colors.secondaryBg),progressColor:r.colors.bodyText});return}t.setOptions({waveColor:r.colors.primary,progressColor:r.colors.bodyText})}},[d,r.colors.bodyText,r.colors.fadedText40,r.colors.primary,r.colors.secondaryBg]);const F=i.useCallback(async()=>{if(d!=="recording"){if(S.current||await U(),!y.current)throw new Error("Record backend not initialized");u.current&&u.current.setOptions({waveColor:r.colors.primary,progressColor:r.colors.primary}),P.current=!1,await y.current.startRecording(),s("recording"),h(null),c(!1),f.current.onRecordStart?.()}},[d,U,r.colors.primary]),L=i.useCallback(()=>{a.current&&u.current&&(a.current.destroy(),a.current=new W,a.current.initialize(u.current),E.current.clear(),c(!1),T(a.current)),P.current=!1},[T]),z=i.useCallback(()=>{a.current?.seekToStart(),c(!1),P.current=!0,u.current&&u.current.setOptions({interact:!0,waveColor:O(r.colors.fadedText40,r.colors.secondaryBg),progressColor:r.colors.bodyText})},[r.colors.bodyText,r.colors.fadedText40,r.colors.secondaryBg]),H=i.useCallback(async()=>{if(d!=="recording")throw new Error("Not currently recording");if(!y.current||!a.current)throw new Error("Backends not initialized");try{const t=await y.current.stopRecording();h(t),await new Promise((k,C)=>{if(!a.current){C(new Error("Player not initialized"));return}const g={resolve:()=>{E.current.delete(g),k()},reject:R=>{E.current.delete(g),C(R)}};E.current.add(g),a.current.load(t).catch(R=>{E.current.delete(g),C(R instanceof Error?R:new Error(String(R)))})}),s("idle"),c(!1),z();const v={durationMs:a.current?.getDuration()??0,sampleRate:typeof b=="number"?b:null,mimeType:t.type||"audio/webm",size:t.size},B={blob:t,meta:v};return f.current.onRecordReady?.(t),B}catch(t){const w=t instanceof Error?t:new Error(String(t));return c(!1),s("idle"),f.current.onError(w),{blob:new Blob,meta:{durationMs:0,sampleRate:null,mimeType:"audio/webm",size:0}}}},[d,z,b]),j=i.useCallback(async t=>{const w=t??p;if(!w){const v=new Error("No recorded audio to approve");f.current.onError(v);return}try{const v=await q(w,b);await f.current.onApprove?.(v),h(null),s("idle")}catch(v){const B=v instanceof Error?v:new Error(String(v));f.current.onError(B)}},[p,b]),N=i.useCallback(()=>{d==="recording"&&y.current?.cancelRecording(),L(),h(null),s("idle"),c(!1),P.current=!1,f.current.onCancel?.()},[d,L]),V=i.useMemo(()=>({isPlaying:()=>a.current?.getIsPlaying()??!1,play:async()=>{if(!a.current)throw new Error("Player not initialized");await a.current.play()},pause:()=>{a.current?.pause()},load:async t=>{if(S.current||await U(),!a.current)throw new Error("Player not initialized");await a.current.load(t),z()},getCurrentTimeMs:()=>a.current?.getCurrentTime()??0,getDurationMs:()=>a.current?.getDuration()??0}),[z,U]),G=i.useCallback(t=>{f.current=t},[]);return i.useEffect(()=>()=>{A()},[A]),{state:d,isPlaybackPlaying:m,mountRef:l,start:F,stop:H,approve:j,cancel:N,destroy:A,playback:V,setEventHandlers:G}}export{se as u};
@@ -1 +1 @@
1
- import{h as l,k as h,j as s,d as n}from"./index.BRfGUOQ-.js";const o=t=>{const a=e=>{const{width:i,elementRef:c}=h();return s(n,{ref:c,children:s(t,{...e,width:i})})};return a.displayName=`withCalculatedWidth(${t.displayName||t.name})`,l(a,t)};export{o as w};
1
+ import{h as l,k as h,j as s,d as n}from"./index.DiwhD0Ic.js";const o=t=>{const a=e=>{const{width:i,elementRef:c}=h();return s(n,{ref:c,children:s(t,{...e,width:i})})};return a.displayName=`withCalculatedWidth(${t.displayName||t.name})`,l(a,t)};export{o as w};
@@ -1 +1 @@
1
- import{r as n,F as f,b7 as p,b8 as h,l as x,k as y,j as i,h as g}from"./index.BRfGUOQ-.js";const m=n.createContext(null);m.displayName="ElementFullscreenContext";const w=f("div",{target:"e5bcvgj0"})(({theme:e,isExpanded:t})=>({width:"100%",height:"100%",...t?{position:"fixed",top:0,left:0,bottom:0,right:0,background:e.colors.bgColor,zIndex:e.zIndices.fullscreenWrapper,padding:e.spacing.md,paddingTop:e.sizes.fullScreenHeaderHeight,overflow:"auto",display:"flex",alignItems:"center",justifyContent:"center"}:{}})),C=()=>{const{setFullScreen:e}=n.useContext(p),[t,s]=n.useState(!1),{fullHeight:a,fullWidth:c}=h(),l=n.useCallback(r=>{s(r),e(r)},[e]),u=n.useCallback(()=>{document.body.style.overflow="hidden",l(!0)},[l]),o=n.useCallback(()=>{document.body.style.overflow="unset",l(!1)},[l]),d=n.useCallback(r=>{r.keyCode===27&&t&&o()},[o,t]);return n.useEffect(()=>(document.addEventListener("keydown",d,!1),()=>{document.removeEventListener("keydown",d,!1)}),[d]),n.useMemo(()=>({expanded:t,zoomIn:u,zoomOut:o,fullHeight:a,fullWidth:c}),[t,u,o,a,c])},F=({children:e})=>{const t=x(),{expanded:s,fullHeight:a,fullWidth:c,zoomIn:l,zoomOut:u}=C(),{width:o,elementRef:d}=y(),r=n.useMemo(()=>({width:s?c:o,height:s?a:void 0,expanded:s,expand:l,collapse:u}),[s,a,c,o,l,u]);return i(m.Provider,{value:r,children:i(w,{ref:d,isExpanded:s,"data-testid":"stFullScreenFrame",theme:t,children:e})})};function S(e){const t=s=>i(F,{children:i(e,{...s})});return t.displayName=`withFullScreenWrapper(${e.displayName||e.name})`,g(t,e)}export{m as E,S as w};
1
+ import{r as n,z as f,b5 as p,b6 as h,l as x,k as y,j as i,h as g}from"./index.DiwhD0Ic.js";const m=n.createContext(null);m.displayName="ElementFullscreenContext";const w=f("div",{target:"e5bcvgj0"})(({theme:e,isExpanded:t})=>({width:"100%",height:"100%",...t?{position:"fixed",top:0,left:0,bottom:0,right:0,background:e.colors.bgColor,zIndex:e.zIndices.fullscreenWrapper,padding:e.spacing.md,paddingTop:e.sizes.fullScreenHeaderHeight,overflow:"auto",display:"flex",alignItems:"center",justifyContent:"center"}:{}})),C=()=>{const{setFullScreen:e}=n.useContext(p),[t,s]=n.useState(!1),{fullHeight:a,fullWidth:c}=h(),l=n.useCallback(r=>{s(r),e(r)},[e]),u=n.useCallback(()=>{document.body.style.overflow="hidden",l(!0)},[l]),o=n.useCallback(()=>{document.body.style.overflow="unset",l(!1)},[l]),d=n.useCallback(r=>{r.keyCode===27&&t&&o()},[o,t]);return n.useEffect(()=>(document.addEventListener("keydown",d,!1),()=>{document.removeEventListener("keydown",d,!1)}),[d]),n.useMemo(()=>({expanded:t,zoomIn:u,zoomOut:o,fullHeight:a,fullWidth:c}),[t,u,o,a,c])},b=({children:e})=>{const t=x(),{expanded:s,fullHeight:a,fullWidth:c,zoomIn:l,zoomOut:u}=C(),{width:o,elementRef:d}=y(),r=n.useMemo(()=>({width:s?c:o,height:s?a:void 0,expanded:s,expand:l,collapse:u}),[s,a,c,o,l,u]);return i(m.Provider,{value:r,children:i(w,{ref:d,isExpanded:s,"data-testid":"stFullScreenFrame",theme:t,children:e})})};function S(e){const t=s=>i(b,{children:i(e,{...s})});return t.displayName=`withFullScreenWrapper(${e.displayName||e.name})`,g(t,e)}export{m as E,S as w};
streamlit/user_info.py CHANGED
@@ -70,15 +70,19 @@ def login(provider: str | None = None) -> None:
70
70
  ``st.user``. If the provider returns an access token, that
71
71
  token is ignored unless you explicitly expose it.
72
72
 
73
- For all providers, there are two shared settings, ``redirect_uri`` and
74
- ``cookie_secret``, which you must specify in an ``[auth]`` dictionary
75
- in ``secrets.toml``. Other settings must be defined as described in the
76
- ``provider`` parameter.
73
+ For all providers, there are three shared settings, ``redirect_uri``,
74
+ ``cookie_secret``, and ``expose_tokens``, which you must specify in an
75
+ ``[auth]`` dictionary in ``secrets.toml``. Other settings must be defined
76
+ as described in the ``provider`` parameter.
77
77
 
78
78
  - ``redirect_uri`` is your app's absolute URL with the pathname
79
79
  ``oauth2callback``. For local development using the default port, this is
80
80
  ``http://localhost:8501/oauth2callback``.
81
81
  - ``cookie_secret`` should be a strong, randomly generated secret.
82
+ - ``expose_tokens`` is a list of token types to expose. The supported token
83
+ types are ``"id"`` and ``"access"``. This is an optional setting, and no
84
+ tokens are exposed by default. For information and examples about exposing
85
+ tokens, see |st.user|_.
82
86
 
83
87
  In addition to the shared settings, the following settings are required:
84
88
 
@@ -148,26 +152,28 @@ def login(provider: str | None = None) -> None:
148
152
  using OIDC with Google, see `Google Identity
149
153
  <https://developers.google.com/identity/openid-connect/openid-connect>`_.
150
154
 
151
- ``.streamlit/secrets.toml``:
155
+ .. code-block:: toml
156
+ :filename: .streamlit/secrets.toml
152
157
 
153
- >>> [auth]
154
- >>> redirect_uri = "http://localhost:8501/oauth2callback"
155
- >>> cookie_secret = "xxx"
156
- >>> client_id = "xxx"
157
- >>> client_secret = "xxx"
158
- >>> server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration" # fmt: skip
158
+ [auth]
159
+ redirect_uri = "http://localhost:8501/oauth2callback"
160
+ cookie_secret = "xxx"
161
+ client_id = "xxx"
162
+ client_secret = "xxx"
163
+ server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration" # fmt: skip
159
164
 
160
- Your app code:
165
+ .. code-block:: python
166
+ :filename: streamlit_app.py
161
167
 
162
- >>> import streamlit as st
163
- >>>
164
- >>> if not st.user.is_logged_in:
165
- >>> if st.button("Log in"):
166
- >>> st.login()
167
- >>> else:
168
- >>> if st.button("Log out"):
169
- >>> st.logout()
170
- >>> st.write(f"Hello, {st.user.name}!")
168
+ import streamlit as st
169
+
170
+ if not st.user.is_logged_in:
171
+ if st.button("Log in"):
172
+ st.login()
173
+ else:
174
+ if st.button("Log out"):
175
+ st.logout()
176
+ st.write(f"Hello, {st.user.name}!")
171
177
 
172
178
  **Example 2: Use a named identity provider**
173
179
 
@@ -184,25 +190,27 @@ def login(provider: str | None = None) -> None:
184
190
  `Microsoft identity platform
185
191
  <https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols-oidc#find-your-apps-openid-configuration-document-uri>`_.
186
192
 
187
- ``.streamlit/secrets.toml``:
193
+ .. code-block:: toml
194
+ :filename: .streamlit/secrets.toml
188
195
 
189
- >>> [auth]
190
- >>> redirect_uri = "http://localhost:8501/oauth2callback"
191
- >>> cookie_secret = "xxx"
192
- >>>
193
- >>> [auth.microsoft]
194
- >>> client_id = "xxx"
195
- >>> client_secret = "xxx"
196
- >>> server_metadata_url = "https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration"
196
+ [auth]
197
+ redirect_uri = "http://localhost:8501/oauth2callback"
198
+ cookie_secret = "xxx"
197
199
 
198
- Your app code:
200
+ [auth.microsoft]
201
+ client_id = "xxx"
202
+ client_secret = "xxx"
203
+ server_metadata_url = "https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration"
199
204
 
200
- >>> import streamlit as st
201
- >>>
202
- >>> if not st.user.is_logged_in:
203
- >>> st.login("microsoft")
204
- >>> else:
205
- >>> st.write(f"Hello, {st.user.name}!")
205
+ .. code-block:: python
206
+ :filename: streamlit_app.py
207
+
208
+ import streamlit as st
209
+
210
+ if not st.user.is_logged_in:
211
+ st.login("microsoft")
212
+ else:
213
+ st.write(f"Hello, {st.user.name}!")
206
214
 
207
215
  **Example 3: Use multiple, named providers**
208
216
 
@@ -214,34 +222,38 @@ def login(provider: str | None = None) -> None:
214
222
  set ``{tenant}`` and ``{subdomain}`` in ``server_metadata_url`` for
215
223
  Microsoft and Okta, respectively.
216
224
 
217
- >>> [auth]
218
- >>> redirect_uri = "http://localhost:8501/oauth2callback"
219
- >>> cookie_secret = "xxx"
220
- >>>
221
- >>> [auth.microsoft]
222
- >>> client_id = "xxx"
223
- >>> client_secret = "xxx"
224
- >>> server_metadata_url = "https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration"
225
- >>>
226
- >>> [auth.okta]
227
- >>> client_id = "xxx"
228
- >>> client_secret = "xxx"
229
- >>> server_metadata_url = "https://{subdomain}.okta.com/.well-known/openid-configuration" # fmt: skip
225
+ .. code-block:: toml
226
+ :filename: .streamlit/secrets.toml
230
227
 
231
- Your app code:
228
+ [auth]
229
+ redirect_uri = "http://localhost:8501/oauth2callback"
230
+ cookie_secret = "xxx"
232
231
 
233
- >>> import streamlit as st
234
- >>>
235
- >>> if not st.user.is_logged_in:
236
- >>> st.header("Log in:")
237
- >>> if st.button("Microsoft"):
238
- >>> st.login("microsoft")
239
- >>> if st.button("Okta"):
240
- >>> st.login("okta")
241
- >>> else:
242
- >>> if st.button("Log out"):
243
- >>> st.logout()
244
- >>> st.write(f"Hello, {st.user.name}!")
232
+ [auth.microsoft]
233
+ client_id = "xxx"
234
+ client_secret = "xxx"
235
+ server_metadata_url = "https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration"
236
+
237
+ [auth.okta]
238
+ client_id = "xxx"
239
+ client_secret = "xxx"
240
+ server_metadata_url = "https://{subdomain}.okta.com/.well-known/openid-configuration"
241
+
242
+ .. code-block:: python
243
+ :filename: streamlit_app.py
244
+
245
+ import streamlit as st
246
+
247
+ if not st.user.is_logged_in:
248
+ st.header("Log in:")
249
+ if st.button("Microsoft"):
250
+ st.login("microsoft")
251
+ if st.button("Okta"):
252
+ st.login("okta")
253
+ else:
254
+ if st.button("Log out"):
255
+ st.logout()
256
+ st.write(f"Hello, {st.user.name}!")
245
257
 
246
258
  **Example 4: Change the default connection settings**
247
259
 
@@ -256,28 +268,30 @@ def login(provider: str | None = None) -> None:
256
268
  `Customize Signup and Login Prompts
257
269
  <https://auth0.com/docs/customize/login-pages/universal-login/customize-signup-and-login-prompts>`_.
258
270
 
259
- ``.streamlit/secrets.toml``:
271
+ .. code-block:: toml
272
+ :filename: .streamlit/secrets.toml
260
273
 
261
- >>> [auth]
262
- >>> redirect_uri = "http://localhost:8501/oauth2callback"
263
- >>> cookie_secret = "xxx"
264
- >>>
265
- >>> [auth.auth0]
266
- >>> client_id = "xxx"
267
- >>> client_secret = "xxx"
268
- >>> server_metadata_url = "https://{account}.{region}.auth0.com/.well-known/openid-configuration" # fmt: skip
269
- >>> client_kwargs = { "prompt" = "login" }
274
+ [auth]
275
+ redirect_uri = "http://localhost:8501/oauth2callback"
276
+ cookie_secret = "xxx"
270
277
 
271
- Your app code:
278
+ [auth.auth0]
279
+ client_id = "xxx"
280
+ client_secret = "xxx"
281
+ server_metadata_url = "https://{account}.{region}.auth0.com/.well-known/openid-configuration"
282
+ client_kwargs = { "prompt" = "login" }
272
283
 
273
- >>> import streamlit as st
274
- >>>
275
- >>> if st.button("Log in"):
276
- >>> st.login("auth0")
277
- >>> if st.user.is_logged_in:
278
- >>> if st.button("Log out"):
279
- >>> st.logout()
280
- >>> st.write(f"Hello, {st.user.name}!)
284
+ .. code-block:: python
285
+ :filename: streamlit_app.py
286
+
287
+ import streamlit as st
288
+
289
+ if st.button("Log in"):
290
+ st.login("auth0")
291
+ if st.user.is_logged_in:
292
+ if st.button("Log out"):
293
+ st.logout()
294
+ st.write(f"Hello, {st.user.name}!)
281
295
 
282
296
  """
283
297
  if provider is None:
@@ -382,37 +396,38 @@ def _get_user_info() -> UserInfoType:
382
396
 
383
397
  class TokensProxy(Mapping[str, str]):
384
398
  """
385
- A read-only, dict-like object for accessing exposed tokens from the
399
+ A read-only, dict-like object for accessing exposed tokens from the\
386
400
  identity provider.
387
401
 
388
402
  This class provides access to tokens that have been explicitly exposed via
389
403
  the ``expose_tokens`` setting in your authentication configuration. Tokens
390
- are accessed through ``st.user.tokens`` and contain sensitive credentials
391
- that your app can use to authenticate with external services on behalf of
392
- the logged-in user.
393
-
394
- To expose tokens, add the ``expose_tokens`` parameter to your authentication
395
- configuration in ``.streamlit/secrets.toml``. You can specify a single token
396
- type as a string or multiple token types as a list. Streamlit supports
397
- exposing ``"id"`` tokens (identity tokens) and ``"access"`` tokens (access
398
- tokens). If ``expose_tokens`` is not configured, ``st.user.tokens`` will be
399
- empty.
400
-
401
- .. Warning::
404
+ contain sensitive credentials that your app can use to authenticate with
405
+ external services on behalf of the logged-in user.
406
+
407
+ To expose tokens in ``st.user.tokens``, add the ``expose_tokens`` parameter to your authentication
408
+ configuration in ``.streamlit/secrets.toml``. ``expose_tokens`` must be in
409
+ the ``[auth]`` section and can't be a nested dictionary. You can specify a
410
+ single token type as a string or multiple token types as a list. Streamlit
411
+ supports exposing ``"id"`` tokens and ``"access"`` tokens. If
412
+ ``expose_tokens`` isn't configured, ``st.user.tokens`` is an empty dict.
413
+
414
+ .. warning::
402
415
  Tokens are sensitive credentials that should be handled securely. Never
403
416
  expose tokens in your app's UI, logs, or error messages. Only use tokens
404
417
  for server-side API calls, and be mindful of token expiration times.
405
418
  Only expose tokens if your app needs them for specific API integrations.
406
419
 
407
- You can access token values using either key notation (``st.user.tokens["id"]``)
408
- or attribute notation (``st.user.tokens.id``). The object is read-only to
409
- prevent accidental modification of sensitive credentials.
420
+ You can access token values using either key or attribute notation. For
421
+ example, use ``st.user.tokens["id"]`` or ``st.user.tokens.id`` to access
422
+ the ``id`` token. The object is read-only to prevent accidental modification of sensitive
423
+ credentials.
410
424
 
411
- .. Note::
412
- If no tokens are exposed or if the user is not logged in,
413
- ``st.user.tokens`` will be an empty dict-like object. Attempting to
414
- access a non-existent token will raise a ``KeyError`` (for key notation)
415
- or ``AttributeError`` (for attribute notation).
425
+ Attributes
426
+ ----------
427
+ id : str
428
+ The identity token. This is only available if ``"id"`` is in ``expose_tokens``.
429
+ access : str
430
+ The access token. This is only available if ``"access"`` is in ``expose_tokens``.
416
431
 
417
432
  Examples
418
433
  --------
@@ -421,27 +436,59 @@ class TokensProxy(Mapping[str, str]):
421
436
  To expose only the identity token, add ``expose_tokens`` to your
422
437
  authentication configuration. This example uses an unnamed default provider.
423
438
 
424
- ``.streamlit/secrets.toml``:
439
+ .. code-block:: toml
440
+ :filename: .streamlit/secrets.toml
425
441
 
426
- >>> [auth]
427
- >>> redirect_uri = "http://localhost:8501/oauth2callback"
428
- >>> cookie_secret = "xxx"
429
- >>> client_id = "xxx"
430
- >>> client_secret = "xxx"
431
- >>> server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration" # fmt: skip
432
- >>> expose_tokens = "id"
442
+ [auth]
443
+ redirect_uri = "http://localhost:8501/oauth2callback"
444
+ cookie_secret = "xxx"
445
+ client_id = "xxx"
446
+ client_secret = "xxx"
447
+ server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration"
448
+ expose_tokens = "id"
433
449
 
434
- Your app code:
450
+ .. code-block:: python
451
+ :filename: streamlit_app.py
435
452
 
436
- >>> import streamlit as st
437
- >>>
438
- >>> if st.user.is_logged_in:
439
- >>> try:
440
- >>> id_token = st.user.tokens["id"]
441
- >>> # Use the token for API verification (never display it!)
442
- >>> st.success("ID token retrieved successfully")
443
- >>> except KeyError:
444
- >>> st.warning("ID token not available")
453
+ import streamlit as st
454
+
455
+ if st.user.is_logged_in:
456
+ id_token = st.user.tokens["id"]
457
+ # Use the token for API verification
458
+
459
+ **Example 2: Expose both ID and access tokens**
460
+
461
+ You can use a list to expose multiple tokens. If you use one or more named
462
+ identity providers, the same tokens must be exposed for all providers in
463
+ the shared ``[auth]`` section.
464
+
465
+ .. code-block:: toml
466
+ :filename: .streamlit/secrets.toml
467
+
468
+ [auth]
469
+ redirect_uri = "http://localhost:8501/oauth2callback"
470
+ cookie_secret = "xxx"
471
+ expose_tokens = ["id", "access"]
472
+
473
+ [auth.google]
474
+ client_id = "xxx"
475
+ client_secret = "xxx"
476
+ server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration"
477
+
478
+ [auth.microsoft]
479
+ client_id = "xxx"
480
+ client_secret = "xxx"
481
+ server_metadata_url = "https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration"
482
+
483
+ .. code-block:: python
484
+ :filename: streamlit_app.py
485
+
486
+ import streamlit as st
487
+
488
+ if st.user.is_logged_in:
489
+ id_token = st.user.tokens["id"]
490
+ access_token = st.user.tokens["access"]
491
+ # Use the tokens for API verification
445
492
  """
446
493
 
447
494
  def __init__(self, tokens: dict[str, str]) -> None:
@@ -511,11 +558,15 @@ class UserInfoProxy(Mapping[str, str | bool | TokensProxy | None]):
511
558
 
512
559
  Attributes
513
560
  ----------
514
- is_logged_in: bool
561
+ is_logged_in : bool
515
562
  Whether a user is logged in. For a locally running app, this attribute
516
563
  is only available when authentication (``st.login()``) is configured in
517
564
  ``secrets.toml``. Otherwise, it does not exist.
518
565
 
566
+ tokens: TokensProxy
567
+ A read-only, dict-like object for accessing exposed tokens from the
568
+ identity provider.
569
+
519
570
  Examples
520
571
  --------
521
572
  **Example 1: Google's identity token**
@@ -529,32 +580,36 @@ class UserInfoProxy(Mapping[str, str | bool | TokensProxy | None]):
529
580
  <https://developers.google.com/identity/openid-connect/openid-connect#obtainuserinfo>`_
530
581
  in Google's docs.
531
582
 
532
- Your app code:
583
+ .. code-block:: python
584
+ :filename: streamlit_app.py
533
585
 
534
- >>> import streamlit as st
535
- >>>
536
- >>> if st.user.is_logged_in:
537
- >>> st.write(st.user)
586
+ import streamlit as st
587
+
588
+ if st.user.is_logged_in:
589
+ st.write(st.user)
538
590
 
539
591
  Displayed data when a user is logged in:
540
592
 
541
- >>> {
542
- >>> "is_logged_in":true
543
- >>> "iss":"https://accounts.google.com"
544
- >>> "azp":"{client_id}.apps.googleusercontent.com"
545
- >>> "aud":"{client_id}.apps.googleusercontent.com"
546
- >>> "sub":"{unique_user_id}"
547
- >>> "email":"{user}@gmail.com"
548
- >>> "email_verified":true
549
- >>> "at_hash":"{access_token_hash}"
550
- >>> "nonce":"{nonce_string}"
551
- >>> "name":"{full_name}"
552
- >>> "picture":"https://lh3.googleusercontent.com/a/{content_path}"
553
- >>> "given_name":"{given_name}"
554
- >>> "family_name":"{family_name}"
555
- >>> "iat":{issued_time}
556
- >>> "exp":{expiration_time}
557
- >>> }
593
+ .. code-block:: json
594
+
595
+ {
596
+ "is_logged_in":true
597
+ "iss":"https://accounts.google.com"
598
+ "azp":"{client_id}.apps.googleusercontent.com"
599
+ "aud":"{client_id}.apps.googleusercontent.com"
600
+ "sub":"{unique_user_id}"
601
+ "email":"{user}@gmail.com"
602
+ "email_verified":true
603
+ "at_hash":"{access_token_hash}"
604
+ "nonce":"{nonce_string}"
605
+ "name":"{full_name}"
606
+ "picture":"https://lh3.googleusercontent.com/a/{content_path}"
607
+ "given_name":"{given_name}"
608
+ "family_name":"{family_name}"
609
+ "iat":{issued_time}
610
+ "exp":{expiration_time}
611
+ "tokens":{}
612
+ }
558
613
 
559
614
  **Example 2: Microsoft's identity token**
560
615
 
@@ -565,32 +620,36 @@ class UserInfoProxy(Mapping[str, str | bool | TokensProxy | None]):
565
620
  <https://learn.microsoft.com/en-us/entra/identity-platform/id-token-claims-reference>`_
566
621
  in Microsoft's docs.
567
622
 
568
- Your app code:
623
+ .. code-block:: python
624
+ :filename: streamlit_app.py
569
625
 
570
- >>> import streamlit as st
571
- >>>
572
- >>> if st.user.is_logged_in:
573
- >>> st.write(st.user)
626
+ import streamlit as st
627
+
628
+ if st.user.is_logged_in:
629
+ st.write(st.user)
574
630
 
575
631
  Displayed data when a user is logged in:
576
632
 
577
- >>> {
578
- >>> "is_logged_in":true
579
- >>> "ver":"2.0"
580
- >>> "iss":"https://login.microsoftonline.com/{tenant_id}/v2.0"
581
- >>> "sub":"{application_user_id}"
582
- >>> "aud":"{application_id}"
583
- >>> "exp":{expiration_time}
584
- >>> "iat":{issued_time}
585
- >>> "nbf":{start_time}
586
- >>> "name":"{full_name}"
587
- >>> "preferred_username":"{username}"
588
- >>> "oid":"{user_GUID}"
589
- >>> "email":"{email}"
590
- >>> "tid":"{tenant_id}"
591
- >>> "nonce":"{nonce_string}"
592
- >>> "aio":"{opaque_string}"
593
- >>> }
633
+ .. code-block:: json
634
+
635
+ {
636
+ "is_logged_in":true
637
+ "ver":"2.0"
638
+ "iss":"https://login.microsoftonline.com/{tenant_id}/v2.0"
639
+ "sub":"{application_user_id}"
640
+ "aud":"{application_id}"
641
+ "exp":{expiration_time}
642
+ "iat":{issued_time}
643
+ "nbf":{start_time}
644
+ "name":"{full_name}"
645
+ "preferred_username":"{username}"
646
+ "oid":"{user_GUID}"
647
+ "email":"{email}"
648
+ "tid":"{tenant_id}"
649
+ "nonce":"{nonce_string}"
650
+ "aio":"{opaque_string}"
651
+ "tokens":{}
652
+ }
594
653
  """
595
654
 
596
655
  def __getitem__(self, key: str) -> str | bool | None | TokensProxy:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: streamlit-nightly
3
- Version: 1.52.3.dev20260113
3
+ Version: 1.53.1.dev20260115
4
4
  Summary: A faster way to build and share data apps
5
5
  Home-page: https://streamlit.io
6
6
  Author: Snowflake Inc