Skip to content

Commit

Permalink
Merge branch 'main' into event-target-checked-does-not-exist-for-chec…
Browse files Browse the repository at this point in the history
…kbox-inputs
  • Loading branch information
DennisHC authored Aug 4, 2023
2 parents cbb6d79 + f053551 commit db0f1aa
Show file tree
Hide file tree
Showing 36 changed files with 581 additions and 238 deletions.
4 changes: 2 additions & 2 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

## Issues

<!-- Link the issues this change resolves, or describe them -->
<!-- Describe or link the issues this change resolves -->

## Summary
## Solution

<!-- Describe how these changes resolve the aforementioned issues -->

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
.jupyter

# --- Python ---
.hatch
.venv
venv
MANIFEST
Expand Down
19 changes: 12 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,32 @@ repos:
hooks:
- id: lint-py-fix
name: Fix Python Lint
entry: hatch run lint-py --fix
language: system
pass_filenames: false
- repo: local
hooks:
- id: lint-py-check
name: Check Python Lint
entry: hatch run lint-py
language: system
args: [--fix]
pass_filenames: false
files: \.py$
- repo: local
hooks:
- id: lint-js-fix
name: Fix JS Lint
entry: hatch run lint-js --fix
language: system
pass_filenames: false
files: \.(js|jsx|ts|tsx)$
- repo: local
hooks:
- id: lint-py-check
name: Check Python Lint
entry: hatch run lint-py
language: system
pass_filenames: false
files: \.py$
- repo: local
hooks:
- id: lint-js-check
name: Check JS Lint
entry: hatch run lint-py
language: system
pass_filenames: false
files: \.(js|jsx|ts|tsx)$
2 changes: 1 addition & 1 deletion docs/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tool.poetry]
name = "docs"
name = "docs_app"
version = "0.0.0"
description = "docs"
authors = ["rmorshea <[email protected]>"]
Expand Down
4 changes: 2 additions & 2 deletions docs/source/_exts/reactpy_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import re
from pathlib import Path
from typing import Any
from typing import Any, ClassVar

