Skip to content

Commit

Permalink
Merge branch 'develop' into tim/ScriptRunnerTyping
Browse files Browse the repository at this point in the history
# By Vincent Donato (3) and others
# Via GitHub
* develop:
  Add temporary fix to download tensorflow less than 2.8 but >=2.6 in order to fix test suite (streamlit#4372)
  Cloud plan titles updated in README (streamlit#4369)
  Actually save the query_string after a script run (streamlit#4334)
  Update Streamlit markdown to be more flexible with links (streamlit#4364)
  Keep support for ICO formats by defaulting to PNG if necessary (streamlit#4343)
  Remove some remaining usage of the term "report" (streamlit#4293)
  Improve error when streamlit is run via `python -m streamlit.cli` (streamlit#4359)

# Conflicts:
#	lib/streamlit/app_session.py
#	lib/streamlit/script_runner.py
  • Loading branch information
tconkling committed Feb 7, 2022
2 parents 9422981 + d153db3 commit b13b035
Show file tree
Hide file tree
Showing 49 changed files with 313 additions and 274 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -61,8 +61,8 @@ Once you deploy your app, you can embed this badge right into your GitHub readme

[Streamlit Cloud](https://streamlit.io/cloud) is our deployment solution for managing, sharing, and collaborating on your Streamlit apps.

- The Teams and Enterprise tiers provide secure single-click deploy, authentication, web editing, versioning, and much more for your Streamlit apps. You can sign-up [here](https://share.streamlit.io/signup).
- The Community tier (formerly Streamlit sharing) is the perfect solution if your app is hosted in a public GitHub repo and you’d like anyone in the world to be able to access it. It's completely free to use and you can sign-up [here](https://share.streamlit.io).
- The Teams and Enterprise plans provide secure single-click deploy, authentication, web editing, versioning, and much more for your Streamlit apps. You can sign-up [here](https://share.streamlit.io/signup).
- The Starter plan is the perfect solution if your app is hosted in a public GitHub repo and you’d like anyone in the world to be able to access it. It's completely free to use and you can sign-up [here](https://share.streamlit.io).

## License

Expand Down
35 changes: 35 additions & 0 deletions e2e/scripts/st_set_page_config_icon.py
@@ -0,0 +1,35 @@
import streamlit as st
import os, fnmatch


def is_assets_favicon_path(path):
if "assets/favicon.ico" in path:
return path


def filter_nones(l):
return list(filter(None, l))


def find(pattern, path):
result = []
for root, dirs, files in os.walk(path):
for name in files:
if fnmatch.fnmatch(name, pattern):
result.append(os.path.join(root, name))
return result


# We want to find the file from 2 directories behind for circle ci
# and for local testing if you are in the e2e/scripts folder
# if you are in the root streamlit directory,
# this script still work but will be slower likely.
paths = find("favicon.ico", "../..")
filtered_paths = filter_nones(list(map(is_assets_favicon_path, paths)))

if len(filtered_paths) != 1:
print("Can't seem to find assets/favicon.ico in the directory you're in.")
else:
st.set_page_config(
page_icon=filtered_paths[0],
)
31 changes: 31 additions & 0 deletions e2e/specs/st_set_page_config_icon.spec.js
@@ -0,0 +1,31 @@
/**
* @license
* Copyright 2018-2022 Streamlit Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

describe("st.set_page_config", () => {
before(() => {
cy.loadApp("http://localhost:3000/");
});

it("sets the page favicon with ico file", () => {
cy.get("link[rel='shortcut icon']")
.should("have.attr", "href")
.should(
"contain",
"92018b2805266c4cb9a98e90c849ce5b5e7ba6d1af423bd7b7c345da.png"
);
});
});
37 changes: 8 additions & 29 deletions frontend/src/App.tsx
Expand Up @@ -409,34 +409,13 @@ export class App extends PureComponent<Props, State> {
this.handleGitInfoChanged(gitInfo),
scriptFinished: (status: ForwardMsg.ScriptFinishedStatus) =>
this.handleScriptFinished(status),
uploadReportProgress: (progress: number) =>
this.handleUploadReportProgress(progress),
reportUploaded: (url: string) => this.handleReportUploaded(url),
})
} catch (err) {
logError(err)
this.showError("Bad message format", err.message)
}
}

handleUploadReportProgress = (progress: number): void => {
const newDialog: DialogProps = {
type: DialogType.UPLOAD_PROGRESS,
progress,
onClose: () => {},
}
this.openDialog(newDialog)
}

handleReportUploaded = (url: string): void => {
const newDialog: DialogProps = {
type: DialogType.UPLOADED,
url,
onClose: () => {},
}
this.openDialog(newDialog)
}

handlePageConfigChanged = (pageConfig: PageConfig): void => {
const {
title,
Expand Down Expand Up @@ -504,11 +483,11 @@ export class App extends PureComponent<Props, State> {
stateChangeProto.scriptIsRunning &&
prevState.scriptRunState !== ScriptRunState.STOP_REQUESTED
) {
// If the report is running, we change our ScriptRunState only
// If the script is running, we change our ScriptRunState only
// if we don't have a pending stop request
scriptRunState = ScriptRunState.RUNNING

// If the scriptCompileError dialog is open and the report starts
// If the scriptCompileError dialog is open and the script starts
// running, close it.
if (
dialog != null &&
Expand All @@ -521,7 +500,7 @@ export class App extends PureComponent<Props, State> {
prevState.scriptRunState !== ScriptRunState.RERUN_REQUESTED &&
prevState.scriptRunState !== ScriptRunState.COMPILATION_ERROR
) {
// If the report is not running, we change our ScriptRunState only
// If the script is not running, we change our ScriptRunState only
// if we don't have a pending rerun request, and we don't have
// a script compilation failure
scriptRunState = ScriptRunState.NOT_RUNNING
Expand Down Expand Up @@ -726,7 +705,7 @@ export class App extends PureComponent<Props, State> {

/**
* Handler for ForwardMsg.scriptFinished messages
* @param status the ScriptFinishedStatus that the report finished with
* @param status the ScriptFinishedStatus that the script finished with
*/
handleScriptFinished(status: ForwardMsg.ScriptFinishedStatus): void {
if (status === ForwardMsg.ScriptFinishedStatus.FINISHED_SUCCESSFULLY) {
Expand Down Expand Up @@ -842,7 +821,7 @@ export class App extends PureComponent<Props, State> {
this.pendingElementsTimerRunning = true

// (BUG #685) When user presses stop, stop adding elements to
// report immediately to avoid race condition.
// the app immediately to avoid race condition.
const scriptIsRunning =
this.state.scriptRunState === ScriptRunState.RUNNING

Expand Down Expand Up @@ -871,7 +850,7 @@ export class App extends PureComponent<Props, State> {
*
* @param alwaysRunOnSave a boolean. If true, UserSettings.runOnSave
* will be set to true, which will result in a request to the Server
* to enable runOnSave for this report.
* to enable runOnSave for this session.
*/
rerunScript = (alwaysRunOnSave = false): void => {
this.closeDialog()
Expand Down Expand Up @@ -937,7 +916,7 @@ export class App extends PureComponent<Props, State> {
)
}

/** Requests that the server stop running the report */
/** Requests that the server stop running the script */
stopScript = (): void => {
if (!this.isServerConnected()) {
logError("Cannot stop app when disconnected from server.")
Expand Down Expand Up @@ -1013,7 +992,7 @@ export class App extends PureComponent<Props, State> {
}

/**
* Updates the report body when there's a connection error.
* Updates the app body when there's a connection error.
*/
handleConnectionError = (errNode: ReactNode): void => {
this.showError("Connection error", errNode)
Expand Down
Binary file added frontend/src/assets/favicon.ico
Binary file not shown.
4 changes: 2 additions & 2 deletions frontend/src/components/core/AppView/AppView.test.tsx
Expand Up @@ -34,7 +34,7 @@ function getProps(props: Partial<AppViewProps> = {}): AppViewProps {

return {
elements: AppRoot.empty(),
scriptRunId: "report 123",
scriptRunId: "script run 123",
scriptRunState: ScriptRunState.NOT_RUNNING,
showStaleElementIndicator: true,
widgetMgr: new WidgetStateManager({
Expand Down Expand Up @@ -72,7 +72,7 @@ describe("AppView element", () => {
const sidebarElement = new ElementNode(
makeElementWithInfoText("sidebar!"),
ForwardMsgMetadata.create({}),
"no report id"
"no script run id"
)

const sidebar = new BlockNode(
Expand Down
8 changes: 3 additions & 5 deletions frontend/src/components/core/AppView/AppView.tsx
Expand Up @@ -38,16 +38,14 @@ import {
export interface AppViewProps {
elements: AppRoot

// The unique ID for the most recent run of the report.
// The unique ID for the most recent script run.
scriptRunId: string

scriptRunState: ScriptRunState

/**
* If true, "stale" elements (that is, elements that were created during a previous
* run of a currently-running report) will be faded out.
*
* (When we're viewing a shared report, this is set to false.)
* run of a currently-running script) will be faded out.
*/
showStaleElementIndicator: boolean

Expand All @@ -64,7 +62,7 @@ export interface AppViewProps {
}

/**
* Renders a Streamlit report. Reports consist of 0 or more elements.
* Renders a Streamlit app.
*/
function AppView(props: AppViewProps): ReactElement {
const {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/core/Block/Block.test.tsx
Expand Up @@ -49,7 +49,7 @@ describe("Vertical Block Component", () => {
const wrapper = mount(
<VerticalBlock
node={block}
reportId={""}
scriptRunId={""}
scriptRunState={ScriptRunState.NOT_RUNNING}
showStaleElementIndicator={false}
widgetsDisabled={false}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/core/Block/styled-components.ts
Expand Up @@ -39,7 +39,7 @@ export interface StyledElementContainerProps {
export const StyledElementContainer = styled.div<StyledElementContainerProps>(
({ theme, isStale, width, elementType }) => ({
width,
// Allows to have absolutely-positioned nodes inside report elements, like
// Allows to have absolutely-positioned nodes inside app elements, like
// floating buttons.
position: "relative",

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/core/MainMenu/MainMenu.tsx
Expand Up @@ -76,7 +76,7 @@ export interface Props {
/** True if we're connected to the Streamlit server. */
isServerConnected: boolean

/** Rerun the report. */
/** Rerun the current script. */
quickRerunCallback: () => void

/** Reload git information message */
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/components/core/StatusWidget/StatusWidget.test.tsx
Expand Up @@ -177,7 +177,7 @@ describe("Tooltip element", () => {
expect(stopScript).toBeCalled()
})

it("shows the rerun button when report changes", () => {
it("shows the rerun button when script changes", () => {
const sessionEventDispatcher = new SessionEventDispatcher()
const rerunScript = jest.fn()

Expand All @@ -196,7 +196,7 @@ describe("Tooltip element", () => {
sessionEventDispatcher.handleSessionEventMsg(
new SessionEvent({
scriptChangedOnDisk: true,
reportWasManuallyStopped: null,
scriptWasManuallyStopped: null,
scriptCompilationException: null,
})
)
Expand All @@ -210,7 +210,7 @@ describe("Tooltip element", () => {
expect(rerunScript).toBeCalledWith(false)
})

it("shows the always rerun button when report changes", () => {
it("shows the always rerun button when script changes", () => {
const sessionEventDispatcher = new SessionEventDispatcher()
const rerunScript = jest.fn()

Expand All @@ -229,7 +229,7 @@ describe("Tooltip element", () => {
sessionEventDispatcher.handleSessionEventMsg(
new SessionEvent({
scriptChangedOnDisk: true,
reportWasManuallyStopped: null,
scriptWasManuallyStopped: null,
scriptCompilationException: null,
})
)
Expand All @@ -243,7 +243,7 @@ describe("Tooltip element", () => {
expect(rerunScript).toBeCalledWith(true)
})

it("does not show the always rerun button when report changes", () => {
it("does not show the always rerun button when script changes", () => {
const sessionEventDispatcher = new SessionEventDispatcher()
const rerunScript = jest.fn()

Expand All @@ -263,7 +263,7 @@ describe("Tooltip element", () => {
sessionEventDispatcher.handleSessionEventMsg(
new SessionEvent({
scriptChangedOnDisk: true,
reportWasManuallyStopped: null,
scriptWasManuallyStopped: null,
scriptCompilationException: null,
})
)
Expand Down

0 comments on commit b13b035

Please sign in to comment.