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

deploy manifest bundle test #395

Merged
merged 9 commits into from
Apr 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions tests/test_bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -2389,3 +2389,53 @@ def test_make_api_bundle_shiny():
bundle_json = json.loads(tar.extractfile("manifest.json").read().decode("utf-8"))
assert shiny_dir_ans["metadata"] == bundle_json["metadata"]
assert shiny_dir_ans["files"].keys() == bundle_json["files"].keys()


pyshiny_manifest_dir = os.path.join(cur_dir, "./testdata/pyshiny_with_manifest")
Copy link
Collaborator

Choose a reason for hiding this comment

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

It doesn't look like this variable is being used.

pyshiny_manifest_file = os.path.join(cur_dir, "./testdata/pyshiny_with_manifest/manifest.json")
Copy link
Collaborator

Choose a reason for hiding this comment

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

This variable doesn't need to be defined globally.



def test_make_manifest_bundle():
Copy link
Collaborator

Choose a reason for hiding this comment

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

This unit test is leaky.

It testing that the subsequent calls to other methods (bundle_add_file, read_manifest_file, etc) are working as expected, more so than testing the guts of make_manifest_bundle. The subsequent calls should be mocked, and this test should validate that the logic internal to make_manifest_bundle is working as expected.

For example, what happens if the 'files' key is missing in the manifest object?

I haven't looked, but there should be other unit tests that bundle_add_file, etc, are working correctly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The intent is to replace manifest and bundle related functions with the Manifest and Bundle classes, so the purpose of these specific tests are to document existing end to end behaviors. A refactored make_manifest_bundle most likely won't have the same logic, but its outputs must still be consistent with the existing behavior.

manifest = {
"version": 1,
"locale": "en_US.UTF-8",
"metadata": {"appmode": "python-shiny", "entrypoint": "app5"},
"python": {
"version": "3.8.12",
"package_manager": {"name": "pip", "version": "23.0.1", "package_file": "requirements.txt"},
},
"files": {
"requirements.txt": {"checksum": "c82f1a9894e5510b2f0c16fa63aaa004"},
"README.md": {"checksum": "7d083dbcdd4731d91bcb470e746b3a38"},
"app5.py": {"checksum": "f7e4b3b7ff0ada525ec388d037ff6c6a"},
"data.csv": {"checksum": "aabd9d1210246c69403532a6a9d24286"},
},
}
with make_manifest_bundle(
pyshiny_manifest_file,
) as bundle, tarfile.open(mode="r:gz", fileobj=bundle) as tar:
names = sorted(tar.getnames())
assert names == [
"README.md",
"app5.py",
"data.csv",
"manifest.json",
"requirements.txt",
]
bundle_json = json.loads(tar.extractfile("manifest.json").read().decode("utf-8"))
assert manifest["metadata"] == bundle_json["metadata"]
assert manifest["files"].keys() == bundle_json["files"].keys()


empty_manifest_file = os.path.join(cur_dir, "./testdata/Manifest_data/empty_manifest.json")
missing_file_manifest = os.path.join(cur_dir, "./testdata/Manifest_data/missing_file_manifest.json")


def test_make_bundle_empty_manifest():
with pytest.raises(Exception):
make_manifest_bundle(empty_manifest_file)


def test_make_bundle_missing_file_in_manifest():
with pytest.raises(FileNotFoundError):
make_manifest_bundle(missing_file_manifest)
Empty file.
21 changes: 21 additions & 0 deletions tests/testdata/Manifest_data/missing_file_manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"version": 1,
"locale": "en_US.UTF-8",
"metadata": {
"appmode": "python-shiny",
"entrypoint": "app5"
},
"python": {
"version": "3.8.12",
"package_manager": {
"name": "pip",
"version": "23.0.1",
"package_file": "requirements.txt"
}
},
"files": {
"app9.py": {
"checksum": "f7e4b3b7ff0ada525ec388d037ff6c6a"
}
}
}
17 changes: 17 additions & 0 deletions tests/testdata/pyshiny_with_manifest/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Top 5% income share

## About this example

A Shiny application makes it easy to transform your analysis into an interactive application using Python so users can ask and answer their own questions in real-time.


