Atharva Shah пре 2 година
родитељ
комит
2ccbfff223

+ 9 - 7
pynecone/app.py

@@ -221,18 +221,20 @@ class App(Base):
         for route in self.pages:
             route = "" if route == "index" else route
 
-            if new_route.startswith(route + "/[[..."):
+            if new_route.startswith(f"{route}/[[..."):
                 raise ValueError(
                     f"You cannot define a route with the same specificity as a optional catch-all route ('{route}' and '{new_route}')"
                 )
 
             route_catchall = utils.catchall_in_route(route)
-            if route_catchall and newroute_catchall:
-                # both route have a catchall, check if preceding path is the same
-                if utils.catchall_prefix(route) == utils.catchall_prefix(new_route):
-                    raise ValueError(
-                        f"You cannot use multiple catchall for the same dynamic path ({route} !== {new_route})"
-                    )
+            if (
+                route_catchall
+                and newroute_catchall
+                and utils.catchall_prefix(route) == utils.catchall_prefix(new_route)
+            ):
+                raise ValueError(
+                    f"You cannot use multiple catchall for the same dynamic path ({route} !== {new_route})"
+                )
 
     def add_custom_404_page(self, component, title=None, image=None, description=None):
         """Define a custom 404 page for any url having no match.

+ 8 - 9
pynecone/compiler/templates.py

@@ -35,8 +35,8 @@ def format_import(lib: str, default: str = "", rest: Optional[Set[str]] = None)
         The compiled import statement.
     """
     # Handle the case of direct imports with no libraries.
-    if lib == "":
-        assert default == "", "No default field allowed for empty library."
+    if not lib:
+        assert not default, "No default field allowed for empty library."
         assert rest is not None and len(rest) > 0, "No fields to import."
         return join([IMPORT_LIB(lib=lib) for lib in sorted(rest)])
 
@@ -45,12 +45,11 @@ def format_import(lib: str, default: str = "", rest: Optional[Set[str]] = None)
     if len(default) == 0 and len(rest) == 0:
         # Handle the case of importing a library with no fields.
         return IMPORT_LIB(lib=lib)
-    else:
-        # Handle importing specific fields from a library.
-        others = f'{{{", ".join(sorted(rest))}}}' if len(rest) > 0 else ""
-        if len(default) > 0 and len(rest) > 0:
-            default += ", "
-        return IMPORT_FIELDS(default=default, others=others, lib=lib)
+    # Handle importing specific fields from a library.
+    others = f'{{{", ".join(sorted(rest))}}}' if len(rest) > 0 else ""
+    if default != "" and len(rest) > 0:
+        default += ", "
+    return IMPORT_FIELDS(default=default, others=others, lib=lib)
 
 
 # Code to render a NextJS Document root.