from docs_app.examples import (
SOURCE_DIR,
Expand All @@ -21,7 +21,7 @@ class WidgetExample(SphinxDirective):
required_arguments = 1
_next_id = 0

option_spec = {
option_spec: ClassVar[dict[str, Any]] = {
"result-is-default-tab": directives.flag,
"activate-button": directives.flag,
}
Expand Down
6 changes: 2 additions & 4 deletions docs/source/_exts/reactpy_view.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import os
import sys

print(sys.path)
from typing import Any, ClassVar

from docs_app.examples import get_normalized_example_name
from docutils.nodes import raw
Expand All @@ -20,7 +18,7 @@ class IteractiveWidget(SphinxDirective):
required_arguments = 1
_next_id = 0

option_spec = {
option_spec: ClassVar[dict[str, Any]] = {
"activate-button": directives.flag,
"margin": float,
}
Expand Down
20 changes: 20 additions & 0 deletions docs/source/about/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,34 @@ more info, see the :ref:`Contributor Guide <Creating a Changelog Entry>`.
Unreleased
----------

**Fixed**

- :pull:`1118` - `module_from_template` is broken with a recent release of `requests`


v1.0.2
------

**Fixed**

- :issue:`1086` - fix rendering bug when children change positions (via :pull:`1085`)


v1.0.1
------

**Changed**

- :pull:`1050` - Warn and attempt to fix missing mime types, which can result in ``reactpy.run`` not working as expected.
- :pull:`1051` - Rename ``reactpy.backend.BackendImplementation`` to ``reactpy.backend.BackendType``
- :pull:`1051` - Allow ``reactpy.run`` to fail in more predictable ways

**Fixed**

- :issue:`930` - better traceback for JSON serialization errors (via :pull:`1008`)
- :issue:`437` - explain that JS component attributes must be JSON (via :pull:`1008`)
- :pull:`1051` - Fix ``reactpy.run`` port assignment sometimes attaching to in-use ports on Windows
- :pull:`1051` - Fix ``reactpy.run`` not recognizing ``fastapi``


v1.0.0
Expand Down
24 changes: 23 additions & 1 deletion docs/source/about/contributor-guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,26 @@ Then, you should be able to activate your development environment with:
hatch shell
From within the shell, to install the projects in this repository, you should then run:

.. code-block:: bash
invoke env
Project Structure
-----------------

This repository is set up to be able to manage many applications and libraries written
in a variety of languages. All projects can be found under the ``src`` directory:

- ``src/py/{project}`` - Python packages
- ``src/js/app`` - ReactPy's built-in JS client
- ``src/js/packages/{project}`` - JS packages

At the root of the repository is a ``pyproject.toml`` file that contains scripts and
their respective dependencies for managing all other projects. Most of these global
scripts can be run via ``hatch run ...`` however, for more complex scripting tasks, we
rely on Invoke_. Scripts implements with Invoke can be found in ``tasks.py``.

Running The Tests
-----------------
Expand Down Expand Up @@ -302,12 +322,14 @@ you should refer to their respective documentation in the links below:
Jupyter
- `reactpy-dash <https://github.com/reactive-python/reactpy-dash>`__ - ReactPy integration for Plotly
Dash
- `django-reactpy <https://github.com/reactive-python/django-reactpy>`__ - ReactPy integration for
- `reactpy-django <https://github.com/reactive-python/reactpy-django>`__ - ReactPy integration for
Django

.. Links
.. =====
.. _Hatch: https://hatch.pypa.io/
.. _Invoke: https://www.pyinvoke.org/
.. _Google Chrome: https://www.google.com/chrome/
.. _Docker: https://docs.docker.com/get-docker/
.. _Git: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
Expand Down
15 changes: 13 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ dependencies = [
"invoke",
# lint
"black",
"ruff",
"ruff==0.0.278", # Ruff is moving really fast, so pinning for now.
"toml",
"flake8",
"flake8-pyproject",
"reactpy-flake8 >=0.7",
# types
"mypy",
"types-toml",
# publish
"semver >=2, <3",
"twine",
Expand All @@ -42,7 +45,15 @@ test-docs = "invoke test-docs"
target-version = ["py39"]
line-length = 88

# --- Flake8 ----------------------------------------------------------------------------
# --- MyPy -----------------------------------------------------------------------------

[tool.mypy]
ignore_missing_imports = true
warn_unused_configs = true
warn_redundant_casts = true
warn_unused_ignores = true

# --- Flake8 ---------------------------------------------------------------------------

[tool.flake8]
select = ["RPY"] # only need to check with reactpy-flake8
Expand Down
9 changes: 0 additions & 9 deletions requirements.txt

This file was deleted.

28 changes: 28 additions & 0 deletions src/py/reactpy/.temp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from reactpy import component, html, run, use_state
from reactpy.core.types import State


@component
def Item(item: str, all_items: State[list[str]]):
color = use_state(None)

def deleteme(event):
all_items.set_value([i for i in all_items.value if (i != item)])

def colorize(event):
color.set_value("blue" if not color.value else None)

return html.div(
{"id": item, "style": {"background_color": color.value}},
html.button({"on_click": colorize}, f"Color {item}"),
html.button({"on_click": deleteme}, f"Delete {item}"),
)


@component
def App():
items = use_state(["A", "B", "C"])
return html._([Item(item, items, key=item) for item in items.value])


run(App)
1 change: 1 addition & 0 deletions src/py/reactpy/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ testpaths = "tests"
xfail_strict = true
python_files = "*asserts.py test_*.py"
asyncio_mode = "auto"
log_cli_level = "INFO"

# --- MyPy -----------------------------------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion src/py/reactpy/reactpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from reactpy.utils import Ref, html_to_vdom, vdom_to_html

__author__ = "The Reactive Python Team"
__version__ = "1.0.1" # DO NOT MODIFY
__version__ = "1.0.2" # DO NOT MODIFY

__all__ = [
"backend",
Expand Down
72 changes: 35 additions & 37 deletions src/py/reactpy/reactpy/backend/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,53 +14,49 @@
from reactpy.utils import vdom_to_html

if TYPE_CHECKING:
import uvicorn
from asgiref.typing import ASGIApplication

PATH_PREFIX = PurePosixPath("/_reactpy")
MODULES_PATH = PATH_PREFIX / "modules"
ASSETS_PATH = PATH_PREFIX / "assets"
STREAM_PATH = PATH_PREFIX / "stream"

CLIENT_BUILD_DIR = Path(_reactpy_file_path).parent / "_static" / "app" / "dist"

try:

async def serve_with_uvicorn(
app: ASGIApplication | Any,
host: str,
port: int,
started: asyncio.Event | None,
) -> None:
"""Run a development server for an ASGI application"""
import uvicorn
except ImportError: # nocov
pass
else:

async def serve_development_asgi(
app: ASGIApplication | Any,
host: str,
port: int,
started: asyncio.Event | None,
) -> None:
"""Run a development server for an ASGI application"""
server = uvicorn.Server(
uvicorn.Config(
app,
host=host,
port=port,
loop="asyncio",
reload=True,
)

server = uvicorn.Server(
uvicorn.Config(
app,
host=host,
port=port,
loop="asyncio",
)
server.config.setup_event_loop()
coros: list[Awaitable[Any]] = [server.serve()]
)
server.config.setup_event_loop()
coros: list[Awaitable[Any]] = [server.serve()]

# If a started event is provided, then use it signal based on `server.started`
if started:
coros.append(_check_if_started(server, started))
# If a started event is provided, then use it signal based on `server.started`
if started:
coros.append(_check_if_started(server, started))

try:
await asyncio.gather(*coros)
finally:
# Since we aren't using the uvicorn's `run()` API, we can't guarantee uvicorn's
# order of operations. So we need to make sure `shutdown()` always has an initialized
# list of `self.servers` to use.
if not hasattr(server, "servers"): # nocov
server.servers = []
await asyncio.wait_for(server.shutdown(), timeout=3)
try:
await asyncio.gather(*coros)
finally:
# Since we aren't using the uvicorn's `run()` API, we can't guarantee uvicorn's
# order of operations. So we need to make sure `shutdown()` always has an initialized
# list of `self.servers` to use.
if not hasattr(server, "servers"): # nocov
server.servers = []
await asyncio.wait_for(server.shutdown(), timeout=3)


async def _check_if_started(server: uvicorn.Server, started: asyncio.Event) -> None:
Expand All @@ -72,8 +68,7 @@ async def _check_if_started(server: uvicorn.Server, started: asyncio.Event) -> N
def safe_client_build_dir_path(path: str) -> Path:
"""Prevent path traversal out of :data:`CLIENT_BUILD_DIR`"""
return traversal_safe_path(
CLIENT_BUILD_DIR,
*("index.html" if path in ("", "/") else path).split("/"),
CLIENT_BUILD_DIR, *("index.html" if path in {"", "/"} else path).split("/")
)


Expand Down Expand Up @@ -140,6 +135,9 @@ class CommonOptions:
url_prefix: str = ""
"""The URL prefix where ReactPy resources will be served from"""

serve_index_route: bool = True
"""Automatically generate and serve the index route (``/``)"""

def __post_init__(self) -> None:
if self.url_prefix and not self.url_prefix.startswith("/"):
msg = "Expected 'url_prefix' to start with '/'"
Expand Down
Loading

0 comments on commit db0f1aa

Please sign in to comment.