-
Notifications
You must be signed in to change notification settings - Fork 4k
added server.FolderWatchList to cli + LocalSourcesWatcher #9656
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
added server.FolderWatchList to cli + LocalSourcesWatcher #9656
Conversation
|
Hey, this is awesome, thanks for the PR! We wanted something like this for a long time. I think it would be great to align this a bit more to the existing |
|
@jrieke for sure I'll implement that today, sorry I was busy during the week! I can definitely do that, and yes i agree using the name folderWatchWhitelist is too long and unnecessary. |
|
@jrieke updated the PR take a look note i removed the need to add the custom_watch_path to the EventsBasedWatcher since that code wasn't needed or used . |
|
Sweet! I just triggered the test runs, let's see if there are any issues. And I also pinged our engineers to give this a proper review. |
Awesome I'll await their feedback, also I update the branch when ever it is behind which requires the test to be run again but i seen that 22 passed and there were no errors. Feel free to trigger it again if you like, and thanks again for being proactive with this PR |
kmcgrady
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @akramsystems! Thank you for creating a PR. I realized my review didn't send out, so apologies for the delay. Overall things are looking good, I provided a couple comments on where we can tighten things up and potentially reduce memory/process overhead. Would you mind taking a look and let me know if it helps us?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably should be validating that the folder is a directory otherwise the is_directory will be not valid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for sure will add this check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do have logic that walks a full directory. https://github.com/streamlit/streamlit/blob/develop/lib/streamlit/watcher/path_watcher.py#L143
It seems to just create a watch on the path, and that can allow for . https://github.com/streamlit/streamlit/blob/develop/lib/streamlit/watcher/path_watcher.py#L119
Perhaps we can just do a watch on the path itself. Perhaps we can modify _register_watcher. We can test if the glob pattern needs to be set. This would reduce watchers generated and perhaps simplify the logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for sure i'll look at incorporating the watch_dir function and try to use the glob pattern to make watching paths easier
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created a seperate function for this as I didn't want to interfere with existing logic which uses the on_file_changed callback, and make it more explicit that this callback can be called for changes to directories
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't need to create this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed this function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as requested using the watch_dir with the usage of glob_pattern to search all subdirectories and types of files to walk the directory files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this will simplify if you update the entire try block to just be this.
kwargs = {}
if is_directory:
kwargs["glob_pattern"] = "**/*"
wm = WatchedModule(
watcher=PathWatcher(filepath, self.on_file_changed, **kwargs),
module_name=module_name,
)
self._watched_modules[filepath] = wmApologies if I was confusing, but my comment was on watch_dir was to borrow the logic from it. Looking at the function, it's simply creating a watcher with the glob pattern, and we already have the watcher, so we just need to specify the glob pattern if it's a directory. self.on_file_changed will have the correct file path because the watcher will supply the directory path, and not the actual file that changed. That's fine with us because we just want to rerun the page if we detect any change.
As an additional cleanup, I might consider modifying the name of on_file_changed to on_path_changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
applied this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needed to be done since the event_based_path_watcher only checks for abs_changed_paths, this approach checks if the path that has changed is a common ancestor of the parent path. making it simple to check for for changes to a directory no matter the file under the directory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I was able to get everything working with removing this code. Seems to work fine in my tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kmcgrady I can remove the check for if changed_path_info is None, but if I remove the for loop going over the watched_paths.items()and checking if they share common path then it fails to update the app there is a change in the directories being watched.
akramsystems
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kmcgrady I made some small changes (and left some comments) let me know your thoughts, or if this was what you had in mind. Your feedback is greatly appreciated! 👍🏽
kmcgrady
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for the delay. I'm working hard to wrap up some stuff before the holidays occur.
I provided some comments with suggested changes. I think we can simplify this a lot more. Can you check to see if the changes work for your use cases. I did some testing of editing files in a directory, and having the script rerun successfully for both Event and Polling Strategy.
I am around this week if you want to talk more. After that, I go on vacation, and will resume reviewing in the new year.
lib/streamlit/config.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You shouldn't need to specify the type_. I think it's a little weird, but I think it should be str because the values are strings, but we will accept multiple strings for the paths. The fact that the default val is a list hints at taking multiple values, and str is inferred by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I was able to get everything working with removing this code. Seems to work fine in my tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't need to create this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this will simplify if you update the entire try block to just be this.
kwargs = {}
if is_directory:
kwargs["glob_pattern"] = "**/*"
wm = WatchedModule(
watcher=PathWatcher(filepath, self.on_file_changed, **kwargs),
module_name=module_name,
)
self._watched_modules[filepath] = wmApologies if I was confusing, but my comment was on watch_dir was to borrow the logic from it. Looking at the function, it's simply creating a watcher with the glob pattern, and we already have the watcher, so we just need to specify the glob pattern if it's a directory. self.on_file_changed will have the correct file path because the watcher will supply the directory path, and not the actual file that changed. That's fine with us because we just want to rerun the page if we detect any change.
As an additional cleanup, I might consider modifying the name of on_file_changed to on_path_changed.
|
Hey @akramsystems Just following up to ask if you plan to continue working on this PR and if the feedback given makes sense. Let me know! :-) |
|
@kmcgrady yes I plan on continuing to work on this PR, sorry i had a surgery in the end of the year so that caused me to delay some of my work. Will continue the grind! Yes your comments make sense i will update the PR |
|
I hope your surgery went well and a speedy recovery. Let me know how I can help! |
|
Hey @akramsystems I updated the title with |
|
+1 this is an awesome addition! |
|
+1 on this! |
🎉 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) |
|
@kmcgrady ready for re-review I applied all but one of your recommendations |
|
@akramsystems Seems like mypy passed just fine, but there seems to be a python test failure. |
8a5e615 to
8367a4c
Compare
…s under the folder to PathWatcher for the LocalSourcesWatcher
…cepting a list of folder paths instead of a single path to watch
…witched to using watch_dir with glob_pattern to easily walk directory + using a new callback to trigger changes within directories specifically + updated events based path watcher to take account for triggering and event to fire the callback function when a directory is changed + updated test to reflect new logic
Trying to set a record for the smallest code contribution to Streamlit. In an ironic twist, I completely ignored the very instructions I'm updating and skipped creating an issue first. ## Describe your changes Fixing a typo in the README.md file: Ff -> If. Tiny change. Big impact. ## GitHub Issue Link (if applicable) Taking the scenic route and skipping the issue for this monumental PR. ## Testing Plan - Visual inspection by reviewer. - Reflecting on the irony of fixing instructions I did not follow... --- **Contribution License Agreement** By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.
… implementation
…ng watched + fixed mypy issues
8367a4c to
0bb7daf
Compare
|
@kmcgrady seems like the tests are passing ? |
|
Great work @akramsystems Approved and merged |
|
HALLALUYAH THANK YOU SO MUCH @kmcgrady |
|
Wohoo, congrats for getting this merged @akramsystems! |
|
Awesome @akramsystems! |
|
@sfc-gh-jesmith it looks like this was merged to I don't think it's just an issue with the release notes, as doing Only dev tags 🤷 . The change definitely exists in the Do you know what's happened to this change, and/or when it's going to make it into a release? Thanks! 🙏 |
|
@adamalton the change will be released in 1.46 |
|
@lukasmasuch Thank you 🙏 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces the new configuration option server.folderWatchList to allow users to specify additional folders to watch for file changes. Key changes include updates to the file watch API (renaming on_file_changed to on_path_changed), new tests for folder-based watching, and corresponding configuration updates.
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| lib/tests/streamlit/watcher/local_sources_watcher_test.py | Updated tests to use the new on_path_changed method and added test_folder_watch_list to verify watcher registration for custom folders. |
| lib/tests/streamlit/config_test.py | Included the new server.folderWatchList option in configuration option keys tests. |
| lib/streamlit/watcher/local_sources_watcher.py | Implemented support for custom watch folders via server.folderWatchList, updated callback naming, and modified _register_watcher accordingly. |
| lib/streamlit/watcher/event_based_path_watcher.py | Adjusted path change event handling to detect file changes within watched directories. |
| lib/streamlit/config.py | Added the new configuration option with an appropriate description. |
Comments suppressed due to low confidence (2)
lib/streamlit/watcher/local_sources_watcher.py:180
- Duplicate assignment to self._watched_modules[filepath] exists after the try block. Removing the redundant assignment would improve code clarity.
self._watched_modules[filepath] = wm
lib/tests/streamlit/watcher/local_sources_watcher_test.py:526
- [nitpick] Consider asserting that the watcher for the main script is also registered as expected, not just the folder watchers, to ensure comprehensive test coverage.
self.assertIn(expected_calls[1], actual_calls)
Hey sorry for taking a while getting back to you, but yes I just replied to the form :D ! |
Describe your changes
This PR adds a new configuration option
server.folderWatchListto allow users to specify a custom path to watch for file changes. Currently, Streamlit only supports watching the directory of the main script or excluding files via a blacklist, but this change provides the flexibility to monitor external directories or specific folders. Additionally, logic has been added to ensure the new path is recursively watched for file changes, and tests have been updated to cover this feature.Note: This is my first time doing a PR to open source, so any feedback would be appreciated.
GitHub Issue Link (if applicable)
Issue Number: #9655
Testing Plan
local_sources_watcher_test.pyto ensure the custom watch path feature behaves as expected.MANUAL TEST
streamlit run app/hello.py --server.runOnSave=true --server.folderWatchList=<BASE_PATH>/test_folder --logger.level=debugapp/hello.py
.streamlit/config.toml
Note: the list of folders should be absolute paths currently, thought this is a good first step and then we can add regex search or relative paths in another PR if possible, since smaller PR's are more manageable/
Contribution License Agreement
By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.