From 981db20f121608aed83af0c4de801fa10ac82d9f Mon Sep 17 00:00:00 2001 From: DeleMike Date: Mon, 24 Jul 2023 16:42:47 +0100 Subject: [PATCH 01/12] generate routes from the app_directory/pages, we generate in the generated dist folder, another folder called 'pages' where we all our generated routes will stored --- starfyre/__main__.py | 8 +++++ starfyre/router.py | 58 +++++++++++++++++++++++++++++++ test-application/pages/about.fyre | 0 test-application/pages/home.fyre | 0 4 files changed, 66 insertions(+) create mode 100644 starfyre/router.py create mode 100644 test-application/pages/about.fyre create mode 100644 test-application/pages/home.fyre diff --git a/starfyre/__main__.py b/starfyre/__main__.py index 6f23386..9b06c06 100644 --- a/starfyre/__main__.py +++ b/starfyre/__main__.py @@ -1,5 +1,7 @@ from starfyre import compile from pathlib import Path +from .router import Router + import sys import os import shutil @@ -76,7 +78,13 @@ def main(path, build): init_file_path = absolute_path / "__init__.py" compile(init_file_path.resolve()) + # At this point, the project has been compiled and the build directory has been created. + # Now, initialize the Router object and use it to handle file-based routing. + + router = Router(absolute_path / "pages") + router.generate_routes() + # But there is no main file in the build directory. create_main_file(str(absolute_path)) diff --git a/starfyre/router.py b/starfyre/router.py new file mode 100644 index 0000000..0564193 --- /dev/null +++ b/starfyre/router.py @@ -0,0 +1,58 @@ +import os +from pathlib import Path + +class Router: + """ + A router that handles file-based routing. + + This router parses the specified pages directory to automatically generate routes based on + the file names. Each file in the pages directory is treated as a separate route, and the + component name is derived from the file name. The routes and their corresponding component + names are stored in a dictionary. + + Parameters: + pages_directory (str): The path to the directory containing the pages files. + Example: + pages_directory = "test_app/pages" + file_router = FileBasedRouter(pages_directory) + """ + + def __init__(self, pages_directory): + super().__init__() + self.pages_directory = pages_directory + self.generate_routes() + print(f'Number of files in "pages" directory is: {len(os.listdir(self.pages_directory))}') + + def generate_routes(self): + """ + Parse the "pages" directory to generate routes. + + This method iterates through each file in the pages directory and adds a new route + to the routes dictionary. The route is derived from the file name, and the component + name is derived from the file name by converting it to title case. + + Example: + If there is a file named "home.fyre" in the test-application/pages directory, the router will + add a route "/home.html". + + Note: + This method is automatically called when the Router is initialized. + """ + for file_name in os.listdir(self.pages_directory): + if file_name.endswith(".fyre"): + route_name = file_name.replace(".fyre", "").lower() + route_path = f"/{route_name}" + print(f'Found file: {file_name} and we have generated this path: {route_path} with name: {route_name}') + + # use this to generate the respective html files in the app's ./pages folder + print(f' dir: {self.pages_directory}') + root_directory = Path(self.pages_directory ) / ".." / "dist/pages" + if not root_directory.exists(): + root_directory.mkdir() + + html_file_path = root_directory / f'{route_name}.html' + print(f'File path for {route_name} is = {html_file_path}') + html_file_path.touch() + + + diff --git a/test-application/pages/about.fyre b/test-application/pages/about.fyre new file mode 100644 index 0000000..e69de29 diff --git a/test-application/pages/home.fyre b/test-application/pages/home.fyre new file mode 100644 index 0000000..e69de29 From ff4929c1f154932a1b505b5fd9d5ddad1450fa99 Mon Sep 17 00:00:00 2001 From: DeleMike Date: Wed, 26 Jul 2023 16:02:18 +0100 Subject: [PATCH 02/12] feat(compiler.py-router.py): generate python build code for user defined routes --- poetry.lock | 577 ++++++++++++++++------- pyproject.toml | 1 + starfyre/__main__.py | 9 +- starfyre/compiler.py | 11 +- starfyre/exceptions.py | 3 +- starfyre/file_router.py | 88 ++++ starfyre/router.py | 58 --- test-application/pages/css_file_test.css | 3 + test-application/pages/home.fyre | 8 + 9 files changed, 533 insertions(+), 225 deletions(-) create mode 100644 starfyre/file_router.py delete mode 100644 starfyre/router.py create mode 100644 test-application/pages/css_file_test.css diff --git a/poetry.lock b/poetry.lock index 5100b1f..b54415b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,158 +1,26 @@ -[[package]] -name = "black" -version = "23.3.0" -description = "The uncompromising code formatter." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] -name = "certifi" -version = "2022.12.7" -description = "Python package for providing Mozilla's CA Bundle." -category = "main" +name = "argcomplete" +version = "3.1.1" +description = "Bash tab completion for argparse" optional = false python-versions = ">=3.6" - -[[package]] -name = "charset-normalizer" -version = "3.1.0" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" -optional = false -python-versions = ">=3.7.0" - -[[package]] -name = "click" -version = "8.1.3" -description = "Composable command line interface toolkit" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" - -[[package]] -name = "idna" -version = "3.4" -description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "packaging" -version = "23.1" -description = "Core utilities for Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "pathspec" -version = "0.11.1" -description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "platformdirs" -version = "3.5.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] - -[[package]] -name = "requests" -version = "2.29.0" -description = "Python HTTP for Humans." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" +files = [ + {file = "argcomplete-3.1.1-py3-none-any.whl", hash = "sha256:35fa893a88deea85ea7b20d241100e64516d6af6d7b0ae2bed1d263d26f70948"}, + {file = "argcomplete-3.1.1.tar.gz", hash = "sha256:6c4c563f14f01440aaffa3eae13441c5db2357b5eec639abe7c0b15334627dff"}, +] [package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "ruff" -version = "0.0.263" -description = "An extremely fast Python linter, written in Rust." -category = "dev" -optional = false -python-versions = ">=3.7" +test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] [[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -category = "dev" +name = "black" +version = "23.3.0" +description = "The uncompromising code formatter." optional = false python-versions = ">=3.7" - -[[package]] -name = "urllib3" -version = "1.26.15" -description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] - -[metadata] -lock-version = "1.1" -python-versions = "^3.10" -content-hash = "450062d8e9e13f4fd5d9addd62f06b4c8845954762c65177a42d0ba9d6e96201" - -[metadata.files] -black = [ +files = [ {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"}, {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"}, {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"}, @@ -179,11 +47,39 @@ black = [ {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"}, {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"}, ] -certifi = [ + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "certifi" +version = "2022.12.7" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, ] -charset-normalizer = [ + +[[package]] +name = "charset-normalizer" +version = "3.1.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, @@ -260,39 +156,329 @@ charset-normalizer = [ {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, ] -click = [ + +[[package]] +name = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, ] -colorama = [ + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -idna = [ + +[[package]] +name = "commitizen" +version = "3.5.3" +description = "Python commitizen client tool" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "commitizen-3.5.3-py3-none-any.whl", hash = "sha256:f5c1290278aa3ee19915dc6a8480f6c4db25c90827e61f70f8fc03b648850029"}, + {file = "commitizen-3.5.3.tar.gz", hash = "sha256:6f5a3536d1cf17580b82ed16643b5754efb1079fcb4de1bc6de8245d8e2cc6a9"}, +] + +[package.dependencies] +argcomplete = ">=1.12.1,<3.2" +charset-normalizer = ">=2.1.0,<4" +colorama = ">=0.4.1,<0.5.0" +decli = ">=0.6.0,<0.7.0" +importlib_metadata = ">=4.13,<7" +jinja2 = ">=2.10.3" +packaging = ">=19" +pyyaml = ">=3.08" +questionary = ">=1.4.0,<2.0.0" +termcolor = ">=1.1,<3" +tomlkit = ">=0.5.3,<1.0.0" + +[[package]] +name = "decli" +version = "0.6.1" +description = "Minimal, easy-to-use, declarative cli tool" +optional = false +python-versions = ">=3.7" +files = [ + {file = "decli-0.6.1-py3-none-any.whl", hash = "sha256:7815ac58617764e1a200d7cadac6315fcaacc24d727d182f9878dd6378ccf869"}, + {file = "decli-0.6.1.tar.gz", hash = "sha256:ed88ccb947701e8e5509b7945fda56e150e2ac74a69f25d47ac85ef30ab0c0f0"}, +] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] -mypy-extensions = [ + +[[package]] +name = "importlib-metadata" +version = "6.8.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "jinja2" +version = "3.1.2" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "markupsafe" +version = "2.1.3" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] -packaging = [ + +[[package]] +name = "packaging" +version = "23.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, ] -pathspec = [ + +[[package]] +name = "pathspec" +version = "0.11.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, ] -platformdirs = [ + +[[package]] +name = "platformdirs" +version = "3.5.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.7" +files = [ {file = "platformdirs-3.5.0-py3-none-any.whl", hash = "sha256:47692bc24c1958e8b0f13dd727307cff1db103fca36399f457da8e05f222fdc4"}, {file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"}, ] -requests = [ + +[package.extras] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] + +[[package]] +name = "prompt-toolkit" +version = "3.0.39" +description = "Library for building powerful interactive command lines in Python" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "prompt_toolkit-3.0.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"}, + {file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"}, +] + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "questionary" +version = "1.10.0" +description = "Python library to build pretty command line user prompts ⭐️" +optional = false +python-versions = ">=3.6,<4.0" +files = [ + {file = "questionary-1.10.0-py3-none-any.whl", hash = "sha256:fecfcc8cca110fda9d561cb83f1e97ecbb93c613ff857f655818839dac74ce90"}, + {file = "questionary-1.10.0.tar.gz", hash = "sha256:600d3aefecce26d48d97eee936fdb66e4bc27f934c3ab6dd1e292c4f43946d90"}, +] + +[package.dependencies] +prompt_toolkit = ">=2.0,<4.0" + +[package.extras] +docs = ["Sphinx (>=3.3,<4.0)", "sphinx-autobuild (>=2020.9.1,<2021.0.0)", "sphinx-autodoc-typehints (>=1.11.1,<2.0.0)", "sphinx-copybutton (>=0.3.1,<0.4.0)", "sphinx-rtd-theme (>=0.5.0,<0.6.0)"] + +[[package]] +name = "requests" +version = "2.29.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ {file = "requests-2.29.0-py3-none-any.whl", hash = "sha256:e8f3c9be120d3333921d213eef078af392fba3933ab7ed2d1cba3b56f2568c3b"}, {file = "requests-2.29.0.tar.gz", hash = "sha256:f2e34a75f4749019bb0e3effb66683630e4ffeaf75819fb51bebef1bf5aef059"}, ] -ruff = [ + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "ruff" +version = "0.0.263" +description = "An extremely fast Python linter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ {file = "ruff-0.0.263-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:ee6c7a77f142c427fa73e1f5f603fc1a39413a36fe6966ed0fc55e97f6921d9c"}, {file = "ruff-0.0.263-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c3b7d4b365207f3e4c40d235127091478e595b31e35b6cd57d940920cdfae68b"}, {file = "ruff-0.0.263-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebc778d95f29c9917e6e7608b2b67815707e6ab8eb5af9341617beda479c3edf"}, @@ -311,11 +497,86 @@ ruff = [ {file = "ruff-0.0.263-py3-none-win_arm64.whl", hash = "sha256:ddf4503595b560bfa5fae92fa2e4cb09ec465ee4cf88cc248f10ad2e956deec3"}, {file = "ruff-0.0.263.tar.gz", hash = "sha256:1008f211ad8aa1d998517ac5bf3d68fbc68ec516d1da89b6081f25ff2f30b687"}, ] -tomli = [ + +[[package]] +name = "termcolor" +version = "2.3.0" +description = "ANSI color formatting for output in terminal" +optional = false +python-versions = ">=3.7" +files = [ + {file = "termcolor-2.3.0-py3-none-any.whl", hash = "sha256:3afb05607b89aed0ffe25202399ee0867ad4d3cb4180d98aaf8eefa6a5f7d475"}, + {file = "termcolor-2.3.0.tar.gz", hash = "sha256:b5b08f68937f138fe92f6c089b99f1e2da0ae56c52b78bf7075fd95420fd9a5a"}, +] + +[package.extras] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] -urllib3 = [ + +[[package]] +name = "tomlkit" +version = "0.11.8" +description = "Style preserving TOML library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, + {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, +] + +[[package]] +name = "urllib3" +version = "1.26.15" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, ] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "wcwidth" +version = "0.2.6" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, + {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, +] + +[[package]] +name = "zipp" +version = "3.16.2" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"}, + {file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.10" +content-hash = "aeb84cb0716b4f597eb38527061e80c3b295fedbee3eb00213f1c068d2a132d2" diff --git a/pyproject.toml b/pyproject.toml index 5f2a50c..0cc7c43 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ requests = "^2.29.0" [tool.poetry.group.dev.dependencies] ruff = "^0.0.263" black = "^23.3.0" +commitizen = "^3.5.3" [build-system] requires = ["poetry-core"] diff --git a/starfyre/__main__.py b/starfyre/__main__.py index 9b06c06..a4bbfa9 100644 --- a/starfyre/__main__.py +++ b/starfyre/__main__.py @@ -1,6 +1,6 @@ from starfyre import compile from pathlib import Path -from .router import Router +from .file_router import FileRouter import sys import os @@ -76,18 +76,17 @@ def main(path, build): if build: # Compile and build project init_file_path = absolute_path / "__init__.py" - + # Note: The routes specified in the pages folder will have generated code in the build directory. compile(init_file_path.resolve()) # At this point, the project has been compiled and the build directory has been created. # Now, initialize the Router object and use it to handle file-based routing. - - router = Router(absolute_path / "pages") + # Basically, generate the html files for the routes + router = FileRouter(absolute_path / "pages") router.generate_routes() # But there is no main file in the build directory. create_main_file(str(absolute_path)) - # Start/run project subprocess.run( [sys.executable, "-m", "build"], diff --git a/starfyre/compiler.py b/starfyre/compiler.py index af66a4b..97d250e 100644 --- a/starfyre/compiler.py +++ b/starfyre/compiler.py @@ -5,9 +5,14 @@ def get_fyre_files(project_dir): fyre_files = [] - for file in os.listdir(project_dir): - if file.endswith(".fyre"): - fyre_files.append(file) + for entry in os.listdir(project_dir): + if entry.endswith(".fyre"): + fyre_files.append(entry) + # check inside the 'pages' folder + if entry == 'pages': + for file_ in os.listdir(project_dir / "pages"): + if file_.endswith(".fyre"): + fyre_files.append(f'pages/{file_}') return fyre_files diff --git a/starfyre/exceptions.py b/starfyre/exceptions.py index accab1f..bdc331f 100644 --- a/starfyre/exceptions.py +++ b/starfyre/exceptions.py @@ -16,4 +16,5 @@ class UnknownTagError(Exception): Attributes: message (str): A description of the error. """ - pass \ No newline at end of file + def __init__(self, message='Unknown tag found.'): + super().__init__(message) \ No newline at end of file diff --git a/starfyre/file_router.py b/starfyre/file_router.py new file mode 100644 index 0000000..680a47d --- /dev/null +++ b/starfyre/file_router.py @@ -0,0 +1,88 @@ +from starfyre import compile + +import os +from pathlib import Path + + +class FileRouter: + """ + A router that handles file-based routing. + + This router parses the specified pages directory to automatically generate routes based on + the file names. Each file in the pages directory is treated as a separate route, and the + component name is derived from the file name. The routes and their corresponding component + names are stored in a dictionary. + + Parameters: + pages_directory (str): The path to the directory containing the pages files. + Example: + pages_directory = "test_app/pages" + file_router = FileBasedRouter(pages_directory) + """ + + def __init__(self, pages_directory): + self.pages_directory = pages_directory + + + def generate_routes(self): + """ + Generate route + """ + routes = [] + print(f'Router: Absolute Path = {self.pages_directory}') + dist_dir = Path(self.pages_directory / ".." / "dist").resolve() + print(f'Directory to write to: {dist_dir}') + if not dist_dir.exists(): + dist_dir.mkdir() + + # get file names in the "pages" directory + for file_name in os.listdir(self.pages_directory): + if file_name.endswith(".fyre"): + route_name = file_name.replace(".fyre", "").lower() + routes.append(route_name) + print(f'Found fyre file: New route will be = {route_name}') + print(f'file path for route is = {dist_dir}/{route_name}.html') + + # read the contents from the generated python files + _generate_output(self, generated_routes=routes, out_dir=dist_dir) + + +def _generate_output(self, generated_routes, out_dir): + """ + Send the output of `render_root(component)` to route html file + """ + # build_dir = Path(self.pages_directory / ".." / "build").resolve() + + # # print(f'build directory = {build_dir}') + # import_lines = [] + # separator_line = '\n\n# ---------- functions call ---------\n\n' + # body_lines = [] + # export_section = '' + + # for file_ in os.listdir(build_dir): + # file_name = file_.replace(".py", "") + + # if file_name in generated_routes: + # print(f'Generated python file: {file_} is defined as a route') + + # # # create a build/route_generator.py file + # # route_gen_file_path = build_dir / "route_generator.py" + # # print(f"Route generator file:{route_gen_file_path}") + + # import_lines.append(f'from .{file_name} import {file_name}') + # body_lines.append(f'{file_name}') + + # # form file content + # import_section = "\n".join(import_lines) + # initial_body = 'def create_routes():' + # for func in body_lines: + # initial_body +=f""" + # {func}""" + + # initial_body += """ + # return + # """ + # main_content = import_section + separator_line + initial_body + # main_content += '\n\nrouter=create_routes()' + # print(main_content) + pass \ No newline at end of file diff --git a/starfyre/router.py b/starfyre/router.py deleted file mode 100644 index 0564193..0000000 --- a/starfyre/router.py +++ /dev/null @@ -1,58 +0,0 @@ -import os -from pathlib import Path - -class Router: - """ - A router that handles file-based routing. - - This router parses the specified pages directory to automatically generate routes based on - the file names. Each file in the pages directory is treated as a separate route, and the - component name is derived from the file name. The routes and their corresponding component - names are stored in a dictionary. - - Parameters: - pages_directory (str): The path to the directory containing the pages files. - Example: - pages_directory = "test_app/pages" - file_router = FileBasedRouter(pages_directory) - """ - - def __init__(self, pages_directory): - super().__init__() - self.pages_directory = pages_directory - self.generate_routes() - print(f'Number of files in "pages" directory is: {len(os.listdir(self.pages_directory))}') - - def generate_routes(self): - """ - Parse the "pages" directory to generate routes. - - This method iterates through each file in the pages directory and adds a new route - to the routes dictionary. The route is derived from the file name, and the component - name is derived from the file name by converting it to title case. - - Example: - If there is a file named "home.fyre" in the test-application/pages directory, the router will - add a route "/home.html". - - Note: - This method is automatically called when the Router is initialized. - """ - for file_name in os.listdir(self.pages_directory): - if file_name.endswith(".fyre"): - route_name = file_name.replace(".fyre", "").lower() - route_path = f"/{route_name}" - print(f'Found file: {file_name} and we have generated this path: {route_path} with name: {route_name}') - - # use this to generate the respective html files in the app's ./pages folder - print(f' dir: {self.pages_directory}') - root_directory = Path(self.pages_directory ) / ".." / "dist/pages" - if not root_directory.exists(): - root_directory.mkdir() - - html_file_path = root_directory / f'{route_name}.html' - print(f'File path for {route_name} is = {html_file_path}') - html_file_path.touch() - - - diff --git a/test-application/pages/css_file_test.css b/test-application/pages/css_file_test.css new file mode 100644 index 0000000..5742530 --- /dev/null +++ b/test-application/pages/css_file_test.css @@ -0,0 +1,3 @@ +.import_test { + padding-top: 10%; + } \ No newline at end of file diff --git a/test-application/pages/home.fyre b/test-application/pages/home.fyre index e69de29..52b7855 100644 --- a/test-application/pages/home.fyre +++ b/test-application/pages/home.fyre @@ -0,0 +1,8 @@ +import "./css_file_test.css" + +def mocked_request(): + return "fetched on the server" + + +

