diff --git a/.gitignore b/.gitignore index 20c041e11..946bff43f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ .jupyter # --- Python --- +.hatch .venv venv MANIFEST diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e4a66f532..ae748a41d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,15 +3,9 @@ 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 - repo: local hooks: @@ -20,6 +14,13 @@ repos: entry: hatch run lint-js --fix language: system pass_filenames: false + - repo: local + hooks: + - id: lint-py-check + name: Check Python Lint + entry: hatch run lint-py + language: system + pass_filenames: false - repo: local hooks: - id: lint-js-check diff --git a/docs/pyproject.toml b/docs/pyproject.toml index d2f47c577..f47b0e944 100644 --- a/docs/pyproject.toml +++ b/docs/pyproject.toml @@ -1,5 +1,5 @@ [tool.poetry] -name = "docs" +name = "docs_app" version = "0.0.0" description = "docs" authors = ["rmorshea "] diff --git a/docs/source/_exts/reactpy_example.py b/docs/source/_exts/reactpy_example.py index c6b054c07..1171d32e0 100644 --- a/docs/source/_exts/reactpy_example.py +++ b/docs/source/_exts/reactpy_example.py @@ -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, @@ -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, } diff --git a/docs/source/_exts/reactpy_view.py b/docs/source/_exts/reactpy_view.py index 7a2bf85a4..6a583998f 100644 --- a/docs/source/_exts/reactpy_view.py +++ b/docs/source/_exts/reactpy_view.py @@ -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 @@ -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, } diff --git a/docs/source/about/contributor-guide.rst b/docs/source/about/contributor-guide.rst index b44be9b7e..f9fb93154 100644 --- a/docs/source/about/contributor-guide.rst +++ b/docs/source/about/contributor-guide.rst @@ -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 ----------------- @@ -308,6 +328,8 @@ you should refer to their respective documentation in the links below: .. 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 diff --git a/src/py/reactpy/reactpy/core/events.py b/src/py/reactpy/reactpy/core/events.py index acc2077b2..cd5de3228 100644 --- a/src/py/reactpy/reactpy/core/events.py +++ b/src/py/reactpy/reactpy/core/events.py @@ -21,7 +21,7 @@ def event( @overload def event( - function: Literal[None] = None, + function: Literal[None] = ..., *, stop_propagation: bool = ..., prevent_default: bool = ..., diff --git a/src/py/reactpy/reactpy/core/layout.py b/src/py/reactpy/reactpy/core/layout.py index 7c24e5ef7..df24a9a0a 100644 --- a/src/py/reactpy/reactpy/core/layout.py +++ b/src/py/reactpy/reactpy/core/layout.py @@ -37,16 +37,16 @@ class Layout: """Responsible for "rendering" components. That is, turning them into VDOM.""" - __slots__ = [ + __slots__: tuple[str, ...] = ( "root", "_event_handlers", "_rendering_queue", "_root_life_cycle_state_id", "_model_states_by_life_cycle_state_id", - ] + ) if not hasattr(abc.ABC, "__weakref__"): # nocov - __slots__.append("__weakref__") + __slots__ += ("__weakref__",) def __init__(self, root: ComponentType) -> None: super().__init__() diff --git a/tasks.py b/tasks.py index 4bbfe52e2..1fcd3c0a3 100644 --- a/tasks.py +++ b/tasks.py @@ -77,14 +77,21 @@ def env(context: Context): @task def env_py(context: Context): """Install Python development environment""" - for py_proj in PY_PROJECTS: - py_proj_toml = toml.load(py_proj / "pyproject.toml") - hatch_default_env = py_proj_toml["tool"]["hatch"]["envs"].get("default", {}) - hatch_default_features = hatch_default_env.get("features", []) - hatch_default_deps = hatch_default_env.get("dependencies", []) + for py_proj in [ + DOCS_DIR, + # Docs installs non-editable versions of packages - ensure + # we overwrite that by installing projects afterwards. + *PY_PROJECTS, + ]: + py_proj_toml_tools = toml.load(py_proj / "pyproject.toml")["tool"] + if "hatch" in py_proj_toml_tools: + install_func = install_hatch_project + elif "poetry" in py_proj_toml_tools: + install_func = install_poetry_project + else: + raise Exit(f"Unknown project type: {py_proj}") with context.cd(py_proj): - context.run(f"pip install '.[{','.join(hatch_default_features)}]'") - context.run(f"pip install {' '.join(map(repr, hatch_default_deps))}") + install_func(context, py_proj) @task @@ -103,6 +110,7 @@ def lint_py(context: Context, fix: bool = False): """Run linters and type checkers""" if fix: context.run("ruff --fix .") + context.run("black .") else: context.run("ruff .") context.run("black --check --diff .") @@ -417,3 +425,22 @@ def publish(dry_run: bool): ) return publish + + +def install_hatch_project(context: Context, path: Path) -> None: + py_proj_toml = toml.load(path / "pyproject.toml") + hatch_default_env = py_proj_toml["tool"]["hatch"]["envs"].get("default", {}) + hatch_default_features = hatch_default_env.get("features", []) + hatch_default_deps = hatch_default_env.get("dependencies", []) + context.run(f"pip install -e '.[{','.join(hatch_default_features)}]'") + context.run(f"pip install {' '.join(map(repr, hatch_default_deps))}") + + +def install_poetry_project(context: Context, path: Path) -> None: + # install dependencies from poetry into the current environment - not in Poetry's venv + poetry_lock = toml.load(path / "poetry.lock") + packages_to_install = [ + f"{package['name']}=={package['version']}" for package in poetry_lock["package"] + ] + context.run("pip install -e .") + context.run(f"pip install {' '.join(packages_to_install)}")