streamlit-nightly 1.52.3.dev20260108__py3-none-any.whl → 1.52.3.dev20260110__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.
- streamlit/components/v2/__init__.py +3 -3
- streamlit/components/v2/types.py +4 -4
- streamlit/config.py +14 -0
- streamlit/elements/lib/options_selector_utils.py +98 -0
- streamlit/elements/widgets/multiselect.py +19 -9
- streamlit/elements/widgets/selectbox.py +12 -24
- streamlit/proto/MetricsEvent_pb2.py +4 -4
- streamlit/proto/MetricsEvent_pb2.pyi +4 -1
- streamlit/proto/PageProfile_pb2.py +6 -6
- streamlit/proto/PageProfile_pb2.pyi +11 -1
- streamlit/runtime/metrics_util.py +4 -0
- streamlit/runtime/runtime.py +3 -0
- streamlit/starlette.py +34 -0
- streamlit/static/index.html +1 -1
- streamlit/static/manifest.json +300 -300
- streamlit/static/static/js/{ErrorOutline.esm.j3b3OjAK.js → ErrorOutline.esm.BcqUpfNe.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.DCizXv6Q.js → FileDownload.esm.CtJWBuub.js} +1 -1
- streamlit/static/static/js/{FileHelper.EpMV5UVe.js → FileHelper.D0dQPhOs.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.lF7Ran5M.js → FormClearHelper.Cm3GDSk6.js} +1 -1
- streamlit/static/static/js/{InputInstructions.CMvqhPhy.js → InputInstructions.D7Hxdzwv.js} +1 -1
- streamlit/static/static/js/{Particles.DsGe8psi.js → Particles.vAUDtAR8.js} +1 -1
- streamlit/static/static/js/{ProgressBar.DzoKn4D-.js → ProgressBar.Dp2CGRba.js} +2 -2
- streamlit/static/static/js/{StreamlitSyntaxHighlighter.CFab0b_b.js → StreamlitSyntaxHighlighter.DC0000nJ.js} +1 -1
- streamlit/static/static/js/{TableChart.esm.nZsTq1Sb.js → TableChart.esm.DDVoSKOT.js} +1 -1
- streamlit/static/static/js/{Toolbar.CFMvwQYl.js → Toolbar.CuMH-Gqe.js} +1 -1
- streamlit/static/static/js/{WidgetLabelHelpIconInline.D2EEUEQX.js → WidgetLabelHelpIconInline.WAReecol.js} +1 -1
- streamlit/static/static/js/{base-input.DKTA2QNz.js → base-input.BX9Jll5o.js} +4 -4
- streamlit/static/static/js/{checkbox.D9H9J-_W.js → checkbox.BzMHUSz1.js} +1 -1
- streamlit/static/static/js/{createDownloadLinkElement.DCk6EhPM.js → createDownloadLinkElement.CviG5BQx.js} +1 -1
- streamlit/static/static/js/{data-grid-overlay-editor.DExrGdqs.js → data-grid-overlay-editor.Dzo9A4l6.js} +1 -1
- streamlit/static/static/js/{downloader.CLJ7BreF.js → downloader.DIDvj0d5.js} +1 -1
- streamlit/static/static/js/{embed.CxOHZWx2.js → embed.C8qeQ38b.js} +6 -6
- streamlit/static/static/js/{es6.C99ebre4.js → es6.Dpcc-U7U.js} +2 -2
- streamlit/static/static/js/{formatNumber.D_w4fBsk.js → formatNumber.CPvuaBa8.js} +1 -1
- streamlit/static/static/js/{iconPosition.Cfhw1RkE.js → iconPosition.y0q-Rqem.js} +1 -1
- streamlit/static/static/js/{iframeResizer.contentWindow.BcWUIYOe.js → iframeResizer.contentWindow.DblExdXF.js} +1 -1
- streamlit/static/static/js/{index.BWK_h3IL.js → index.B-g6lwYa.js} +1 -1
- streamlit/static/static/js/{index.DoLorXMA.js → index.B10MmI2m.js} +1 -1
- streamlit/static/static/js/{index.Dx8TcTHV.js → index.B6vCS66f.js} +6 -6
- streamlit/static/static/js/{index.Bp_LrAiI.js → index.B9TG5Ah8.js} +1 -1
- streamlit/static/static/js/{index.CrJ9KZpt.js → index.BDb0PRvK.js} +1 -1
- streamlit/static/static/js/{index.1AemKTSK.js → index.BGufEmCz.js} +1 -1
- streamlit/static/static/js/{index.7Q3Iaebc.js → index.BItU4jMo.js} +1 -1
- streamlit/static/static/js/{index.D18KqoUa.js → index.BPMqWDef.js} +1 -1
- streamlit/static/static/js/index.BTHi5W25.js +1 -0
- streamlit/static/static/js/{index.BHx4Qw7z.js → index.BVN9cI-k.js} +1 -1
- streamlit/static/static/js/index.BWOP7HFT.js +1 -0
- streamlit/static/static/js/{index.DDx6TP95.js → index.BXYgO5B8.js} +1 -1
- streamlit/static/static/js/{index.DkSjHoXw.js → index.BZBWLU1C.js} +8 -8
- streamlit/static/static/js/{index.f_s01aPm.js → index.BfZdZpv-.js} +2 -2
- streamlit/static/static/js/{index.C7_5JMRC.js → index.Bxe7fKbw.js} +1 -1
- streamlit/static/static/js/{index.BcbR2mbc.js → index.C1ElSZEy.js} +1 -1
- streamlit/static/static/js/index.C26ZOVFL.js +1 -0
- streamlit/static/static/js/{index.aJ3XRx8R.js → index.C7lwRBvF.js} +1 -1
- streamlit/static/static/js/{index.CGX2fllG.js → index.C93QGPyk.js} +1 -1
- streamlit/static/static/js/{index.COjurlZk.js → index.CCDejIvL.js} +2 -2
- streamlit/static/static/js/index.CcMmNHAq.js +1 -0
- streamlit/static/static/js/index.D42y-GeO.js +1 -0
- streamlit/static/static/js/{index.C0VFHmJN.js → index.D69ULFWq.js} +1 -1
- streamlit/static/static/js/{index.V4C1Oi-F.js → index.DB4MbQ40.js} +3 -3
- streamlit/static/static/js/{index.DJ4GBc1k.js → index.DRFJgBf-.js} +1 -1
- streamlit/static/static/js/{index.BXQNt1hj.js → index.DTK-btqV.js} +1 -1
- streamlit/static/static/js/{index.CFE-yHdT.js → index.DZEQ0G7H.js} +1 -1
- streamlit/static/static/js/{index.Bu3Lto_G.js → index.DaU1ayM7.js} +1 -1
- streamlit/static/static/js/{index.DSSQzzPk.js → index.Dla9XiNe.js} +2 -2
- streamlit/static/static/js/{index.DiZfOR0A.js → index.DmQqT9OM.js} +1 -1
- streamlit/static/static/js/{index.DuFqxjbN.js → index.DppScppA.js} +1 -1
- streamlit/static/static/js/{index.Dqphk1ee.js → index.Dr8b3Vn6.js} +1 -1
- streamlit/static/static/js/{index.CPo5dtx7.js → index.DvQ7-afx.js} +1 -1
- streamlit/static/static/js/{index.ATP5607r.js → index.F-NmmwfK.js} +1 -1
- streamlit/static/static/js/{index.gnFSTAhI.js → index.MKI8t7l2.js} +1 -1
- streamlit/static/static/js/{index.BXnQdCa5.js → index.RRAKXgBZ.js} +1 -1
- streamlit/static/static/js/{index.CyVBY8PG.js → index.VSsf6tsu.js} +2 -2
- streamlit/static/static/js/{index.DcudoGfL.js → index.aEeM0ekc.js} +1 -1
- streamlit/static/static/js/{index.Ds-w0zIo.js → index.eweE9HKU.js} +1 -1
- streamlit/static/static/js/{index.CBZQ_6AF.js → index.gr6yGiCL.js} +1 -1
- streamlit/static/static/js/{index.mZ1qbnKs.js → index.kKkHk9Mc.js} +1 -1
- streamlit/static/static/js/index.pMvzHC7z.js +1 -0
- streamlit/static/static/js/{index.DIIdzDwK.js → index.pgifwCIr.js} +1 -1
- streamlit/static/static/js/index.q83b8_8b.js +1 -0
- streamlit/static/static/js/{index.BzQChe4y.js → index.u2AvcQQT.js} +1 -1
- streamlit/static/static/js/{index.CrzXL2V8.js → index.w2_VrtVw.js} +1 -1
- streamlit/static/static/js/{index.DbmtfcDm.js → index.wv1DYVsn.js} +1 -1
- streamlit/static/static/js/{index.COZICZL6.js → index.x4j6nnNb.js} +1 -1
- streamlit/static/static/js/{input.CZPD7mCu.js → input.BoJqOS7a.js} +1 -1
- streamlit/static/static/js/{main.CX1jAiMw.js → main.B5XmUwmQ.js} +1 -1
- streamlit/static/static/js/{memory.m0jC5ULx.js → memory.9izgq54V.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.Dy0iTeCo.js → number-overlay-editor.PqOGQcLn.js} +1 -1
- streamlit/static/static/js/{pandasStylerUtils.D9jj-wHU.js → pandasStylerUtils.DUtF2t3R.js} +1 -1
- streamlit/static/static/js/{sandbox.CbvG1iAz.js → sandbox.DgKTHPLO.js} +1 -1
- streamlit/static/static/js/{styled-components.Cw3ioniY.js → styled-components.D4x8jmOI.js} +1 -1
- streamlit/static/static/js/{throttle.CAwhGpn0.js → throttle.DxEHIIp7.js} +1 -1
- streamlit/static/static/js/{timepicker.Bh3m6Pjp.js → timepicker.CDks5DWI.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.DM0o32JS.js → toConsumableArray.CvTQRsV-.js} +1 -1
- streamlit/static/static/js/uniqueId.RScLN3St.js +1 -0
- streamlit/static/static/js/{useBasicWidgetState.C9zOVP8a.js → useBasicWidgetState.D6_b0IqA.js} +1 -1
- streamlit/static/static/js/{useIntlLocale.Bo42aN1U.js → useIntlLocale.Ctz17A7g.js} +1 -1
- streamlit/static/static/js/{useTextInputAutoExpand.DmyHLDxl.js → useTextInputAutoExpand.PAFB5o1T.js} +1 -1
- streamlit/static/static/js/{useUpdateUiValue.aWXWpqmw.js → useUpdateUiValue.CcTvmGlb.js} +1 -1
- streamlit/static/static/js/{useWaveformController.DlE14M1X.js → useWaveformController.vLi36Ir4.js} +1 -1
- streamlit/static/static/js/{withCalculatedWidth.B5JFJSmG.js → withCalculatedWidth.BtA2jL5-.js} +1 -1
- streamlit/static/static/js/{withFullScreenWrapper.dgVioHk1.js → withFullScreenWrapper.CeeoYBpc.js} +1 -1
- streamlit/web/bootstrap.py +105 -10
- streamlit/web/cli.py +21 -4
- streamlit/web/server/app_discovery.py +421 -0
- streamlit/web/server/server.py +0 -13
- streamlit/web/server/starlette/__init__.py +2 -1
- streamlit/web/server/starlette/starlette_app.py +326 -3
- streamlit/web/server/starlette/starlette_routes.py +27 -8
- {streamlit_nightly-1.52.3.dev20260108.dist-info → streamlit_nightly-1.52.3.dev20260110.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.52.3.dev20260108.dist-info → streamlit_nightly-1.52.3.dev20260110.dist-info}/RECORD +115 -113
- streamlit/static/static/js/index.BOGNGR9a.js +0 -1
- streamlit/static/static/js/index.C-lnh8pI.js +0 -1
- streamlit/static/static/js/index.C98anBCM.js +0 -1
- streamlit/static/static/js/index.CFtGP8pH.js +0 -1
- streamlit/static/static/js/index.Cg59Loqx.js +0 -1
- streamlit/static/static/js/index.CiU2Tdcl.js +0 -1
- streamlit/static/static/js/index.DpnqUQVD.js +0 -1
- streamlit/static/static/js/uniqueId.DtV_RZzG.js +0 -1
- {streamlit_nightly-1.52.3.dev20260108.data → streamlit_nightly-1.52.3.dev20260110.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.52.3.dev20260108.dist-info → streamlit_nightly-1.52.3.dev20260110.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.52.3.dev20260108.dist-info → streamlit_nightly-1.52.3.dev20260110.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.52.3.dev20260108.dist-info → streamlit_nightly-1.52.3.dev20260110.dist-info}/top_level.txt +0 -0
streamlit/static/static/js/{useWaveformController.DlE14M1X.js → useWaveformController.vLi36Ir4.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{l as Z,r as i,aQ as M,aR as $,aS as O}from"./index.DkSjHoXw.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),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 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),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,aR as M,ab as $,aS as O}from"./index.BZBWLU1C.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};
|
streamlit/static/static/js/{withCalculatedWidth.B5JFJSmG.js → withCalculatedWidth.BtA2jL5-.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{h as l,k as h,j as s,d as n}from"./index.
|
|
1
|
+
import{h as l,k as h,j as s,d as n}from"./index.BZBWLU1C.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};
|
streamlit/static/static/js/{withFullScreenWrapper.dgVioHk1.js → withFullScreenWrapper.CeeoYBpc.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as n,F as f,
|
|
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.BZBWLU1C.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};
|
streamlit/web/bootstrap.py
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
import asyncio
|
|
18
|
+
import mimetypes
|
|
18
19
|
import os
|
|
19
20
|
import signal
|
|
20
21
|
import sys
|
|
@@ -123,18 +124,10 @@ def _fix_sys_argv(main_script_path: str, args: list[str]) -> None:
|
|
|
123
124
|
|
|
124
125
|
|
|
125
126
|
def _on_server_start(server: Server) -> None:
|
|
126
|
-
|
|
127
|
+
prepare_streamlit_environment(server.main_script_path)
|
|
127
128
|
_print_url(server.is_running_hello)
|
|
128
129
|
report_watchdog_availability()
|
|
129
130
|
|
|
130
|
-
# Load secrets.toml if it exists. If the file doesn't exist, this
|
|
131
|
-
# function will return without raising an exception. We catch any parse
|
|
132
|
-
# errors and display them here.
|
|
133
|
-
try:
|
|
134
|
-
secrets.load_if_toml_exists()
|
|
135
|
-
except Exception:
|
|
136
|
-
_LOGGER.exception("Failed to load secrets.toml file")
|
|
137
|
-
|
|
138
131
|
def maybe_open_browser() -> None:
|
|
139
132
|
if config.get_option("server.headless"):
|
|
140
133
|
# Don't open browser when in headless mode.
|
|
@@ -165,6 +158,55 @@ def _fix_pydeck_mapbox_api_warning() -> None:
|
|
|
165
158
|
os.environ["MAPBOX_API_KEY"] = config.get_option("mapbox.token")
|
|
166
159
|
|
|
167
160
|
|
|
161
|
+
def _initialize_mimetypes() -> None:
|
|
162
|
+
"""Ensure common MIME types are correctly registered.
|
|
163
|
+
|
|
164
|
+
Some systems may have misconfigured /etc/mime.types, so we explicitly
|
|
165
|
+
register the types we need for serving web assets correctly.
|
|
166
|
+
"""
|
|
167
|
+
mimetypes.add_type("text/html", ".html")
|
|
168
|
+
mimetypes.add_type("application/javascript", ".js")
|
|
169
|
+
mimetypes.add_type("application/javascript", ".mjs")
|
|
170
|
+
mimetypes.add_type("text/css", ".css")
|
|
171
|
+
mimetypes.add_type("image/webp", ".webp")
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def prepare_streamlit_environment(main_script_path: str) -> None:
|
|
175
|
+
"""Prepare the Streamlit environment for running an app.
|
|
176
|
+
|
|
177
|
+
This function sets up the environment needed for Streamlit to run correctly.
|
|
178
|
+
It should be called before starting the runtime, whether using the CLI
|
|
179
|
+
(`streamlit run`) or an ASGI server (`uvicorn myapp:app`).
|
|
180
|
+
|
|
181
|
+
This function:
|
|
182
|
+
- Ensures common MIME types are correctly registered
|
|
183
|
+
- Sets the MAPBOX_API_KEY environment variable for PyDeck
|
|
184
|
+
- Loads secrets from secrets.toml if it exists
|
|
185
|
+
- Validates static folder configuration
|
|
186
|
+
|
|
187
|
+
Parameters
|
|
188
|
+
----------
|
|
189
|
+
main_script_path
|
|
190
|
+
Path to the main Streamlit script.
|
|
191
|
+
|
|
192
|
+
Notes
|
|
193
|
+
-----
|
|
194
|
+
This function is automatically called by ``streamlit run``. When using
|
|
195
|
+
``st.App`` with uvicorn directly, this is called during the ASGI lifespan
|
|
196
|
+
startup phase.
|
|
197
|
+
"""
|
|
198
|
+
_initialize_mimetypes()
|
|
199
|
+
_fix_pydeck_mapbox_api_warning()
|
|
200
|
+
|
|
201
|
+
# Load secrets.toml if it exists
|
|
202
|
+
try:
|
|
203
|
+
secrets.load_if_toml_exists()
|
|
204
|
+
except Exception:
|
|
205
|
+
_LOGGER.exception("Failed to load secrets.toml file")
|
|
206
|
+
|
|
207
|
+
_maybe_print_static_folder_warning(main_script_path)
|
|
208
|
+
|
|
209
|
+
|
|
168
210
|
def _maybe_print_static_folder_warning(main_script_path: str) -> None:
|
|
169
211
|
"""Prints a warning if the static folder is misconfigured."""
|
|
170
212
|
|
|
@@ -287,6 +329,53 @@ def _install_config_watchers(flag_options: dict[str, Any]) -> None:
|
|
|
287
329
|
watch_file(filename, on_config_changed)
|
|
288
330
|
|
|
289
331
|
|
|
332
|
+
def run_asgi_app(
|
|
333
|
+
main_script_path: str,
|
|
334
|
+
app_import_string: str,
|
|
335
|
+
args: list[str],
|
|
336
|
+
flag_options: dict[str, Any],
|
|
337
|
+
) -> None:
|
|
338
|
+
"""Run a Streamlit st.App with uvicorn.
|
|
339
|
+
|
|
340
|
+
This function is called when `streamlit run` detects an st.App instance
|
|
341
|
+
in the script. It sets up the process environment and starts uvicorn.
|
|
342
|
+
|
|
343
|
+
The App instance handles its own Streamlit-specific setup via its lifespan
|
|
344
|
+
(e.g., loading secrets, preparing runtime), while this function handles
|
|
345
|
+
the process-level setup that the CLI is responsible for.
|
|
346
|
+
|
|
347
|
+
Parameters
|
|
348
|
+
----------
|
|
349
|
+
main_script_path
|
|
350
|
+
Path to the main Streamlit script containing the st.App.
|
|
351
|
+
app_import_string
|
|
352
|
+
Import string for uvicorn (e.g., "myapp:app").
|
|
353
|
+
args
|
|
354
|
+
Arguments to pass to the script (sys.argv).
|
|
355
|
+
flag_options
|
|
356
|
+
Config options from CLI flags.
|
|
357
|
+
"""
|
|
358
|
+
from streamlit.web.server.starlette.starlette_server import UvicornRunner
|
|
359
|
+
|
|
360
|
+
# Process-level setup (CLI responsibility)
|
|
361
|
+
_fix_sys_path(main_script_path)
|
|
362
|
+
_fix_sys_argv(main_script_path, args)
|
|
363
|
+
_install_config_watchers(flag_options)
|
|
364
|
+
|
|
365
|
+
# Set server mode for metrics tracking (CLI-managed st.App)
|
|
366
|
+
config._server_mode = "starlette-app"
|
|
367
|
+
|
|
368
|
+
# Report watchdog availability for file watching
|
|
369
|
+
report_watchdog_availability()
|
|
370
|
+
|
|
371
|
+
# Run the ASGI app using UvicornRunner
|
|
372
|
+
# UvicornRunner handles: port retry, SSL, WebSocket config, signal handling
|
|
373
|
+
# The st.App's lifespan will call prepare_streamlit_environment()
|
|
374
|
+
# Note: URL is printed inside UvicornRunner after port is finalized
|
|
375
|
+
runner = UvicornRunner(app_import_string)
|
|
376
|
+
runner.run()
|
|
377
|
+
|
|
378
|
+
|
|
290
379
|
def run(
|
|
291
380
|
main_script_path: str,
|
|
292
381
|
is_hello: bool,
|
|
@@ -303,9 +392,15 @@ def run(
|
|
|
303
392
|
_fix_sys_path(main_script_path)
|
|
304
393
|
_fix_tornado_crash()
|
|
305
394
|
_fix_sys_argv(main_script_path, args)
|
|
306
|
-
_fix_pydeck_mapbox_api_warning()
|
|
307
395
|
_install_config_watchers(flag_options)
|
|
308
396
|
|
|
397
|
+
# Set server mode for metrics tracking
|
|
398
|
+
# The Server class may use Starlette (via server.useStarlette config) or Tornado
|
|
399
|
+
if config.get_option("server.useStarlette"):
|
|
400
|
+
config._server_mode = "starlette-managed"
|
|
401
|
+
else:
|
|
402
|
+
config._server_mode = "tornado"
|
|
403
|
+
|
|
309
404
|
# Create the server. It won't start running yet.
|
|
310
405
|
server = Server(main_script_path, is_hello)
|
|
311
406
|
|
streamlit/web/cli.py
CHANGED
|
@@ -292,7 +292,8 @@ def _main_run(
|
|
|
292
292
|
# Set the main script path to use it for config & secret files
|
|
293
293
|
# While its a bit suboptimal, we need to store this into a module-level
|
|
294
294
|
# variable before we load the config options via `load_config_options`
|
|
295
|
-
|
|
295
|
+
main_script_path = os.path.abspath(file)
|
|
296
|
+
_config._main_script_path = main_script_path
|
|
296
297
|
|
|
297
298
|
bootstrap.load_config_options(flag_options=flag_options or {})
|
|
298
299
|
if args is None:
|
|
@@ -301,11 +302,27 @@ def _main_run(
|
|
|
301
302
|
if flag_options is None:
|
|
302
303
|
flag_options = {}
|
|
303
304
|
|
|
304
|
-
is_hello = _get_command_line_as_string() == "streamlit hello"
|
|
305
|
-
|
|
306
305
|
check_credentials()
|
|
307
306
|
|
|
308
|
-
|
|
307
|
+
# Check if the script contains an ASGI app instance (st.App, FastAPI, Starlette).
|
|
308
|
+
# This intentionally supports non-Streamlit ASGI frameworks to enable `streamlit run`
|
|
309
|
+
# as a unified entry point for projects that combine Streamlit with other frameworks.
|
|
310
|
+
from streamlit.web.server.app_discovery import discover_asgi_app
|
|
311
|
+
|
|
312
|
+
discovery_result = discover_asgi_app(Path(main_script_path))
|
|
313
|
+
|
|
314
|
+
if discovery_result.is_asgi_app:
|
|
315
|
+
# Run as ASGI app with uvicorn
|
|
316
|
+
bootstrap.run_asgi_app(
|
|
317
|
+
main_script_path,
|
|
318
|
+
discovery_result.import_string, # type: ignore[arg-type]
|
|
319
|
+
args,
|
|
320
|
+
flag_options,
|
|
321
|
+
)
|
|
322
|
+
else:
|
|
323
|
+
# Run as traditional Streamlit app
|
|
324
|
+
is_hello = _get_command_line_as_string() == "streamlit hello"
|
|
325
|
+
bootstrap.run(main_script_path, is_hello, args, flag_options)
|
|
309
326
|
|
|
310
327
|
|
|
311
328
|
# SUBCOMMAND cache
|