Skip to content

Commit cfa0938

Browse files
committed
Merge branch 'main' into local-storage
2 parents e4be3e5 + f065655 commit cfa0938

File tree

10 files changed

+101
-29
lines changed

10 files changed

+101
-29
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
.jupyter
1212

1313
# --- Python ---
14+
.hatch
1415
.venv
1516
venv
1617
MANIFEST

.pre-commit-config.yaml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,9 @@ repos:
33
hooks:
44
- id: lint-py-fix
55
name: Fix Python Lint
6-
entry: hatch run lint-py --fix
7-
language: system
8-
pass_filenames: false
9-
- repo: local
10-
hooks:
11-
- id: lint-py-check
12-
name: Check Python Lint
136
entry: hatch run lint-py
147
language: system
8+
args: [--fix]
159
pass_filenames: false
1610
- repo: local
1711
hooks:
@@ -20,6 +14,13 @@ repos:
2014
entry: hatch run lint-js --fix
2115
language: system
2216
pass_filenames: false
17+
- repo: local
18+
hooks:
19+
- id: lint-py-check
20+
name: Check Python Lint
21+
entry: hatch run lint-py
22+
language: system
23+
pass_filenames: false
2324
- repo: local
2425
hooks:
2526
- id: lint-js-check

docs/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[tool.poetry]
2-
name = "docs"
2+
name = "docs_app"
33
version = "0.0.0"
44
description = "docs"
55
authors = ["rmorshea <[email protected]>"]

docs/source/_exts/reactpy_example.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import re
44
from pathlib import Path
5-
from typing import Any
5+
from typing import Any, ClassVar
66

