Code Monkey home page Code Monkey logo

pynecone's Introduction

+ Searching for Pynecone? You are in the right repo. Pynecone has been renamed to Reflex. +
Reflex Logo Reflex Logo

✨ Performant, customizable web apps in pure Python. Deploy in seconds. ✨

PyPI version tests versions Documentation Discord


English | 简体中文 | 繁體中文 | Türkçe | हिंदी | Português (Brasil) | Italiano | Español | 한국어 | 日本語 | Deutsch | Persian (پارسی)


Reflex

Reflex is a library to build full-stack web apps in pure Python.

Key features:

  • Pure Python - Write your app's frontend and backend all in Python, no need to learn Javascript.
  • Full Flexibility - Reflex is easy to get started with, but can also scale to complex apps.
  • Deploy Instantly - After building, deploy your app with a single command or host it on your own server.

See our architecture page to learn how Reflex works under the hood.

⚙️ Installation

Open a terminal and run (Requires Python 3.8+):

pip install reflex

🥳 Create your first app

Installing reflex also installs the reflex command line tool.

Test that the install was successful by creating a new project. (Replace my_app_name with your project name):

mkdir my_app_name
cd my_app_name
reflex init

This command initializes a template app in your new directory.

You can run this app in development mode:

reflex run

You should see your app running at http://localhost:3000.

Now you can modify the source code in my_app_name/my_app_name.py. Reflex has fast refreshes so you can see your changes instantly when you save your code.

🫧 Example App

Let's go over an example: creating an image generation UI around DALL·E. For simplicity, we just call the OpenAI API, but you could replace this with an ML model run locally.

 

A frontend wrapper for DALL·E, shown in the process of generating an image.

 

Here is the complete code to create this. This is all done in one Python file!

import reflex as rx
import openai

openai_client = openai.OpenAI()


class State(rx.State):
    """The app state."""

    prompt = ""
    image_url = ""
    processing = False
    complete = False

    def get_image(self):
        """Get the image from the prompt."""
        if self.prompt == "":
            return rx.window_alert("Prompt Empty")

        self.processing, self.complete = True, False
        yield
        response = openai_client.images.generate(
            prompt=self.prompt, n=1, size="1024x1024"
        )
        self.image_url = response.data[0].url
        self.processing, self.complete = False, True


def index():
    return rx.center(
        rx.vstack(
            rx.heading("DALL-E", font_size="1.5em"),
            rx.input(
                placeholder="Enter a prompt..",
                on_blur=State.set_prompt,
                width="25em",
            ),
            rx.button(
                "Generate Image", 
                on_click=State.get_image,
                width="25em",
                loading=State.processing
            ),
            rx.cond(
                State.complete,
                rx.image(src=State.image_url, width="20em"),
            ),
            align="center",
        ),
        width="100%",
        height="100vh",
    )

# Add state and page to the app.
app = rx.App()
app.add_page(index, title="Reflex:DALL-E")

Let's break this down.

Explaining the differences between backend and frontend parts of the DALL-E app.

Reflex UI

Let's start with the UI.

def index():
    return rx.center(
        ...
    )

This index function defines the frontend of the app.

We use different components such as center, vstack, input, and button to build the frontend. Components can be nested within each other to create complex layouts. And you can use keyword args to style them with the full power of CSS.

Reflex comes with 60+ built-in components to help you get started. We are actively adding more components, and it's easy to create your own components.

State

Reflex represents your UI as a function of your state.

class State(rx.State):
    """The app state."""
    prompt = ""
    image_url = ""
    processing = False
    complete = False

The state defines all the variables (called vars) in an app that can change and the functions that change them.

Here the state is comprised of a prompt and image_url. There are also the booleans processing and complete to indicate when to disable the button (during image generation) and when to show the resulting image.

Event Handlers

def get_image(self):
    """Get the image from the prompt."""
    if self.prompt == "":
        return rx.window_alert("Prompt Empty")

    self.processing, self.complete = True, False
    yield
    response = openai_client.images.generate(
        prompt=self.prompt, n=1, size="1024x1024"
    )
    self.image_url = response.data[0].url
    self.processing, self.complete = False, True