@@ -163,7 +162,7 @@ USE_EFFECT = join(
     [
         "useEffect(() => {{",
         "  if(!isReady) {{",
-        f"    return;",
+        "    return;",
         "  }}",
         f"  if (!{SOCKET}.current) {{{{",
         f"    connect({SOCKET}, {{state}}, {{set_state}}, {RESULT}, {SET_RESULT}, {ROUTER}, {EVENT_ENDPOINT})",

+ 8 - 9
pynecone/components/component.py

@@ -92,14 +92,13 @@ class Component(Base, ABC):
             if key in triggers:
                 # Event triggers are bound to event chains.
                 field_type = EventChain
-            else:
-                # If the key is not in the fields, skip it.
-                if key not in props:
-                    continue
-
+            elif key in props:
                 # Set the field type.
                 field_type = fields[key].type_
 
+            else:
+                continue
+
             # Check whether the key is a component prop.
             if utils._issubclass(field_type, Var):
                 try:
@@ -292,9 +291,9 @@ class Component(Base, ABC):
                 )
 
         children = [
-            Bare.create(contents=Var.create(child, is_string=True))
-            if not isinstance(child, Component)
-            else child
+            child
+            if isinstance(child, Component)
+            else Bare.create(contents=Var.create(child, is_string=True))
             for child in children
         ]
         return cls(children=children, **props)
@@ -454,7 +453,7 @@ class CustomComponent(Component):
             if utils._issubclass(type_, Base):
                 try:
                     value = BaseVar(name=value.json(), type_=type_, is_local=True)
-                except:
+                except Exception:
                     value = Var.create(value)
             else:
                 value = Var.create(value, is_string=type(value) is str)

+ 1 - 1
pynecone/components/forms/pininput.py

@@ -77,7 +77,7 @@ class PinInput(ChakraComponent):
         Returns:
             The pin input component.
         """
-        if len(children) == 0 and "length" in props:
+        if not children and "length" in props:
             children = [PinInputField()] * props["length"]
         return super().create(*children, **props)
 

+ 1 - 1
pynecone/components/forms/rangeslider.py

@@ -68,7 +68,7 @@ class RangeSlider(ChakraComponent):
         Returns:
             The RangeSlider component.
         """
-        if len(children) == 0:
+        if not children:
             children = [
                 RangeSliderTrack.create(
                     RangeSliderFilledTrack.create(),

+ 1 - 1
pynecone/components/forms/slider.py

@@ -68,7 +68,7 @@ class Slider(ChakraComponent):
         Returns:
             The slider component.
         """
-        if len(children) == 0:
+        if not children:
             children = [
                 SliderTrack.create(
                     SliderFilledTrack.create(),

+ 8 - 6
pynecone/components/graphing/plotly.py

@@ -42,11 +42,13 @@ const Plot = dynamic(() => import('react-plotly.js'), { ssr: false });
 """
 
     def _render(self) -> Tag:
-        if isinstance(self.data, Figure):
-            if self.layout is None:
-                if self.width is not None:
-                    layout = Var.create({"width": self.width, "height": self.height})
-                    assert layout is not None
-                    self.layout = layout
+        if (
+            isinstance(self.data, Figure)
+            and self.layout is None
+            and self.width is not None
+        ):
+            layout = Var.create({"width": self.width, "height": self.height})
+            assert layout is not None
+            self.layout = layout
 
         return super()._render()

+ 46 - 52
pynecone/components/graphing/victory.py

@@ -78,10 +78,9 @@ def format_area(x: List, y: List, y0: Optional[List] = None) -> List:
     """
     if y0 is None:
         return format_xy(x, y)
-    else:
-        if len(x) != len(y) or len(x) != len(y0):
-            raise ValueError("x, y, and y0 must be the same length")
-        return [{"x": x[i], "y": y[i], "y0": y0[i]} for i in range(len(x))]
+    if len(x) != len(y) or len(x) != len(y0):
+        raise ValueError("x, y, and y0 must be the same length")
+    return [{"x": x[i], "y": y[i], "y0": y0[i]} for i in range(len(x))]
 
 
 def format_bar(x: List, y: List, y0: Optional[List] = None) -> List:
@@ -100,10 +99,9 @@ def format_bar(x: List, y: List, y0: Optional[List] = None) -> List:
     """
     if y0 is None:
         return format_xy(x, y)
-    else:
-        if len(x) != len(y) or len(x) != len(y0):
-            raise ValueError("x, y, and y0 must be the same length")
-        return [{"x": x[i], "y": y[i], "y0": y0[i]} for i in range(len(x))]
+    if len(x) != len(y) or len(x) != len(y0):
+        raise ValueError("x, y, and y0 must be the same length")
+    return [{"x": x[i], "y": y[i], "y0": y0[i]} for i in range(len(x))]
 
 
 def format_box_plot(
@@ -135,40 +133,37 @@ def format_box_plot(
         ValueError: If y is not provided and min, max, median, q1, and q3 are not provided.
         ValueError: If y is not provided and x, min, max, median, q1, and q3 are not the same length.
     """
-    data = []
     if x is None:
         raise ValueError("x must be specified")
 
     if y is not None:
         return format_xy(x, y)
 
-    else:
-        if min_ is None or max_ is None or median is None or q1 is None or q3 is None:
-            raise ValueError(
-                "min, max, median, q1, and q3 must be specified if y is not provided"
-            )
-        if (
-            len(x) != len(min_)
-            or len(x) != len(max_)
-            or len(x) != len(median)
-            or len(x) != len(q1)
-            or len(x) != len(q3)
-        ):
-            raise ValueError(
-                "x, min, max, median, q1, and q3 must be the same length and specified if y is not provided"
-            )
-        for i in range(len(x)):
-            data.append(
-                {
-                    "x": x[i],
-                    "min": min_[i],
-                    "max": max_[i],
-                    "median": median[i],
-                    "q1": q1[i],
-                    "q3": q3[i],
-                }
-            )
-    return data
+    if min_ is None or max_ is None or median is None or q1 is None or q3 is None:
+        raise ValueError(
+            "min, max, median, q1, and q3 must be specified if y is not provided"
+        )
+    if (
+        len(x) != len(min_)
+        or len(x) != len(max_)
+        or len(x) != len(median)
+        or len(x) != len(q1)
+        or len(x) != len(q3)
+    ):
+        raise ValueError(
+            "x, min, max, median, q1, and q3 must be the same length and specified if y is not provided"
+        )
+    return [
+        {
+            "x": x[i],
+            "min": min_[i],
+            "max": max_[i],
+            "median": median[i],
+            "q1": q1[i],
+            "q3": q3[i],
+        }
+        for i in range(len(x))
+    ]
 
 
 def format_histogram(x: List) -> List:
@@ -210,10 +205,9 @@ def format_pie(x: List, y: List, label: Optional[List] = None) -> List:
 
     if label is None:
         return format_xy(x, y)
-    else:
-        if len(x) != len(y) or len(x) != len(label):
-            raise ValueError("x, y, and label must be the same length")
-        return [{"x": x[i], "y": y[i], "label": label[i]} for i in range(len(x))]
+    if len(x) != len(y) or len(x) != len(label):
+        raise ValueError("x, y, and label must be the same length")
+    return [{"x": x[i], "y": y[i], "label": label[i]} for i in range(len(x))]
 
 
 def format_voronoi(x: List, y: List) -> List:
@@ -314,26 +308,26 @@ def data(graph: str, x: List, y: Optional[List] = None, **kwargs) -> List:
         ValueError: If graph is not provided.
         ValueError: If graph is not supported.
     """
-    if graph == "box_plot":
-        return format_box_plot(x, y, **kwargs)
+    if graph == "area":
+        return format_area(x, y, **kwargs)  # type: ignore
     elif graph == "bar":
         return format_bar(x, y)  # type: ignore
-    elif graph == "line":
-        return format_line(x, y)  # type: ignore
-    elif graph == "scatter":
-        return format_scatter(x, y, **kwargs)  # type: ignore
-    elif graph == "area":
-        return format_area(x, y, **kwargs)  # type: ignore
+    elif graph == "box_plot":
+        return format_box_plot(x, y, **kwargs)
+    elif graph == "candlestick":
+        return format_candlestick(x, **kwargs)
+    elif graph == "error_bar":
+        return format_error_bar(x, y, **kwargs)  # type: ignore
     elif graph == "histogram":
         return format_histogram(x)
+    elif graph == "line":
+        return format_line(x, y)  # type: ignore
     elif graph == "pie":
         return format_pie(x, y, **kwargs)  # type: ignore
+    elif graph == "scatter":
+        return format_scatter(x, y, **kwargs)  # type: ignore
     elif graph == "voronoi":
         return format_voronoi(x, y)  # type: ignore
-    elif graph == "candlestick":
-        return format_candlestick(x, **kwargs)
-    elif graph == "error_bar":
-        return format_error_bar(x, y, **kwargs)  # type: ignore
     else:
         raise ValueError("Invalid graph type")
 

+ 1 - 1
pynecone/components/layout/foreach.py

@@ -31,7 +31,7 @@ class Foreach(Component):
         """
         try:
             type_ = iterable.type_.__args__[0]
-        except:
+        except Exception:
             type_ = Any
         arg = BaseVar(name="_", type_=type_, is_local=True)
         return cls(

+ 1 - 5
pynecone/components/navigation/link.py

@@ -34,9 +34,5 @@ class Link(ChakraComponent):
         Returns:
             The component.
         """
-        kwargs = {}
-        if "href" in props:
-            kwargs["href"] = props.pop("href")
-        else:
-            kwargs["href"] = "#"
+        kwargs = {"href": props.pop("href") if "href" in props else "#"}
         return NextLink.create(super().create(*children, **props), **kwargs)

+ 1 - 1
pynecone/components/tags/iter_tag.py

@@ -91,7 +91,7 @@ class IterTag(Tag):
         """
         try:
             type_ = self.iterable.type_.__args__[0]
-        except:
+        except Exception:
             type_ = Any
         arg = BaseVar(
             name=utils.get_unique_variable_name(),

+ 1 - 1
pynecone/constants.py

@@ -195,11 +195,11 @@ class Endpoint(Enum):
 class PathArgType(SimpleNamespace):
     """Type of pathArg extracted from URI path."""
 
+    # Typecast to str is needed for Enum to work.
     SINGLE = str("arg_single")
     LIST = str("arg_list")
 
 
-# ROUTE REGEXs
 class RouteRegex(SimpleNamespace):
     """Regex used for extracting path args in path."""
 

+ 2 - 2
pynecone/event.py

@@ -65,10 +65,10 @@ class EventHandler(Base):
             # Otherwise, convert to JSON.
             try:
                 values.append(json.dumps(arg))
-            except TypeError:
+            except TypeError as e:
                 raise TypeError(
                     f"Arguments to event handlers must be Vars or JSON-serializable. Got {arg} of type {type(arg)}."
-                )
+                ) from e
         payload = tuple(zip(fn_args, values))
 
         # Return the event spec.

+ 2 - 2
pynecone/state.py

@@ -157,7 +157,7 @@ class State(Base, ABC):
         Returns:
             The substates of the state.
         """
-        return {subclass for subclass in cls.__subclasses__()}
+        return set(cls.__subclasses__())
 
     @classmethod
     @functools.lru_cache()
@@ -408,7 +408,7 @@ class State(Base, ABC):
                 events = await fn(**event.payload)
             else:
                 events = fn(**event.payload)
-        except:
+        except Exception:
             error = traceback.format_exc()
             print(error)
             return StateUpdate(

+ 12 - 33
pynecone/utils.py

@@ -1,7 +1,9 @@
 """General utility functions."""
 
+
 from __future__ import annotations
 
+import contextlib
 import inspect
 import json
 import os
@@ -87,14 +89,11 @@ def is_generic_alias(cls: GenericType) -> bool:
     if isinstance(cls, _GenericAlias):
         return True
 
-    try:
+    with contextlib.suppress(ImportError):
         from typing import _SpecialGenericAlias  # type: ignore
 
         if isinstance(cls, _SpecialGenericAlias):
             return True
-    except ImportError:
-        pass
-
     # For newer versions of Python.
     try:
         from types import GenericAlias  # type: ignore
@@ -113,17 +112,11 @@ def is_union(cls: GenericType) -> bool:
     Returns:
         Whether the class is a Union.
     """
-    try:
+    with contextlib.suppress(ImportError):
         from typing import _UnionGenericAlias  # type: ignore
 
         return isinstance(cls, _UnionGenericAlias)
-    except ImportError:
-        pass
-
-    if is_generic_alias(cls):
-        return cls.__origin__ == Union
-
-    return False
+    return cls.__origin__ == Union if is_generic_alias(cls) else False
 
 
 def get_base_class(cls: GenericType) -> Type:
@@ -138,10 +131,7 @@ def get_base_class(cls: GenericType) -> Type:
     if is_union(cls):
         return tuple(get_base_class(arg) for arg in get_args(cls))
 
-    if is_generic_alias(cls):
-        return get_base_class(cls.__origin__)
-
-    return cls
+    return get_base_class(cls.__origin__) if is_generic_alias(cls) else cls
 
 
 def _issubclass(cls: GenericType, cls_check: GenericType) -> bool:
@@ -157,7 +147,7 @@ def _issubclass(cls: GenericType, cls_check: GenericType) -> bool:
     # Special check for Any.
     if cls_check == Any:
         return True
-    if cls == Any or cls == Callable:
+    if cls in [Any, Callable]:
         return False
     cls_base = get_base_class(cls)
     cls_check_base = get_base_class(cls_check)
@@ -361,8 +351,7 @@ def get_app() -> ModuleType:
     config = get_config()
     module = ".".join([config.app_name, config.app_name])
     sys.path.insert(0, os.getcwd())
-    app = __import__(module, fromlist=(constants.APP_VAR,))
-    return app
+    return __import__(module, fromlist=(constants.APP_VAR,))
 
 
 def create_config(app_name: str):
@@ -570,12 +559,7 @@ def get_num_workers() -> int:
     Returns:
         The number of backend worker processes.
     """
-    if get_redis() is None:
-        # If there is no redis, then just use 1 worker.
-        return 1
-
-    # Use the number of cores * 2 + 1.
-    return (os.cpu_count() or 1) * 2 + 1
+    return 1 if get_redis() is None else (os.cpu_count() or 1) * 2 + 1
 
 
 def get_api_port() -> int:
@@ -888,9 +872,7 @@ def format_route(route: str) -> str:
     """
     route = route.strip(os.path.sep)
     route = to_snake_case(route).replace("_", "-")
-    if route == "":
-        return constants.INDEX_ROUTE
-    return route
+    return constants.INDEX_ROUTE if route == "" else route
 
 
 def format_cond(
@@ -936,7 +918,7 @@ def format_event_handler(handler: EventHandler) -> str:
     try:
         # Try to get the state from the module.
         state = vars(sys.modules[handler.fn.__module__])[state_name]
-    except:
+    except Exception:
         # If the state isn't in the module, just return the function name.
         return handler.fn.__qualname__
     return ".".join([state.get_full_name(), name])
@@ -1128,10 +1110,7 @@ def get_handler_args(event_spec: EventSpec, arg: Var) -> Tuple[Tuple[str, str],
         The handler args.
     """
     args = inspect.getfullargspec(event_spec.handler.fn).args
-    if len(args) > 2:
-        return event_spec.args
-    else:
-        return ((args[1], arg.name),)
+    return event_spec.args if len(args) > 2 else ((args[1], arg.name),)
 
 
 def fix_events(events: Optional[List[Event]], token: str) -> List[Event]:

+ 5 - 12
pynecone/var.py

@@ -64,7 +64,7 @@ class Var(ABC):
             value = json.loads(to_json(value))["data"]
             type_ = Figure
 
-        name = json.dumps(value) if not isinstance(value, str) else value
+        name = value if isinstance(value, str) else json.dumps(value)
 
         return BaseVar(name=name, type_=type_, is_local=is_local, is_string=is_string)
 
@@ -118,10 +118,7 @@ class Var(ABC):
         Returns:
             The wrapped var, i.e. {state.var}.
         """
-        if self.is_local:
-            out = self.full_name
-        else:
-            out = utils.wrap(self.full_name, "{")
+        out = self.full_name if self.is_local else utils.wrap(self.full_name, "{")
         if self.is_string:
             out = utils.format_string(out)
         return out
@@ -263,7 +260,7 @@ class Var(ABC):
         if other is None:
             name = f"{op}{self.full_name}"
         else:
-            props = (self, other) if not flip else (other, self)
+            props = (other, self) if flip else (self, other)
             name = f"{props[0].full_name} {op} {props[1].full_name}"
             if fn is None:
                 name = utils.wrap(name, "(")
@@ -620,9 +617,7 @@ class Var(ABC):
         Returns:
             The full name of the var.
         """
-        if self.state == "":
-            return self.name
-        return ".".join([self.state, self.name])
+        return self.name if self.state == "" else ".".join([self.state, self.name])
 
     def set_state(self, state: Type[State]) -> Any:
         """Set the state of the var.
@@ -685,9 +680,7 @@ class BaseVar(Var, Base):
             return {}
         if issubclass(type_, tuple):
             return ()
-        if issubclass(type_, set):
-            return set()
-        return None
+        return set() if issubclass(type_, set) else None
 
     def get_setter_name(self, include_state: bool = True) -> str:
         """Get the name of the var's generated setter function.

+ 1 - 1
tests/components/test_component.py

@@ -300,4 +300,4 @@ def test_custom_component_hash(my_component):
     """
     component1 = CustomComponent(component_fn=my_component, prop1="test", prop2=1)
     component2 = CustomComponent(component_fn=my_component, prop1="test", prop2=2)
-    assert set([component1, component2]) == {component1}
+    assert {component1, component2} == {component1}

+ 2 - 2
tests/test_var.py

@@ -195,9 +195,9 @@ def test_var_list_slicing():
     """Test that we can slice into list vars."""
     lst = BaseVar(name="lst", type_=List[int])
 
-    assert str(lst[0:1]) == "{lst.slice(0, 1)}"
     assert str(lst[:1]) == "{lst.slice(0, 1)}"
-    assert str(lst[0:]) == "{lst.slice(0, undefined)}"
+    assert str(lst[:1]) == "{lst.slice(0, 1)}"
+    assert str(lst[:]) == "{lst.slice(0, undefined)}"
 
 
 def test_dict_indexing():