Hello, World!

+
From 29d312a5cfe2eae2c217ffc019a2b076af6472b5 Mon Sep 17 00:00:00 2001 From: DeleMike Date: Fri, 28 Jul 2023 13:32:46 +0100 Subject: [PATCH 03/12] send output of render into generated html file --- starfyre/file_router.py | 120 +++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 51 deletions(-) diff --git a/starfyre/file_router.py b/starfyre/file_router.py index 680a47d..921137c 100644 --- a/starfyre/file_router.py +++ b/starfyre/file_router.py @@ -1,7 +1,9 @@ -from starfyre import compile +from starfyre import create_component, render import os +import sys from pathlib import Path +import importlib class FileRouter: @@ -9,15 +11,13 @@ class FileRouter: A router that handles file-based routing. This router parses the specified pages directory to automatically generate routes based on - the file names. Each file in the pages directory is treated as a separate route, and the - component name is derived from the file name. The routes and their corresponding component - names are stored in a dictionary. + the file names. Each file in the pages directory is treated as a separate route. Parameters: pages_directory (str): The path to the directory containing the pages files. Example: - pages_directory = "test_app/pages" - file_router = FileBasedRouter(pages_directory) + pages_directory = "test-application/pages" + file_router = FileRouter(pages_directory) """ def __init__(self, pages_directory): @@ -26,12 +26,29 @@ def __init__(self, pages_directory): def generate_routes(self): """ - Generate route + Generate routes and create corresponding HTML files. + + This method generates routes based on the file names in the specified pages directory. Each file in the + pages directory with a ".fyre" extension is considered a separate route. The route names are derived from + the file names by removing the ".fyre" extension and converting the names to lowercase. + + The generated route names are stored in a list, and corresponding HTML files are created in the specified + "dist" directory. The HTML files are created by transpiling the components using the `_build_output` method. + + Note: + - This method should be called after initializing the `FileRouter` object. + - The `_build_output` method is responsible for generating the HTML files. + + Example: + pages_directory = "test_app/pages" + router = FileRouter(pages_directory) + router.generate_routes() # This generates the routes and corresponding HTML files. + + Raises: + FileNotFoundError: If the specified pages directory does not exist. """ routes = [] - print(f'Router: Absolute Path = {self.pages_directory}') dist_dir = Path(self.pages_directory / ".." / "dist").resolve() - print(f'Directory to write to: {dist_dir}') if not dist_dir.exists(): dist_dir.mkdir() @@ -40,49 +57,50 @@ def generate_routes(self): if file_name.endswith(".fyre"): route_name = file_name.replace(".fyre", "").lower() routes.append(route_name) - print(f'Found fyre file: New route will be = {route_name}') - print(f'file path for route is = {dist_dir}/{route_name}.html') + # print(f'Found fyre file: New route will be = {route_name}') + # print(f'file path for route is = {dist_dir}/{route_name}.html') # read the contents from the generated python files - _generate_output(self, generated_routes=routes, out_dir=dist_dir) + self._build_output(generated_routes=routes, out_dir=dist_dir) -def _generate_output(self, generated_routes, out_dir): - """ - Send the output of `render_root(component)` to route html file - """ - # build_dir = Path(self.pages_directory / ".." / "build").resolve() - - # # print(f'build directory = {build_dir}') - # import_lines = [] - # separator_line = '\n\n# ---------- functions call ---------\n\n' - # body_lines = [] - # export_section = '' - - # for file_ in os.listdir(build_dir): - # file_name = file_.replace(".py", "") - - # if file_name in generated_routes: - # print(f'Generated python file: {file_} is defined as a route') - - # # # create a build/route_generator.py file - # # route_gen_file_path = build_dir / "route_generator.py" - # # print(f"Route generator file:{route_gen_file_path}") - - # import_lines.append(f'from .{file_name} import {file_name}') - # body_lines.append(f'{file_name}') - - # # form file content - # import_section = "\n".join(import_lines) - # initial_body = 'def create_routes():' - # for func in body_lines: - # initial_body +=f""" - # {func}""" - - # initial_body += """ - # return - # """ - # main_content = import_section + separator_line + initial_body - # main_content += '\n\nrouter=create_routes()' - # print(main_content) - pass \ No newline at end of file + def _build_output(self, generated_routes, out_dir): + """ + Transpile the output of `render(component)` to route HTML files. + + This method takes a list of generated routes and an output directory and transpiles the components + using `render(component)`. The resulting components are then written to corresponding HTML files + in the output directory. + + Parameters: + generated_routes (list): A list of route names (strings) generated from the pages directory. + out_dir (str): The path to the output directory where the HTML files will be written. + + Example: + pages_directory = "test_app/pages" + router = FileRouter(pages_directory) + router.generate_routes() # This generates the `generated_routes` list. + out_directory = "test_app/dist" + router._build_output(generated_routes, out_directory) + """ + print(f'Generated routes: {generated_routes}') + + root = Path(out_dir / "..").resolve() + app_name = (str(root).split('/'))[-1] # get the user defined project name + + for route_name in generated_routes: + # Get the module name dynamically based on the route_name + module_name = f"{Path(app_name)}.build.{route_name}" + + try: + module = importlib.import_module(module_name) + except ModuleNotFoundError: + print(f"Error: Could not import module '{module_name}'.") + continue + + component = module.__dict__[route_name] + result = str(render(component)) + + # write to component file + with open(out_dir / f"{route_name}.html", "w") as html_file: + html_file.write(result) From a7219be55b5a818adda1883886c671717aa11c91 Mon Sep 17 00:00:00 2001 From: DeleMike Date: Fri, 4 Aug 2023 15:06:15 +0100 Subject: [PATCH 04/12] fix(router): Enhance route generation --- starfyre/__main__.py | 33 +++++---------- starfyre/compiler.py | 11 ++++- starfyre/exceptions.py | 45 +++++++++++++++++---- starfyre/file_router.py | 42 +++++++++++-------- test-application/pages/about.fyre | 67 +++++++++++++++++++++++++++++++ 5 files changed, 149 insertions(+), 49 deletions(-) diff --git a/starfyre/__main__.py b/starfyre/__main__.py index a4bbfa9..9cc69c0 100644 --- a/starfyre/__main__.py +++ b/starfyre/__main__.py @@ -1,6 +1,6 @@ from starfyre import compile from pathlib import Path -from .file_router import FileRouter +from starfyre.file_router import FileRouter import sys import os @@ -15,42 +15,27 @@ def write_js_file(path): dist_path.mkdir(exist_ok=True) js_store = pkg_resources.path("starfyre.js", "store.js") shutil.copy(str(js_store), path + "/dist/store.js") - - + def create_main_file(path): """ Creates a main file in the build directory. This file will be used to run the project. - Every starfyre build will have an `__init__.py` file in the build directory. + Every starfyre build will have an `__init__.py` file in the build directory. And the `__init__.py` file will have a component that will render the root component. It will be named `app`. You can have a look at the `test-application/build/__init__.py` file to see what it looks like. - The main file is also responsible for adding the `store.js` file to the `index.html` file. + The main file is also responsible for adding the `store.js` file """ output_file_path = path + "/build/__main__.py" write_js_file(path) with open(output_file_path, "w") as f: f.write( - """ -from . import app -import os -from pathlib import Path - - -if __name__ == '__main__': - path_ = os.path.dirname(os.path.abspath(__file__)) - directory = Path(path_ ) / ".." / "dist" - if not directory.exists(): - directory.mkdir() - - with open(f"{directory}/index.html", "w") as f: - f.write("") - f.write(app) -""" - ) +"""if __name__ == '__main__': + pass + """) @click.command() @@ -82,8 +67,8 @@ def main(path, build): # At this point, the project has been compiled and the build directory has been created. # Now, initialize the Router object and use it to handle file-based routing. # Basically, generate the html files for the routes - router = FileRouter(absolute_path / "pages") - router.generate_routes() + file_router = FileRouter(absolute_path / "pages") + file_router.generate_routes() # But there is no main file in the build directory. create_main_file(str(absolute_path)) diff --git a/starfyre/compiler.py b/starfyre/compiler.py index 97d250e..8bece96 100644 --- a/starfyre/compiler.py +++ b/starfyre/compiler.py @@ -1,3 +1,5 @@ +from starfyre.exceptions import InitFyreMissingError, IndexFileConflictError + import os import re from pathlib import Path @@ -12,6 +14,9 @@ def get_fyre_files(project_dir): if entry == 'pages': for file_ in os.listdir(project_dir / "pages"): if file_.endswith(".fyre"): + # check for the invalid 'index.fyre' + if file_.lower() == 'index.fyre': + raise IndexFileConflictError() fyre_files.append(f'pages/{file_}') return fyre_files @@ -207,7 +212,11 @@ def compile(entry_file_name): build_dir = project_dir / "build" build_dir.mkdir(exist_ok=True) - fyre_files = get_fyre_files(project_dir) + fyre_files = get_fyre_files(project_dir) + + # check if __init__.fyre exist else stop compilation + if '__init__.fyre' not in fyre_files: + raise InitFyreMissingError() for fyre_file in fyre_files: python_file_name = fyre_file.replace(".fyre", ".py") diff --git a/starfyre/exceptions.py b/starfyre/exceptions.py index bdc331f..5df2799 100644 --- a/starfyre/exceptions.py +++ b/starfyre/exceptions.py @@ -3,18 +3,47 @@ Classes: - UnknownTagError: An exception raised when encountering an unknown tag during parsing. + - InitFyreMissingError: An exception raised when the '__init__.fyre' file is missing. + - IndexFileConflictError: An exception raised when there is an 'index.fyre' file in the pages folder. """ + class UnknownTagError(Exception): - """Exception raised when an unknown tag is encountered during parsing. + """Exception raised when an unknown tag is encountered during parsing. + + This exception is raised when the parser encounters a tag that is not recognized as + a generic HTML tag or a custom component. It indicates that the tag is unknown and + cannot be processed correctly. + + Attributes: + message (str): A description of the error. + """ + pass + +class InitFyreMissingError(Exception): + """ + Exception raised when the '__init__.fyre' file is missing. + """ + def __init__(self, message="Error: '__init__.fyre' file is missing."): + super().__init__(message) + +class IndexFileConflictError(Exception): + """Exception raised when there is an 'index.fyre' file in the pages folder. - This exception is raised when the parser encounters a tag that is not recognized as - a generic HTML tag or a custom component. It indicates that the tag is unknown and - cannot be processed correctly. + This exception is raised when the router encounters an 'index.fyre' file + in the specified pages directory. Such a file is not allowed, as it would + conflict with the generation of the main 'index.html' file that is produced + from the transpilation of the '__init__.fyre' file. - Attributes: + Using 'index.fyre' in the pages folder would result in an ambiguity between + the manually provided 'index.fyre' and the automatically generated 'index.html'. + + Attributes: message (str): A description of the error. - """ - def __init__(self, message='Unknown tag found.'): - super().__init__(message) \ No newline at end of file + """ + + def __init__(self, message="'index.fyre' is not allowed as it conflicts with 'index.html' generation. Please rename the file to avoid this conflict."): + super().__init__(message) + + diff --git a/starfyre/file_router.py b/starfyre/file_router.py index 921137c..3fc15a3 100644 --- a/starfyre/file_router.py +++ b/starfyre/file_router.py @@ -1,4 +1,5 @@ -from starfyre import create_component, render +from starfyre import create_component, render_root +from starfyre.exceptions import IndexFileConflictError import os import sys @@ -23,7 +24,6 @@ class FileRouter: def __init__(self, pages_directory): self.pages_directory = pages_directory - def generate_routes(self): """ Generate routes and create corresponding HTML files. @@ -41,8 +41,8 @@ def generate_routes(self): Example: pages_directory = "test_app/pages" - router = FileRouter(pages_directory) - router.generate_routes() # This generates the routes and corresponding HTML files. + file_router = FileRouter(pages_directory) + file_router.generate_routes() # This generates the routes and corresponding HTML files. Raises: FileNotFoundError: If the specified pages directory does not exist. @@ -56,20 +56,19 @@ def generate_routes(self): for file_name in os.listdir(self.pages_directory): if file_name.endswith(".fyre"): route_name = file_name.replace(".fyre", "").lower() + if route_name.lower() == 'index': + raise IndexFileConflictError() routes.append(route_name) - # print(f'Found fyre file: New route will be = {route_name}') - # print(f'file path for route is = {dist_dir}/{route_name}.html') # read the contents from the generated python files self._build_output(generated_routes=routes, out_dir=dist_dir) - def _build_output(self, generated_routes, out_dir): """ - Transpile the output of `render(component)` to route HTML files. + Transpile the output of `render_root(component)` to route HTML files. This method takes a list of generated routes and an output directory and transpiles the components - using `render(component)`. The resulting components are then written to corresponding HTML files + using `render_root(component)`. The resulting components are then written to corresponding HTML files in the output directory. Parameters: @@ -83,24 +82,35 @@ def _build_output(self, generated_routes, out_dir): out_directory = "test_app/dist" router._build_output(generated_routes, out_directory) """ - print(f'Generated routes: {generated_routes}') + # index.html is to be generated first since it is the entry point of the app + generated_routes.insert(0, 'app') + # print(f'Generated routes: {generated_routes}') root = Path(out_dir / "..").resolve() - app_name = (str(root).split('/'))[-1] # get the user defined project name + # get the user defined project name + app_name = (str(root).split('/'))[-1] for route_name in generated_routes: - # Get the module name dynamically based on the route_name - module_name = f"{Path(app_name)}.build.{route_name}" + print(f'route name is = {route_name}') + + if route_name.lower() == 'app': + component_key = 'app' # For the 'app' component in `build/__init__.py` + else: + component_key = route_name + + module_name = f"{Path(app_name)}.build.{route_name}" if route_name else f"{Path(app_name)}.build" try: module = importlib.import_module(module_name) + component = module.__dict__[component_key] + result = str(render_root(component)) if route_name else component except ModuleNotFoundError: print(f"Error: Could not import module '{module_name}'.") continue - component = module.__dict__[route_name] - result = str(render(component)) - # write to component file + if route_name == '': + route_name = 'index' # rename to index with open(out_dir / f"{route_name}.html", "w") as html_file: + html_file.write("") html_file.write(result) diff --git a/test-application/pages/about.fyre b/test-application/pages/about.fyre index e69de29..6668107 100644 --- a/test-application/pages/about.fyre +++ b/test-application/pages/about.fyre @@ -0,0 +1,67 @@ + + + + +
+

