new: documentation

fix: config env parsing
This commit is contained in:
L-Nafaryus 2024-09-06 11:13:25 +05:00
parent 8d03a3e3b0
commit 714a9d0879
Signed by: L-Nafaryus
GPG Key ID: 553C97999B363D38
26 changed files with 638 additions and 25 deletions

3
.gitignore vendored
View File

@ -13,3 +13,6 @@ __pycache__/
.pytest_cache
.coverage
/site
src/materia/docs

52
docs/api.md Normal file
View File

@ -0,0 +1,52 @@
---
hide:
- navigation
- toc
---
<style>
.md-typeset h1,
.md-content__button {
display: none;
}
.md-main__inner {
max-width: 100%; /* or 100%, if you want to stretch to full-width */
margin-top: 0;
}
.md-content__inner {
margin: 0;
padding-top: 0;
}
.md-content__inner > p {
margin: 0;
}
.md-content__inner::before {
display: none;
}
.md-footer__inner {
display: none;
}
.md-footer__inner:not([hidden]) {
display: none;
}
</style>
<rapi-doc
spec-url="/api/openapi.json"
theme = "dark"
show-header = "false"
show-info = "false"
allow-authentication = "true"
allow-server-selection = "true"
allow-api-list-style-selection = "true"
theme = "dark"
render-style = "focused"
bg-color="#1e2129"
primary-color="#a47bea"
regular-font="Roboto"
mono-font="Roboto Mono"
show-method-in-nav-bar="as-colored-text">
<img slot="logo" style="display: none"/>
</rapi-doc>
<script
type="module"
src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"
></script>

BIN
docs/img/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

BIN
docs/img/logo-full.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

12
docs/index.md Normal file
View File

@ -0,0 +1,12 @@
# Materia
<style>
.md-content .md-typeset h1 { display: none; }
</style>
<p align="center">
<a href="https://materia.elnafo.ru"><img src="img/logo-full.png" alt="Materia"></a>
</p>
<p align="center">
<em>Materia is easy and fast cloud storage</em>
</p>

1
docs/reference/app.md Normal file
View File

@ -0,0 +1 @@
::: materia.app

1
docs/reference/core.md Normal file
View File

@ -0,0 +1 @@
::: materia.core

5
docs/reference/index.md Normal file
View File

@ -0,0 +1,5 @@
# Reference
Here's the reference or code API, the classes, functions, parameters, attributes, and
all the Materia parts.

1
docs/reference/models.md Normal file
View File

@ -0,0 +1 @@
::: materia.models

View File

@ -0,0 +1 @@
::: materia.routers

View File

@ -0,0 +1 @@
::: materia.security

1
docs/reference/tasks.md Normal file
View File

@ -0,0 +1 @@
::: materia.tasks

View File

