Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@abokey1
Copy link
Contributor

@abokey1 abokey1 commented Mar 9, 2025

Describe your changes

This PR enables st.page_link to automatically pick the icon (if any) from an st.Page.

GitHub Issue Link (if applicable)

Closes #9743

Testing Plan

  • Explanation of why no additional tests are needed
  • Unit Tests (JS and/or Python) ✅
  • E2E Tests
  • Any manual testing needed?

There is a typo in one of the commits, "e2e" instead of "unit"


Contribution License Agreement

By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

@abokey1 abokey1 changed the title Fix/inherit icon page Make st.page_link inherit icon from st.Page Mar 9, 2025
@sfc-gh-lwilby sfc-gh-lwilby self-assigned this Mar 9, 2025
@sfc-gh-lwilby
Copy link
Collaborator

I think since previously we did not send the icon in the proto and now we will send it always when a StreamlitPage is provided, it would be good to add some test coverage to the frontend tests that verify the beahviour when an empty string is provided for the icon (this seems to be the default in StreamlitPage).

@sfc-gh-lwilby sfc-gh-lwilby added security-assessment-completed Security assessment has been completed for PR change:feature PR contains new feature or enhancement implementation labels Mar 9, 2025
@sfc-gh-lwilby
Copy link
Collaborator

Pending behaviour change approval from @jrieke

@sfc-gh-lwilby sfc-gh-lwilby added the impact:users PR changes affect end users label Mar 9, 2025
@abokey1
Copy link
Contributor Author

abokey1 commented Mar 9, 2025

I think since previously we did not send the icon in the proto and now we will send it always when a StreamlitPage is provided, it would be good to add some test coverage to the frontend tests that verify the beahviour when an empty string is provided for the icon (this seems to be the default in StreamlitPage).

Sure, I'll add more tests. But before, I wonder why self._icon isn't reassigned during the StreamlitPage initialization while it is in page_link. Do you have an idea ?

if self._icon:
validate_icon_or_emoji(self._icon)

if icon is not None:
page_link_proto.icon = validate_icon_or_emoji(icon)

@sfc-gh-lwilby
Copy link
Collaborator

I think since previously we did not send the icon in the proto and now we will send it always when a StreamlitPage is provided, it would be good to add some test coverage to the frontend tests that verify the beahviour when an empty string is provided for the icon (this seems to be the default in StreamlitPage).

Sure, I'll add more tests. But before, I wonder why self._icon isn't reassigned during the StreamlitPage initialization while it is in page_link. Do you have an idea ?

if self._icon:
validate_icon_or_emoji(self._icon)

if icon is not None:
page_link_proto.icon = validate_icon_or_emoji(icon)

In button.py it is being added to the proto message that will be sent to the streamlit FE.

@abokey1
Copy link
Contributor Author

abokey1 commented Mar 9, 2025

I think since previously we did not send the icon in the proto and now we will send it always when a StreamlitPage is provided, it would be good to add some test coverage to the frontend tests that verify the beahviour when an empty string is provided for the icon (this seems to be the default in StreamlitPage).

Sure, I'll add more tests. But before, I wonder why self._icon isn't reassigned during the StreamlitPage initialization while it is in page_link. Do you have an idea ?

if self._icon:
validate_icon_or_emoji(self._icon)

if icon is not None:
page_link_proto.icon = validate_icon_or_emoji(icon)

In button.py it is being added to the proto message that will be sent to the streamlit FE.

I'm saying that because it feels a bit counter intuitive to me (both in terms of consistency and the fact that validate_icon_or_emoji is supposed to return a string). That being said, currently in develop using the code below, the first st.page_link works fine while the second one triggers a StreamlitAPIException: The value "" is not a valid emoji.

page = st.Page(
    "a_page_path_stem.py",
    title="A title",
    icon="",
)

st.page_link(page) # works fine
st.page_link(page, icon="")  # triggers an error

By the way, I added a few more tests but the last one is failing because of this behaviour..

@sfc-gh-lwilby
Copy link
Collaborator

I think since previously we did not send the icon in the proto and now we will send it always when a StreamlitPage is provided, it would be good to add some test coverage to the frontend tests that verify the beahviour when an empty string is provided for the icon (this seems to be the default in StreamlitPage).

Sure, I'll add more tests. But before, I wonder why self._icon isn't reassigned during the StreamlitPage initialization while it is in page_link. Do you have an idea ?

if self._icon:
validate_icon_or_emoji(self._icon)

if icon is not None:
page_link_proto.icon = validate_icon_or_emoji(icon)

In button.py it is being added to the proto message that will be sent to the streamlit FE.

I'm saying that because it feels a bit counter intuitive to me (both in terms of consistency and the fact that validate_icon_or_emoji is supposed to return a string). That being said, currently in develop using the code below, the first st.page_link works fine while the second one triggers a StreamlitAPIException: The value "" is not a valid emoji.

page = st.Page(
    "a_page_path_stem.py",
    title="A title",
    icon="",
)

st.page_link(page) # works fine
st.page_link(page, icon="")  # triggers an error

By the way, I added a few more tests but the last one is failing because of this behaviour..

I don't follow your concern about consistency. You must assign the value to the proto message in button.py because that is how the server communicates with the frontend. Maybe you can give an example of what you want to do differently to demonstrate your concern?

