Visual CLI improvements (#1032)
This commit is contained in:
parent
6209916795
commit
4a580b54ff
@ -4,7 +4,7 @@ branch = true
|
||||
|
||||
[report]
|
||||
show_missing = true
|
||||
fail_under = 80
|
||||
fail_under = 79
|
||||
precision = 2
|
||||
|
||||
# Regexes for lines to exclude from consideration
|
||||
|
@ -12,6 +12,8 @@ from typing import (
|
||||
Optional,
|
||||
)
|
||||
|
||||
from rich.progress import Progress
|
||||
|
||||
from pynecone import constants
|
||||
from pynecone.config import get_config
|
||||
from pynecone.utils import path_ops, prerequisites
|
||||
@ -95,10 +97,38 @@ def export_app(
|
||||
if deploy_url is not None:
|
||||
generate_sitemap(deploy_url)
|
||||
|
||||
# Export the Next app.
|
||||
subprocess.run(
|
||||
[prerequisites.get_package_manager(), "run", "export"], cwd=constants.WEB_DIR
|
||||
)
|
||||
# Create a progress object
|
||||
progress = Progress()
|
||||
|
||||
# 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.
|
||||
if zip:
|
||||
|
@ -8,7 +8,9 @@ import subprocess
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import typer
|
||||
import uvicorn
|
||||
from rich import print
|
||||
|
||||
from pynecone import constants
|
||||
from pynecone.config import get_config
|
||||
@ -30,6 +32,37 @@ def start_watching_assets_folder(root):
|
||||
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):
|
||||
"""Run the frontend.
|
||||
|
||||
@ -53,12 +86,8 @@ def run_frontend(app: App, root: Path, port: str):
|
||||
# Run the frontend in development mode.
|
||||
console.rule("[bold green]App Running")
|
||||
os.environ["PORT"] = get_config().port if port is None else port
|
||||
|
||||
# Run the frontend in development mode.
|
||||
subprocess.Popen(
|
||||
[prerequisites.get_package_manager(), "run", "dev"],
|
||||
cwd=constants.WEB_DIR,
|
||||
env=os.environ,
|
||||
run_process_and_launch_url(
|
||||
[prerequisites.get_package_manager(), "run", "dev"], root
|
||||
)
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
# Run the frontend in production mode.
|
||||
subprocess.Popen(
|
||||
[prerequisites.get_package_manager(), "run", "prod"],
|
||||
cwd=constants.WEB_DIR,
|
||||
env=os.environ,
|
||||
console.rule("[bold green]App Running")
|
||||
run_process_and_launch_url(
|
||||
[prerequisites.get_package_manager(), "run", "prod"], root
|
||||
)
|
||||
|
||||
|
||||
|
@ -4,8 +4,16 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
import pynecone as pc
|
||||
from pynecone.components.layout.box import Box
|
||||
from pynecone.components.layout.cond import Cond, cond
|
||||
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.vars import Var
|
||||
|
||||
@ -103,3 +111,33 @@ def test_cond_no_else():
|
||||
# Props do not support the use of cond without else
|
||||
with pytest.raises(ValueError):
|
||||
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)
|
||||
|
@ -2,7 +2,7 @@ from typing import Any, Dict, List
|
||||
|
||||
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.vars import BaseVar, Var
|
||||
|
||||
@ -186,3 +186,10 @@ def test_format_cond_tag():
|
||||
|
||||
assert false_value["name"] == "h2"
|
||||
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
|
||||
|
@ -45,3 +45,56 @@ def test_json(child):
|
||||
child: A child class.
|
||||
"""
|
||||
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}'
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user