Skip to content

Commit

Permalink
Merge pull request #12 from ramedina86/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
ramedina86 authored May 1, 2023
2 parents 36daf6f + 4de00df commit 7827570
Show file tree
Hide file tree
Showing 16 changed files with 2,117 additions and 5,674 deletions.
22 changes: 22 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/python
{
"name": "Python 3",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/python:0-3.11"

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "pip3 install --user -r requirements.txt",

// Configure tool-specific properties.
// "customizations": {},

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ Streamsync is an open-source framework for creating data apps. Build user interf
Getting started with Streamsync is easy. It works on Linux, Mac and Windows.

```sh
pip install streamsync
pip install streamsync[ds]
streamsync hello
```

- The first command will install Streamsync using `pip`.
- The first command will install Streamsync using `pip` and include the optional data science dependencies.
- The second command will create a demo application in the subfolder "hello" and start Streamsync Builder, the framework's visual editor, which will be accessible via a local URL.

We recommend using a virtual environment.
Expand Down
3 changes: 0 additions & 3 deletions apps/hello/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ def handle_story_download(state):
state.file_download(data, file_name)


def handle_open_streamsync_website(state):
state.open_url("https://streamsync.cloud")

# LOAD / GENERATE DATA


Expand Down
19 changes: 1 addition & 18 deletions apps/hello/ui.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"metadata": {
"streamsync_version": "0.1.4"
"streamsync_version": "0.1.5"
},
"components": {
"root": {
Expand Down Expand Up @@ -911,23 +911,6 @@
"click": "handle_story_download"
},
"visible": true
},
"c9c3a3fa-df85-47d6-a01d-01c4a4ac7b9e": {
"id": "c9c3a3fa-df85-47d6-a01d-01c4a4ac7b9e",
"type": "button",
"content": {
"text": "Visit streamsync.cloud",
"icon": "link",
"buttonColor": "#29cf00",
"buttonTextColor": "#ffffff",
"buttonShadow": "0px 3px 14px -12px #000000"
},
"parentId": "70d82458-a08f-4005-8f96-dc8d3ba92fad",
"position": 1,
"handlers": {
"click": "handle_open_streamsync_website"
},
"visible": true
}
}
}
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ cp -r ./apps/hello ./src/streamsync/app_templates

# PYTHON PACKAGE BUILD

