mirror of
https://github.com/rio-labs/rio.git
synced 2026-02-09 23:29:30 -06:00
329 lines
8.8 KiB
Python
329 lines
8.8 KiB
Python
import textwrap
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from pyfakefs.fake_filesystem import FakeFilesystem, PatchMode
|
|
from pyfakefs.fake_filesystem_unittest import Patcher
|
|
|
|
from rio.cli.run_project.app_loading import load_user_app
|
|
from rio.project_config import RioProjectConfig
|
|
|
|
|
|
# Per default, importing from the fake file system doesn't work. So we must
|
|
# define a custom fixture which enables that.
|
|
@pytest.fixture
|
|
def fs():
|
|
with Patcher(patch_open_code=PatchMode.AUTO) as p:
|
|
yield p.fs
|
|
|
|
|
|
def create_project(
|
|
fs: FakeFilesystem,
|
|
file_hierarchy: str,
|
|
*,
|
|
app_file: str,
|
|
main_module: str,
|
|
) -> RioProjectConfig:
|
|
FILE_CONTENTS_BY_NAME = {
|
|
"foo_page.py": """
|
|
import rio
|
|
|
|
|
|
@rio.page(url_segment='foo-was-loaded-correctly')
|
|
class FooPage(rio.Component):
|
|
def build(self):
|
|
return rio.Text('foo')
|
|
"""
|
|
}
|
|
|
|
file_hierarchy = textwrap.dedent(file_hierarchy).strip()
|
|
|
|
directories_by_indent = {0: Path()}
|
|
rio_toml_location: Path | None = None
|
|
|
|
for line in file_hierarchy.splitlines():
|
|
file_name = line.lstrip()
|
|
indent = (len(line) - len(file_name)) // 4
|
|
directory = directories_by_indent[indent]
|
|
|
|
# Create the file/folder
|
|
if file_name.endswith("/"):
|
|
new_directory = directory / file_name.rstrip("/")
|
|
directories_by_indent[indent + 1] = new_directory
|
|
|
|
# new_directory.mkdir()
|
|
fs.create_dir(new_directory)
|
|
else:
|
|
new_file = directory / file_name
|
|
|
|
fs.create_file(
|
|
new_file, contents=FILE_CONTENTS_BY_NAME.get(file_name, "")
|
|
)
|
|
|
|
if file_name == "rio.toml":
|
|
rio_toml_location = new_file
|
|
|
|
(directories_by_indent[0] / app_file).write_text("""
|
|
import rio
|
|
|
|
app = rio.App(build=rio.Spacer)
|
|
""")
|
|
|
|
assert rio_toml_location is not None
|
|
|
|
return RioProjectConfig(
|
|
file_path=rio_toml_location.absolute(),
|
|
toml_dict={
|
|
"app": {
|
|
"app-type": "website",
|
|
"main-module": main_module,
|
|
}
|
|
},
|
|
dirty_keys=set(),
|
|
)
|
|
|
|
|
|
def test_project_file(fs: FakeFilesystem):
|
|
config = create_project(
|
|
fs,
|
|
"""
|
|
my-project/
|
|
my_app.py
|
|
pages/
|
|
foo_page.py
|
|
rio.toml
|
|
""",
|
|
app_file="my-project/my_app.py",
|
|
main_module="my_app",
|
|
)
|
|
app = load_user_app(config).app
|
|
|
|
assert app.name == "My App"
|
|
assert app.assets_dir == Path("my-project/assets").absolute()
|
|
assert app.pages[0].url_segment == "foo-was-loaded-correctly"
|
|
|
|
|
|
def test_src_folder(fs: FakeFilesystem):
|
|
config = create_project(
|
|
fs,
|
|
"""
|
|
my-project/
|
|
src/
|
|
assets/
|
|
my_app.py
|
|
pages/
|
|
foo_page.py
|
|
rio.toml
|
|
""",
|
|
app_file="my-project/src/my_app.py",
|
|
main_module="my_app",
|
|
)
|
|
app = load_user_app(config).app
|
|
|
|
assert app.name == "My App"
|
|
assert app.assets_dir == Path("my-project/src/assets").absolute()
|
|
assert app.pages[0].url_segment == "foo-was-loaded-correctly"
|
|
|
|
|
|
def test_simple_project_dir(fs: FakeFilesystem):
|
|
config = create_project(
|
|
fs,
|
|
"""
|
|
my-project/
|
|
my_project/
|
|
__init__.py
|
|
assets/
|
|
pages/
|
|
foo_page.py
|
|
rio.toml
|
|
""",
|
|
app_file="my-project/my_project/__init__.py",
|
|
main_module="my_project",
|
|
)
|
|
app = load_user_app(config).app
|
|
|
|
assert app.name == "My Project"
|
|
assert app.assets_dir == Path("my-project/my_project/assets").absolute()
|
|
assert app.pages[0].url_segment == "foo-was-loaded-correctly"
|
|
|
|
|
|
def test_submodule(fs: FakeFilesystem):
|
|
config = create_project(
|
|
fs,
|
|
"""
|
|
my-project/
|
|
my_project/
|
|
__init__.py
|
|
app.py
|
|
assets/
|
|
pages/
|
|
foo_page.py
|
|
rio.toml
|
|
""",
|
|
app_file="my-project/my_project/app.py",
|
|
main_module="my_project.app",
|
|
)
|
|
app = load_user_app(config).app
|
|
|
|
assert app.name == "App"
|
|
assert app.assets_dir == Path("my-project/my_project/assets").absolute()
|
|
assert app.pages[0].url_segment == "foo-was-loaded-correctly"
|
|
|
|
|
|
@pytest.mark.xfail(reason="Waiting for new pyfakefs version to be published")
|
|
def test_import_sibling_module(fs: FakeFilesystem):
|
|
config = create_project(
|
|
fs,
|
|
"""
|
|
my-project/
|
|
foo.py
|
|
bar.py
|
|
rio.toml
|
|
""",
|
|
app_file="my-project/foo.py",
|
|
main_module="bar",
|
|
)
|
|
Path("my-project/bar.py").write_text("""
|
|
# Note: The import statement doesn't work with pyfakefs, so we have to use
|
|
# importlib.
|
|
import importlib
|
|
app = importlib.import_module('foo').app
|
|
""")
|
|
app = load_user_app(config).app
|
|
|
|
assert app.name == "Bar"
|
|
assert app.assets_dir == Path("my-project").absolute()
|
|
assert not app.pages
|
|
|
|
|
|
@pytest.mark.xfail(reason="Waiting for new pyfakefs version to be published")
|
|
def test_import_from_submodule(fs: FakeFilesystem):
|
|
config = create_project(
|
|
fs,
|
|
"""
|
|
my-project/
|
|
my_project/
|
|
__init__.py
|
|
app.py
|
|
assets/
|
|
pages/
|
|
foo_page.py
|
|
helper.py
|
|
rio.toml
|
|
""",
|
|
app_file="my-project/helper.py",
|
|
main_module="my_project.app",
|
|
)
|
|
Path("my-project/my_project/app.py").write_text("""
|
|
# Note: The import statement doesn't work with pyfakefs, so we have to use
|
|
# importlib.
|
|
import importlib
|
|
app = importlib.import_module('helper').app
|
|
""")
|
|
app = load_user_app(config).app
|
|
|
|
assert app.name == "App"
|
|
assert app.assets_dir == Path("my-project/my_project/assets").absolute()
|
|
assert app.pages[0].url_segment == "foo-was-loaded-correctly"
|
|
|
|
|
|
@pytest.mark.xfail(reason="Waiting for new pyfakefs version to be published")
|
|
def test_relative_import_from_pages(fs: FakeFilesystem):
|
|
config = create_project(
|
|
fs,
|
|
"""
|
|
my-project/
|
|
my_project/
|
|
__init__.py
|
|
app.py
|
|
assets/
|
|
pages/
|
|
fancy_page.py
|
|
rio.toml
|
|
""",
|
|
app_file="my-project/my_project/app.py",
|
|
main_module="my_project.app",
|
|
)
|
|
Path("my-project/my_project/pages/fancy_page.py").write_text("""
|
|
# Note: The import statement doesn't work with pyfakefs, so we have to use
|
|
# importlib.
|
|
import importlib.util
|
|
app_module = importlib.import_module(importlib.util.resolve_name('..app', __package__))
|
|
_ = app_module.app # Just to make sure the right file was imported
|
|
|
|
|
|
import rio
|
|
|
|
@rio.page(url_segment='fancy-page-was-loaded-correctly')
|
|
class FancyPage(rio.Component):
|
|
def build(self):
|
|
return rio.Text('fancy')
|
|
""")
|
|
app = load_user_app(config).app
|
|
|
|
assert app.name == "App"
|
|
assert app.assets_dir == Path("my-project/my_project/assets").absolute()
|
|
assert app.pages[0].url_segment == "fancy-page-was-loaded-correctly"
|
|
|
|
|
|
def test_relative_paths_with_module(fs: FakeFilesystem):
|
|
config = create_project(
|
|
fs,
|
|
"""
|
|
my-project/
|
|
my_app.py
|
|
my/
|
|
assets/
|
|
pages/
|
|
foo_page.py
|
|
rio.toml
|
|
""",
|
|
app_file="my-project/my_app.py",
|
|
main_module="my_app",
|
|
)
|
|
Path("my-project/my_app.py").write_text("""
|
|
import rio
|
|
|
|
app = rio.App(
|
|
build=rio.Spacer,
|
|
assets_dir='my/assets',
|
|
pages='my/pages',
|
|
)
|
|
""")
|
|
app = load_user_app(config).app
|
|
|
|
assert app.name == "My App"
|
|
assert app.assets_dir == Path("my-project/my/assets").absolute()
|
|
assert app.pages[0].url_segment == "foo-was-loaded-correctly"
|
|
|
|
|
|
def test_relative_paths_with_package(fs: FakeFilesystem):
|
|
config = create_project(
|
|
fs,
|
|
"""
|
|
my-project/
|
|
my_project/
|
|
__init__.py
|
|
my/
|
|
pages/
|
|
foo_page.py
|
|
rio.toml
|
|
""",
|
|
app_file="my-project/my_project/__init__.py",
|
|
main_module="my_project",
|
|
)
|
|
Path("my-project/my_project/__init__.py").write_text("""
|
|
import rio
|
|
|
|
app = rio.App(
|
|
build=rio.Spacer,
|
|
assets_dir='my/assets',
|
|
pages='my/pages',
|
|
)
|
|
""")
|
|
app = load_user_app(config).app
|
|
|
|
assert app.name == "My Project"
|
|
assert app.assets_dir == Path("my-project/my_project/my/assets").absolute()
|
|
assert app.pages[0].url_segment == "foo-was-loaded-correctly"
|