streamlit-nightly 1.53.1.dev20260117__py3-none-any.whl → 1.53.1.dev20260121__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 (113) hide show
  1. streamlit/__init__.py +0 -4
  2. streamlit/connections/snowflake_connection.py +5 -2
  3. streamlit/dataframe_util.py +4 -2
  4. streamlit/elements/lib/built_in_chart_utils.py +3 -0
  5. streamlit/elements/lib/column_config_utils.py +3 -1
  6. streamlit/elements/widgets/radio.py +91 -31
  7. streamlit/elements/widgets/time_widgets.py +58 -7
  8. streamlit/hello/dataframe_demo.py +1 -1
  9. streamlit/proto/Radio_pb2.py +4 -2
  10. streamlit/proto/Radio_pb2.pyi +20 -3
  11. streamlit/static/index.html +1 -1
  12. streamlit/static/manifest.json +308 -308
  13. streamlit/static/static/js/{ErrorOutline.esm.CqVEQ-uJ.js → ErrorOutline.esm.C6VdLmcj.js} +1 -1
  14. streamlit/static/static/js/{FileDownload.esm.G-HJG6nt.js → FileDownload.esm.g3HiTWnX.js} +1 -1
  15. streamlit/static/static/js/{FileHelper.Bd4bPp0Y.js → FileHelper.DkZahZIe.js} +1 -1
  16. streamlit/static/static/js/{FormClearHelper.B74VElyu.js → FormClearHelper.CnDHLc6s.js} +1 -1
  17. streamlit/static/static/js/{InputInstructions.ClBLOwfm.js → InputInstructions.CJwgA0Sj.js} +1 -1
  18. streamlit/static/static/js/{Particles.CyYskark.js → Particles.BA0kQsJM.js} +1 -1
  19. streamlit/static/static/js/{ProgressBar.vWX1Igzt.js → ProgressBar.N6Nzla-b.js} +1 -1
  20. streamlit/static/static/js/{StreamlitSyntaxHighlighter.BNhyeEtl.js → StreamlitSyntaxHighlighter.DF8uiu4N.js} +1 -1
  21. streamlit/static/static/js/{TableChart.esm.Mk-Hvy1t.js → TableChart.esm.Ne8F0PNs.js} +1 -1
  22. streamlit/static/static/js/{Toolbar.NhlhlTzK.js → Toolbar.h597G9NG.js} +1 -1
  23. streamlit/static/static/js/{WidgetLabelHelpIconInline.Ch9VDnrM.js → WidgetLabelHelpIconInline.BMPpOfi3.js} +1 -1
  24. streamlit/static/static/js/{base-input.DSh9H2uv.js → base-input.CTx0w60a.js} +1 -1
  25. streamlit/static/static/js/{checkbox.DCFAQrRB.js → checkbox.otYZO7w2.js} +1 -1
  26. streamlit/static/static/js/{createDownloadLinkElement.D5zpcd24.js → createDownloadLinkElement.Az9SilWU.js} +1 -1
  27. streamlit/static/static/js/{data-grid-overlay-editor.GAqbIurd.js → data-grid-overlay-editor.Blj_5PJn.js} +1 -1
  28. streamlit/static/static/js/{downloader.C1MBZFo2.js → downloader.ur6VTRo6.js} +1 -1
  29. streamlit/static/static/js/{embed.CZG6oOsc.js → embed.Bo5Mp3yp.js} +1 -1
  30. streamlit/static/static/js/{es6.toHnBzIb.js → es6.Q-xD3Lx8.js} +2 -2
  31. streamlit/static/static/js/{formatNumber.BsU-5o3V.js → formatNumber._OZtRfH-.js} +1 -1
  32. streamlit/static/static/js/{iconPosition.OKOYrH6A.js → iconPosition.owgMmPXc.js} +1 -1
  33. streamlit/static/static/js/{iframeResizer.contentWindow.D6yxU4DL.js → iframeResizer.contentWindow.CVCEnOeT.js} +1 -1
  34. streamlit/static/static/js/{index.DwgEkDLk.js → index.1wQkO9-P.js} +1 -1
  35. streamlit/static/static/js/{index.DhGqPx_f.js → index.2pNQcghF.js} +1 -1
  36. streamlit/static/static/js/{index.BHWCIpbw.js → index.9GyNEnVn.js} +1 -1
  37. streamlit/static/static/js/{index._t3w-7R0.js → index.BBFXXyOE.js} +1 -1
  38. streamlit/static/static/js/{index.DbCS2N3T.js → index.BOH_U_Ua.js} +1 -1
  39. streamlit/static/static/js/{index.YRiVxrFw.js → index.BTy77A4v.js} +1 -1
  40. streamlit/static/static/js/{index.DR8Ty3j4.js → index.BZMDU-qx.js} +1 -1
  41. streamlit/static/static/js/{index.EOvPT8N-.js → index.BdKmWvyd.js} +1 -1
  42. streamlit/static/static/js/{index.SBwNLdli.js → index.BkFxYQoo.js} +1 -1
  43. streamlit/static/static/js/{index.0iCXW13-.js → index.BlZAOJTf.js} +1 -1
  44. streamlit/static/static/js/{index.DGrQJk9x.js → index.BtKtuLWl.js} +1 -1
  45. streamlit/static/static/js/{index.C_w1nWis.js → index.Buip23l3.js} +1 -1
  46. streamlit/static/static/js/{index.CXLtvxrQ.js → index.Bw5t0A1a.js} +1 -1
  47. streamlit/static/static/js/{index.B8mzpc1l.js → index.ByHx8_go.js} +1 -1
  48. streamlit/static/static/js/{index.Bs4E_0D7.js → index.Byo1IU24.js} +1 -1
  49. streamlit/static/static/js/{index.Bh0_7PvD.js → index.ByzGGHA-.js} +1 -1
  50. streamlit/static/static/js/{index.BVbT0yWJ.js → index.C-xuUZos.js} +1 -1
  51. streamlit/static/static/js/{index.Dl2MB5Tx.js → index.C0X75KQC.js} +1 -1
  52. streamlit/static/static/js/{index.CV4niwLB.js → index.C5MX205D.js} +1 -1
  53. streamlit/static/static/js/{index.Blo8DAcU.js → index.CECvn-YK.js} +1 -1
  54. streamlit/static/static/js/{index.P0_E3iNi.js → index.CHfpPdI8.js} +1 -1
  55. streamlit/static/static/js/{index.BU8aUWlo.js → index.CT8A-jH3.js} +1 -1
  56. streamlit/static/static/js/{index.CJCEiqv2.js → index.CT93Qeic.js} +1 -1
  57. streamlit/static/static/js/{index.E4x2UBkh.js → index.CZKvO8_W.js} +1 -1
  58. streamlit/static/static/js/{index.AkleAg_w.js → index.Ccjs4i9w.js} +1 -1
  59. streamlit/static/static/js/{index.BkYhb--A.js → index.CeCHrefy.js} +1 -1
  60. streamlit/static/static/js/{index.qjO5OK90.js → index.Cpn4aUEp.js} +6 -6
  61. streamlit/static/static/js/{index.5CwvMIZq.js → index.D-VZVj73.js} +1 -1
  62. streamlit/static/static/js/{index.D94k70Hg.js → index.DA1Zwrh6.js} +1 -1
  63. streamlit/static/static/js/{index.COcj-WpN.js → index.DAddHkEE.js} +1 -1
  64. streamlit/static/static/js/{index.BXqtIpgi.js → index.DAjvUscA.js} +1 -1
  65. streamlit/static/static/js/{index.D7Hgmilz.js → index.DPa8c-h5.js} +1 -1
  66. streamlit/static/static/js/{index.XgBfXgN1.js → index.DUoWDMOZ.js} +1 -1
  67. streamlit/static/static/js/{index.CqywI2eW.js → index.DYqiNZKP.js} +1 -1
  68. streamlit/static/static/js/{index.BW0F_Pbs.js → index.DcZ6Y6tq.js} +1 -1
  69. streamlit/static/static/js/{index.dGk9EWLh.js → index.DfDGWP9w.js} +1 -1
  70. streamlit/static/static/js/{index.D0h2EJ_T.js → index.DiEHlHgD.js} +1 -1
  71. streamlit/static/static/js/{index.Ch4X_YdF.js → index.DkmkM-3F.js} +1 -1
  72. streamlit/static/static/js/{index.Dq0ZbGYZ.js → index.Vo6SwZW9.js} +1 -1
  73. streamlit/static/static/js/{index.Bhr3IHkD.js → index.X86xhkRz.js} +1 -1
  74. streamlit/static/static/js/index.Z5FSW1PS.js +3 -0
  75. streamlit/static/static/js/{index.DJ8OTQbk.js → index.d4eN08zp.js} +1 -1
  76. streamlit/static/static/js/{index.1sBZt_1I.js → index.hri4IXS4.js} +5 -5
  77. streamlit/static/static/js/{index.CGt5hnLi.js → index.jADyDjmJ.js} +1 -1
  78. streamlit/static/static/js/{index.ia5Ub9p7.js → index.jZuoBudL.js} +1 -1
  79. streamlit/static/static/js/{index.C6LOxzFC.js → index.oieFJFkX.js} +1 -1
  80. streamlit/static/static/js/{index.-pgbbiGJ.js → index.rpudgXQV.js} +1 -1
  81. streamlit/static/static/js/{index.MZ7ugsN-.js → index.zR1le1Pe.js} +1 -1
  82. streamlit/static/static/js/{input.Bavj6HHJ.js → input.FrKOgyiF.js} +1 -1
  83. streamlit/static/static/js/{main.dnUTEH_j.js → main.DRehwjQT.js} +1 -1
  84. streamlit/static/static/js/{memory.Czf1Sxzc.js → memory.B2wgPAbQ.js} +1 -1
  85. streamlit/static/static/js/{number-overlay-editor.CRQIke3a.js → number-overlay-editor.CnTj7Q_W.js} +1 -1
  86. streamlit/static/static/js/{pandasStylerUtils.agmr-LQ2.js → pandasStylerUtils.CWancxgS.js} +1 -1
  87. streamlit/static/static/js/{sandbox.BlCiIomw.js → sandbox.DuleaI7G.js} +1 -1
  88. streamlit/static/static/js/{styled-components.Bz3KSbhj.js → styled-components.g3zaW9ch.js} +1 -1
  89. streamlit/static/static/js/{throttle.B1o314FW.js → throttle.Dta7xRnz.js} +1 -1
  90. streamlit/static/static/js/{timepicker.3x4ndo9E.js → timepicker.Bg1hWKQe.js} +1 -1
  91. streamlit/static/static/js/{toConsumableArray.BeHbBK8g.js → toConsumableArray.C3xlVjBM.js} +1 -1
  92. streamlit/static/static/js/uniqueId.2p-nMqYS.js +1 -0
  93. streamlit/static/static/js/{useBasicWidgetState.CFP4_PTk.js → useBasicWidgetState.CERZ06R-.js} +1 -1
  94. streamlit/static/static/js/{useIntlLocale.BJubkaPQ.js → useIntlLocale.DTs1RN9G.js} +1 -1
  95. streamlit/static/static/js/{useTextInputAutoExpand.DBGwhM4R.js → useTextInputAutoExpand.B6f9P3jg.js} +1 -1
  96. streamlit/static/static/js/{useUpdateUiValue.CyufNQfR.js → useUpdateUiValue.ByVBXV8J.js} +1 -1
  97. streamlit/static/static/js/{useWaveformController.Dj5h0D8Y.js → useWaveformController.D6wABMbB.js} +1 -1
  98. streamlit/static/static/js/{withCalculatedWidth.D0IRb-7w.js → withCalculatedWidth.Bd4vFDHU.js} +1 -1
  99. streamlit/static/static/js/{withFullScreenWrapper.CHBnw0Co.js → withFullScreenWrapper.CDnDcnIh.js} +1 -1
  100. streamlit/testing/v1/element_tree.py +2 -2
  101. streamlit/user_info.py +0 -39
  102. streamlit/watcher/event_based_path_watcher.py +37 -7
  103. streamlit/watcher/path_watcher.py +60 -1
  104. streamlit/watcher/util.py +26 -10
  105. streamlit/web/bootstrap.py +11 -2
  106. {streamlit_nightly-1.53.1.dev20260117.dist-info → streamlit_nightly-1.53.1.dev20260121.dist-info}/METADATA +1 -1
  107. {streamlit_nightly-1.53.1.dev20260117.dist-info → streamlit_nightly-1.53.1.dev20260121.dist-info}/RECORD +111 -111
  108. {streamlit_nightly-1.53.1.dev20260117.dist-info → streamlit_nightly-1.53.1.dev20260121.dist-info}/WHEEL +1 -1
  109. streamlit/static/static/js/index.DRGDE5oo.js +0 -3
  110. streamlit/static/static/js/uniqueId.Zn1vZBLX.js +0 -1
  111. {streamlit_nightly-1.53.1.dev20260117.data → streamlit_nightly-1.53.1.dev20260121.data}/scripts/streamlit.cmd +0 -0
  112. {streamlit_nightly-1.53.1.dev20260117.dist-info → streamlit_nightly-1.53.1.dev20260121.dist-info}/entry_points.txt +0 -0
  113. {streamlit_nightly-1.53.1.dev20260117.dist-info → streamlit_nightly-1.53.1.dev20260121.dist-info}/top_level.txt +0 -0