## Learn more

* [Shiny for Python documentation](https://shiny.rstudio.com/py)
* [Shiny for Python examples](https://shinylive.io/py/examples/)

## Requirements

* Python version 3.7 or higher

<!-- NOTE: this file is generated -->
92 changes: 92 additions & 0 deletions tests/testdata/pyshiny_with_manifest/app5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import altair as alt
import pandas as pd
from shinywidgets import output_widget, render_widget
from shiny import App, reactive, ui

income_shares = pd.read_csv("data.csv")
countries = income_shares["Entity"].unique().tolist()

select_countries = {
"default": ["Australia", "China", "Germany", "Japan", "United States"],
"latam": ["Argentina", "Uruguay"],
"apac": ["Australia", "China", "Singapore", "Japan", "Korea, South"],
"emea": ["Mauritius", "France", "Italy", "Norway", "Spain"],
"na": ["United States", "Canada"],
}

app_ui = ui.page_fluid(
ui.panel_title("Top 5% Income Share"),
ui.p("Share of income received by the richest 5% of the population"),
ui.layout_sidebar(
ui.panel_sidebar(
ui.input_selectize(
"countries",
"Countries:",
choices=countries,
multiple=True,
selected=select_countries["default"],
),
ui.p("Regions:"),
ui.TagList(
ui.div(
{"class": "btn-group"},
ui.input_action_button("apac", "APAC"),
ui.input_action_button("emea", "EMEA"),
ui.input_action_button("latam", "LATAM"),
ui.input_action_button("na", "NA"),
)
),
ui.input_slider(
"year_range",
"Year Range:",
min=1946,
max=2015,
value=(1946, 2015),
sep="",
),
),
ui.panel_main(
output_widget("income_plot", width="800px"),
),
),
)


def server(input, output, session):
@reactive.Calc
def plot_data():
df = income_shares.loc[
(income_shares["Entity"].isin(input.countries()))
& (income_shares["Year"] >= input.year_range()[0])
& (income_shares["Year"] <= input.year_range()[1])
]
return df

@output
@render_widget
def income_plot():
chart = (
alt.Chart(plot_data())
.mark_line()
.encode(
x=alt.X("Year", axis=alt.Axis(format="d")),
y=alt.Y("Percent", axis=alt.Axis(format="~s")),
color="Entity",
strokeDash="Entity",
)
)
return chart

def make_button_listener(name):
@reactive.Effect
@reactive.event(input[name])
def _():
ui.update_selectize("countries", selected=select_countries[name])

for name in select_countries.keys():
make_button_listener(name)


app = App(app_ui, server)
if __name__ == "__main__":
app.run()
11 changes: 11 additions & 0 deletions tests/testdata/pyshiny_with_manifest/data.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Entity,Code,Year,Percent
Argentina,ARG,1953,29.07
Argentina,ARG,1954,30.28
Argentina,ARG,1956,28.96
Argentina,ARG,1959,30.41
Argentina,ARG,1961,28
Argentina,ARG,1997,22.45
Australia,AUS,1946,21.76
Australia,AUS,1947,23.41
Australia,AUS,1948,23.35

30 changes: 30 additions & 0 deletions tests/testdata/pyshiny_with_manifest/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"version": 1,
"locale": "en_US.UTF-8",
"metadata": {
"appmode": "python-shiny",
"entrypoint": "app5"
},
"python": {
"version": "3.8.12",
"package_manager": {
"name": "pip",
"version": "23.0.1",
"package_file": "requirements.txt"
}
},
"files": {
"requirements.txt": {
"checksum": "c82f1a9894e5510b2f0c16fa63aaa004"
},
"README.md": {
"checksum": "7d083dbcdd4731d91bcb470e746b3a38"
},
"app5.py": {
"checksum": "f7e4b3b7ff0ada525ec388d037ff6c6a"
},
"data.csv": {
"checksum": "aabd9d1210246c69403532a6a9d24286"
}
}
}
5 changes: 5 additions & 0 deletions tests/testdata/pyshiny_with_manifest/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
shiny
shinywidgets
altair
pandas
vega