diff --git a/pdm.lock b/pdm.lock index 7834134..8f72391 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev", "lint"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:9a51ac6f18e9540b411123e883a7fe33424114a5a1142117d73b11a193c5b818" +content_hash = "sha256:d269afb584605edc385b4458a4a435bb4486704fc49bac8428c25ddb816a1ece" [[metadata.targets]] requires_python = ">=3.8" @@ -15,7 +15,7 @@ name = "anyio" version = "4.4.0" requires_python = ">=3.8" summary = "High level compatibility layer for multiple asynchronous event loop implementations" -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "exceptiongroup>=1.0.2; python_version < \"3.11\"", "idna>=2.8", @@ -32,7 +32,7 @@ name = "certifi" version = "2024.7.4" requires_python = ">=3.6" summary = "Python package for providing Mozilla's CA Bundle." -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, @@ -43,7 +43,7 @@ name = "cffi" version = "1.16.0" requires_python = ">=3.8" summary = "Foreign Function Interface for Python calling C code." -groups = ["dev"] +groups = ["default", "dev"] marker = "platform_python_implementation != \"PyPy\"" dependencies = [ "pycparser", @@ -119,7 +119,7 @@ name = "click" version = "8.1.7" requires_python = ">=3.7" summary = "Composable command line interface toolkit" -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "colorama; platform_system == \"Windows\"", "importlib-metadata; python_version < \"3.8\"", @@ -134,8 +134,8 @@ name = "colorama" version = "0.4.6" requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" summary = "Cross-platform colored terminal text." -groups = ["dev"] -marker = "sys_platform == \"win32\" or platform_system == \"Windows\"" +groups = ["default", "dev"] +marker = "platform_system == \"Windows\" or sys_platform == \"win32\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -146,7 +146,7 @@ name = "cryptography" version = "43.0.0" requires_python = ">=3.7" summary = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "cffi>=1.12; platform_python_implementation != \"PyPy\"", ] @@ -194,7 +194,7 @@ files = [ name = "editorconfig" version = "0.12.4" summary = "EditorConfig File Locator and Interpreter for Python" -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "EditorConfig-0.12.4.tar.gz", hash = "sha256:24857fa1793917dd9ccf0c7810a07e05404ce9b823521c7dce22a4fb5d125f80"}, ] @@ -204,7 +204,7 @@ name = "exceptiongroup" version = "1.2.2" requires_python = ">=3.7" summary = "Backport of PEP 654 (exception groups)" -groups = ["dev"] +groups = ["default", "dev"] marker = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, @@ -216,7 +216,7 @@ name = "faker" version = "26.0.0" requires_python = ">=3.8" summary = "Faker is a Python package that generates fake data for you." -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "python-dateutil>=2.4", ] @@ -230,7 +230,7 @@ name = "fast-query-parsers" version = "1.0.3" requires_python = ">=3.8" summary = "Ultra-fast query string and url-encoded form-data parsers" -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "fast_query_parsers-1.0.3-cp38-abi3-macosx_10_7_x86_64.whl", hash = "sha256:afbf71c1b4398dacfb9d84755eb026f8e759f68a066f1f3cc19e471fc342e74f"}, {file = "fast_query_parsers-1.0.3-cp38-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:42f26875311d1b151c3406adfa39ec2db98df111a369d75f6fa243ec8462f147"}, @@ -266,7 +266,7 @@ name = "h11" version = "0.14.0" requires_python = ">=3.7" summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "typing-extensions; python_version < \"3.8\"", ] @@ -280,7 +280,7 @@ name = "httpcore" version = "1.0.5" requires_python = ">=3.8" summary = "A minimal low-level HTTP client." -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "certifi", "h11<0.15,>=0.13", @@ -295,7 +295,7 @@ name = "httptools" version = "0.6.1" requires_python = ">=3.8.0" summary = "A collection of framework independent HTTP protocol utils." -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f"}, {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563"}, @@ -340,7 +340,7 @@ name = "httpx" version = "0.27.0" requires_python = ">=3.8" summary = "The next generation HTTP client." -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "anyio", "certifi", @@ -369,7 +369,7 @@ name = "idna" version = "3.7" requires_python = ">=3.5" summary = "Internationalized Domain Names in Applications (IDNA)" -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, @@ -380,7 +380,7 @@ name = "importlib-metadata" version = "8.2.0" requires_python = ">=3.8" summary = "Read metadata from Python packages" -groups = ["dev"] +groups = ["default", "dev"] marker = "python_version < \"3.10\"" dependencies = [ "typing-extensions>=3.6.4; python_version < \"3.8\"", @@ -396,7 +396,7 @@ name = "importlib-resources" version = "6.4.0" requires_python = ">=3.8" summary = "Read resources from Python packages" -groups = ["dev"] +groups = ["default", "dev"] marker = "python_version < \"3.9\"" dependencies = [ "zipp>=3.1.0; python_version < \"3.10\"", @@ -424,7 +424,7 @@ files = [ name = "jsbeautifier" version = "1.15.1" summary = "JavaScript unobfuscator and beautifier." -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "editorconfig>=0.12.2", "six>=1.13.0", @@ -435,10 +435,10 @@ files = [ [[package]] name = "litestar" -version = "2.9.1" +version = "2.10.0" requires_python = "<4.0,>=3.8" summary = "Litestar - A production-ready, highly performant, extensible ASGI API Framework" -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "anyio>=3", "click", @@ -455,13 +455,13 @@ dependencies = [ "typing-extensions", ] files = [ - {file = "litestar-2.9.1-py3-none-any.whl", hash = "sha256:fe3e4ec91a9c24af652775fed5fa4d789902f165cabbd7d2e62821fec1f69462"}, - {file = "litestar-2.9.1.tar.gz", hash = "sha256:7c13bb4dd7b1c77f6c462262cfe401ca6429eab3e4d98f38586b68268bd5ac97"}, + {file = "litestar-2.10.0-py3-none-any.whl", hash = "sha256:a4fbdb108bfb41e07b56aee6dbdd70f94328f4d4265ebfde1662aef320224375"}, + {file = "litestar-2.10.0.tar.gz", hash = "sha256:c25d5134c6848dfa752494948a644af1fb085143a0bce6d0840fe957b0738432"}, ] [[package]] name = "litestar" -version = "2.9.1" +version = "2.10.0" extras = ["cryptography", "jinja", "standard"] requires_python = "<4.0,>=3.8" summary = "Litestar - A production-ready, highly performant, extensible ASGI API Framework" @@ -472,13 +472,34 @@ dependencies = [ "jinja2", "jinja2>=3.1.2", "jsbeautifier", - "litestar==2.9.1", + "litestar==2.10.0", "uvicorn[standard]", "uvloop>=0.18.0; sys_platform != \"win32\"", ] files = [ - {file = "litestar-2.9.1-py3-none-any.whl", hash = "sha256:fe3e4ec91a9c24af652775fed5fa4d789902f165cabbd7d2e62821fec1f69462"}, - {file = "litestar-2.9.1.tar.gz", hash = "sha256:7c13bb4dd7b1c77f6c462262cfe401ca6429eab3e4d98f38586b68268bd5ac97"}, + {file = "litestar-2.10.0-py3-none-any.whl", hash = "sha256:a4fbdb108bfb41e07b56aee6dbdd70f94328f4d4265ebfde1662aef320224375"}, + {file = "litestar-2.10.0.tar.gz", hash = "sha256:c25d5134c6848dfa752494948a644af1fb085143a0bce6d0840fe957b0738432"}, +] + +[[package]] +name = "litestar" +version = "2.10.0" +extras = ["cryptography", "standard"] +requires_python = "<4.0,>=3.8" +summary = "Litestar - A production-ready, highly performant, extensible ASGI API Framework" +groups = ["default"] +dependencies = [ + "cryptography", + "fast-query-parsers>=1.0.2", + "jinja2", + "jsbeautifier", + "litestar==2.10.0", + "uvicorn[standard]", + "uvloop>=0.18.0; sys_platform != \"win32\"", +] +files = [ + {file = "litestar-2.10.0-py3-none-any.whl", hash = "sha256:a4fbdb108bfb41e07b56aee6dbdd70f94328f4d4265ebfde1662aef320224375"}, + {file = "litestar-2.10.0.tar.gz", hash = "sha256:c25d5134c6848dfa752494948a644af1fb085143a0bce6d0840fe957b0738432"}, ] [[package]] @@ -486,7 +507,7 @@ name = "markdown-it-py" version = "3.0.0" requires_python = ">=3.8" summary = "Python port of markdown-it. Markdown parsing, done right!" -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "mdurl~=0.1", ] @@ -560,7 +581,7 @@ name = "mdurl" version = "0.1.2" requires_python = ">=3.7" summary = "Markdown URL utilities" -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, @@ -571,7 +592,7 @@ name = "msgspec" version = "0.18.6" requires_python = ">=3.8" summary = "A fast serialization and validation library, with builtin support for JSON, MessagePack, YAML, and TOML." -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "msgspec-0.18.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:77f30b0234eceeff0f651119b9821ce80949b4d667ad38f3bfed0d0ebf9d6d8f"}, {file = "msgspec-0.18.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a76b60e501b3932782a9da039bd1cd552b7d8dec54ce38332b87136c64852dd"}, @@ -616,7 +637,7 @@ name = "multidict" version = "6.0.5" requires_python = ">=3.7" summary = "multidict implementation" -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, @@ -776,7 +797,7 @@ name = "polyfactory" version = "2.16.2" requires_python = "<4.0,>=3.8" summary = "Mock data generation factories" -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "faker", "typing-extensions>=4.6.0", @@ -809,7 +830,7 @@ name = "pycparser" version = "2.22" requires_python = ">=3.8" summary = "C parser in Python" -groups = ["dev"] +groups = ["default", "dev"] marker = "platform_python_implementation != \"PyPy\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, @@ -821,7 +842,7 @@ name = "pygments" version = "2.18.0" requires_python = ">=3.8" summary = "Pygments is a syntax highlighting package written in Python." -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, @@ -847,7 +868,7 @@ name = "python-dateutil" version = "2.9.0.post0" requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" summary = "Extensions to the standard Python datetime module" -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "six>=1.5", ] @@ -861,7 +882,7 @@ name = "python-dotenv" version = "1.0.1" requires_python = ">=3.8" summary = "Read key-value pairs from a .env file and set them as environment variables" -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, @@ -872,7 +893,7 @@ name = "pyyaml" version = "6.0.1" requires_python = ">=3.6" summary = "YAML parser and emitter for Python" -groups = ["dev", "lint"] +groups = ["default", "dev", "lint"] 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"}, @@ -920,7 +941,7 @@ name = "rich" version = "13.7.1" requires_python = ">=3.7.0" summary = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "markdown-it-py>=2.2.0", "pygments<3.0.0,>=2.13.0", @@ -936,7 +957,7 @@ name = "rich-click" version = "1.8.3" requires_python = ">=3.7" summary = "Format click help output nicely with rich" -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "click>=7", "importlib-metadata; python_version < \"3.8\"", @@ -980,7 +1001,7 @@ name = "six" version = "1.16.0" requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" summary = "Python 2 and 3 compatibility utilities" -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, @@ -991,7 +1012,7 @@ name = "sniffio" version = "1.3.1" requires_python = ">=3.7" summary = "Sniff out which async library your code is running under" -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -1009,12 +1030,22 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "types-click" +version = "7.1.8" +summary = "Typing stubs for click" +groups = ["lint"] +files = [ + {file = "types-click-7.1.8.tar.gz", hash = "sha256:b6604968be6401dc516311ca50708a0a28baa7a0cb840efd7412f0dbbff4e092"}, + {file = "types_click-7.1.8-py3-none-any.whl", hash = "sha256:8cb030a669e2e927461be9827375f83c16b8178c365852c060a34e24871e7e81"}, +] + [[package]] name = "typing-extensions" version = "4.12.2" requires_python = ">=3.8" summary = "Backported and Experimental Type Hints for Python 3.8+" -groups = ["dev", "lint"] +groups = ["default", "dev", "lint"] files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -1025,7 +1056,7 @@ name = "uvicorn" version = "0.30.3" requires_python = ">=3.8" summary = "The lightning-fast ASGI server." -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "click>=7.0", "h11>=0.8", @@ -1042,7 +1073,7 @@ version = "0.30.3" extras = ["standard"] requires_python = ">=3.8" summary = "The lightning-fast ASGI server." -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "colorama>=0.4; sys_platform == \"win32\"", "httptools>=0.5.0", @@ -1063,7 +1094,7 @@ name = "uvloop" version = "0.19.0" requires_python = ">=3.8.0" summary = "Fast implementation of asyncio event loop on top of libuv" -groups = ["dev"] +groups = ["default", "dev"] marker = "sys_platform != \"win32\"" files = [ {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"}, @@ -1121,7 +1152,7 @@ name = "watchfiles" version = "0.22.0" requires_python = ">=3.8" summary = "Simple, modern and high performance file watching and code reload in python." -groups = ["dev"] +groups = ["default", "dev"] dependencies = [ "anyio>=3.0.0", ] @@ -1208,7 +1239,7 @@ name = "websockets" version = "12.0" requires_python = ">=3.8" summary = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, @@ -1289,7 +1320,7 @@ name = "zipp" version = "3.19.2" requires_python = ">=3.8" summary = "Backport of pathlib-compatible object wrapper for zip files" -groups = ["dev"] +groups = ["default", "dev"] marker = "python_version < \"3.10\"" files = [ {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, diff --git a/pyproject.toml b/pyproject.toml index fe0c5dd..1693d9a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,6 +8,8 @@ authors = [ dependencies = [ "ruff>=0.5.4", "Jinja2>=3.1.4", + "rich-click>=1.8.3", + "litestar[cryptography,standard]>=2.10.0", ] requires-python = ">=3.8" readme = "README.md" @@ -17,19 +19,6 @@ license = {text = "MIT"} requires = ["pdm-backend"] build-backend = "pdm.backend" -[tool.pdm] -distribution = true - -[tool.pdm.dev-dependencies] -dev = [ - "litestar[standard,cryptography,jinja]>=2.9.1", -] -lint = [ - "pyright>=1.1.376", - "mypy>=1.11.1", - "pre-commit>=3.5.0", -] - [project.scripts] litestar = "litestar_manage.__main__:run_cli" @@ -203,7 +192,7 @@ exclude = '''(?x)( |^dist/ |^.venv/ |^node_modules/ -|^migrations/ +|^src/litestar_manage/template/ ) ''' implicit_reexport = false @@ -214,6 +203,7 @@ warn_return_any = true warn_unreachable = true warn_unused_configs = true warn_unused_ignores = true +mypy_path = "src/litestar_manage/stubs/" [[tool.mypy.overrides]] disallow_untyped_decorators = false @@ -244,8 +234,8 @@ module = ["app.db.migrations.*", "app.lib.dto.*"] [tool.pyright] -exclude = ["litestar_manage/template"] -include = ["litestar_manage", "tests"] +exclude = ["src/litestar_manage/template"] +include = ["src/litestar_manage", "tests"] [tool.git-cliff.changelog] body = """ @@ -309,3 +299,17 @@ sort_commits = "oldest" split_commits = false tag_pattern = "v[0-9]*" topo_order = false + +[tool.pdm] +distribution = true + +[tool.pdm.dev-dependencies] +dev = [ + "litestar[standard,cryptography,jinja]>=2.9.1", +] +lint = [ + "pyright>=1.1.376", + "mypy>=1.11.1", + "pre-commit>=3.5.0", + "types-click>=7.1.8", +] diff --git a/src/litestar_manage/__main__.py b/src/litestar_manage/__main__.py index 5643931..bf259b9 100644 --- a/src/litestar_manage/__main__.py +++ b/src/litestar_manage/__main__.py @@ -3,6 +3,10 @@ # SPDX-License-Identifier: MIT from __future__ import annotations +from typing import cast + +from rich_click import RichCommand + def run_cli() -> None: """Application Entrypoint.""" @@ -22,7 +26,7 @@ def run_cli() -> None: print(exc) # noqa: T201 sys.exit(1) else: - litestar_group.add_command(project_group) + litestar_group.add_command(cast(RichCommand, project_group)) run_litestar_cli() diff --git a/src/litestar_manage/cli.py b/src/litestar_manage/cli.py index 17b247a..8f85204 100644 --- a/src/litestar_manage/cli.py +++ b/src/litestar_manage/cli.py @@ -1,6 +1,5 @@ from __future__ import annotations -import os from pathlib import Path from click import group, option @@ -23,7 +22,7 @@ def project_group() -> None: def init_project(app_name: str) -> None: """CLI command to initialize a Litestar project""" template_dir = Path(__file__).parent / "template" - output_dir = Path(os.getcwd()) + output_dir = Path.cwd() ctx = RenderingContext(app_name=app_name) render_template(template_dir, output_dir, ctx, run_ruff=True) diff --git a/src/litestar_manage/renderer.py b/src/litestar_manage/renderer.py index 96bb441..b3bf8e1 100644 --- a/src/litestar_manage/renderer.py +++ b/src/litestar_manage/renderer.py @@ -3,19 +3,23 @@ import os import shutil import subprocess +import sys +import sysconfig from dataclasses import dataclass from pathlib import Path -from typing import List from jinja2 import Template -from ruff.__main__ import find_ruff_bin def render_template( - template_dir: Path, output_dir: Path, ctx: RenderingContext, run_ruff: bool = True + template_dir: Path, + output_dir: Path, + ctx: RenderingContext, + run_ruff: bool = True, ) -> None: """Renders a template from template_dir to output_dir using the provided context. - Optionally runs ruff on the generated files.""" + Optionally runs ruff on the generated files. + """ _render_jinja_dir(template_dir, output_dir, ctx) if run_ruff: @@ -25,9 +29,10 @@ def render_template( "I", "--fix", "--unsafe-fixes", + "--silent", str(output_dir.absolute()), ) - _run_ruff("format", str(output_dir.absolute())) + _run_ruff("format", "--silent", str(output_dir.absolute())) @dataclass @@ -38,8 +43,10 @@ class RenderingContext: def _render_jinja_dir( - input_directory: Path, output_directory: Path, ctx: RenderingContext -) -> List[Path]: + input_directory: Path, + output_directory: Path, + ctx: RenderingContext, +) -> list[Path]: """Recursively renders all files in the input directory to the output directory, while preserving the file-tree structure. Returns the list of paths to the created files. @@ -63,9 +70,11 @@ def _render_jinja_dir( if render_body: with ( - open(path, "r", encoding="utf-8") as input_file, - open( - output_directory / rendered_name, "w", encoding="utf-8" + Path.open(path, encoding="utf-8") as input_file, + Path.open( + output_directory / rendered_name, + "w", + encoding="utf-8", ) as output_file, ): output_file.write(Template(input_file.read()).render(ctx.__dict__)) @@ -77,13 +86,44 @@ def _render_jinja_dir( elif path.is_dir(): files_written.extend( - _render_jinja_dir(path, output_directory / rendered_name, ctx) + _render_jinja_dir(path, output_directory / rendered_name, ctx), ) return files_written +def find_ruff_bin() -> Path: + """Return the ruff binary path.""" + + ruff_exe = Path("ruff" + sysconfig.get_config_var("EXE")) + + scripts_path = Path(sysconfig.get_path("scripts")) / ruff_exe + if scripts_path.is_file(): + return scripts_path + + if sys.version_info >= (3, 10): # noqa: UP036 + user_scheme = sysconfig.get_preferred_scheme("user") + elif os.name == "nt": + user_scheme = "nt_user" + elif sys.platform == "darwin" and sys._framework: + user_scheme = "osx_framework_user" + else: + user_scheme = "posix_user" + + user_path = Path(sysconfig.get_path("scripts", scheme=user_scheme)) / ruff_exe + if user_path.is_file(): + return user_path + + # Search in `bin` adjacent to package root (as created by `pip install --target`). + pkg_root = Path(__file__).parent.parent + target_path = pkg_root / "bin" / ruff_exe + if target_path.is_file(): + return target_path + + raise FileNotFoundError(scripts_path) + + def _run_ruff(*options: str) -> None: """Runs ruff with provided options""" ruff = os.fsdecode(find_ruff_bin()) - subprocess.run([ruff, *options]) + subprocess.run([ruff, *options], check=False) diff --git a/src/litestar_manage/template/src/app/__init__.py b/src/litestar_manage/template/app/__init__.py similarity index 100% rename from src/litestar_manage/template/src/app/__init__.py rename to src/litestar_manage/template/app/__init__.py diff --git a/src/litestar_manage/template/src/app/assets/.gitkeep b/src/litestar_manage/template/app/__main__.py similarity index 100% rename from src/litestar_manage/template/src/app/assets/.gitkeep rename to src/litestar_manage/template/app/__main__.py diff --git a/src/litestar_manage/template/src/app/app.py b/src/litestar_manage/template/app/app.py similarity index 94% rename from src/litestar_manage/template/src/app/app.py rename to src/litestar_manage/template/app/app.py index 6d930c8..46bc5b5 100644 --- a/src/litestar_manage/template/src/app/app.py +++ b/src/litestar_manage/template/app/app.py @@ -22,7 +22,7 @@ def create_app() -> Litestar: from app.controllers.web import WebController logging_middleware_config = LoggingMiddlewareConfig() - session_config = CookieBackendConfig(secret=urandom(16)) # type: ignore + session_config = CookieBackendConfig(secret=urandom(16)) return Litestar( route_handlers=[ diff --git a/src/litestar_manage/template/src/app/controllers/__init__.py b/src/litestar_manage/template/app/assets/.gitkeep similarity index 100% rename from src/litestar_manage/template/src/app/controllers/__init__.py rename to src/litestar_manage/template/app/assets/.gitkeep diff --git a/src/litestar_manage/template/src/app/config.py b/src/litestar_manage/template/app/config.py similarity index 100% rename from src/litestar_manage/template/src/app/config.py rename to src/litestar_manage/template/app/config.py diff --git a/src/litestar_manage/template/src/app/tests/__init__.py b/src/litestar_manage/template/app/controllers/__init__.py similarity index 100% rename from src/litestar_manage/template/src/app/tests/__init__.py rename to src/litestar_manage/template/app/controllers/__init__.py diff --git a/src/litestar_manage/template/src/app/controllers/web.py b/src/litestar_manage/template/app/controllers/web.py similarity index 100% rename from src/litestar_manage/template/src/app/controllers/web.py rename to src/litestar_manage/template/app/controllers/web.py diff --git a/src/litestar_manage/template/src/app/templates/index.html.jinja2 b/src/litestar_manage/template/app/templates/index.html.jinja2 similarity index 100% rename from src/litestar_manage/template/src/app/templates/index.html.jinja2 rename to src/litestar_manage/template/app/templates/index.html.jinja2 diff --git a/src/litestar_manage/template/app/tests/__init__.py b/src/litestar_manage/template/app/tests/__init__.py new file mode 100644 index 0000000..e69de29