An empty string is not a valid emoji, so this error seems correct to me. We want to let people know that they haven't provided an actual icon at the API level so that they can correct their code. Internally, whether we send an empty string for this property or leave it out of the proto message is an implementation detail and as long as it is handled correctly E2E either way should be fine.

@abokey1
Copy link
Contributor Author

abokey1 commented Mar 9, 2025

I think since previously we did not send the icon in the proto and now we will send it always when a StreamlitPage is provided, it would be good to add some test coverage to the frontend tests that verify the beahviour when an empty string is provided for the icon (this seems to be the default in StreamlitPage).

Sure, I'll add more tests. But before, I wonder why self._icon isn't reassigned during the StreamlitPage initialization while it is in page_link. Do you have an idea ?

if self._icon:
validate_icon_or_emoji(self._icon)

if icon is not None:
page_link_proto.icon = validate_icon_or_emoji(icon)

In button.py it is being added to the proto message that will be sent to the streamlit FE.

I'm saying that because it feels a bit counter intuitive to me (both in terms of consistency and the fact that validate_icon_or_emoji is supposed to return a string). That being said, currently in develop using the code below, the first st.page_link works fine while the second one triggers a StreamlitAPIException: The value "" is not a valid emoji.

page = st.Page(
    "a_page_path_stem.py",
    title="A title",
    icon="",
)

st.page_link(page) # works fine
st.page_link(page, icon="")  # triggers an error

By the way, I added a few more tests but the last one is failing because of this behaviour..

I don't follow your concern about consistency. You must assign the value to the proto message in button.py because that is how the server communicates with the frontend. Maybe you can give an example of what you want to do differently to demonstrate your concern?

An empty string is not a valid emoji, so this error seems correct to me. We want to let people know that they haven't provided an actual icon at the API level so that they can correct their code. Internally, whether we send an empty string for this property or leave it out of the proto message is an implementation detail and as long as it is handled correctly E2E either way should be fine.

Thanks for the explanation. Actually, I used the term consistency because I was expecting the error to be triggered in both cases (see below) but I'm overlooking something for sure.

# case 1
page_1 = st.Page(
    "a_page_path_stem.py",
    title="A title",
    icon="", # should? trigger an error
)

# case 2
page_2 = st.Page(
    "a_page_path_stem.py",
    title="A title",
    icon=":material/animation:",
)
st.page_link(page_2, icon="") # triggers an error

@sfc-gh-lwilby
Copy link
Collaborator

Thanks for the explanation. Actually, I used the term consistency because I was expecting the error to be triggered in both cases (see below) but I'm overlooking something for sure.

# case 1
page_1 = st.Page(
    "a_page_path_stem.py",
    title="A title",
    icon="", # should? trigger an error
)

# case 2
page_2 = st.Page(
    "a_page_path_stem.py",
    title="A title",
    icon=":material/animation:",
)
st.page_link(page_2, icon="") # triggers an error

I see, this is a bit different then the example you provided previously, I agree that it would be clearer if st.page and st.page_link both throw an error if icon is an empty string. Before making that change we should also get agreement from @jrieke on the behaviour change for st.page.

@sfc-gh-lwilby
Copy link
Collaborator

Note: I was thinking of React tests to cover a blank string for the icon in the proto. I think currently we don't have tests for that but it seems we do check if icon is truthy and skip rendering if it is not.

@sfc-gh-jrieke
Copy link
Contributor

Yeah this seems fine to me!

I'm wondering if there are situations where you have an icon on the page but don't want it to show up on the page link. But that seems like such a small niche case that I wouldn't worry about it now and just wait to see if someone complains. In the original issue, it was mentioned that we could allow icon=False for this situation. I think that's an option, but I also don't love that API; so I'd just merge this as is now and worry about that special case later :)

@sfc-gh-lwilby
Copy link
Collaborator

@abokey1 I think the pending items before merging this PR are:

  • Potentially make the handling of an empty string consistent between st.page and st.page_link as you suggested. We have agreement from Johannes on this so I think it would be good to add it here.
  • React test coverage.

Are you able to look into these items? If not I might be able to find some time to finish this off so we can merge it.

@snyk-io
Copy link
Contributor

snyk-io bot commented Jun 4, 2025

🎉 Snyk checks have passed. No issues have been found so far.

security/snyk check is complete. No issues have been found. (View Details)

license/snyk check is complete. No issues have been found. (View Details)

Copy link
Collaborator

@lukasmasuch lukasmasuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@sfc-gh-lwilby sfc-gh-lwilby added change:bugfix PR contains bug fix implementation change:feature PR contains new feature or enhancement implementation and removed change:feature PR contains new feature or enhancement implementation labels Jun 13, 2025
@sfc-gh-lwilby sfc-gh-lwilby merged commit 96dec88 into streamlit:develop Jun 13, 2025
37 of 40 checks passed
@sfc-gh-lwilby
Copy link
Collaborator

@abokey1 made some updates to add tests and make the change you suggested to keep the handling of icon="" consistent and merged. Thank-you for contributing 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:bugfix PR contains bug fix implementation impact:users PR changes affect end users security-assessment-completed Security assessment has been completed for PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inherit icon in st.page_link from st.Page

4 participants