Visual CLI improvements (#1032)

This commit is contained in:
Alek Petuskey 2023-05-16 20:42:53 -07:00 committed by GitHub
parent 6209916795
commit 4a580b54ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 172 additions and 16 deletions

View File

@ -4,7 +4,7 @@ branch = true
[report] [report]
show_missing = true show_missing = true
fail_under = 80 fail_under = 79
precision = 2 precision = 2
# Regexes for lines to exclude from consideration # Regexes for lines to exclude from consideration

View File

@ -12,6 +12,8 @@ from typing import (
Optional, Optional,
) )
from rich.progress import Progress
from pynecone import constants from pynecone import constants
from pynecone.config import get_config from pynecone.config import get_config
from pynecone.utils import path_ops, prerequisites from pynecone.utils import path_ops, prerequisites
@ -95,10 +97,38 @@ def export_app(
if deploy_url is not None: if deploy_url is not None:
generate_sitemap(deploy_url) generate_sitemap(deploy_url)
# Export the Next app. # Create a progress object
subprocess.run( progress = Progress()
[prerequisites.get_package_manager(), "run", "export"], cwd=constants.WEB_DIR
) # Add a single task to the progress object
task = progress.add_task("Building app... ", total=500)
# Start the progress bar
with progress:
# Run the subprocess command
process = subprocess.Popen(
[prerequisites.get_package_manager(), "run", "export"],
cwd=constants.WEB_DIR,
stderr=subprocess.DEVNULL,
stdout=subprocess.PIPE, # Redirect stdout to a pipe
universal_newlines=True, # Set universal_newlines to True for text mode
)
# Read the output of the subprocess line by line
if process.stdout:
for line in iter(process.stdout.readline, ""):
# Update the progress bar based on the output
if "Linting and checking " in line:
progress.update(task, advance=100)
elif "Compiled successfully" in line:
progress.update(task, advance=100)
elif "Route (pages)" in line:
progress.update(task, advance=100)
elif "automatically rendered as static HTML" in line:
progress.update(task, advance=100)
elif "Export successful" in line:
progress.update(task, completed=500)
break # Exit the loop if the completion message is found
# Zip up the app. # Zip up the app.
if zip: if zip:

View File

@ -8,7 +8,9 @@ import subprocess
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import typer
import uvicorn import uvicorn
from rich import print
from pynecone import constants from pynecone import constants
from pynecone.config import get_config from pynecone.config import get_config
@ -30,6 +32,37 @@ def start_watching_assets_folder(root):
asset_watch.start() asset_watch.start()
def run_process_and_launch_url(run_command: list[str], root: Path):
"""Run the process and launch the URL.
Args:
run_command: The command to run.
root: root path of the project.
"""
process = subprocess.Popen(
run_command,
cwd=constants.WEB_DIR,
env=os.environ,
stderr=subprocess.DEVNULL,
stdout=subprocess.PIPE,
universal_newlines=True,
)
message_found = False
if process.stdout:
for line in process.stdout:
if "ready started server on" in line:
url = line.split("url: ")[-1].strip()
print(f"App running at: [bold green]{url}")
typer.launch(url)
message_found = True
break
if not message_found and process.stdout:
for line in process.stdout:
print(line, end="")
def run_frontend(app: App, root: Path, port: str): def run_frontend(app: App, root: Path, port: str):
"""Run the frontend. """Run the frontend.
@ -53,12 +86,8 @@ def run_frontend(app: App, root: Path, port: str):
# Run the frontend in development mode. # Run the frontend in development mode.
console.rule("[bold green]App Running") console.rule("[bold green]App Running")
os.environ["PORT"] = get_config().port if port is None else port os.environ["PORT"] = get_config().port if port is None else port
run_process_and_launch_url(
# Run the frontend in development mode. [prerequisites.get_package_manager(), "run", "dev"], root
subprocess.Popen(
[prerequisites.get_package_manager(), "run", "dev"],
cwd=constants.WEB_DIR,
env=os.environ,
) )
@ -80,10 +109,9 @@ def run_frontend_prod(app: App, root: Path, port: str):
os.environ["PORT"] = get_config().port if port is None else port os.environ["PORT"] = get_config().port if port is None else port
# Run the frontend in production mode. # Run the frontend in production mode.
subprocess.Popen( console.rule("[bold green]App Running")
[prerequisites.get_package_manager(), "run", "prod"], run_process_and_launch_url(
cwd=constants.WEB_DIR, [prerequisites.get_package_manager(), "run", "prod"], root
env=os.environ,
) )

View File

@ -4,8 +4,16 @@ from typing import Any
import pytest import pytest
import pynecone as pc import pynecone as pc
from pynecone.components.layout.box import Box
from pynecone.components.layout.cond import Cond, cond from pynecone.components.layout.cond import Cond, cond
from pynecone.components.layout.fragment import Fragment from pynecone.components.layout.fragment import Fragment
from pynecone.components.layout.responsive import (
desktop_only,
mobile_and_tablet,
mobile_only,
tablet_and_desktop,
tablet_only,
)
from pynecone.components.typography.text import Text from pynecone.components.typography.text import Text
from pynecone.vars import Var from pynecone.vars import Var
@ -103,3 +111,33 @@ def test_cond_no_else():
# Props do not support the use of cond without else # Props do not support the use of cond without else
with pytest.raises(ValueError): with pytest.raises(ValueError):
cond(True, "hello") cond(True, "hello")
def test_mobile_only():
"""Test the mobile_only responsive component."""
component = mobile_only("Content")
assert isinstance(component, Box)
def test_tablet_only():
"""Test the tablet_only responsive component."""
component = tablet_only("Content")
assert isinstance(component, Box)
def test_desktop_only():
"""Test the desktop_only responsive component."""
component = desktop_only("Content")
assert isinstance(component, Box)
def test_tablet_and_desktop():
"""Test the tablet_and_desktop responsive component."""
component = tablet_and_desktop("Content")
assert isinstance(component, Box)
def test_mobile_and_tablet():
"""Test the mobile_and_tablet responsive component."""
component = mobile_and_tablet("Content")
assert isinstance(component, Box)

View File

@ -2,7 +2,7 @@ from typing import Any, Dict, List
import pytest import pytest
from pynecone.components.tags import CondTag, Tag from pynecone.components.tags import CondTag, Tag, tagless
from pynecone.event import EVENT_ARG, EventChain, EventHandler, EventSpec from pynecone.event import EVENT_ARG, EventChain, EventHandler, EventSpec
from pynecone.vars import BaseVar, Var from pynecone.vars import BaseVar, Var
@ -186,3 +186,10 @@ def test_format_cond_tag():
assert false_value["name"] == "h2" assert false_value["name"] == "h2"
assert false_value["contents"] == "False content" assert false_value["contents"] == "False content"
def test_tagless_string_representation():
"""Test that the string representation of a tagless is correct."""
tag = tagless.Tagless(contents="Hello world")
expected_output = "Hello world"
assert str(tag) == expected_output

View File

@ -45,3 +45,56 @@ def test_json(child):
child: A child class. child: A child class.
""" """
assert child.json().replace(" ", "") == '{"num":3.14,"key":"pi"}' assert child.json().replace(" ", "") == '{"num":3.14,"key":"pi"}'
@pytest.fixture
def complex_child() -> Base:
"""A child class.
Returns:
A child class.
"""
class Child(Base):
num: float
key: str
name: str
age: int
active: bool
return Child(num=3.14, key="pi", name="John Doe", age=30, active=True)
def test_complex_get_fields(complex_child):
"""Test that the fields are set correctly.
Args:
complex_child: A child class.
"""
assert complex_child.get_fields().keys() == {"num", "key", "name", "age", "active"}
def test_complex_set(complex_child):
"""Test setting fields.
Args:
complex_child: A child class.
"""
complex_child.set(num=1, key="a", name="Jane Doe", age=28, active=False)
assert complex_child.num == 1
assert complex_child.key == "a"
assert complex_child.name == "Jane Doe"
assert complex_child.age == 28
assert complex_child.active is False
def test_complex_json(complex_child):
"""Test converting to json.
Args:
complex_child: A child class.
"""
assert (
complex_child.json().replace(" ", "")
== '{"num":3.14,"key":"pi","name":"JohnDoe","age":30,"active":true}'
)