77
from docs_app.examples import (
88
SOURCE_DIR,
@@ -21,7 +21,7 @@ class WidgetExample(SphinxDirective):
2121
required_arguments = 1
2222
_next_id = 0
2323

24-
option_spec = {
24+
option_spec: ClassVar[dict[str, Any]] = {
2525
"result-is-default-tab": directives.flag,
2626
"activate-button": directives.flag,
2727
}

docs/source/_exts/reactpy_view.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import os
2-
import sys
3-
4-
print(sys.path)
2+
from typing import Any, ClassVar
53

64
from docs_app.examples import get_normalized_example_name
75
from docutils.nodes import raw
@@ -20,7 +18,7 @@ class IteractiveWidget(SphinxDirective):
2018
required_arguments = 1
2119
_next_id = 0
2220

23-
option_spec = {
21+
option_spec: ClassVar[dict[str, Any]] = {
2422
"activate-button": directives.flag,
2523
"margin": float,
2624
}

docs/source/about/contributor-guide.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,26 @@ Then, you should be able to activate your development environment with:
118118
119119
hatch shell
120120
121+
From within the shell, to install the projects in this repository, you should then run:
122+
123+
.. code-block:: bash
124+
125+
invoke env
126+
127+
Project Structure
128+
-----------------
129+
130+
This repository is set up to be able to manage many applications and libraries written
131+
in a variety of languages. All projects can be found under the ``src`` directory:
132+
133+
- ``src/py/{project}`` - Python packages
134+
- ``src/js/app`` - ReactPy's built-in JS client
135+
- ``src/js/packages/{project}`` - JS packages
136+
137+
At the root of the repository is a ``pyproject.toml`` file that contains scripts and
138+
their respective dependencies for managing all other projects. Most of these global
139+
scripts can be run via ``hatch run ...`` however, for more complex scripting tasks, we
140+
rely on Invoke_. Scripts implements with Invoke can be found in ``tasks.py``.
121141

122142
Running The Tests
123143
-----------------
@@ -308,6 +328,8 @@ you should refer to their respective documentation in the links below:
308328
.. Links
309329
.. =====
310330
331+
.. _Hatch: https://hatch.pypa.io/
332+
.. _Invoke: https://www.pyinvoke.org/
311333
.. _Google Chrome: https://www.google.com/chrome/
312334
.. _Docker: https://docs.docker.com/get-docker/
313335
.. _Git: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git

pyproject.toml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ dependencies = [
1818
"flake8",
1919
"flake8-pyproject",
2020
"reactpy-flake8 >=0.7",
21+
# types
22+
"mypy",
23+
"types-toml",
2124
# publish
2225
"semver >=2, <3",
2326
"twine",
@@ -42,7 +45,15 @@ test-docs = "invoke test-docs"
4245
target-version = ["py39"]
4346
line-length = 88
4447

45-
# --- Flake8 ----------------------------------------------------------------------------
48+
# --- MyPy -----------------------------------------------------------------------------
49+
50+
[tool.mypy]
51+
ignore_missing_imports = true
52+
warn_unused_configs = true
53+
warn_redundant_casts = true
54+
warn_unused_ignores = true
55+
56+
# --- Flake8 ---------------------------------------------------------------------------
4657

4758
[tool.flake8]
4859
select = ["RPY"] # only need to check with reactpy-flake8

src/py/reactpy/reactpy/core/events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def event(
2121

2222
@overload
2323
def event(
24-
function: Literal[None] = None,
24+
function: Literal[None] = ...,
2525
*,
2626
stop_propagation: bool = ...,
2727
prevent_default: bool = ...,

src/py/reactpy/reactpy/core/layout.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,16 @@
3737
class Layout:
3838
"""Responsible for "rendering" components. That is, turning them into VDOM."""
3939

40-
__slots__ = [
40+
__slots__: tuple[str, ...] = (
4141
"root",
4242
"_event_handlers",
4343
"_rendering_queue",
4444
"_root_life_cycle_state_id",
4545
"_model_states_by_life_cycle_state_id",
46-
]
46+
)
4747

4848
if not hasattr(abc.ABC, "__weakref__"): # nocov
49-
__slots__.append("__weakref__")
49+
__slots__ += ("__weakref__",)
5050

5151
def __init__(self, root: ComponentType) -> None:
5252
super().__init__()

tasks.py

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from invoke import task
1616
from invoke.context import Context
1717
from invoke.exceptions import Exit
18+
from invoke.runners import Result
1819

1920
# --- Typing Preamble ------------------------------------------------------------------
2021

@@ -77,14 +78,21 @@ def env(context: Context):
7778
@task
7879
def env_py(context: Context):
7980
"""Install Python development environment"""
80-
for py_proj in PY_PROJECTS:
81-
py_proj_toml = toml.load(py_proj / "pyproject.toml")
82-
hatch_default_env = py_proj_toml["tool"]["hatch"]["envs"].get("default", {})
83-
hatch_default_features = hatch_default_env.get("features", [])
84-
hatch_default_deps = hatch_default_env.get("dependencies", [])
81+
for py_proj in [
82+
DOCS_DIR,
83+
# Docs installs non-editable versions of packages - ensure
84+
# we overwrite that by installing projects afterwards.
85+
*PY_PROJECTS,
86+
]:
87+
py_proj_toml_tools = toml.load(py_proj / "pyproject.toml")["tool"]
88+
if "hatch" in py_proj_toml_tools:
89+
install_func = install_hatch_project
90+
elif "poetry" in py_proj_toml_tools:
91+
install_func = install_poetry_project
92+
else:
93+
raise Exit(f"Unknown project type: {py_proj}")
8594
with context.cd(py_proj):
86-
context.run(f"pip install '.[{','.join(hatch_default_features)}]'")
87-
context.run(f"pip install {' '.join(map(repr, hatch_default_deps))}")
95+
install_func(context, py_proj)
8896

8997

9098
@task
@@ -103,6 +111,7 @@ def lint_py(context: Context, fix: bool = False):
103111
"""Run linters and type checkers"""
104112
if fix:
105113
context.run("ruff --fix .")
114+
context.run("black .")
106115
else:
107116
context.run("ruff .")
108117
context.run("black --check --diff .")
@@ -278,7 +287,9 @@ def get_packages(context: Context) -> dict[str, PackageInfo]:
278287

279288
def make_py_pkg_info(context: Context, pkg_dir: Path) -> PackageInfo:
280289
with context.cd(pkg_dir):
281-
proj_metadata = json.loads(context.run("hatch project metadata").stdout)
290+
proj_metadata = json.loads(
291+
ensure_result(context, "hatch project metadata").stdout
292+
)
282293
return PackageInfo(
283294
name=proj_metadata["name"],
284295
path=pkg_dir,
@@ -321,7 +332,9 @@ def get_current_tags(context: Context) -> set[str]:
321332
line
322333
for line in map(
323334
str.strip,
324-
context.run("git tag --points-at HEAD", hide=True).stdout.splitlines(),
335+
ensure_result(
336+
context, "git tag --points-at HEAD", hide=True
337+
).stdout.splitlines(),
325338
)
326339
if line
327340
}
@@ -410,10 +423,36 @@ def publish(dry_run: bool):
410423

411424
context.run(
412425
"twine upload dist/*",
413-
env_dict={
426+
env={
414427
"TWINE_USERNAME": twine_username,
415428
"TWINE_PASSWORD": twine_password,
416429
},
417430
)
418431

419432
return publish
433+
434+
435+
def install_hatch_project(context: Context, path: Path) -> None:
436+
py_proj_toml = toml.load(path / "pyproject.toml")
437+
hatch_default_env = py_proj_toml["tool"]["hatch"]["envs"].get("default", {})
438+
hatch_default_features = hatch_default_env.get("features", [])
439+
hatch_default_deps = hatch_default_env.get("dependencies", [])
440+
context.run(f"pip install -e '.[{','.join(hatch_default_features)}]'")
441+
context.run(f"pip install {' '.join(map(repr, hatch_default_deps))}")
442+
443+
444+
def install_poetry_project(context: Context, path: Path) -> None:
445+
# install dependencies from poetry into the current environment - not in Poetry's venv
446+
poetry_lock = toml.load(path / "poetry.lock")
447+
packages_to_install = [
448+
f"{package['name']}=={package['version']}" for package in poetry_lock["package"]
449+
]
450+
context.run("pip install -e .")
451+
context.run(f"pip install {' '.join(packages_to_install)}")
452+
453+
454+
def ensure_result(context: Context, *args: Any, **kwargs: Any) -> Result:
455+
result = context.run(*args, **kwargs)
456+
if result is None:
457+
raise Exit("Command failed")
458+
return result

0 commit comments

Comments
 (0)