Skip to content

Commit

Permalink
Deploy button py (streamlit#2535)
Browse files Browse the repository at this point in the history
* Python side

* format

* import

* todo

* #  * git binary or GitPython not installed

* undo white spaces

* undo white spaces

* undo white spaces

* handle_git_information_request

* git_info_changed

* Using enum

* ahead_commits and uncommitted_files as properties

* format
  • Loading branch information
arraydude committed Jan 4, 2021
1 parent bfb7cfc commit 0bbc7aa
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 32 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ cffi_bin

# Pyenv Stuff
.python-version
venv

# Autogenerated Protobufs
lib/streamlit/proto/*_pb2.py
Expand Down
35 changes: 34 additions & 1 deletion lib/streamlit/git_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ def __init__(self, path):

self.repo = git.Repo(path, search_parent_directories=True)
self.git_version = self.repo.git.version_info

if self.git_version >= MIN_GIT_VERSION:
git_root = self.repo.git.rev_parse("--show-toplevel")
self.module = os.path.relpath(path, git_root)

except:
# The git repo must be invalid for the following reasons:
# * git binary or GitPython not installed
Expand All @@ -47,13 +47,46 @@ def is_valid(self) -> bool:
def tracking_branch(self):
if not self.is_valid():
return None

if self.is_head_detached:
return None

return self.repo.active_branch.tracking_branch()

@property
def untracked_files(self):
return self.repo.untracked_files

@property
def is_head_detached(self):
return self.repo.head.is_detached

@property
def uncommitted_files(self):
if not self.is_valid():
return None

return [item.a_path for item in self.repo.index.diff(None)]

@property
def ahead_commits(self):
if not self.is_valid():
return None

try:
remote, branch_name = self.get_tracking_branch_remote()
remote_branch = "/".join([remote.name, branch_name])

return list(self.repo.iter_commits(f"{remote_branch}..{branch_name}"))
except:
return list()

def get_tracking_branch_remote(self):
if not self.is_valid():
return None

tracking_branch = self.tracking_branch

if tracking_branch is None:
return None

Expand Down
53 changes: 32 additions & 21 deletions lib/streamlit/report_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from streamlit.logger import get_logger
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
from streamlit.proto.ClientState_pb2 import ClientState
from streamlit.proto.GitInfo_pb2 import GitInfo
from streamlit.server.server_util import serialize_forward_msg
from streamlit.storage.file_storage import FileStorage
from streamlit.watcher.local_sources_watcher import LocalSourcesWatcher
Expand All @@ -59,6 +60,7 @@ class ReportSession(object):
and widget state.
A ReportSession is attached to each thread involved in running its Report.
"""

def __init__(self, ioloop, script_path, command_line, uploaded_file_manager):
Expand Down Expand Up @@ -345,34 +347,14 @@ def _enqueue_file_change_message(self):
msg.session_event.report_changed_on_disk = True
self.enqueue(msg)

def get_deploy_params(self):
try:
from streamlit.git_util import GitRepo

self._repo = GitRepo(self._report.script_path)
return self._repo.get_repo_info()
except:
# Issues can arise based on the git structure
# (e.g. if branch is in DETACHED HEAD state,
# git is not installed, etc)
# In this case, catch any errors
return None

def _enqueue_new_report_message(self):
self._report.generate_new_id()

msg = ForwardMsg()
msg.new_report.report_id = self._report.report_id
msg.new_report.name = self._report.name
msg.new_report.script_path = self._report.script_path

# git deploy params
deploy_params = self.get_deploy_params()
if deploy_params is not None:
repo, branch, module = deploy_params
msg.new_report.deploy_params.repository = repo
msg.new_report.deploy_params.branch = branch
msg.new_report.deploy_params.module = module

# Immutable session data. We send this every time a new report is
# started, to avoid having to track whether the client has already
# received it. It does not change from run to run; it's up to the
Expand Down Expand Up @@ -423,6 +405,34 @@ def _enqueue_report_finished_message(self, status):
msg.report_finished = status
self.enqueue(msg)

def handle_git_information_request(self):
msg = ForwardMsg()

try:
from streamlit.git_util import GitRepo

self._repo = GitRepo(self._report.script_path)

repo, branch, module = self._repo.get_repo_info()

msg.git_info_changed.repository = repo
msg.git_info_changed.branch = branch
msg.git_info_changed.module = module

msg.git_info_changed.untracked_files[:] = self._repo.untracked_files
msg.git_info_changed.uncommitted_files[:] = self._repo.uncommitted_files

if self._repo.is_head_detached:
msg.git_info_changed.state = GitInfo.GitStates.HEAD_DETACHED
elif len(self._repo.ahead_commits) > 0:
msg.git_info_changed.state = GitInfo.GitStates.AHEAD_OF_REMOTE
else:
msg.git_info_changed.state = GitInfo.GitStates.DEFAULT
except:
pass

self.enqueue(msg)

def handle_rerun_script_request(self, client_state=None, is_preheat=False):
"""Tell the ScriptRunner to re-run its report.
Expand All @@ -431,6 +441,7 @@ def handle_rerun_script_request(self, client_state=None, is_preheat=False):
client_state : streamlit.proto.ClientState_pb2.ClientState | None
The ClientState protobuf to run the script with, or None
to use previous client state.
is_preheat: boolean
True if this ReportSession should run the script immediately, and
then ignore the next rerun request if it matches the already-ran
Expand Down
2 changes: 2 additions & 0 deletions lib/streamlit/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,8 @@ def on_message(self, payload):
yield self._session.handle_save_request(self)
elif msg_type == "rerun_script":
self._session.handle_rerun_script_request(msg.rerun_script)
elif msg_type == "load_git_info":
self._session.handle_git_information_request()
elif msg_type == "clear_cache":
self._session.handle_clear_cache_request()
elif msg_type == "set_run_on_save":
Expand Down
8 changes: 0 additions & 8 deletions lib/tests/streamlit/report_session_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,6 @@ def get_option(name):
# Expect func to be called only once, inside enqueue().
func.assert_called_once()

@patch("streamlit.report_session.LocalSourcesWatcher")
@pytest.mark.usefixtures("del_path")
def test_get_deploy_params_with_no_git(self, _1):
"""Make sure we try to handle execution control requests."""
rs = ReportSession(None, report_session.__file__, "", UploadedFileManager())

self.assertIsNone(rs.get_deploy_params())

@patch("streamlit.report_session.config")
@patch("streamlit.report_session.Report")
@patch("streamlit.report_session.LocalSourcesWatcher")
Expand Down
2 changes: 2 additions & 0 deletions proto/streamlit/proto/BackMsg.proto
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ message BackMsg {
bool close_connection = 10;

ClientState rerun_script = 11;

bool load_git_info = 12;
}

reserved 1, 3, 4, 8, 9;
Expand Down
6 changes: 4 additions & 2 deletions proto/streamlit/proto/ForwardMsg.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import "streamlit/proto/PageConfig.proto";
import "streamlit/proto/PageInfo.proto";
import "streamlit/proto/SessionEvent.proto";
import "streamlit/proto/SessionState.proto";
import "streamlit/proto/GitInfo.proto";

// A message sent from Proxy to the browser
message ForwardMsg {
Expand Down Expand Up @@ -49,6 +50,7 @@ message ForwardMsg {
PageInfo page_info_changed = 12;
PageConfig page_config_changed = 13;
ReportFinishedStatus report_finished = 6;
GitInfo git_info_changed = 14;

// Upload progress messages.

Expand All @@ -75,7 +77,7 @@ message ForwardMsg {
string ref_hash = 11;
}

// Next: 14
// Next: 15
}

// ForwardMsgMetadata contains all data that does _not_ get hashed (or cached)
Expand All @@ -102,4 +104,4 @@ message ElementDimensionSpec {

// height in CSS points
uint32 height = 2;
}
}
34 changes: 34 additions & 0 deletions proto/streamlit/proto/GitInfo.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright 2018-2020 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.
*/

syntax = "proto3";

// Message used to update page metadata.
message GitInfo {
string repository = 1;
string branch = 2;
string module = 3;
repeated string untracked_files = 4;
repeated string uncommitted_files = 5;

enum GitStates {
DEFAULT = 0;
HEAD_DETACHED = 1;
AHEAD_OF_REMOTE = 2;
}

GitStates state = 6;
}
1 change: 1 addition & 0 deletions proto/streamlit/proto/NewReport.proto
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ message NewReport {
// "/foo/bar/foo.py"
string script_path = 4;

// @todo This will be deprecated with the frontend changes
DeployParams deploy_params = 5;
}

Expand Down

0 comments on commit 0bbc7aa

Please sign in to comment.