@ -164,6 +164,49 @@
postgresql-devel = bonfire.packages.x86_64-linux.postgresql;
redis-devel = bonfire.packages.x86_64-linux.redis;
materia-devel = let
user = "materia";
dataDir = "/var/lib/materia";
entryPoint = pkgs.writeTextDir "entrypoint.sh" ''
materia start
'';
in
pkgs.dockerTools.buildImage {
name = "materia";
tag = "latest";
copyToRoot = pkgs.buildEnv {
name = "image-root";
pathsToLink = ["/bin" "/etc" "/"];
paths = with pkgs; [
bash
self.packages.x86_64-linux.materia
entryPoint
];
};
runAsRoot = with pkgs; ''
#!${runtimeShell}
${dockerTools.shadowSetup}
groupadd -r ${user}
useradd -r -g ${user} --home-dir=${dataDir} ${user}
mkdir -p ${dataDir}
chown -R ${user}:${user} ${dataDir}
'';
config = {
Entrypoint = ["bash" "/entrypoint.sh"];
StopSignal = "SIGINT";
User = "${user}:${user}";
WorkingDir = dataDir;
ExposedPorts = {
"54601/tcp" = {};
};
Env = [
"MATERIA_APPLICATION__WORKING_DIRECTORY=${dataDir}"
];
};
};
};
devShells.x86_64-linux.default = pkgs.mkShell {

89
mkdocs.yml Normal file
View File

@ -0,0 +1,89 @@
site_name: Materia Documentation
site_description: Materia cloud storage
#site_url:
repo_name: L-Nafaryus/materia
repo_url: https://vcs.elnafo.ru/L-Nafaryus/materia
copyright: Copyright &copy; 2024 L-Nafaryus
theme:
name: material
features:
- content.code.annotate
- content.code.copy
# - content.code.select
- content.footnote.tooltips
- content.tabs.link
- content.tooltips
- navigation.footer
- navigation.indexes
- navigation.instant
- navigation.instant.prefetch
# - navigation.instant.preview
- navigation.instant.progress
- navigation.path
- navigation.tabs
- navigation.tabs.sticky
- navigation.top
- navigation.tracking
- search.highlight
- search.share
- search.suggest
- toc.follow
logo: img/favicon.png
favicon: img/favicon.png
palette:
- media: "(prefers-color-scheme: light)"
scheme: slate
primary: deep purple
accent: deep purple
toggle:
icon: material/weather-sunny
name: Switch to light mode
- media: "(prefers-color-scheme: dark)"
scheme: default
primary: deep purple
accent: deep purple
toggle:
icon: material/weather-night
name: Switch to dark mode
plugins:
- search:
- mkdocstrings:
handlers:
python:
paths: [src] # search packages in the src folder
options:
extensions:
- griffe_typingdoc
#preload_modules:
#- sqlalchemy
#docstring_style: sphinx
show_submodules: true
show_source: true
show_if_no_docstring: true
show_symbol_type_heading: true
show_symbol_type_toc: true
show_root_heading: true
unwrap_annotated: true
merge_init_into_class: true
docstring_section_style: spacy
signature_crossrefs: true
inherited_members: true
members_order: source
separate_signature: true
filters:
- '!^_'
nav:
- Materia: index.md
- Reference:
- reference/index.md
- reference/app.md
- reference/core.md
- reference/models.md
- reference/routers.md
- reference/security.md
- reference/tasks.md
- API: api.md

332
pdm.lock
View File

@ -5,7 +5,7 @@
groups = ["default", "dev"]
strategy = ["cross_platform", "inherit_metadata"]
lock_version = "4.4.1"
content_hash = "sha256:ba7a816a8bfe503b899a8eba3e5ca58e2d751a278c19b1c1db6e647f83fcd62d"
content_hash = "sha256:764de758c9c4b274659cef493a76abb117253e6ccf30dce9f4e61a74afce2228"
[[package]]
name = "aiofiles"
@ -157,6 +157,17 @@ files = [
{file = "authlib-1.3.1.tar.gz", hash = "sha256:7ae843f03c06c5c0debd63c9db91f9fda64fa62a42a77419fa15fbb7e7a58917"},
]
[[package]]
name = "babel"
version = "2.16.0"
requires_python = ">=3.8"
summary = "Internationalization utilities"
groups = ["dev"]
files = [
{file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"},
{file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"},
]
[[package]]
name = "bcrypt"
version = "4.1.2"
@ -264,7 +275,7 @@ name = "certifi"
version = "2024.7.4"
requires_python = ">=3.6"
summary = "Python package for providing Mozilla's CA Bundle."
groups = ["default"]
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"},
@ -310,7 +321,7 @@ name = "charset-normalizer"
version = "3.3.2"
requires_python = ">=3.7.0"
summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
groups = ["default"]
groups = ["default", "dev"]
files = [
{file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
@ -393,7 +404,6 @@ 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 = ["default", "dev"]
marker = "sys_platform == \"win32\" or platform_system == \"Windows\""
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
@ -584,6 +594,19 @@ files = [
{file = "fastapi-0.112.0.tar.gz", hash = "sha256:d262bc56b7d101d1f4e8fc0ad2ac75bb9935fec504d2b7117686cec50710cf05"},
]
[[package]]
name = "ghp-import"
version = "2.1.0"
summary = "Copy your docs directly to the gh-pages branch."
groups = ["dev"]
dependencies = [
"python-dateutil>=2.8.1",
]
files = [
{file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"},
{file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"},
]
[[package]]
name = "greenlet"
version = "3.0.3"
@ -603,6 +626,35 @@ files = [
{file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"},
]
[[package]]
name = "griffe"
version = "1.2.0"
requires_python = ">=3.8"
summary = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
groups = ["dev"]
dependencies = [
"colorama>=0.4",
]
files = [
{file = "griffe-1.2.0-py3-none-any.whl", hash = "sha256:a8b2fcb1ecdc5a412e646b0b4375eb20a5d2eac3a11dd8c10c56967a4097663c"},
{file = "griffe-1.2.0.tar.gz", hash = "sha256:1c9f6ef7455930f3f9b0c4145a961c90385d1e2cbc496f7796fbff560ec60d31"},
]
[[package]]
name = "griffe-typingdoc"
version = "0.2.6"
requires_python = ">=3.8"
summary = "Griffe extension for PEP 727 Documentation Metadata in Typing."
groups = ["dev"]
dependencies = [
"griffe>=0.49",
"typing-extensions>=4.7",
]
files = [
{file = "griffe_typingdoc-0.2.6-py3-none-any.whl", hash = "sha256:2726e6cf1e986f42fe9cab4a95cef103a745327f035a32055816849ca47893e4"},
{file = "griffe_typingdoc-0.2.6.tar.gz", hash = "sha256:852a17c1e2d29bbbf14a287e7cc5982669343cf60a4ea1618e486eb57aba3248"},
]
[[package]]
name = "gunicorn"
version = "22.0.0"
@ -726,7 +778,7 @@ name = "idna"
version = "3.7"
requires_python = ">=3.5"
summary = "Internationalized Domain Names in Applications (IDNA)"
groups = ["default"]
groups = ["default", "dev"]
files = [
{file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
{file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
@ -748,7 +800,7 @@ name = "jinja2"
version = "3.1.4"
requires_python = ">=3.7"
summary = "A very fast and expressive template engine."
groups = ["default"]
groups = ["default", "dev"]
dependencies = [
"MarkupSafe>=2.0",
]
@ -856,12 +908,23 @@ files = [
{file = "Mako-1.3.5.tar.gz", hash = "sha256:48dbc20568c1d276a2698b36d968fa76161bf127194907ea6fc594fa81f943bc"},
]
[[package]]
name = "markdown"
version = "3.7"
requires_python = ">=3.8"
summary = "Python implementation of John Gruber's Markdown."
groups = ["dev"]
files = [
{file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"},
{file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"},
]
[[package]]
name = "markupsafe"
version = "2.1.5"
requires_python = ">=3.7"
summary = "Safely add untrusted strings to HTML/XML markup."
groups = ["default"]
groups = ["default", "dev"]
files = [
{file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"},
{file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"},
@ -888,6 +951,147 @@ dependencies = [
"loguru<1.0.0,>=0.7.2",
]
[[package]]
name = "mergedeep"
version = "1.3.4"
requires_python = ">=3.6"
summary = "A deep merge function for 🐍."
groups = ["dev"]
files = [
{file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"},
{file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"},
]
[[package]]
name = "mkdocs"
version = "1.6.1"
requires_python = ">=3.8"
summary = "Project documentation with Markdown."
groups = ["dev"]
dependencies = [
"click>=7.0",
"colorama>=0.4; platform_system == \"Windows\"",
"ghp-import>=1.0",
"jinja2>=2.11.1",
"markdown>=3.3.6",
"markupsafe>=2.0.1",
"mergedeep>=1.3.4",
"mkdocs-get-deps>=0.2.0",
"packaging>=20.5",
"pathspec>=0.11.1",
"pyyaml-env-tag>=0.1",
"pyyaml>=5.1",
"watchdog>=2.0",
]
files = [
{file = "mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e"},
{file = "mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2"},
]
[[package]]
name = "mkdocs-autorefs"
version = "1.2.0"
requires_python = ">=3.8"
summary = "Automatically link across pages in MkDocs."
groups = ["dev"]
dependencies = [
"Markdown>=3.3",
"markupsafe>=2.0.1",
"mkdocs>=1.1",
]
files = [
{file = "mkdocs_autorefs-1.2.0-py3-none-any.whl", hash = "sha256:d588754ae89bd0ced0c70c06f58566a4ee43471eeeee5202427da7de9ef85a2f"},
{file = "mkdocs_autorefs-1.2.0.tar.gz", hash = "sha256:a86b93abff653521bda71cf3fc5596342b7a23982093915cb74273f67522190f"},
]
[[package]]
name = "mkdocs-get-deps"
version = "0.2.0"
requires_python = ">=3.8"
summary = "MkDocs extension that lists all dependencies according to a mkdocs.yml file"
groups = ["dev"]
dependencies = [
"mergedeep>=1.3.4",
"platformdirs>=2.2.0",
"pyyaml>=5.1",
]
files = [
{file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"},
{file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"},
]
[[package]]
name = "mkdocs-material"
version = "9.5.34"
requires_python = ">=3.8"
summary = "Documentation that simply works"
groups = ["dev"]
dependencies = [
"babel~=2.10",
"colorama~=0.4",
"jinja2~=3.0",
"markdown~=3.2",
"mkdocs-material-extensions~=1.3",
"mkdocs~=1.6",
"paginate~=0.5",
"pygments~=2.16",
"pymdown-extensions~=10.2",
"regex>=2022.4",
"requests~=2.26",
]
files = [
{file = "mkdocs_material-9.5.34-py3-none-any.whl", hash = "sha256:54caa8be708de2b75167fd4d3b9f3d949579294f49cb242515d4653dbee9227e"},
{file = "mkdocs_material-9.5.34.tar.gz", hash = "sha256:1e60ddf716cfb5679dfd65900b8a25d277064ed82d9a53cd5190e3f894df7840"},
]
[[package]]
name = "mkdocs-material-extensions"
version = "1.3.1"
requires_python = ">=3.8"
summary = "Extension pack for Python Markdown and MkDocs Material."
groups = ["dev"]
files = [
{file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"},
{file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"},
]
[[package]]
name = "mkdocstrings"
version = "0.26.0"
requires_python = ">=3.8"
summary = "Automatic documentation from sources, for MkDocs."
groups = ["dev"]
dependencies = [
"Jinja2>=2.11.1",
"Markdown>=3.6",
"MarkupSafe>=1.1",
"click>=7.0",
"mkdocs-autorefs>=1.2",
"mkdocs>=1.4",
"platformdirs>=2.2",
"pymdown-extensions>=6.3",
]
files = [
{file = "mkdocstrings-0.26.0-py3-none-any.whl", hash = "sha256:1aa227fe94f88e80737d37514523aacd473fc4b50a7f6852ce41447ab23f2654"},
{file = "mkdocstrings-0.26.0.tar.gz", hash = "sha256:ff9d0de28c8fa877ed9b29a42fe407cfe6736d70a1c48177aa84fcc3dc8518cd"},
]
[[package]]
name = "mkdocstrings-python"
version = "1.10.9"
requires_python = ">=3.8"
summary = "A Python handler for mkdocstrings."
groups = ["dev"]
dependencies = [
"griffe>=0.49",
"mkdocs-autorefs>=1.0",
"mkdocstrings>=0.25",
]
files = [
{file = "mkdocstrings_python-1.10.9-py3-none-any.whl", hash = "sha256:cbe98710a6757dfd4dff79bf36cb9731908fb4c69dd2736b15270ae7a488243d"},
{file = "mkdocstrings_python-1.10.9.tar.gz", hash = "sha256:f344aaa47e727d8a2dc911e063025e58e2b7fb31a41110ccc3902aa6be7ca196"},
]
[[package]]
name = "more-itertools"
version = "10.3.0"
@ -932,6 +1136,16 @@ files = [
{file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
]
[[package]]
name = "paginate"
version = "0.5.7"
summary = "Divides large result sets into pages for easier browsing"
groups = ["dev"]
files = [
{file = "paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591"},
{file = "paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945"},
]
[[package]]
name = "pathspec"
version = "0.12.1"
@ -1166,6 +1380,17 @@ files = [
{file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"},
]
[[package]]
name = "pygments"
version = "2.18.0"
requires_python = ">=3.8"
summary = "Pygments is a syntax highlighting package written in Python."
groups = ["dev"]
files = [
{file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
{file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
]
[[package]]
name = "pyjwt"
version = "2.9.0"
@ -1177,6 +1402,21 @@ files = [
{file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"},
]
[[package]]
name = "pymdown-extensions"
version = "10.9"
requires_python = ">=3.8"
summary = "Extension pack for Python Markdown."
groups = ["dev"]
dependencies = [
"markdown>=3.6",
"pyyaml",
]
files = [
{file = "pymdown_extensions-10.9-py3-none-any.whl", hash = "sha256:d323f7e90d83c86113ee78f3fe62fc9dee5f56b54d912660703ea1816fed5626"},
{file = "pymdown_extensions-10.9.tar.gz", hash = "sha256:6ff740bcd99ec4172a938970d42b96128bdc9d4b9bcad72494f29921dc69b753"},
]
[[package]]
name = "pyright"
version = "1.1.374"
@ -1242,7 +1482,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 = ["default"]
groups = ["default", "dev"]
dependencies = [
"six>=1.5",
]
@ -1278,7 +1518,7 @@ name = "pyyaml"
version = "6.0.1"
requires_python = ">=3.6"
summary = "YAML parser and emitter for Python"
groups = ["default"]
groups = ["default", "dev"]
files = [
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
@ -1290,6 +1530,20 @@ files = [
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
]
[[package]]
name = "pyyaml-env-tag"
version = "0.1"
requires_python = ">=3.6"
summary = "A custom YAML tag for referencing environment variables in YAML files. "
groups = ["dev"]
dependencies = [
"pyyaml",
]
files = [
{file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"},
{file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
]
[[package]]
name = "redis"
version = "5.0.8"
@ -1317,12 +1571,37 @@ files = [
{file = "redis-5.0.8.tar.gz", hash = "sha256:0c5b10d387568dfe0698c6fad6615750c24170e548ca2deac10c649d463e9870"},
]
[[package]]
name = "regex"
version = "2024.7.24"
requires_python = ">=3.8"
summary = "Alternative regular expression module, to replace re."
groups = ["dev"]
files = [
{file = "regex-2024.7.24-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:fe4ebef608553aff8deb845c7f4f1d0740ff76fa672c011cc0bacb2a00fbde86"},
{file = "regex-2024.7.24-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:74007a5b25b7a678459f06559504f1eec2f0f17bca218c9d56f6a0a12bfffdad"},
{file = "regex-2024.7.24-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7df9ea48641da022c2a3c9c641650cd09f0cd15e8908bf931ad538f5ca7919c9"},
{file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a1141a1dcc32904c47f6846b040275c6e5de0bf73f17d7a409035d55b76f289"},
{file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80c811cfcb5c331237d9bad3bea2c391114588cf4131707e84d9493064d267f9"},
{file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7214477bf9bd195894cf24005b1e7b496f46833337b5dedb7b2a6e33f66d962c"},
{file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d55588cba7553f0b6ec33130bc3e114b355570b45785cebdc9daed8c637dd440"},
{file = "regex-2024.7.24-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:558a57cfc32adcf19d3f791f62b5ff564922942e389e3cfdb538a23d65a6b610"},
{file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a512eed9dfd4117110b1881ba9a59b31433caed0c4101b361f768e7bcbaf93c5"},
{file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:86b17ba823ea76256b1885652e3a141a99a5c4422f4a869189db328321b73799"},
{file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5eefee9bfe23f6df09ffb6dfb23809f4d74a78acef004aa904dc7c88b9944b05"},
{file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:731fcd76bbdbf225e2eb85b7c38da9633ad3073822f5ab32379381e8c3c12e94"},
{file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eaef80eac3b4cfbdd6de53c6e108b4c534c21ae055d1dbea2de6b3b8ff3def38"},
{file = "regex-2024.7.24-cp312-cp312-win32.whl", hash = "sha256:185e029368d6f89f36e526764cf12bf8d6f0e3a2a7737da625a76f594bdfcbfc"},
{file = "regex-2024.7.24-cp312-cp312-win_amd64.whl", hash = "sha256:2f1baff13cc2521bea83ab2528e7a80cbe0ebb2c6f0bfad15be7da3aed443908"},
{file = "regex-2024.7.24.tar.gz", hash = "sha256:9cfd009eed1a46b27c14039ad5bbc5e71b6367c5b2e6d5f5da0ea91600817506"},
]
[[package]]
name = "requests"
version = "2.32.3"
requires_python = ">=3.8"
summary = "Python HTTP for Humans."
groups = ["default"]
groups = ["default", "dev"]
dependencies = [
"certifi>=2017.4.17",
"charset-normalizer<4,>=2",
@ -1339,7 +1618,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 = ["default"]
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"},
@ -1471,7 +1750,7 @@ name = "typing-extensions"
version = "4.12.2"
requires_python = ">=3.8"
summary = "Backported and Experimental Type Hints for Python 3.8+"
groups = ["default"]
groups = ["default", "dev"]
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"},
@ -1493,7 +1772,7 @@ name = "urllib3"
version = "2.2.2"
requires_python = ">=3.8"
summary = "HTTP library with thread-safe connection pooling, file post, and more."
groups = ["default"]
groups = ["default", "dev"]
files = [
{file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
{file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
@ -1579,6 +1858,33 @@ files = [
{file = "vine-5.1.0.tar.gz", hash = "sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0"},
]
[[package]]
name = "watchdog"
version = "5.0.0"
requires_python = ">=3.9"
summary = "Filesystem events monitoring"
groups = ["dev"]
files = [
{file = "watchdog-5.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1e26f570dd7f5178656affb24d6f0e22ce66c8daf88d4061a27bfb9ac866b40d"},
{file = "watchdog-5.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d146331e6b206baa9f6dd40f72b5783ad2302c240df68e7fce196d30588ccf7b"},
{file = "watchdog-5.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6c96b1706430839872a3e33b9370ee3f7a0079f6b828129d88498ad1f96a0f45"},
{file = "watchdog-5.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:bc16d448a74a929b896ed9578c25756b2125400b19b3258be8d9a681c7ae8e71"},
{file = "watchdog-5.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:7e6b0e9b8a9dc3865d65888b5f5222da4ba9c4e09eab13cff5e305e7b7e7248f"},
{file = "watchdog-5.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4fe6780915000743074236b21b6c37419aea71112af62237881bc265589fe463"},
{file = "watchdog-5.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0710e9502727f688a7e06d48078545c54485b3d6eb53b171810879d8223c362a"},
{file = "watchdog-5.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:d76efab5248aafbf8a2c2a63cd7b9545e6b346ad1397af8b862a3bb3140787d8"},
{file = "watchdog-5.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:ff4e957c45c446de34c513eadce01d0b65da7eee47c01dce472dd136124552c9"},
{file = "watchdog-5.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:16c1aa3377bb1f82c5e24277fcbf4e2cac3c4ce46aaaf7212d53caa9076eb7b7"},
{file = "watchdog-5.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:22fcad6168fc43cf0e709bd854be5b8edbb0b260f0a6f28f1ea9baa53c6907f7"},
{file = "watchdog-5.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:0120b2fa65732797ffa65fa8ee5540c288aa861d91447df298626d6385a24658"},
{file = "watchdog-5.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2aa59fab7ff75281778c649557275ca3085eccbdf825a0e2a5ca3810e977afe5"},
{file = "watchdog-5.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:78db0fe0336958fc0e1269545c980b6f33d04d184ba191b2800a8b71d3e971a9"},
{file = "watchdog-5.0.0-py3-none-win32.whl", hash = "sha256:d1acef802916083f2ad7988efc7decf07e46e266916c0a09d8fb9d387288ea12"},
{file = "watchdog-5.0.0-py3-none-win_amd64.whl", hash = "sha256:3c2d50fdb86aa6df3973313272f5a17eb26eab29ff5a0bf54b6d34597b4dc4e4"},
{file = "watchdog-5.0.0-py3-none-win_ia64.whl", hash = "sha256:1d17ec7e022c34fa7ddc72aa41bf28c9d1207ffb193df18ba4f6fde453725b3c"},
{file = "watchdog-5.0.0.tar.gz", hash = "sha256:990aedb9e2f336b45a70aed9c014450e7c4a70fd99c5f5b1834d57e1453a177e"},
]
[[package]]
name = "watchfiles"
version = "0.22.0"

View File

@ -48,7 +48,7 @@ requires = ["pdm-backend"]
build-backend = "pdm.backend"
[project.scripts]
materia = "materia.main:main"
materia = "materia.app.cli:cli"
[tool.pyright]
reportGeneralTypeIssues = false
@ -70,6 +70,9 @@ dev = [
"pytest-asyncio>=0.23.7",
"asgi-lifespan>=2.1.0",
"pytest-cov>=5.0.0",
"mkdocs-material>=9.5.34",
"mkdocstrings-python>=1.10.9",
"griffe-typingdoc>=0.2.6",
]
[tool.pdm.build]

View File

@ -2,11 +2,13 @@ from contextlib import _AsyncGeneratorContextManager, asynccontextmanager
import os
import sys
from typing import AsyncIterator, TypedDict, Self, Optional
from pathlib import Path
import uvicorn
from fastapi import FastAPI
from fastapi.routing import APIRoute
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from materia.core import (
Config,
Logger,
@ -78,8 +80,9 @@ class Application:
async def prepare_working_directory(self):
try:
self.logger.debug("Changing working directory")
os.chdir(self.config.application.working_directory.resolve())
path = self.config.application.working_directory.resolve()
self.logger.debug(f"Changing working directory to {path}")
os.chdir(path)
except FileNotFoundError as e:
self.logger.error("Failed to change working directory: {}", e)
sys.exit()
@ -117,7 +120,11 @@ class Application:
self.backend = FastAPI(
title="materia",
version="0.1.0",
docs_url="/api/docs",
docs_url=None,
redoc_url=None,
swagger_ui_init_oauth=None,
swagger_ui_oauth2_redirect_url=None,
openapi_url="/api/openapi.json",
lifespan=lifespan,
)
self.backend.add_middleware(
@ -127,6 +134,7 @@ class Application:
allow_methods=["*"],
allow_headers=["*"],
)
self.backend.include_router(routers.docs.router)
self.backend.include_router(routers.api.router)
self.backend.include_router(routers.resources.router)
self.backend.include_router(routers.root.router)

View File

@ -15,7 +15,8 @@ def cli():
@cli.command()
@click.option("--config", type=Path)
def start(config: Path):
@click.option("--debug", "-d", is_flag=True, default=False, help="Enable debug output.")
def start(config: Path, debug: bool):
config_path = config
logger = Logger.new()
@ -48,6 +49,9 @@ def start(config: Path):
logger.info("Using the default configuration.")
config = Config()
if debug:
config.log.level = "debug"
async def main():
app = await Application.new(config)
await app.start()

View File

@ -150,7 +150,7 @@ class Repository(BaseModel):
capacity: int = 5 << 30
class Config(BaseSettings, env_prefix="materia_", env_nested_delimiter="_"):
class Config(BaseSettings, env_prefix="materia_", env_nested_delimiter="__"):
application: Application = Application()
log: Log = Log()
server: Server = Server()

View File

@ -77,7 +77,9 @@ class Database:
async with database.connection() as connection:
await connection.rollback()
except Exception as e:
raise DatabaseError(f"Failed to connect to database: {url}") from e
raise DatabaseError(
f"Failed to connect to database '{url}': {e}"
) from e
return database

View File

@ -1 +1 @@
from materia.routers import middleware, api, resources, root
from materia.routers import middleware, api, resources, root, docs

View File

@ -1,11 +1,17 @@
from fastapi import APIRouter
from fastapi import APIRouter, HTTPException
from materia.routers.api.auth import auth, oauth
from materia.routers.api import user, repository, directory, file
from materia.routers.api import docs, user, repository, directory, file
router = APIRouter(prefix="/api")
router.include_router(docs.router)
router.include_router(auth.router)
router.include_router(oauth.router)
router.include_router(user.router)
router.include_router(repository.router)
router.include_router(directory.router)
router.include_router(file.router)
@router.get("/api/{catchall:path}", status_code=404, include_in_schema=False)
def not_found():
raise HTTPException(status_code=404)

View File

View File

@ -0,0 +1,40 @@
from fastapi import APIRouter, Request
from fastapi.responses import HTMLResponse
router = APIRouter()
@router.get("/docs", response_class=HTMLResponse, include_in_schema=False)
async def rapidoc(request: Request):
return f"""
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<link href='http://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
<script
type="module"
src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"
></script>
</head>
<body>
<rapi-doc
spec-url="{request.app.openapi_url}"
theme = "dark"
show-header = "false"
show-info = "true"
allow-authentication = "true"
allow-server-selection = "true"
allow-api-list-style-selection = "true"
theme = "dark"
render-style = "focused"
bg-color="#1e2129"
primary-color="#a47bea"
regular-font="Roboto"
mono-font="Roboto Mono"
show-method-in-nav-bar="as-colored-text">
<img slot="logo" style="display: none"/>
</rapi-doc>
</body>
</html>
"""

View File

@ -0,0 +1,33 @@
from fastapi import APIRouter, Request, Response, status, HTTPException, Depends
from fastapi.responses import HTMLResponse, FileResponse
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
import mimetypes
from pathlib import Path
from materia.core.misc import optional
from materia.routers import middleware
from materia import docs as materia_docs
router = APIRouter()
# templates = Jinja2Templates(directory=Path(materia_docs.__path__[0]))
# p = Path(__file__).parent.joinpath("..", "docs").resolve()
# router.mount("/docs", StaticFiles(directory="doces", html=True), name="docs")
@router.get("/docs/{catchall:path}", include_in_schema=False)
async def docs(request: Request, ctx: middleware.Context = Depends()):
docs_directory = Path(materia_docs.__path__[0]).resolve()
target = docs_directory.joinpath(request.path_params["catchall"]).resolve()
if not optional(target.relative_to, docs_directory):
raise HTTPException(status.HTTP_403_FORBIDDEN)
if target.is_dir() and (index := target.joinpath("index.html")).is_file():
return FileResponse(index)
if not target.is_file():
raise HTTPException(status.HTTP_404_NOT_FOUND)
return FileResponse(target)

View File

@ -1,5 +1,5 @@
from pathlib import Path
from fastapi import APIRouter, Request
from fastapi import APIRouter, Request, HTTPException
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
@ -13,6 +13,7 @@ else:
templates = Jinja2Templates(directory=Path(materia_frontend.__path__[0]) / "dist")
@router.get("/{spa:path}", response_class=HTMLResponse)
@router.get("/{spa:path}", response_class=HTMLResponse, include_in_schema=False)
async def root(request: Request):
# raise HTTPException(404)
return templates.TemplateResponse(request, "base.html", {"view": "app"})