@@ -1 +1 @@
1
- import{l as Z,r as i,aP as M,aa as $,aQ as O}from"./index.qjO5OK90.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
+ import{l as Z,r as i,aP as M,aa as $,aQ as O}from"./index.Cpn4aUEp.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.qjO5OK90.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.Cpn4aUEp.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,z as f,b5 as p,b6 as h,l as x,k as y,j as i,h as g}from"./index.qjO5OK90.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};
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.Cpn4aUEp.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};
@@ -993,8 +993,8 @@ class Radio(Widget, Generic[T]):
993
993
  """
994
994
  ws = WidgetState()
995
995
  ws.id = self.id
996
- if self.index is not None:
997
- ws.int_value = self.index
996
+ if self.index is not None and len(self.options) > 0:
997
+ ws.string_value = self.options[self.index]
998
998
  return ws
999
999
 
1000
1000
 
streamlit/user_info.py CHANGED
@@ -30,10 +30,6 @@ from streamlit.auth_util import (
30
30
  is_authlib_installed,
31
31
  validate_auth_credentials,
32
32
  )
33
- from streamlit.deprecation_util import (
34
- make_deprecated_name_warning,
35
- show_deprecation_warning,
36
- )
37
33
  from streamlit.errors import StreamlitAPIException, StreamlitAuthError
38
34
  from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
39
35
  from streamlit.runtime.metrics_util import gather_metrics
@@ -701,38 +697,3 @@ class UserInfoProxy(Mapping[str, str | bool | TokensProxy | None]):
701
697
  """Access exposed tokens via a dict-like object."""
702
698
  user_info = _get_user_info()
703
699
  return TokensProxy(cast("dict[str, str]", user_info.get("tokens", {})))
704
-
705
-
706
- has_shown_experimental_user_warning = False
707
-
708
-
709
- def maybe_show_deprecated_user_warning() -> None:
710
- """Show a deprecation warning for the experimental_user alias."""
711
- global has_shown_experimental_user_warning # noqa: PLW0603
712
-
713
- if not has_shown_experimental_user_warning:
714
- has_shown_experimental_user_warning = True
715
- show_deprecation_warning(
716
- make_deprecated_name_warning(
717
- "experimental_user",
718
- "user",
719
- "2025-11-06",
720
- )
721
- )
722
-
723
-
724
- class DeprecatedUserInfoProxy(UserInfoProxy):
725
- """
726
- A deprecated alias for UserInfoProxy.
727
-
728
- This class is deprecated and will be removed in a future version of
729
- Streamlit.
730
- """
731
-
732
- def __getattribute__(self, name: str) -> Any:
733
- maybe_show_deprecated_user_warning()
734
- return super().__getattribute__(name)
735
-
736
- def __getitem__(self, key: str) -> Any:
737
- maybe_show_deprecated_user_warning()
738
- return super().__getitem__(key)
@@ -69,7 +69,20 @@ def _get_abs_folder_path(path: str) -> str:
69
69
 
70
70
 
71
71
  class EventBasedPathWatcher:
72
- """Watches a single path on disk using watchdog."""
72
+ """Watches a single path on disk using watchdog.
73
+
74
+ Behavior differs based on whether watching a file or directory:
75
+
76
+ **File watching:** Detects content changes via MD5 hash comparison. The
77
+ callback receives the file path and is invoked when content changes. With
78
+ allow_nonexistent=True, also detects file creation.
79
+
80
+ **Directory watching:** Detects any file activity within the directory
81
+ (creation, deletion, modification). The callback receives the actual
82
+ changed file path (not the directory). Note that glob_pattern only affects
83
+ the initial state hash, not which events trigger callbacks - all file
84
+ events in the directory invoke the callback.
85
+ """
73
86
 
74
87
  @staticmethod
75
88
  def close_all() -> None:
@@ -91,17 +104,22 @@ class EventBasedPathWatcher:
91
104
  Parameters
92
105
  ----------
93
106
  path : str
94
- The path to watch.
107
+ The path to watch (file or directory).
95
108
  on_changed : Callable[[str], None]
96
- Callback to call when the path changes.
109
+ Callback invoked when changes are detected. For files, receives
110
+ the file path. For directories, receives the path of the actual
111
+ changed file within the directory.
97
112
  glob_pattern : str or None
98
- A glob pattern to filter the files in a directory that should be
99
- watched. Only relevant when creating an EventBasedPathWatcher on a
100
- directory.
113
+ A glob pattern for initial state detection when watching a
114
+ directory (e.g., "*.py"). Note: This does NOT filter which file
115
+ events trigger the callback - all file events in the directory
116
+ will invoke the callback regardless of this pattern.
101
117
  allow_nonexistent : bool
102
118
  If True, the watcher will not raise an exception if the path does
103
119
  not exist. This can be used to watch for the creation of a file or
104
- directory at a given path.
120
+ directory at a given path. Note: The parent directory of the path
121
+ must exist for watching to work. If the parent doesn't exist, the
122
+ watcher is silently skipped.
105
123
  """
