Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a File Uploader Widget #488

Merged
merged 44 commits into from Dec 9, 2019

Conversation

dcaminos
Copy link
Contributor

@dcaminos dcaminos commented Oct 21, 2019

#120

Example:

file_png = st.file_uploader("Upload a PNG image", type=([".png"]))

if file_png:
    file_png_bytes = st.file_reader(file_png)
    st.image(file_png_bytes)

Screen Shot 2019-10-28 at 12 04 18 PM (2)

@dcaminos dcaminos requested review from a team and removed request for a team October 21, 2019 19:14
@dcaminos dcaminos added the WIP label Oct 21, 2019
@dcaminos dcaminos requested a review from a team as a code owner October 22, 2019 14:10
@dcaminos dcaminos removed the WIP label Oct 22, 2019
Copy link
Contributor

@tconkling tconkling left a comment

Choose a reason for hiding this comment

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

Hey - this looks really good! I left some mostly nit-picky comments on style.

But the big thing missing is tests :)

  • FileManager should have its own small test suite
  • ReportSession should have tests for handle_new_file and handle_file_chunk (alternately, I think these tests could exist in Server_test.py - there are a number of tests in there that simulate a Websocket connection from the client, and send test messages to and from that simulated client.)
  • The widget itself should have a simple Cypress test

frontend/src/App.tsx Outdated Show resolved Hide resolved
frontend/src/App.tsx Outdated Show resolved Hide resolved
frontend/src/App.tsx Outdated Show resolved Hide resolved
frontend/src/App.tsx Outdated Show resolved Hide resolved
frontend/src/App.tsx Outdated Show resolved Hide resolved
proto/streamlit/proto/FileReader.proto Outdated Show resolved Hide resolved
proto/streamlit/proto/FileUploadStatus.proto Outdated Show resolved Hide resolved
lib/streamlit/ReportSession.py Outdated Show resolved Hide resolved
frontend/src/lib/WidgetStateManager.ts Outdated Show resolved Hide resolved
frontend/src/lib/WidgetStateManager.ts Outdated Show resolved Hide resolved
examples/file_uploader.py Outdated Show resolved Hide resolved
@tvst
Copy link
Contributor

tvst commented Oct 25, 2019

Found a bug: the file uploader gets into a "loading forever" state when you pass the wrong kind of file.

Steps to repro:

  1. Run examples/file_uploader.py
  2. In the CSV file uploader, pass in an MP3 file
    Expected: the file uploads, but the script throws an exception that appears in the app when it tries to read the MP3 as a CSV
    Actual: the file uploader never finishes uploading the file

@dcaminos
Copy link
Contributor Author

dcaminos commented Oct 25, 2019

@tconkling I fixed all your comments and added a test for FileManager (the most important one). ReportSession and Cypress tests are missing yet.

@tvst I fixed that bug (I check the file type before start the upload) and added a method to cancel the upload.

examples/file_uploader.py Outdated Show resolved Hide resolved
frontend/src/App.tsx Outdated Show resolved Hide resolved
frontend/src/App.tsx Outdated Show resolved Hide resolved
frontend/src/App.tsx Outdated Show resolved Hide resolved
frontend/src/App.tsx Outdated Show resolved Hide resolved
proto/streamlit/proto/BackMsg.proto Outdated Show resolved Hide resolved
proto/streamlit/proto/BackMsg.proto Outdated Show resolved Hide resolved
proto/streamlit/proto/BackMsg.proto Outdated Show resolved Hide resolved
proto/streamlit/proto/BackMsg.proto Outdated Show resolved Hide resolved
proto/streamlit/proto/Element.proto Outdated Show resolved Hide resolved
@dcaminos
Copy link
Contributor Author

dcaminos commented Nov 21, 2019

@ajinkya933 that source code is old, you should not use file_reader any more (that was my first approach).

Try to run this:

import streamlit as st

the_file = st.file_uploader("Upload a file", type=["pdf"])

if the_file is None:
    'Result:', None
else:
    'Result:', len(the_file)

@ajinkya933
Copy link

@ajinkya933 that source code is old, you should not use file_reader any more (that was my first approach).

Try to run this:

import streamlit as st

the_file = st.file_uploader("Upload a file", type=["pdf"])

if the_file is None:
    'Result:', None
else:
    'Result:', len(the_file)

Have you installed streamlit from here: https://github.com/streamlit/streamlit/wiki/Contributing#Ubuntu.

I am having trouble installing develop version of streamlit as pointed out by @tconkling initially I run

ajinkya@ajinkya-H310M-S2:~/Music/streamlit/lib$ pip3 install -e . --user
Obtaining file:///home/ajinkya/Music/streamlit/lib

for which I get a message Successfully installed streamlit

But when I do run $ streamlit --version i get