Within the state, we define functions called event handlers that change the state vars. Event handlers are the way that we can modify the state in Reflex. They can be called in response to user actions, such as clicking a button or typing in a text box. These actions are called events.

Our DALL·E. app has an event handler, get_image to which get this image from the OpenAI API. Using yield in the middle of an event handler will cause the UI to update. Otherwise the UI will update at the end of the event handler.

Routing

Finally, we define our app.

app = rx.App()

We add a page from the root of the app to the index component. We also add a title that will show up in the page preview/browser tab.

app.add_page(index, title="DALL-E")

You can create a multi-page app by adding more pages.

📑 Resources

📑 Docs   |   🗞️ Blog   |   📱 Component Library   |   🖼️ Gallery   |   🛸 Deployment  

✅ Status

Reflex launched in December 2022 with the name Pynecone.

As of February 2024, our hosting service is in alpha! During this time anyone can deploy their apps for free. See our roadmap to see what's planned.

Reflex has new releases and features coming every week! Make sure to ⭐ star and 👀 watch this repository to stay up to date.

Contributing

We welcome contributions of any size! Below are some good ways to get started in the Reflex community.

  • Join Our Discord: Our Discord is the best place to get help on your Reflex project and to discuss how you can contribute.
  • GitHub Discussions: A great way to talk about features you want added or things that are confusing/need clarification.
  • GitHub Issues: Issues are an excellent way to report bugs. Additionally, you can try and solve an existing issue and submit a PR.

We are actively looking for contributors, no matter your skill level or experience. To contribute check out CONTIBUTING.md

All Thanks To Our Contributors:

License

Reflex is open-source and licensed under the Apache License 2.0.

pynecone's People

Contributors

abulvenz avatar adhami3310 avatar alek99 avatar benedikt-bartscher avatar cllatser avatar d29107d avatar elijahahianyo avatar ericwb avatar fhu-yezi avatar hellambro avatar hongyuhansonyao avatar invrainbow avatar iron3oxide avatar jackie-pc avatar kasun avatar kbrgl avatar lendemor avatar martinxu9 avatar masenf avatar milochen0418 avatar peteryusuke avatar picklelo avatar qu3vipon avatar r0b2g1t avatar sheldonchiu avatar taijuwu avatar tgberkeley avatar thavocado avatar wassafshahzad avatar yummy-yums avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pynecone's Issues

Embedding Pynecone in other apps

One of the issues i had with streamlit (from what i remember) is that you can't easily embed streamlit into existing applications, and the same seems to be true here.

It would be really cool if i could do pynecone.run() from an existing app and bind state to existing modules. It would allow one to take existing APIs and wire them up quickly to a pyonecone GUI.

I know that is certainly easier said than done. Go ahead and close this issue if that is too far out of scope or isn't feasible.

Thank you for your efforts, pynecone is neat.

Event Trigger Lambda Arguments Error

Describe the bug
Lambda need to be able to take in arguments other than ints. Currently non in arguments throw errors for event triggers that use lambdas

To Reproduce

class State(pc.State):
    choices = ["A", "B", "C"]
    
    def set_choice(self, index: int, answer: str):
        self.choices[index] = answer
        self.choices = self.choices

def index():
    return pc.vstack(
        pc.heading(State.choices),
        pc.button(
            "First",
            on_click= lambda: State.set_choice(0, "Changed")
        ),
        pc.button(
            "Second",
            on_click= lambda: State.set_choice(1, "Changed")
        ),
        pc.button(
            "Third",
            on_click= lambda: State.set_choice(2, "Changed")
        )
    )

Expected behavior
Should set the index of the choices to changed depending on button clicked.
Screenshots
NA

** Specifics (please complete the following information):**

  • Python Version: 3.10
  • Pynecone Version: 0.1.8
  • OS: Mac
  • Browser (Optional):

Additional context
None

Passing strings to event handler functions via lambda

Describe the bug
Using a lambda function to bundle args to an event handler function works if the args are numbers, but not if they are strings