rm -f ./dist/*
rm -rf ./dist/*
python -m build
4 changes: 4 additions & 0 deletions docs/docs/backend-initiated-actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ def handle_open_streamsync_website(state):

The URL will be safely opened with `noopener` and `noreferrer` options.

::: warning Popup blockers
Given that the URL is opened asynchronously, popup blockers will likely block the new window —unless the user has opted in.
:::

## Changing the active page

The active page and route parameters can be changed using the methods `set_page` and `set_route_vars`. This is explained in more detail in [Page Routes](page-routes.html).
12 changes: 10 additions & 2 deletions docs/docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
It works on Linux, Mac and Windows. Python 3.9.2 or higher is required.

```sh
pip install streamsync
pip install streamsync[ds]
streamsync hello
```

- The first command will install Streamsync using `pip`.
- The first command will install Streamsync using `pip` and include the optional data science dependencies.
- The second command will create a demo application in the subfolder "hello" and start Streamsync Builder, the framework's visual editor, which will be accessible via a local URL.

We recommend using a virtual environment.
Expand Down Expand Up @@ -64,3 +64,11 @@ You can specify a port and host. Specifying `--host 0.0.0.0` enables you to shar
```sh
streamsync run my_app --port 5000 --host 0.0.0.0
```

## Running as a module

If you need to run Streamsync as a module, you can use the `streamsync.command_line` module.

```sh
python -m streamsync.command_line run my_app
```
2 changes: 2 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[mypy]
plugins = pydantic.mypy
20 changes: 15 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,35 @@ dependencies = [
"fastapi >= 0.89.1, < 1",
"websockets >= 10.4, < 11",
"uvicorn >= 0.20.0, < 1",
"watchdog >= 2.2.1, < 3",
"pandas >= 1.5.3, < 2",
"plotly-express >= 0.4.1, < 1",
"watchdog >= 2.2.1, < 3"
]

dynamic = ["version"]

[project.optional-dependencies]
ds = [
"pandas >= 1.5.3, < 2",
"plotly-express >= 0.4.1, < 1"
]
test = [
"pandas >= 1.5.3, < 2",
"plotly-express >= 0.4.1, < 1",
"pytest-asyncio >= 0.21.0, < 1",
"pytest >= 7.0.0, < 8",
"altair >= 4.1.0, < 5",
"httpx >= 0.18.2, < 1"
]
build = [
"pandas >= 1.5.3, < 2",
"plotly-express >= 0.4.1, < 1",
"build >= 0.7.0, < 1",
"mypy >= 0.900, < 2",
"mypy >= 1.2.0, < 2",
"pandas-stubs >= 2.0.0, <3",
"pytest >= 7.0.0, < 8",
"pytest-asyncio >= 0.21.0, < 1",
"altair >= 4.1.0, < 5",
"httpx >= 0.18.2, < 1"
"httpx >= 0.18.2, < 1",
"build >= 0.10.0, < 1"
]

[project.scripts]
Expand Down
2 changes: 1 addition & 1 deletion src/streamsync/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from streamsync.core import Readable, FileWrapper, BytesWrapper, Config
from streamsync.core import initial_state, component_manager, session_manager, session_verifier

VERSION = "0.1.5"
VERSION = "0.1.6"

component_manager
session_manager
Expand Down
3 changes: 0 additions & 3 deletions src/streamsync/app_templates/hello/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ def handle_story_download(state):
state.file_download(data, file_name)


def handle_open_streamsync_website(state):
state.open_url("https://streamsync.cloud")

# LOAD / GENERATE DATA


Expand Down
19 changes: 1 addition & 18 deletions src/streamsync/app_templates/hello/ui.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"metadata": {
"streamsync_version": "0.1.4"
"streamsync_version": "0.1.5"
},
"components": {
"root": {
Expand Down Expand Up @@ -911,23 +911,6 @@
"click": "handle_story_download"
},
"visible": true
},
"c9c3a3fa-df85-47d6-a01d-01c4a4ac7b9e": {
"id": "c9c3a3fa-df85-47d6-a01d-01c4a4ac7b9e",
"type": "button",
"content": {
"text": "Visit streamsync.cloud",
"icon": "link",
"buttonColor": "#29cf00",
"buttonTextColor": "#ffffff",
"buttonShadow": "0px 3px 14px -12px #000000"
},
"parentId": "70d82458-a08f-4005-8f96-dc8d3ba92fad",
"position": 1,
"handlers": {
"click": "handle_open_streamsync_website"
},
"visible": true
}
}
}
56 changes: 41 additions & 15 deletions src/streamsync/command_line.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import sys
from typing import Optional
import streamsync.serve
import argparse
import os
Expand All @@ -11,7 +13,7 @@ def main():
parser.add_argument("command", choices=[
"run", "edit", "create", "hello"])
parser.add_argument(
"path", nargs='?', help="Path to the app's folder")
"path", nargs="?", help="Path to the app's folder")
parser.add_argument(
"--port", help="The port on which to run the server.")
parser.add_argument(
Expand All @@ -20,40 +22,63 @@ def main():
args = parser.parse_args()
command = args.command
default_port = 3006 if command in ("edit", "hello") else 3005
port = int(args.port) if args.port else default_port

port = int(args.port) if args.port else default_port
absolute_app_path = _get_absolute_app_path(
args.path) if args.path else None

if command in ("run", "edit") and args.path is None:
logging.error("A path to a folder containing a Streamsync app is required. For example, streamsync edit my_app.")
return

default_host = "127.0.0.1"
host = args.host if args.host else default_host

if command in ("edit", "hello") and host != default_host:
host = args.host if args.host else None

_perform_checks(command, absolute_app_path, host)
_route(command, absolute_app_path, port, host)

def _perform_checks(command: str, absolute_app_path: str, host: Optional[str]):
is_path_folder = absolute_app_path is not None and os.path.isdir(absolute_app_path)

if command in ("run", "edit") and is_path_folder is False:
logging.error("A path to a folder containing a Streamsync app is required. For example: streamsync edit my_app")
sys.exit(1)

if command in ("create") and absolute_app_path is None:
logging.error("A target folder is required to create a Streamsync app. For example: streamsync create my_app")
sys.exit(1)

if command in ("edit", "hello") and host is not None:
logging.warning("Streamsync has been enabled in edit mode with a host argument\nThis is enabled for local development purposes (such as a local VM).\nDon't expose Streamsync Builder to the Internet. We recommend using a SSH tunnel instead.")
logging.warning("Streamsync Builder will only accept local requests (via HTTP origin header).")

if command in ("edit"):
if command in ("hello"):
try:
import pandas
import plotly.express # type: ignore
except ImportError:
logging.error("Running streamsync hello requires pandas and plotly.express. Install them with:\npip install streamsync[ds]")
sys.exit(1)

# Builder is hardcoded to use default host (local)

def _route(command: str, absolute_app_path: str, port: int, host: Optional[str]):
if host is None:
host = "127.0.0.1"
if command in ("edit"):
streamsync.serve.serve(
absolute_app_path, mode="edit", port=port, host=host)
if command in ("run"):
streamsync.serve.serve(
absolute_app_path, mode="run", port=port, host=host)
elif command in ("hello"):
create_app("hello", template_name="hello")
create_app("hello", template_name="hello", overwrite=True)
streamsync.serve.serve("hello", mode="edit",
port=port, host=host)
elif command in ("create"):
create_app(absolute_app_path)

def create_app(app_path: str, template_name: str = "default", overwrite=False):
is_folder_created = os.path.exists(app_path)
is_folder_empty = True if not is_folder_created else len(os.listdir(app_path)) == 0

if not overwrite and not is_folder_empty:
logging.error("The target folder must be empty or not already exist.")
sys.exit(1)

def create_app(app_path: str, template_name: str = "default"):
server_path = os.path.dirname(__file__)
template_path = os.path.join(server_path, "app_templates", template_name)
shutil.copytree(template_path, app_path, dirs_exist_ok=True)
Expand All @@ -67,5 +92,6 @@ def _get_absolute_app_path(app_path: str):
return os.path.join(os.getcwd(), app_path)



if __name__ == "__main__":
main()
Loading

0 comments on commit 7827570

Please sign in to comment.