$ streamlit --version
Traceback (most recent call last):
  File "/home/ajinkya/.local/bin/streamlit", line 11, in <module>
    load_entry_point('streamlit', 'console_scripts', 'streamlit')()
  File "/home/ajinkya/.local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 489, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/home/ajinkya/.local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2852, in load_entry_point
    return ep.load()
  File "/home/ajinkya/.local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2443, in load
    return self.resolve()
  File "/home/ajinkya/.local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2449, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
  File "/home/ajinkya/Music/streamlit/lib/streamlit/__init__.py", line 96, in <module>
    from streamlit.DeltaGenerator import DeltaGenerator as _DeltaGenerator
  File "/home/ajinkya/Music/streamlit/lib/streamlit/DeltaGenerator.py", line 35, in <module>
    from streamlit.proto import Balloons_pb2
ImportError: cannot import name 'Balloons_pb2'

After getting this error I followed instructions here (https://github.com/streamlit/streamlit/wiki/Contributing#Ubuntu) and heres my output error
here is the detailed error log (#728)

@dcaminos dcaminos requested a review from tvst November 25, 2019 20:51
outline: 0;
}

.stFileUploaderError {
Copy link
Contributor

Choose a reason for hiding this comment

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

We only add st to the top-level classname in each component.

Also, wrap the whole CSS in .stFileUploader { and then you can just rename this to .uploadError or something. For example:

.stFileUploader {
  ...
  .uploadError {
    ...
  }
  ...
}

...same with everything else in this file.

That's what we've been doing in the CSS for other elements.

padding-top: 1rem;
outline: 0px;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are all these -webkit properties needed? It's best to avoid browser-specific code.


// The default file size allowed by server config is 50MB.
// The best message size to don't freeze the server is 10MB
const chunkByteLimit = 10 * 1e6 //10MB
Copy link
Contributor

Choose a reason for hiding this comment

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

What if the user sets the limit to 5MB? Does this break anything?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, we have a validation to check if the widget accept the file first

Examples
--------
>>> file = st.file_uploader("Upload a image", type=["png"])
>>> if file != None:
Copy link
Contributor

Choose a reason for hiding this comment

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

is not None


Examples
--------
>>> file = st.file_uploader("Upload a image", type=["png"])
Copy link
Contributor

Choose a reason for hiding this comment

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

type="png"

----------
label : str or None
A short label explaining to the user what this file uploader is for.
type : list of string or None
Copy link
Contributor

Choose a reason for hiding this comment

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

type : str or list of str or None

@@ -32,6 +33,14 @@
]


# Add the Streamlit lib folder when in dev mode, since otherwise we end up with
# weird situations where the ID of a class in one run is the same as in another
Copy link
Contributor

Choose a reason for hiding this comment

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

Ooops, this should be "is not the same" (I forgot the "not")

@universewill
Copy link

@ajinkya933 Have you installed the file-uploader branch into your Python environment? Simply running demo.py won't work; assuming you had previously run pip install streamlit, then when you import streamlit as st in a source file, you're getting the installed release version of streamlit.
You should probably do something like:

$ pip uninstall streamlit
$ pip install -e <path/to/file-uploader/branch/checkout>

The pip documentation contains more details about local project installs: https://pip.pypa.io/en/stable/reference/pip_install/#local-project-installs

@tconkling I have followed your steps. And have noticed that I have to install streamlit from issue120/file-uploader branch. However there are series of errors I get when I install streamlit develop branch errors:(#728)

I hope someone will help me rectify them

i try to run ' pip install -e path/to/code' command but it tells me no setup.py found.
How to install?

@universewill
Copy link

@ajinkya933 Have you installed the file-uploader branch into your Python environment? Simply running demo.py won't work; assuming you had previously run pip install streamlit, then when you import streamlit as st in a source file, you're getting the installed release version of streamlit.
You should probably do something like:

$ pip uninstall streamlit
$ pip install -e <path/to/file-uploader/branch/checkout>

The pip documentation contains more details about local project installs: https://pip.pypa.io/en/stable/reference/pip_install/#local-project-installs

@tconkling I have followed your steps. And have noticed that I have to install streamlit from issue120/file-uploader branch. However there are series of errors I get when I install streamlit develop branch errors:(#728)
I hope someone will help me rectify them

i try to run ' pip install -e path/to/code' command but it tells me no setup.py found.
How to install?

solved by 'cd streamlit/lib' first

@universewill
Copy link

@ajinkya933 that source code is old, you should not use file_reader any more (that was my first approach).
Try to run this:

import streamlit as st

the_file = st.file_uploader("Upload a file", type=["pdf"])

if the_file is None:
    'Result:', None
else:
    'Result:', len(the_file)

Have you installed streamlit from here: https://github.com/streamlit/streamlit/wiki/Contributing#Ubuntu.

I am having trouble installing develop version of streamlit as pointed out by @tconkling initially I run

ajinkya@ajinkya-H310M-S2:~/Music/streamlit/lib$ pip3 install -e . --user
Obtaining file:///home/ajinkya/Music/streamlit/lib

for which I get a message Successfully installed streamlit

But when I do run $ streamlit --version i get

$ streamlit --version
Traceback (most recent call last):
  File "/home/ajinkya/.local/bin/streamlit", line 11, in <module>
    load_entry_point('streamlit', 'console_scripts', 'streamlit')()
  File "/home/ajinkya/.local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 489, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/home/ajinkya/.local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2852, in load_entry_point
    return ep.load()
  File "/home/ajinkya/.local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2443, in load
    return self.resolve()
  File "/home/ajinkya/.local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2449, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
  File "/home/ajinkya/Music/streamlit/lib/streamlit/__init__.py", line 96, in <module>
    from streamlit.DeltaGenerator import DeltaGenerator as _DeltaGenerator
  File "/home/ajinkya/Music/streamlit/lib/streamlit/DeltaGenerator.py", line 35, in <module>
    from streamlit.proto import Balloons_pb2
ImportError: cannot import name 'Balloons_pb2'

After getting this error I followed instructions here (https://github.com/streamlit/streamlit/wiki/Contributing#Ubuntu) and heres my output error
here is the detailed error log (#728)

get same error

@Stamenov
Copy link

Stamenov commented Dec 2, 2019

Hey,
I am looking forward to this feature as a very nice addition to the streamlit widgets.
What is there left to be done? Perhaps I can help.
Best.

@ajinkya933
Copy link

Hey,
I am looking forward to this feature as a very nice addition to the streamlit widgets.
What is there left to be done? Perhaps I can help.
Best.

Perhaps you can help me in resolving this issue #728 File uploader feature is available in develop branch but I am having a tough time installing it

@@ -53,6 +54,18 @@
to suppress the warning.
"""

# based on: https://stackoverflow.com/questions/43506378/how-to-get-source-code-of-function-that-is-wrapped-by-a-decorator
# In Python 2, the @functools.wraps() decorator does not set the convenience __wrapped__
if sys.version_info[0:2] >= (3, 4): # Python v3.4+?
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like it might be 3.2

New in version 3.2: Automatic addition of the wrapped attribute.

To allow access to the original function for introspection and other purposes (e.g. bypassing a caching decorator such as lru_cache()), this function automatically adds a wrapped attribute to the wrapper that refers to the original function.

Changed in version 3.4: The wrapped attribute now always refers to the wrapped function, even if that function defined a wrapped attribute. (see issue 17482)

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh I just read the comment on stackoverflow, so I see why you chose 3.4

if sys.version_info[0:2] >= (3, 4): # Python v3.4+?
wraps = functools.wraps # built-in has __wrapped__ attribute
else:
def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we add some tests for python 2?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, if this doesn't work, a caching test will fail.

@dcaminos dcaminos dismissed tconkling’s stale review December 9, 2019 22:21

All problems have been solved

@dcaminos dcaminos merged commit 01caeec into streamlit:develop Dec 9, 2019
@dcaminos dcaminos deleted the issue120/file-uploader branch December 9, 2019 22:22
@dancebean
Copy link

Is there a way to install the latest version from this branch of repo directly, since this PR has been merged? Since it has not been included in the latest released version, pip install won't get the most updated version

@vanpelt
Copy link

vanpelt commented Dec 14, 2019

@dancebean pip install --upgrade git+git://github.com/streamlit/streamlit.git@master#egg=streamlit

@RichardOberdieck
Copy link

RichardOberdieck commented Dec 16, 2019

@dancebean pip install --upgrade git+git://github.com/streamlit/streamlit.git@master#egg=streamlit

This breaks when using conda and windows. Just saw this issue with Windows and the develop branch. Is there any indication when this will be released?

@treuille
Copy link
Contributor

treuille commented Jan 1, 2020

@dancebean, @vanpelt (👋), and @RichardOberdieck : Please note that file_uploader has been released in 0.52 in experimental form.

Also, you can find instructions to build Streamlit from source here.

Happy New Year! 🎆

@universewill
Copy link

@dancebean, @vanpelt (👋), and @RichardOberdieck : Please note that file_uploader has been released in 0.52 in experimental form.

Also, you can find instructions to build Streamlit from source here.

Happy New Year! 🎆

Great work! Besides, how to upload an image and write to local as an image file?

@universewill
Copy link

universewill commented Jan 2, 2020

@dancebean, @vanpelt (👋), and @RichardOberdieck : Please note that file_uploader has been released in 0.52 in experimental form.
Also, you can find instructions to build Streamlit from source here.
Happy New Year! 🎆

Great work! Besides, how to upload an image and write to local as an image file?

This can do:

uploaded_file = st.file_uploader("Choose a image file", type=["png", 'jpg', 'jpeg', 'tiff'])
if uploaded_file is not None:
    im = Image.open(uploaded_file)
    im.save('test.jpg', quality=95)

@treuille
Copy link
Contributor

treuille commented Jan 3, 2020

Great, @universewill . Please also know that file_uploader has an experimental API and may change!

@fathimanourin
Copy link

I get the following error when i run this

import streamlit as st

file_png = st.file_uploader("Upload a PNG image", type=([".png"]))

if file_png:
    file_png_bytes = st.file_reader(file_png)
    st.image(file_png_bytes)

AttributeError:`` module 'streamlit' has no attribute 'file_reader'
Traceback:
File "/home/fathima/.local/lib/python3.8/site-packages/streamlit/script_runner.py", line 338, in _run_script
exec(code, module.dict)
File "/home/fathima/Documents/Internship/frontend.py", line 6, in
file_png_bytes = st.file_reader(file_png)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet