widgetti / solara

A Pure Python, React-style Framework for Scaling Your Jupyter and Web Apps
https://solara.dev
MIT License
1.89k stars 138 forks source link

__future__ annotations import and dataclass in multipage projects gives AttributeError #489

Open langestefan opened 8 months ago

langestefan commented 8 months ago

This is #208, but the issue still appears in multi-page projects.

I am on the latest version 1.25.1.

log ```python (project-name-py3.12) vscode ➜ /workspaces/pvcast-frontend (solara) $ solara run test Solara server is starting at http://localhost:8765 Traceback (most recent call last): File "/workspaces/pvcast-frontend/.venv/bin/solara", line 8, in sys.exit(main()) ^^^^^^ File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/solara/__main__.py", line 706, in main cli() File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/click/core.py", line 1157, in __call__ return self.main(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/rich_click/rich_command.py", line 126, in main rv = self.invoke(ctx) ^^^^^^^^^^^^^^^^ File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/click/core.py", line 1688, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/click/core.py", line 1434, in invoke return ctx.invoke(self.callback, **ctx.params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/click/core.py", line 783, in invoke return __callback(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/solara/__main__.py", line 428, in run start_server() File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/solara/__main__.py", line 400, in start_server server.run() File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/uvicorn/server.py", line 62, in run return asyncio.run(self.serve(sockets=sockets)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/asyncio/runners.py", line 194, in run return runner.run(main) ^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/asyncio/runners.py", line 118, in run return self._loop.run_until_complete(task) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/asyncio/base_events.py", line 684, in run_until_complete return future.result() ^^^^^^^^^^^^^^^ File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/uvicorn/server.py", line 69, in serve config.load() File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/uvicorn/config.py", line 458, in load self.loaded_app = import_from_string(self.app) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/uvicorn/importer.py", line 21, in import_from_string module = importlib.import_module(module_str) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/importlib/__init__.py", line 90, in import_module return _bootstrap._gcd_import(name[level:], package, level) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "", line 1387, in _gcd_import File "", line 1360, in _find_and_load File "", line 1331, in _find_and_load_unlocked File "", line 935, in _load_unlocked File "", line 994, in exec_module File "", line 488, in _call_with_frames_removed File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/solara/server/starlette.py", line 47, in from . import app as appmod File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/solara/server/app.py", line 407, in apps["__default__"] = AppScript(os.environ.get("SOLARA_APP", "solara.website.pages:Page")) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/solara/server/app.py", line 69, in __init__ app = self._execute() ^^^^^^^^^^^^^^^ File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/solara/server/app.py", line 97, in _execute routes = solara.generate_routes_directory(self.path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/solara/autorouting.py", line 475, in generate_routes_directory route = _generate_route_path(subpath, layout=layout, first=first, has_index=has_index) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/solara/autorouting.py", line 507, in _generate_route_path module = source_to_module(subpath, initial_namespace=initial_namespace) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/workspaces/pvcast-frontend/.venv/lib/python3.12/site-packages/solara/autorouting.py", line 37, in source_to_module exec(ast, mod.__dict__) File "/workspaces/pvcast-frontend/test/sol.py", line 9, in @dataclass(frozen=True) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/dataclasses.py", line 1256, in wrap return _process_class(cls, init, repr, eq, order, unsafe_hash, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/dataclasses.py", line 983, in _process_class and _is_type(type, cls, dataclasses, dataclasses.KW_ONLY, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/dataclasses.py", line 749, in _is_type ns = sys.modules.get(cls.__module__).__dict__ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute '__dict__'. Did you mean: '__dir__'? ```

How to reproduce:

  1. Create a folder to hold your pages, for example test
  2. Create the file test/sol.py:
    
    from __future__ import annotations
    from typing import Optional

from dataclasses import dataclass, field import solara

@dataclass(frozen=True) class FilterItem: name: str min: Optional[float] = field(default=None) max: Optional[float] = field(default=None)

@solara.component def Page(): solara.Markdown("## Foobar")


3. Run `solara run test`
maartenbreddels commented 7 months ago

I am not sure we can fix this (but will keep this open). The workaround would be to run as a package. e.g.

solara run mypackage.pages