To Reproduce
Steps to reproduce the behavior:
The code

pc.button("STOP", on_click=lambda: State.status_change(index, "stop"))

Compiles the string literal to a bareword in the javascript:

<Button onClick={() => Event([E("state.status_change", {index:0,change:stop})])}>
{`STOP`}</Button>

This causes an error as the event payload is not transmitted properly

Traceback (most recent call last):
  File "/home/p/.asdf/installs/python/3.10.6/lib/python3.10/site-packages/pynecone/state.py", line 357, in process
    events = fn(**event.payload)
TypeError: State.status_change() missing 1 required positional argument: 'change'

The state function is

def status_change(self, index, change):
        self.services[index].status = change
        self.services = self.services

Expected behavior
It would be expected to compile to the following Javascript

<Button onClick={() => Event([E("state.status_change", {index:0,change:"stop"})])}>
{`STOP`}</Button>

The offending code is likely in pynecone/utils.py at

def format_event(event_spec: EventSpec) -> str:
    """Format an event.
    Args:
        event_spec: The event to format.
    Returns:
        The compiled event.
    """
    args = ",".join([":".join((name, val)) for name, val in event_spec.args])
    return f"E(\"{format_event_fn(event_spec.handler.fn)}\", {wrap(args, '{')})"

I think val needs to be wrapped and escaped if it is a string

** Specifics (please complete the following information):**

  • Python Version: 3.10.6
  • Pynecone Version: pynecone-io==0.1.8
  • OS: Ubuntu 22.04
  • Browser (Optional):

Computed Vars optimization

Cool framework!

There are keys dropped when typing in the <input> field for the 'Computed Vars' demo in the docs

E.g. typing 'Hello World' at normal speed shows as 'HELO WLD' in the computed heading.

Error running pc init

