Create Github Action for pytest (#12)

This commit is contained in:
Nikhil Rao 2022-11-21 18:50:59 -08:00 committed by GitHub
parent 1f817c637f
commit c4b1f2c669
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 101 additions and 39 deletions

39
.github/workflows/python-checks.yml vendored Normal file
View File

@ -0,0 +1,39 @@
name: Python application
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- uses: snok/install-poetry@v1
with:
version: 1.1.14
virtualenvs-create: true
virtualenvs-in-project: true
- run: poetry install --no-interaction --no-root
- run: poetry install --no-interaction
- run: poetry run pytest tests
- run: poetry run pyright pynecone tests
- run: poetry run pydocstyle pynecone tests
- run: poetry run darglint pynecone tests

View File

@ -1,30 +1,13 @@
"""Create a list of components from an iterable.""" """Create a list of components from an iterable."""
from __future__ import annotations from __future__ import annotations
from typing import Any, List, Protocol, runtime_checkable from typing import Any, Callable, List
from pynecone.components.component import Component from pynecone.components.component import Component
from pynecone.components.tags import IterTag, Tag from pynecone.components.tags import IterTag, Tag
from pynecone.var import BaseVar, Var from pynecone.var import BaseVar, Var
@runtime_checkable
class RenderFn(Protocol):
"""A function that renders a component."""
def __call__(self, *args, **kwargs) -> Component:
"""Render a component.
Args:
*args: The positional arguments.
**kwargs: The keyword arguments.
Returns: # noqa: DAR202
The rendered component.
"""
...
class Foreach(Component): class Foreach(Component):
"""Display a foreach.""" """Display a foreach."""
@ -32,10 +15,10 @@ class Foreach(Component):
iterable: Var[List] iterable: Var[List]
# A function from the render args to the component. # A function from the render args to the component.
render_fn: RenderFn render_fn: Callable
@classmethod @classmethod
def create(cls, iterable: Var[List], render_fn: RenderFn, **props) -> Foreach: def create(cls, iterable: Var[List], render_fn: Callable, **props) -> Foreach:
"""Create a foreach component. """Create a foreach component.
Args: Args:

View File

@ -14,7 +14,7 @@ class Markdown(Component):
tag = "ReactMarkdown" tag = "ReactMarkdown"
src: Var[str] = "" # type: ignore src: Var[str]
def _get_custom_code(self) -> str: def _get_custom_code(self) -> str:
return "import 'katex/dist/katex.min.css'" return "import 'katex/dist/katex.min.css'"

View File

@ -1,3 +1,5 @@
"""The Pynecone config."""
from typing import Optional from typing import Optional
from pynecone import constants from pynecone import constants

View File

@ -467,7 +467,11 @@ class StateManager(Base):
redis: Any = None redis: Any = None
def setup(self, state: Type[State]): def setup(self, state: Type[State]):
"""Setup the state manager.""" """Set up the state manager.
Args:
state: The state class to use.
"""
self.state = state self.state = state
self.redis = utils.get_redis() self.redis = utils.get_redis()

View File

@ -15,7 +15,6 @@ import sys
from collections import defaultdict from collections import defaultdict
from subprocess import PIPE from subprocess import PIPE
from typing import _GenericAlias # type: ignore from typing import _GenericAlias # type: ignore
from typing import _UnionGenericAlias # type: ignore
from typing import ( from typing import (
TYPE_CHECKING, TYPE_CHECKING,
Any, Any,
@ -71,7 +70,7 @@ def get_base_class(cls: Type) -> Type:
""" """
# For newer versions of Python. # For newer versions of Python.
try: try:
from types import GenericAlias from types import GenericAlias # type: ignore
if isinstance(cls, GenericAlias): if isinstance(cls, GenericAlias):
return get_base_class(cls.__origin__) return get_base_class(cls.__origin__)
@ -79,11 +78,18 @@ def get_base_class(cls: Type) -> Type:
pass pass
# Check Union types first. # Check Union types first.
if isinstance(cls, _UnionGenericAlias): try:
return tuple(get_base_class(arg) for arg in get_args(cls)) from typing import _UnionGenericAlias # type: ignore
if isinstance(cls, _UnionGenericAlias):
return tuple(get_base_class(arg) for arg in get_args(cls))
except:
pass
# Check other generic aliases. # Check other generic aliases.
if isinstance(cls, _GenericAlias): if isinstance(cls, _GenericAlias):
if cls.__origin__ == Union:
return tuple(get_base_class(arg) for arg in get_args(cls))
return get_base_class(cls.__origin__) return get_base_class(cls.__origin__)
# This is the base class. # This is the base class.
@ -105,7 +111,7 @@ def _issubclass(
# Special check for Any. # Special check for Any.
if cls_check == Any: if cls_check == Any:
return True return True
if cls == Any: if cls == Any or cls == Callable:
return False return False
cls_base = get_base_class(cls) cls_base = get_base_class(cls)
cls_check_base = get_base_class(cls_check) cls_check_base = get_base_class(cls_check)
@ -240,8 +246,13 @@ def get_config() -> Config:
Returns: Returns:
The app config. The app config.
""" """
from pynecone.config import Config
sys.path.append(os.getcwd()) sys.path.append(os.getcwd())
return __import__(constants.CONFIG_MODULE).config try:
return __import__(constants.CONFIG_MODULE).config
except:
return Config(app_name="")
def get_bun_path(): def get_bun_path():
@ -694,9 +705,9 @@ def format_string(string: str) -> str:
Returns: Returns:
The formatted string. The formatted string.
""" """
# Escale backticks. # Escape backticks.
string = string.replace("\`", "`") # type: ignore string = string.replace(r"\`", "`")
string = string.replace("`", "\`") # type: ignore string = string.replace("`", r"\`")
# Wrap the string so it looks like {`string`}. # Wrap the string so it looks like {`string`}.
string = wrap(string, "`") string = wrap(string, "`")
@ -859,7 +870,7 @@ def get_redis():
The redis client. The redis client.
""" """
try: try:
import redis import redis # type: ignore
except: except:
return None return None

View File

@ -4,7 +4,7 @@ import pytest
from pynecone.components import Box from pynecone.components import Box
from pynecone.components.tags import CondTag, IterTag, Tag from pynecone.components.tags import CondTag, IterTag, Tag
from pynecone.event import EventHandler, EventSpec, EventChain from pynecone.event import EventChain, EventHandler, EventSpec
from pynecone.var import BaseVar, Var from pynecone.var import BaseVar, Var

View File

@ -3,8 +3,8 @@ from typing import Type
import pytest import pytest
from pynecone.app import App, DefaultState from pynecone.app import App, DefaultState
from pynecone.middleware import HydrateMiddleware
from pynecone.components import Box from pynecone.components import Box
from pynecone.middleware import HydrateMiddleware
from pynecone.state import State from pynecone.state import State
from pynecone.style import Style from pynecone.style import Style
@ -21,7 +21,11 @@ def app() -> App:
@pytest.fixture @pytest.fixture
def index_page(): def index_page():
"""An index page.""" """An index page.
Returns:
The index page.
"""
def index(): def index():
return Box.create("Index") return Box.create("Index")
@ -31,7 +35,11 @@ def index_page():
@pytest.fixture @pytest.fixture
def about_page(): def about_page():
"""An index page.""" """An about page.
Returns:
The about page.
"""
def about(): def about():
return Box.create("About") return Box.create("About")
@ -107,7 +115,7 @@ def test_initialize_with_state(TestState: Type[State]):
"""Test setting the state of an app. """Test setting the state of an app.
Args: Args:
DefaultState: The default state. TestState: The default state.
""" """
app = App(state=TestState) app = App(state=TestState)
assert app.state == TestState assert app.state == TestState
@ -123,7 +131,7 @@ def test_set_and_get_state(TestState: Type[State]):
"""Test setting and getting the state of an app with different tokens. """Test setting and getting the state of an app with different tokens.
Args: Args:
DefaultState: The default state. TestState: The default state.
""" """
app = App(state=TestState) app = App(state=TestState)

View File

@ -1,6 +1,21 @@
import pytest import pytest
from pynecone.event import Event, EventHandler, EventSpec from pynecone.event import Event, EventHandler, EventSpec
from pynecone.var import Var
def make_var(value) -> Var:
"""Make a variable.
Args:
value: The value of the var.
Returns:
The var.
"""
var = Var.create(value)
assert var is not None
return var
def test_create_event(): def test_create_event():
@ -28,7 +43,7 @@ def test_call_event_handler():
assert event_spec.args == () assert event_spec.args == ()
handler = EventHandler(fn=test_fn_with_args) handler = EventHandler(fn=test_fn_with_args)
event_spec = handler("first", "second") event_spec = handler(make_var("first"), make_var("second"))
assert event_spec.handler == handler assert event_spec.handler == handler
assert event_spec.local_args == () assert event_spec.local_args == ()