starfyre

+ Explore +
+ + +
From c0ac32d866f305bdecf63384f957491bb707e894 Mon Sep 17 00:00:00 2001 From: DeleMike Date: Fri, 4 Aug 2023 22:37:52 +0100 Subject: [PATCH 05/12] fix generator bug --- starfyre/file_router.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/starfyre/file_router.py b/starfyre/file_router.py index 3fc15a3..75ad927 100644 --- a/starfyre/file_router.py +++ b/starfyre/file_router.py @@ -98,18 +98,18 @@ def _build_output(self, generated_routes, out_dir): else: component_key = route_name - module_name = f"{Path(app_name)}.build.{route_name}" if route_name else f"{Path(app_name)}.build" + module_name = f"{Path(app_name)}.build.{route_name}" if not route_name == 'app' else f"{Path(app_name)}.build" try: module = importlib.import_module(module_name) component = module.__dict__[component_key] - result = str(render_root(component)) if route_name else component + result = str(render_root(component)) if not route_name == 'app' else component except ModuleNotFoundError: print(f"Error: Could not import module '{module_name}'.") continue # write to component file - if route_name == '': + if route_name == 'app': route_name = 'index' # rename to index with open(out_dir / f"{route_name}.html", "w") as html_file: html_file.write("") From bd4012fac65052fb0951eb2d9f3ff1ea86dcfb2b Mon Sep 17 00:00:00 2001 From: DeleMike Date: Tue, 8 Aug 2023 14:35:10 +0100 Subject: [PATCH 06/12] refactor file gen logic from router to main.py --- starfyre/__main__.py | 84 +++++++++++++++++++++++++++++++---------- starfyre/file_router.py | 55 +-------------------------- 2 files changed, 65 insertions(+), 74 deletions(-) diff --git a/starfyre/__main__.py b/starfyre/__main__.py index 9cc69c0..d90a468 100644 --- a/starfyre/__main__.py +++ b/starfyre/__main__.py @@ -15,29 +15,70 @@ def write_js_file(path): dist_path.mkdir(exist_ok=True) js_store = pkg_resources.path("starfyre.js", "store.js") shutil.copy(str(js_store), path + "/dist/store.js") - -def create_main_file(path): - """ - Creates a main file in the build directory. - - This file will be used to run the project. - Every starfyre build will have an `__init__.py` file in the build directory. - And the `__init__.py` file will have a component that will render the root component. It will be named `app`. - You can have a look at the `test-application/build/__init__.py` file to see what it looks like. - - The main file is also responsible for adding the `store.js` file - """ +def build_routes_output(generated_routes, path): output_file_path = path + "/build/__main__.py" write_js_file(path) with open(output_file_path, "w") as f: f.write( -"""if __name__ == '__main__': - pass - """) +f""" +from starfyre import create_component, render_root +from starfyre.exceptions import IndexFileConflictError + +import os +import sys +from pathlib import Path +import importlib +def _build_output(generated_routes, path): + user_routes = generated_routes[:] + # index.html is to be generated first since it is the entry point of the app + user_routes.insert(0, 'app') + + print(f"Generated routes: {{user_routes}}") + + out_dir = Path(path + "/dist").resolve() + root = Path(out_dir / "..").resolve() + + # get the user defined project name + app_name = (str(root).split('/'))[-1] + + for route_name in user_routes: + print(f'route name is = {{route_name}}') + + if route_name.lower() == 'app': + component_key = 'app' # For the 'app' component in `build/__init__.py` + else: + component_key = route_name + + if route_name == 'app': + module_name = f"{{Path(app_name)}}.build" + else: + module_name= f"{{Path(app_name)}}.build.{{route_name}}" + + try: + module = importlib.import_module(module_name) + print(f"Module is = {{module}}") + component = module.__dict__[component_key] + result = str(render_root(component)) if not route_name == 'app' else component + except ModuleNotFoundError: + print(f"Error: Could not import module '{{module_name}}'.") + continue + + # write to component file + if route_name == 'app': + route_name = 'index' # rename to index + with open(out_dir / f"{{route_name}}.html", "w") as html_file: + html_file.write("") + html_file.write(result) + + +if __name__ == '__main__': + _build_output(generated_routes={generated_routes}, path="{path}") + """) + @click.command() @click.option("--path", help="Path to the project") @click.option("--build", is_flag=True, help="Compile and build package") @@ -57,6 +98,7 @@ def main(path, build): # Convert path to absolute path absolute_path = Path(path).resolve() + print(f'Absoulte path = {absolute_path}') if build: # Compile and build project @@ -66,17 +108,19 @@ def main(path, build): # At this point, the project has been compiled and the build directory has been created. # Now, initialize the Router object and use it to handle file-based routing. - # Basically, generate the html files for the routes + # Basically, get all the file names from the "pages" directory file_router = FileRouter(absolute_path / "pages") - file_router.generate_routes() + routes = file_router.generate_routes() - # But there is no main file in the build directory. - create_main_file(str(absolute_path)) + # We have to create the main file. + # The main file will be used to generate the HTML output for all routes found by the FileRouter, index route inclusively. + build_routes_output(generated_routes=routes, path=str(absolute_path)) + # Start/run project subprocess.run( [sys.executable, "-m", "build"], cwd=path, - stdout=subprocess.PIPE, + # stdout=subprocess.PIPE, stderr=None, ) diff --git a/starfyre/file_router.py b/starfyre/file_router.py index 75ad927..fd2cb09 100644 --- a/starfyre/file_router.py +++ b/starfyre/file_router.py @@ -60,57 +60,4 @@ def generate_routes(self): raise IndexFileConflictError() routes.append(route_name) - # read the contents from the generated python files - self._build_output(generated_routes=routes, out_dir=dist_dir) - - def _build_output(self, generated_routes, out_dir): - """ - Transpile the output of `render_root(component)` to route HTML files. - - This method takes a list of generated routes and an output directory and transpiles the components - using `render_root(component)`. The resulting components are then written to corresponding HTML files - in the output directory. - - Parameters: - generated_routes (list): A list of route names (strings) generated from the pages directory. - out_dir (str): The path to the output directory where the HTML files will be written. - - Example: - pages_directory = "test_app/pages" - router = FileRouter(pages_directory) - router.generate_routes() # This generates the `generated_routes` list. - out_directory = "test_app/dist" - router._build_output(generated_routes, out_directory) - """ - # index.html is to be generated first since it is the entry point of the app - generated_routes.insert(0, 'app') - # print(f'Generated routes: {generated_routes}') - - root = Path(out_dir / "..").resolve() - # get the user defined project name - app_name = (str(root).split('/'))[-1] - - for route_name in generated_routes: - print(f'route name is = {route_name}') - - if route_name.lower() == 'app': - component_key = 'app' # For the 'app' component in `build/__init__.py` - else: - component_key = route_name - - module_name = f"{Path(app_name)}.build.{route_name}" if not route_name == 'app' else f"{Path(app_name)}.build" - - try: - module = importlib.import_module(module_name) - component = module.__dict__[component_key] - result = str(render_root(component)) if not route_name == 'app' else component - except ModuleNotFoundError: - print(f"Error: Could not import module '{module_name}'.") - continue - - # write to component file - if route_name == 'app': - route_name = 'index' # rename to index - with open(out_dir / f"{route_name}.html", "w") as html_file: - html_file.write("") - html_file.write(result) + return routes From 7530196488a4da21984e574c21497307a9db2006 Mon Sep 17 00:00:00 2001 From: DeleMike Date: Wed, 9 Aug 2023 15:17:36 +0100 Subject: [PATCH 07/12] rename functions and add docstrings --- starfyre/__main__.py | 30 ++++++++++++++++++++---------- starfyre/file_router.py | 31 ++++++++++++++++--------------- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/starfyre/__main__.py b/starfyre/__main__.py index d90a468..551f452 100644 --- a/starfyre/__main__.py +++ b/starfyre/__main__.py @@ -22,8 +22,7 @@ def build_routes_output(generated_routes, path): with open(output_file_path, "w") as f: f.write( -f""" -from starfyre import create_component, render_root + f'''from starfyre import create_component, render_root from starfyre.exceptions import IndexFileConflictError import os @@ -31,7 +30,18 @@ def build_routes_output(generated_routes, path): from pathlib import Path import importlib -def _build_output(generated_routes, path): +def generate_pages(generated_routes, path): + """ + Generate HTML pages for each route in the provided list of routes. + + Parameters: + - generated_routes (list): List of generated routes. + - path (str): Path to the project directory. + + This function generates HTML pages for each route provided in the `generated_routes` list. + It imports the necessary components for each route, renders them using Starfyre, + and writes the rendered content to corresponding HTML files. + """ user_routes = generated_routes[:] # index.html is to be generated first since it is the entry point of the app @@ -76,9 +86,9 @@ def _build_output(generated_routes, path): if __name__ == '__main__': - _build_output(generated_routes={generated_routes}, path="{path}") - """) - + generate_pages(generated_routes={generated_routes}, path="{path}") + ''') + @click.command() @click.option("--path", help="Path to the project") @click.option("--build", is_flag=True, help="Compile and build package") @@ -105,22 +115,22 @@ def main(path, build): init_file_path = absolute_path / "__init__.py" # Note: The routes specified in the pages folder will have generated code in the build directory. compile(init_file_path.resolve()) - + # At this point, the project has been compiled and the build directory has been created. # Now, initialize the Router object and use it to handle file-based routing. # Basically, get all the file names from the "pages" directory file_router = FileRouter(absolute_path / "pages") - routes = file_router.generate_routes() + routes = file_router.populate_router() # We have to create the main file. # The main file will be used to generate the HTML output for all routes found by the FileRouter, index route inclusively. build_routes_output(generated_routes=routes, path=str(absolute_path)) - + # Start/run project subprocess.run( [sys.executable, "-m", "build"], cwd=path, - # stdout=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=None, ) diff --git a/starfyre/file_router.py b/starfyre/file_router.py index fd2cb09..0881165 100644 --- a/starfyre/file_router.py +++ b/starfyre/file_router.py @@ -22,27 +22,28 @@ class FileRouter: """ def __init__(self, pages_directory): - self.pages_directory = pages_directory + """ + Initialize the FileRouter with the specified pages directory. - def generate_routes(self): + Args: + pages_directory (str): The path to the directory containing the pages files. """ - Generate routes and create corresponding HTML files. + self.pages_directory = pages_directory - This method generates routes based on the file names in the specified pages directory. Each file in the - pages directory with a ".fyre" extension is considered a separate route. The route names are derived from - the file names by removing the ".fyre" extension and converting the names to lowercase. + def populate_router(self): + """ + Collect route names from files in the specified pages directory. - The generated route names are stored in a list, and corresponding HTML files are created in the specified - "dist" directory. The HTML files are created by transpiling the components using the `_build_output` method. + This method collects route names based on the file names in the specified pages directory. + Each file in the pages directory with a ".fyre" extension is considered a separate route. + The route names are derived from the file names by removing the ".fyre" extension and + converting the names to lowercase. - Note: - - This method should be called after initializing the `FileRouter` object. - - The `_build_output` method is responsible for generating the HTML files. + The generated route names are stored in a list, and corresponding HTML files are created + in the specified "dist" directory. - Example: - pages_directory = "test_app/pages" - file_router = FileRouter(pages_directory) - file_router.generate_routes() # This generates the routes and corresponding HTML files. + Returns: + list: A list of generated route names. Raises: FileNotFoundError: If the specified pages directory does not exist. From 9500525b5e006ebaa2b86f6b9fd029580f04c568 Mon Sep 17 00:00:00 2001 From: DeleMike Date: Tue, 15 Aug 2023 10:42:22 +0100 Subject: [PATCH 08/12] add more docstring to file router --- starfyre/__main__.py | 2 +- starfyre/file_router.py | 25 +++++++++++-------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/starfyre/__main__.py b/starfyre/__main__.py index 551f452..162da93 100644 --- a/starfyre/__main__.py +++ b/starfyre/__main__.py @@ -71,7 +71,7 @@ def generate_pages(generated_routes, path): try: module = importlib.import_module(module_name) print(f"Module is = {{module}}") - component = module.__dict__[component_key] + component = getattr(module, component_key, f"{{component_key}} does not exist") result = str(render_root(component)) if not route_name == 'app' else component except ModuleNotFoundError: print(f"Error: Could not import module '{{module_name}}'.") diff --git a/starfyre/file_router.py b/starfyre/file_router.py index 0881165..c5c4908 100644 --- a/starfyre/file_router.py +++ b/starfyre/file_router.py @@ -8,22 +8,19 @@ class FileRouter: - """ - A router that handles file-based routing. - - This router parses the specified pages directory to automatically generate routes based on - the file names. Each file in the pages directory is treated as a separate route. - - Parameters: - pages_directory (str): The path to the directory containing the pages files. - Example: - pages_directory = "test-application/pages" - file_router = FileRouter(pages_directory) - """ - def __init__(self, pages_directory): """ - Initialize the FileRouter with the specified pages directory. + A router that handles file-based routing. + + This router parses the specified pages directory to automatically generate routes based on + the file names. Each file in the pages directory is treated as a separate route. + + Parameters: + pages_directory (str): The path to the directory containing the pages files. + Example: + pages_directory = "test-application/pages" + file_router = FileRouter(pages_directory) + Initialize the FileRouter with the specified pages directory. Args: pages_directory (str): The path to the directory containing the pages files. From c9366f864e7ca9de0ebb27f93cd4f35d61f93798 Mon Sep 17 00:00:00 2001 From: DeleMike Date: Tue, 15 Aug 2023 13:30:38 +0100 Subject: [PATCH 09/12] build render output for component --- starfyre/__main__.py | 38 ++++++++++++++++++++------------------ starfyre/compiler.py | 8 ++++++-- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/starfyre/__main__.py b/starfyre/__main__.py index 162da93..8499d86 100644 --- a/starfyre/__main__.py +++ b/starfyre/__main__.py @@ -9,7 +9,6 @@ import click import importlib.resources as pkg_resources - def write_js_file(path): dist_path = Path(path) / "dist" dist_path.mkdir(exist_ok=True) @@ -17,9 +16,17 @@ def write_js_file(path): shutil.copy(str(js_store), path + "/dist/store.js") def build_routes_output(generated_routes, path): - output_file_path = path + "/build/__main__.py" write_js_file(path) + output_file_path = path + "/build/__main__.py" + init_file_path = path + "/build/__init__.py" + user_routes = generated_routes[:] + user_routes.insert(0, 'app') + + # create empty __init__.py file + with open(init_file_path, "w"): + pass + with open(output_file_path, "w") as f: f.write( f'''from starfyre import create_component, render_root @@ -42,12 +49,6 @@ def generate_pages(generated_routes, path): It imports the necessary components for each route, renders them using Starfyre, and writes the rendered content to corresponding HTML files. """ - user_routes = generated_routes[:] - - # index.html is to be generated first since it is the entry point of the app - user_routes.insert(0, 'app') - - print(f"Generated routes: {{user_routes}}") out_dir = Path(path + "/dist").resolve() root = Path(out_dir / "..").resolve() @@ -55,24 +56,26 @@ def generate_pages(generated_routes, path): # get the user defined project name app_name = (str(root).split('/'))[-1] - for route_name in user_routes: + for route_name in generated_routes: print(f'route name is = {{route_name}}') if route_name.lower() == 'app': - component_key = 'app' # For the 'app' component in `build/__init__.py` + component_key = 'app' # For the 'app' component in `build/pages/__init__.py` else: component_key = route_name if route_name == 'app': - module_name = f"{{Path(app_name)}}.build" + module_name = f"{{Path(app_name)}}.build.pages" else: - module_name= f"{{Path(app_name)}}.build.{{route_name}}" + module_name= f"{{Path(app_name)}}.build.pages.{{route_name}}" try: module = importlib.import_module(module_name) - print(f"Module is = {{module}}") - component = getattr(module, component_key, f"{{component_key}} does not exist") - result = str(render_root(component)) if not route_name == 'app' else component + if component_key == 'app': + component = getattr(module, component_key, f"{{component_key}} does not exist") + else: + component = getattr(module, f'rendered_{{component_key}}') + result = str(component) except ModuleNotFoundError: print(f"Error: Could not import module '{{module_name}}'.") continue @@ -84,9 +87,8 @@ def generate_pages(generated_routes, path): html_file.write("") html_file.write(result) - if __name__ == '__main__': - generate_pages(generated_routes={generated_routes}, path="{path}") + generate_pages(generated_routes={user_routes}, path="{path}") ''') @click.command() @@ -130,7 +132,7 @@ def main(path, build): subprocess.run( [sys.executable, "-m", "build"], cwd=path, - stdout=subprocess.PIPE, + # stdout=subprocess.PIPE, stderr=None, ) diff --git a/starfyre/compiler.py b/starfyre/compiler.py index 8bece96..0fd03be 100644 --- a/starfyre/compiler.py +++ b/starfyre/compiler.py @@ -146,7 +146,7 @@ def fx_{root_name}(): ''' else: return f''' -from starfyre import create_component +from starfyre import create_component, render_root def fx_{root_name}(): component = create_component(""" @@ -163,6 +163,7 @@ def fx_{root_name}(): return component {root_name}=fx_{root_name}() +rendered_{root_name} = render_root({root_name}) ''' @@ -191,7 +192,7 @@ def transpile_to_python( final_python_lines.append(main_content) file_name = output_file_name.split("/")[-1] #getting the file itself "without the path" - output_file_name = project_dir / "build" / file_name + output_file_name = project_dir / "build" / "pages" /file_name with open(output_file_name, "w") as output_file: output_file.write("".join(final_python_lines)) #result of the transpiled @@ -212,6 +213,9 @@ def compile(entry_file_name): build_dir = project_dir / "build" build_dir.mkdir(exist_ok=True) + build_dir = project_dir / "build"/ "pages" # create build pages dir + build_dir.mkdir(exist_ok=True) + fyre_files = get_fyre_files(project_dir) # check if __init__.fyre exist else stop compilation From 6c578b7eb3ab5086b9c1ab7694d7fd0a64e1edae Mon Sep 17 00:00:00 2001 From: DeleMike Date: Thu, 17 Aug 2023 11:00:01 +0100 Subject: [PATCH 10/12] create template file for build/__main__.py construction --- starfyre/__main__.py | 86 +++++++++------------------------------ starfyre/main_template.py | 76 ++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 66 deletions(-) create mode 100644 starfyre/main_template.py diff --git a/starfyre/__main__.py b/starfyre/__main__.py index 4c27437..0bb76be 100644 --- a/starfyre/__main__.py +++ b/starfyre/__main__.py @@ -1,6 +1,7 @@ from starfyre import compile from pathlib import Path from starfyre.file_router import FileRouter +from starfyre.main_template import get_main_template import sys import os @@ -16,80 +17,35 @@ def write_js_file(path): shutil.copy(str(js_store), path + "/dist/store.js") def build_routes_output(generated_routes, path): + """ + Build the HTML output files for each generated route and create the main execution file. + + Parameters: + - generated_routes (list): List of generated route names. + - path (str): Path to the project directory. + + This function gets the HTML output for each generated route based on the provided `generated_routes` list. + It also creates the main execution file (__main__.py) that orchestrates rendering and writing HTML content to files. + The rendered HTML content is generated by importing and utilizing the corresponding components for each route. + + Args: + generated_routes (list): A list of route names that have been generated. + path (str): The path to the project directory. + """ write_js_file(path) output_file_path = path + "/build/__main__.py" init_file_path = path + "/build/__init__.py" user_routes = generated_routes[:] user_routes.insert(0, 'app') - + main_script_content = get_main_template(user_routes=user_routes, path=path) + # create empty __init__.py file with open(init_file_path, "w"): pass with open(output_file_path, "w") as f: - f.write( - f'''from starfyre import create_component, render_root -from starfyre.exceptions import IndexFileConflictError - -import os -import sys -from pathlib import Path -import importlib - -def generate_pages(generated_routes, path): - """ - Generate HTML pages for each route in the provided list of routes. - - Parameters: - - generated_routes (list): List of generated routes. - - path (str): Path to the project directory. - - This function generates HTML pages for each route provided in the `generated_routes` list. - It imports the necessary components for each route, renders them using Starfyre, - and writes the rendered content to corresponding HTML files. - """ - - out_dir = Path(path + "/dist").resolve() - root = Path(out_dir / "..").resolve() - - # get the user defined project name - app_name = (str(root).split('/'))[-1] - - for route_name in generated_routes: - print(f'route name is = {{route_name}}') - - if route_name.lower() == 'app': - component_key = 'app' # For the 'app' component in `build/pages/__init__.py` - else: - component_key = route_name - - if route_name == 'app': - module_name = f"{{Path(app_name)}}.build.pages" - else: - module_name= f"{{Path(app_name)}}.build.pages.{{route_name}}" - - try: - module = importlib.import_module(module_name) - if component_key == 'app': - component = getattr(module, component_key, f"{{component_key}} does not exist") - else: - component = getattr(module, f'rendered_{{component_key}}') - result = str(component) - except ModuleNotFoundError: - print(f"Error: Could not import module '{{module_name}}'.") - continue - - # write to component file - if route_name == 'app': - route_name = 'index' # rename to index - with open(out_dir / f"{{route_name}}.html", "w") as html_file: - html_file.write("") - html_file.write(result) - -if __name__ == '__main__': - generate_pages(generated_routes={user_routes}, path="{path}") - ''') + f.write(main_script_content) @click.command() @click.option("--path", help="Path to the project") @@ -132,12 +88,10 @@ def main(path, build): result = subprocess.run( [sys.executable, "-m", "build"], cwd=path, - # stdout=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=None, ) - print(result.stdout.decode("utf-8")) - if __name__ == "__main__": main() diff --git a/starfyre/main_template.py b/starfyre/main_template.py new file mode 100644 index 0000000..84dfbc1 --- /dev/null +++ b/starfyre/main_template.py @@ -0,0 +1,76 @@ +def get_main_template(user_routes, path): + """ + Template for the main execution script to generate HTML pages for generated routes. + + This module defines the template for the main execution script that generates HTML pages + for each route in the provided list of generated routes. The script imports the necessary + components for each route, renders them using Starfyre, and writes the rendered content + to corresponding HTML files. + + The template contains placeholders for variables that will be dynamically substituted when + the script is used. The placeholders include the generated routes list and the path to the + project directory. + """ + + return f"""import os +import sys +from pathlib import Path +import importlib + + +def generate_pages(generated_routes, path): + ''' + Generate HTML pages for each route in the provided list of routes. + + Parameters: + - generated_routes (list): List of generated routes. + - path (str): Path to the project directory. + + This function generates HTML pages for each route provided in the `generated_routes` list. + It imports the necessary components for each route, renders them using Starfyre, + and writes the rendered content to corresponding HTML files. + ''' + + out_dir = Path(path + "/dist").resolve() + root = Path(out_dir / "..").resolve() + + # get the user defined project name + app_name = (str(root).split('/'))[-1] + + for route_name in generated_routes: + print(f'route name is = {{route_name}}') + + if route_name.lower() == 'app': + component_key = 'app' # For the 'app' component in `build/pages/__init__.py` + else: + component_key = route_name + + if route_name == 'app': + module_name = f"{{Path(app_name)}}.build.pages" + else: + module_name= f"{{Path(app_name)}}.build.pages.{{route_name}}" + + try: + module = importlib.import_module(module_name) + if component_key == 'app': + component = getattr(module, component_key, f"{{component_key}} does not exist") + else: + component = getattr(module, f'rendered_{{component_key}}') + result = str(component) + except ModuleNotFoundError: + print(f"Error: Could not import module '{{module_name}}'.") + continue + + # write to component file + if route_name == 'app': + route_name = 'index' # rename to index + with open(out_dir / f"{{route_name}}.html", "w") as html_file: + html_file.write("") + html_file.write(result) + + + +if __name__ == '__main__': + generate_pages(generated_routes={user_routes}, path="{path}") + """ + From 5e24c320f067cda94ca6689e8e3766eff4a7cd88 Mon Sep 17 00:00:00 2001 From: DeleMike Date: Sun, 20 Aug 2023 22:25:59 +0100 Subject: [PATCH 11/12] fix app imports and improve code style --- starfyre/__main__.py | 26 +++++++++++----------- starfyre/compiler.py | 4 ++-- starfyre/file_router.py | 3 +++ test-application/{ => pages}/__init__.fyre | 0 4 files changed, 18 insertions(+), 15 deletions(-) rename test-application/{ => pages}/__init__.fyre (100%) diff --git a/starfyre/__main__.py b/starfyre/__main__.py index 0bb76be..83b5035 100644 --- a/starfyre/__main__.py +++ b/starfyre/__main__.py @@ -10,13 +10,15 @@ import click import importlib.resources as pkg_resources + def write_js_file(path): dist_path = Path(path) / "dist" dist_path.mkdir(exist_ok=True) js_store = pkg_resources.path("starfyre.js", "store.js") shutil.copy(str(js_store), path + "/dist/store.js") -def build_routes_output(generated_routes, path): + +def prepare_html_and_main(generated_routes, path): """ Build the HTML output files for each generated route and create the main execution file. @@ -26,7 +28,7 @@ def build_routes_output(generated_routes, path): This function gets the HTML output for each generated route based on the provided `generated_routes` list. It also creates the main execution file (__main__.py) that orchestrates rendering and writing HTML content to files. - The rendered HTML content is generated by importing and utilizing the corresponding components for each route. + The rendered HTML content is generated by importing and utilizing the corresponding components for each route in the __main__ file. Args: generated_routes (list): A list of route names that have been generated. @@ -34,18 +36,16 @@ def build_routes_output(generated_routes, path): """ write_js_file(path) - output_file_path = path + "/build/__main__.py" + main_file_path = path + "/build/__main__.py" init_file_path = path + "/build/__init__.py" - user_routes = generated_routes[:] - user_routes.insert(0, 'app') - main_script_content = get_main_template(user_routes=user_routes, path=path) + main_file_content = get_main_template(user_routes=generated_routes, path=path) # create empty __init__.py file - with open(init_file_path, "w"): - pass + Path(init_file_path).touch() + + with open(main_file_path, "w") as f: + f.write(main_file_content) - with open(output_file_path, "w") as f: - f.write(main_script_content) @click.command() @click.option("--path", help="Path to the project") @@ -66,7 +66,7 @@ def main(path, build): # Convert path to absolute path absolute_path = Path(path).resolve() - print(f'Absoulte path = {absolute_path}') + print(f'Absolute path of the project = {absolute_path}') if build: # Compile and build project @@ -82,13 +82,13 @@ def main(path, build): # We have to create the main file. # The main file will be used to generate the HTML output for all routes found by the FileRouter, index route inclusively. - build_routes_output(generated_routes=routes, path=str(absolute_path)) + prepare_html_and_main(generated_routes=routes, path=str(absolute_path)) # Start/run project result = subprocess.run( [sys.executable, "-m", "build"], cwd=path, - stdout=subprocess.PIPE, + # stdout=subprocess.PIPE, stderr=None, ) diff --git a/starfyre/compiler.py b/starfyre/compiler.py index 0fd03be..bf857e4 100644 --- a/starfyre/compiler.py +++ b/starfyre/compiler.py @@ -218,8 +218,8 @@ def compile(entry_file_name): fyre_files = get_fyre_files(project_dir) - # check if __init__.fyre exist else stop compilation - if '__init__.fyre' not in fyre_files: + # check if pages/__init__.fyre exist else stop compilation + if 'pages/__init__.fyre' not in fyre_files: raise InitFyreMissingError() for fyre_file in fyre_files: diff --git a/starfyre/file_router.py b/starfyre/file_router.py index c5c4908..f6357d3 100644 --- a/starfyre/file_router.py +++ b/starfyre/file_router.py @@ -54,6 +54,9 @@ def populate_router(self): for file_name in os.listdir(self.pages_directory): if file_name.endswith(".fyre"): route_name = file_name.replace(".fyre", "").lower() + if route_name == '__init__': + routes.insert(0, 'app') + continue # do no add '__init__' as a route found rather use 'app' if route_name.lower() == 'index': raise IndexFileConflictError() routes.append(route_name) diff --git a/test-application/__init__.fyre b/test-application/pages/__init__.fyre similarity index 100% rename from test-application/__init__.fyre rename to test-application/pages/__init__.fyre From 1fd1868d6f48ab3f6866638f28decdaa48bfe6c2 Mon Sep 17 00:00:00 2001 From: DeleMike Date: Wed, 23 Aug 2023 23:38:12 +0100 Subject: [PATCH 12/12] use descriptive names --- starfyre/__main__.py | 6 +++--- starfyre/{main_template.py => build_main_file_content.py} | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename starfyre/{main_template.py => build_main_file_content.py} (98%) diff --git a/starfyre/__main__.py b/starfyre/__main__.py index 83b5035..f7bbcf9 100644 --- a/starfyre/__main__.py +++ b/starfyre/__main__.py @@ -1,7 +1,7 @@ from starfyre import compile from pathlib import Path from starfyre.file_router import FileRouter -from starfyre.main_template import get_main_template +from starfyre.build_main_file_content import get_build_main_file_content import sys import os @@ -38,7 +38,7 @@ def prepare_html_and_main(generated_routes, path): main_file_path = path + "/build/__main__.py" init_file_path = path + "/build/__init__.py" - main_file_content = get_main_template(user_routes=generated_routes, path=path) + main_file_content = get_build_main_file_content(user_routes=generated_routes, path=path) # create empty __init__.py file Path(init_file_path).touch() @@ -88,7 +88,7 @@ def main(path, build): result = subprocess.run( [sys.executable, "-m", "build"], cwd=path, - # stdout=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=None, ) diff --git a/starfyre/main_template.py b/starfyre/build_main_file_content.py similarity index 98% rename from starfyre/main_template.py rename to starfyre/build_main_file_content.py index 84dfbc1..f83821c 100644 --- a/starfyre/main_template.py +++ b/starfyre/build_main_file_content.py @@ -1,4 +1,4 @@ -def get_main_template(user_routes, path): +def get_build_main_file_content(user_routes, path): """ Template for the main execution script to generate HTML pages for generated routes.