106
124
  self._path = os.path.realpath(path)
107
125
  self._on_changed = on_changed
@@ -189,6 +207,18 @@ class _MultiPathWatcher:
189
207
  folder_handler, folder_path, recursive=True
190
208
  )
191
209
  self._folder_handlers[folder_path] = folder_handler
210
+ except FileNotFoundError:
211
+ # This happens when watching a non-existent file whose parent
212
+ # directory also doesn't exist (e.g., .streamlit/config.toml
213
+ # when .streamlit/ hasn't been created yet). This is expected
214
+ # and not an error - we just can't watch until the directory
215
+ # is created.
216
+ _LOGGER.debug(
217
+ "Cannot watch path %s: directory %s does not exist",
218
+ path,
219
+ folder_path,
220
+ )
221
+ return
192
222
  except Exception as ex:
193
223
  _LOGGER.warning(
194
224
  "Failed to schedule watch observer for path %s",
@@ -137,8 +137,37 @@ def watch_file(
137
137
  path: str,
138
138
  on_file_changed: Callable[[str], None],
139
139
  watcher_type: str | None = None,
140
+ *, # keyword-only arguments:
141
+ allow_nonexistent: bool = False,
140
142
  ) -> bool:
141
- return _watch_path(path, on_file_changed, watcher_type)
143
+ """Watch a file for changes.
144
+
145
+ The callback is invoked when the file's content changes (detected via MD5).
146
+ If allow_nonexistent is True, the watcher will also detect when the file
147
+ is created.
148
+
149
+ Parameters
150
+ ----------
151
+ path
152
+ Path to the file to watch.
153
+ on_file_changed
154
+ Callback invoked with the file path when changes are detected.
155
+ watcher_type
156
+ Optional watcher type ('watchdog', 'poll', 'auto', or 'none').
157
+ allow_nonexistent
158
+ If True, watch for file creation even if the file doesn't exist yet.
159
+ Note: The file's parent directory must exist for watching to work.
160
+ If the parent directory doesn't exist, the watcher silently skips
161
+ watching (the file can't be created without its parent directory).
162
+
163
+ Returns
164
+ -------
165
+ bool
166
+ True if the watcher was successfully created.
167
+ """
168
+ return _watch_path(
169
+ path, on_file_changed, watcher_type, allow_nonexistent=allow_nonexistent
170
+ )
142
171
 
143
172
 
144
173
  def watch_dir(
@@ -149,6 +178,36 @@ def watch_dir(
149
178
  glob_pattern: str | None = None,
150
179
  allow_nonexistent: bool = False,
151
180
  ) -> bool:
181
+ """Watch a directory for file changes.
182
+
183
+ The callback is invoked for any file activity within the directory,
184
+ including file creation, deletion, and content modifications. The callback
185
+ receives the path of the actual changed file (not the directory path).
186
+
187
+ Note: The glob_pattern parameter only affects the initial state detection
188
+ (which files are counted when determining if the directory changed). It does
189
+ NOT filter which file events trigger the callback - all file events in the
190
+ directory will invoke the callback regardless of glob_pattern.
191
+
192
+ Parameters
193
+ ----------
194
+ path
195
+ Path to the directory to watch.
196
+ on_dir_changed
197
+ Callback invoked with the changed file path when changes are detected.
198
+ watcher_type
199
+ Optional watcher type ('watchdog', 'poll', 'auto', or 'none').
200
+ glob_pattern
201
+ Glob pattern for initial state detection (e.g., "*.py"). Does not
202
+ filter runtime events.
203
+ allow_nonexistent
204
+ If True, watch for directory creation even if it doesn't exist yet.
205
+
206
+ Returns
207
+ -------
208
+ bool
209
+ True if the watcher was successfully created.
210
+ """
152
211
  # Add a trailing slash to the path to ensure
153
212
  # that its interpreted as a directory.
154
213
  path = os.path.join(path, "")
streamlit/watcher/util.py CHANGED
@@ -63,11 +63,19 @@ def calc_md5_with_blocking_retries(
63
63
  # There's a race condition where sometimes file_path no longer exists when
64
64
  # we try to read it (since the file is in the process of being written).
65
65
  # So here we retry a few times using this loop. See issue #186.
66
- content = _do_with_retries(
67
- lambda: _get_file_content(path),
68
- (FileNotFoundError, PermissionError),
69
- path,
70
- )
66
+ try:
67
+ content = _do_with_retries(
68
+ lambda: _get_file_content(path),
69
+ (FileNotFoundError, PermissionError),
70
+ path,
71
+ )
72
+ except StreamlitMaxRetriesError:
73
+ # If allow_nonexistent is True and the file was deleted between our
74
+ # exists check and the read, treat it as nonexistent instead of raising.
75
+ if allow_nonexistent:
76
+ content = path.encode("UTF-8")
77
+ else:
78
+ raise
71
79
 
72
80
  return calc_md5(content)
73
81
 
@@ -91,11 +99,19 @@ def path_modification_time(path: str, allow_nonexistent: bool = False) -> float:
91
99
 
92
100
  # Use retries to avoid race condition where file may be in the process of being
93
101
  # modified.
94
- return _do_with_retries(
95
- lambda: os.stat(path).st_mtime,
96
- (FileNotFoundError, PermissionError),
97
- path,
98
- )
102
+ try:
103
+ return _do_with_retries(
104
+ lambda: os.stat(path).st_mtime,
105
+ (FileNotFoundError, PermissionError),
106
+ path,
107
+ )
108
+ except StreamlitMaxRetriesError:
109
+ # If allow_nonexistent is True and the file was deleted between our
110
+ # exists check and the stat call, return 0.0 instead of raising.
111
+ # This handles the race condition where a file is deleted while being watched.
112
+ if allow_nonexistent:
113
+ return 0.0
114
+ raise
99
115
 
100
116
 
101
117
  def _get_file_content(file_path: str) -> bytes:
@@ -325,8 +325,17 @@ def _install_config_watchers(flag_options: dict[str, Any]) -> None:
325
325
  load_config_options(flag_options)
326
326
 
327
327
  for filename in config.get_config_files("config.toml"):
328
- if os.path.exists(filename):
329
- watch_file(filename, on_config_changed)
328
+ # Watch each config file path directly, even if it doesn't exist yet.
329
+ # This allows detecting both file creation and subsequent modifications.
330
+ # We use the poll watcher because:
331
+ # 1. It handles non-existent paths gracefully, including when parent
332
+ # directories (like ~/.streamlit/) don't exist yet. The event-based
333
+ # watcher requires the parent directory to exist to schedule a watch.
334
+ # 2. Config files change rarely, so the polling overhead is negligible.
335
+ # 3. The 200ms poll interval latency is imperceptible for config reloads.
336
+ watch_file(
337
+ filename, on_config_changed, watcher_type="poll", allow_nonexistent=True
338
+ )
330
339
 
331
340
 
332
341
  def run_asgi_app(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: streamlit-nightly
3
- Version: 1.53.1.dev20260117
3
+ Version: 1.53.1.dev20260121
4
4
  Summary: A faster way to build and share data apps
5
5
  Home-page: https://streamlit.io
6
6
  Author: Snowflake Inc