──────────────────────────────────────────────── Starting Pynecone App ────────────────────────────────────────────────
─────────────────────────────────────────────── Installing Dependencies ───────────────────────────────────────────────
Traceback (most recent call last):
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 86, in run_code
exec(code, run_globals)
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\Scripts\pc.exe_main
.py", line 7, in
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\site-packages\typer\main.py", line 214, in call
return get_command(self)(*args, **kwargs)
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 1130, in call
return self.main(*args, **kwargs)
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 1055, in main
rv = self.invoke(ctx)
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 1657, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 1404, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 760, in invoke
return __callback(*args, **kwargs)
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\site-packages\typer\main.py", line 532, in wrapper
return callback(**use_params) # type: ignore
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\site-packages\pynecone\pc.py", line 78, in run
frontend_cmd(app)
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\site-packages\pynecone\utils.py", line 363, in run_frontend
setup_frontend(app)
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\site-packages\pynecone\utils.py", line 345, in setup_frontend
install_dependencies()
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\site-packages\pynecone\utils.py", line 320, in install_dependencies
subprocess.call([get_bun_path(), "install"], cwd=constants.WEB_DIR, stdout=PIPE)
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 345, in call
with Popen(*popenargs, **kwargs) as p:
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 966, in init
self._execute_child(args, executable, preexec_fn, close_fds,
File "C:\Users\bojan\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1435, in _execute_child
hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
FileNotFoundError: [WinError 2] The system cannot find the file specified

I have just installed pynecone,i have py and node,everything seems fine on my end

TypeError: Object of type EventHandler is not JSON serializable

Trying to put together a simple app that queries an API endpoint, gets the result of the query, and displays it in a modal. Using this as a POC to understand how to work with pyncone. I am receiving the following error, and cannot determine where its coming from.

───────────────────────────────────────────────────────────────────────────────── Starting Pynecone App ──────────────────────────────────────────────────────────────────────────────────
Traceback (most recent call last):
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/bin/pc", line 8, in <module>
    sys.exit(main())
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/lib/python3.10/site-packages/typer/main.py", line 214, in __call__
    return get_command(self)(*args, **kwargs)
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/lib/python3.10/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/lib/python3.10/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/lib/python3.10/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/lib/python3.10/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/lib/python3.10/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/lib/python3.10/site-packages/typer/main.py", line 532, in wrapper
    return callback(**use_params)  # type: ignore
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/lib/python3.10/site-packages/pynecone/pc.py", line 68, in run
    app = utils.get_app()
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/lib/python3.10/site-packages/pynecone/utils.py", line 314, in get_app
    app = __import__(module, fromlist=(constants.APP_VAR,))
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/cmdb_lookup/cmdb_lookup.py", line 53, in <module>
    app.add_page(index)
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/lib/python3.10/site-packages/pynecone/app.py", line 220, in add_page
    component = component if isinstance(component, Component) else component(*args)
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/cmdb_lookup/cmdb_lookup.py", line 32, in index
    pc.modal(
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/lib/python3.10/site-packages/pynecone/components/component.py", line 278, in create
    return cls(children=children, **props)
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/lib/python3.10/site-packages/pynecone/components/component.py", line 101, in __init__
    kwargs[key] = Var.create(value)
  File "/Users/pacea/workspace/websites/pynecone/cmdb_lookup/.venv/lib/python3.10/site-packages/pynecone/var.py", line 67, in create
    name = json.dumps(value) if not isinstance(value, str) else value
  File "/usr/local/Cellar/[email protected]/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/usr/local/Cellar/[email protected]/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/local/Cellar/[email protected]/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/local/Cellar/[email protected]/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type EventHandler is not JSON serializable

My app code looks like this:

"""Welcome to Pynecone! This file outlines the steps to create a basic app."""
from pcconfig import config
import pynecone as pc

from .state import State, CMDBState

def index():
    return pc.center(
        pc.vstack(
            pc.heading("CMDB Query", font_size="2em"),
            pc.box("Enter the Application CI Value to query for in the CMDB"),
            pc.input(
                placeholder="Application CI Value",
                on_blur=CMDBState.set_application_ci,
                size="small",
                variant="outline",
            ),
            pc.button(
                "Submit",
                bg="blue",
                color="white",
                size="md",
                on_click=CMDBState.get_value,
            ),
            pc.cond(
                CMDBState.processing,
                pc.circular_progress(is_indeterminate=True),
                pc.cond(
                    CMDBState.completed,
                    pc.modal(
                        pc.modal_overlay(
                            pc.modal_content(
                                pc.modal_header(f"Entry for {CMDBState.application.ApplicationCI}"),
                                pc.modal_body(pc.box(CMDBState.application)),
                                pc.modal_footer(pc.button("Close", on_click=CMDBState.toggle_modal)),
                            )
                        ),
                        is_open=CMDBState.toggle_modal,
                    ),
                ),
            ),
            spacing="1.5em",
            font_size="2em",
        ),
        padding_top="10%",
    )

app = pc.App(state=State)
app.add_page(index)
app.compile()

and my state looks like:

import pynecone as pc
import json
import requests


class Application(pc.Base):
    ApplicationCI: str
    ServiceNowId: str
    Domain: int
    BusinessRegion: str
    Confidentiality: str
    BusinessSubDomain: str
    Availability: str
    BusinessDomain: str
    SME: str
    RTO: int
    RPO: int
    Integrity: str
    CostCenter: str
    BusinessArea: str
    Owner: str
    ApplicationSupport: str
    Manager: str
    ExecutiveManager: str


class State(pc.State):
    pass


class CMDBState(State):
    applicationCI: str = ""
    application: Application = None
    completed: bool = False
    processing: bool = False
    retrieved: bool = False

    def set_application_ci(self, value):
        self.applicationCI = value

    def toggle_modal(self):
        self.retrieved = not (self.show_modal)

    def get_value(self):
        # set processing to true to show the loading spinner
        self.processing = True
        url = f"https://someurl/?type=name&id=${self.applicationCI}"
        response = requests.get(url, verify=False)
        response = json.loads(response.text)
        if response == {}:
            # if the response is empty, set retrieved to false to hide the todo
            self.retrieved = False
            # set processing to false to hide the loading spinner
            self.processing = False
            return
        self.application = Application(**response)
        # set processing to false to hide the loading spinner
        self.processing = False
        # set retrieved to true to show the todo
        self.retrieved = True

any help would be greatly appreciated

Issue with radio_group and pc.model

Describe the bug
radio_group works well with the options are defined as a global list but when read from a pc.model it doesn't work

To Reproduce

"""Welcome to Pynecone! This file outlines the steps to create a basic app."""
from pcconfig import config
from typing import List
import pynecone as pc

docs_url = "https://pynecone.io/docs/getting-started/introduction"
filename = f"{config.app_name}/{config.app_name}.py"

class RadioModel(pc.Model, table=True):

    title: str
    options: List[str]
    tooltip: str

class State(pc.State):
    """The app state."""

    answer: str

    @pc.var
    def get_radiomodel(self) -> List[RadioModel]:

        return [ RadioModel(title="this is a title", options = ["option 1", "option 2"], tooltip="easy")]

    def set_answer(self, test):
        self.answer = answer

def index():
    return pc.center(
        pc.vstack(
            pc.foreach(
                State.get_radiomodel, lambda a_model: display_form(a_model)
            ),
            spacing="1.5em",
            font_size="2em",
        ),
        padding_top="10%",
    )

options = [ "option 3", "options 4"]
def display_form(model: RadioModel):

    return pc.form_control(
        # pc.badge(State.answer, color_scheme="green"),
        pc.radio_group(
            model.options, #options, 
            on_change=State.set_answer,
        ),
        pc.form_helper_text(model.tooltip),
        is_required=True,
    )
    
# Add state and page to the app.
app = pc.App(state=State)
app.add_page(index)
app.compile()

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
image
vs
image

** Specifics (please complete the following information):**

  • Python Version: 3.8.10
  • Pynecone Version: 0.1.8
  • OS: WSL2
  • Browser (Optional): Edge

Additional context
Add any other context about the problem here.

Visually Hidden (Useful for Screen Readers)

Integrate the VisuallyHidden Chakra-UI component, which is a common technique used in web accessibility to hide content from the visual client, but keep it readable for screen readers.

Possible wrong name in ResponsiveGrid doc

On the doc page for ResponsiveGrid, there is the following text:

SimpleGrid provides a friendly interface to create responsive grid layouts with ease. SimpleGrid composes Box so you can pass all the Box props and css grid props with addition to the ones below.

SimpleGrid is not mentionned anywhere else, shouldn't it be ResponsiveGrid?

Add clear way to export to static site

For apps with no state (only frontends), it should be possible to export the Pynecone app to a static site, to be hosted on S3, Github Pages, etc.

We just have to run next export on the web directory after compiling the app. We already do this when running the app in production mode, but we can maybe add a command pc export that will only do this portion of it.

replace `requests` with `httpx`

httpx is a requests-like Python network package. It can be a drop-in replacement of requests.

HTTPX GitHub Repo

Documentation

Just search for any use of requests and I only found the command line tool pc use it, for a subcommand deploy which is unused now, so feel free to leave it there until we release the deploy feature.

Add pc.iframe

Add an iframe component would be nice additional and should be fairly easy to add.

Surpress Fast Refresh Warning

NextJs is giving the warning:

warn - Fast Refresh had to perform a full reload. Read more: https://nextjs.org/docs/basic-features/fast-refresh#how-it-works

We should surprise this.

Audio Component?

Does there exist a component like similar to Streamlit audio? Or plans to implement? Would be lovely :)

Specify extra bun packages in pcconfig

Currently if you want to add extra bun packages (i.e. to wrap your own react components) you need to manually do a bun add in the .web directory. Instead, we should specify this all in the pcconfig.py to keep with our philosophy of not having to touch the .web folder. Also, it has the advantage that we can add the packages again every time we rerun pc init.

Ensure underscores convert to hyphens for path names

I was running into an issue using a page function that includes an underscore.

For example, if I use this:

def sign_up():

Instead of this:

def signup():

I'll get this error at /sign_up:

Unhandled Runtime Error
Error: Invariant: attempted to hard navigate to the same URL

After some exploration, I think it's because of the underscore.

I can fix the problem as follows:

app.add_page(sign_up, path="/sign-up")

I'm not sure why this is happening because in add_page() you call utils.format_route(path), which should solve this.

If it helps, I'm importing this page as follows:

from pynecone_experiment.pages.sign_up import sign_up

Setting the value of an input to a pc.computed does not work

Describe the bug
In the Computed Vars example, I tried changing the pc.heading(UppercaseState.upper_text) to pc.input(value=UppercaseState.upper_text) but this does not work. It does not work when I set this "computed input" to be controlled, either.

To Reproduce
(Described above.)

Expected behavior
I expected this to work, since setting the value of one input to the output of another input is not uncommon. I would then have tried to use an on_change handler on the computed input to store if the user edited the translation output and what they edited it to. (I had a similar use case in the research study interface I’d demoed.)

If on Desktop (please complete the following information):
Firefox 106 on macOS Monterey.

Computed Var example doesn't work if @pc.computed handler doesn't specify return type

Describe the bug
The computed vars example no longer works if the return type annotation is removed. It shows an error as follows:

Traceback (most recent call last):
  File "/Users/kabir/.pyenv/versions/3.10.2/lib/python3.10/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/Users/kabir/.pyenv/versions/3.10.2/lib/python3.10/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/kabir/.pyenv/versions/3.10.2/lib/python3.10/site-packages/uvicorn/subprocess.py", line 76, in subprocess_started
    target(sockets=sockets)
  File "/Users/kabir/.pyenv/versions/3.10.2/lib/python3.10/site-packages/uvicorn/server.py", line 60, in run
    return asyncio.run(self.serve(sockets=sockets))
  File "/Users/kabir/.pyenv/versions/3.10.2/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/Users/kabir/.pyenv/versions/3.10.2/lib/python3.10/asyncio/base_events.py", line 641, in run_until_complete
    return future.result()
  File "/Users/kabir/.pyenv/versions/3.10.2/lib/python3.10/site-packages/uvicorn/server.py", line 67, in serve
    config.load()
  File "/Users/kabir/.pyenv/versions/3.10.2/lib/python3.10/site-packages/uvicorn/config.py", line 458, in load
    self.loaded_app = import_from_string(self.app)
  File "/Users/kabir/.pyenv/versions/3.10.2/lib/python3.10/site-packages/uvicorn/importer.py", line 21, in import_from_string
    module = importlib.import_module(module_str)
  File "/Users/kabir/.pyenv/versions/3.10.2/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/Users/kabir/Repos/translator/./translator/translator.py", line 51, in <module>
    app.add_page(index, title=title)
  File "/Users/kabir/.pyenv/versions/3.10.2/lib/python3.10/site-packages/pynecone/app.py", line 169, in add_page
    component = component if isinstance(component, Component) else component()
  File "/Users/kabir/Repos/translator/./translator/translator.py", line 41, in index
    pc.input(value=State.translation),
  File "/Users/kabir/.pyenv/versions/3.10.2/lib/python3.10/site-packages/pynecone/components/component.py", line 202, in create
    return cls(children=children, **attrs)
  File "/Users/kabir/.pyenv/versions/3.10.2/lib/python3.10/site-packages/pynecone/components/component.py", line 132, in __init__
    assert expected_type == Any or issubclass(
TypeError: issubclass() arg 1 must be a class

To Reproduce

Screen Shot 2022-10-29 at 2 12 26 PM

Use this code but remove the -> str.

Expected behavior
I expected this to work, or provide a descriptive error message saying that a return type is required. In general, I expected the entire API surface to work with or without type annotations.

Add way to clear uncontrolled input

Currently in order to clear the value of a pc.input you need to make it a controlled input (i.e. set the value and on_change props together). This has the downside of making a network call with every keystroke. We need a more performant way to achieve this.

Possibly react refs?

Allow state var to be input to select form

I might be missing something, but at the moment it seems like state vars cannot be used as inputs to the select form. If possible this would be a really nice feature for creating dynamic dropdown options (for instance values retrieved via API calls).

Make some dependencies optional

Just installed this library use Poetry and poetry show --tree seems to be that:

pynecone 0.0.70 Build your CLI with ease
├── certifi *
├── jinja2 *
│   └── markupsafe >=2.0
├── keyring *
│   ├── (some deps)
├── pika *
├── python-dotenv *
├── pyyaml *
├── requests *
│   ├── (some-deps)
├── requests-toolbelt *
│   └── (some deps)
├── sqlalchemy *
│   └── greenlet !=0.4.17
└── tabulate *

When I want to use MongoDB as my database, I don't use the internal ORM provided by Pynecone, and the dependence SQLAlchemy is not nesserary for me. We can detect if user installed this library when they try to import a module which need it, and this dependence should not be included by default.

extras in pyproject.toml may be helpful for this, we can install the ORM-ready version with pynecone[orm], and all the optional dependencies installed version with pynecone[all].

By the way, httpx is a better replacement for requests, it support HTTP/2 and asyncio, and may be helpful for the support of async function in next versions. If you think that is a good idea, I will open another issue about it.

Ability of put any HTML to App

As you know, lots of Python plotting libraries support to output the result to HTML. Take PyEcharts for example, just use your_graph_obj.render_notebook(), and put the output to App, you got a wonderful graph based on Echarts.

It can let us support more plotting libraries with just a bit work.

`pc run` fails on WSL2

Hi,

OS: Ubuntu on WSL2 on Win10
Env: virtualenv with pynecone installed
NodeJS 16.18.1
Python 3.8.10

I just tried pynecone (pc init and pc run) and I have this error:

(.venv) matt@wsl2:~/projects/git/pynecone$ pc init
[21:03:20] Initialize the app directory.                                                                                                                                                                 pc.py:31
           Initializing the web directory.                                                                                                                                                               pc.py:47
           Finished Initializing: pynecone                                                                                                                                                               pc.py:51
(.venv) matt@wsl2:~/projects/git/pynecone$ pc run
───────────────────────────────────────────────────────────────────────────────────────────── Starting Pynecone App ─────────────────────────────────────────────────────────────────────────────────────────────
Traceback (most recent call last):
  File "/home/matt/projects/git/pynecone/.venv/bin/pc", line 8, in <module>
    sys.exit(main())
  File "/home/matt/projects/git/pynecone/.venv/lib/python3.8/site-packages/typer/main.py", line 214, in __call__
    return get_command(self)(*args, **kwargs)
  File "/home/matt/projects/git/pynecone/.venv/lib/python3.8/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/home/matt/projects/git/pynecone/.venv/lib/python3.8/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/home/matt/projects/git/pynecone/.venv/lib/python3.8/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/matt/projects/git/pynecone/.venv/lib/python3.8/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/matt/projects/git/pynecone/.venv/lib/python3.8/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/home/matt/projects/git/pynecone/.venv/lib/python3.8/site-packages/typer/main.py", line 532, in wrapper
    return callback(**use_params)  # type: ignore
  File "/home/matt/projects/git/pynecone/.venv/lib/python3.8/site-packages/pynecone/pc.py", line 68, in run
    app = utils.get_app()
  File "/home/matt/projects/git/pynecone/.venv/lib/python3.8/site-packages/pynecone/utils.py", line 314, in get_app
    app = __import__(module, fromlist=(constants.APP_VAR,))
ModuleNotFoundError: No module named 'pynecone.pynecone'
pip freeze
anyio==3.6.2
async-timeout==4.0.2
certifi==2022.12.7
charset-normalizer==2.1.1
click==8.1.3
commonmark==0.9.1
fastapi==0.88.0
greenlet==2.0.1
gunicorn==20.1.0
h11==0.14.0
idna==3.4
plotly==5.11.0
pydantic==1.10.2
Pygments==2.13.0
pynecone-io==0.1.8
redis==4.4.0
requests==2.28.1
rich==12.6.0
sniffio==1.3.0
SQLAlchemy==1.4.41
sqlalchemy2-stubs==0.0.2a29
sqlmodel==0.0.8
starlette==0.22.0
tenacity==8.1.0
typer==0.4.2
typing-extensions==4.4.0
urllib3==1.26.13
uvicorn==0.20.0

Any idea

Make pc run prod work without redis

  • If redis is not available, we should run gunicorn with only one worker.
  • Currently it will be buggy since each worker has its own state dict.

Add support for React hooks

Hi guys, cool project! I'm trying to migrate a basic Chakra + FastAPI app to Pynecone but a bit stuck on implementing the classic Chakra ColorModeSwitcher component.

Is there any way currently to access the color mode hooks? I imagine there are use cases beyond these hooks, but being able to use hooks from other libraries.

Example component to implement:

import * as React from "react"
import {
  useColorMode,
  useColorModeValue,
  IconButton,
  IconButtonProps,
} from "@chakra-ui/react"
import { FaMoon, FaSun } from "react-icons/fa"

type ColorModeSwitcherProps = Omit<IconButtonProps, "aria-label">

export const ColorModeSwitcher: React.FC<ColorModeSwitcherProps> = (props) => {
  const { toggleColorMode } = useColorMode()
  const text = useColorModeValue("dark", "light")
  const SwitchIcon = useColorModeValue(FaMoon, FaSun)

  return (
    <IconButton
      size="md"
      fontSize="lg"
      variant="ghost"
      color="current"
      marginLeft="2"
      onClick={toggleColorMode}
      icon={<SwitchIcon />}
      aria-label={`Switch to ${text} mode`}
      {...props}
    />
  )
}

Indexing not working for props in state.

Describe the bug
Indexing vars in the state is not working.

To Reproduce

class ArgState(State):
    colors: list[str] = ["rgba(222,44,12)", "white", "#007ac2"]

    def change_color(self, color, index):
        self.colors[index] = color
        # Colors must be set not mutated (Warning below example about mutations.)
        self.colors = self.colors

def index():
  return pc.hstack(
      pc.input(default_value=ArgState.colors[0], on_blur=lambda c: ArgState.change_color(c, 0), bg=ArgState.colors[0]),
      pc.input(on_blur=lambda c: ArgState.change_color(c, 1), bg=ArgState.colors[1]),
      pc.input(on_blur=lambda c: ArgState.change_color(c, 2), bg=ArgState.colors[2]),
  )

Expected behavior
Be able to index into the colors list.

If on Desktop (please complete the following information):
Chrom on macOS Monterey.

Accordion item cannot be closed

Problem:

When defining an accordion, all the accordion_panel() start closed.
However, once opened, it is impossible to close them again by clicking on their related accordion_button().

Expected:

Clicking an accordion_button() should close the related accordion_panel().

How to reproduce:
Use the examples in the documentation at Accordion

Edit:

Oops, according to #3 it's already solved.

However default behavior for me (and in the doc too) still seems to be that allow_toggle=False.
I'm using Version : 0.1.8

[Question] is there a way to pass a parameter to pc.button(is_active=State.is_active)?

Hi again,

I'd like to pass a parameter in the State.is_active(self, index) method so that I can distinguish 2 buttons sharing the same state. Is it possible? Using a lambda like in the twitter example?

        pc.button(
            pc.icon(tag="AddIcon", color="white", height="1em"),
            on_click=lambda: HomeState.follow_user(friend.username),
            bg="rgb(29, 161, 242)",
        ),

I tried something like that but no luck

class State(pc.State):

    def is_active(self, index: int) -> bool:
        return self.butstate[index]

...

    return pc.button(
        model.title,
        size="lg",
        on_click=State.switch,
        style=button_style,
        is_active=lambda: State.is_active(0),
    )
Error: TypeError: Object of type function is not JSON serializable

Ways to disable line feed in datatable?

I want to display some data, with a column called article title which can be up to 30 chars ( If it is too long, I will strip it ), but I want to enable horizontal scoll when screen width is too small to display all the chars.

I tried to add white-space: nowrap to the root node of datatable in DevTools, and it is work for my case, but when I turns to add kwargs in pc.datatable, it doesn't work.

Is the attr has been attched to a wrong DOM node? It is a Bug to fix or there are another way to do it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.