cloudoll 4.1.0__tar.gz → 4.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. cloudoll-4.2.1/AGENTS.md +5 -0
  2. cloudoll-4.2.1/AI.md +32 -0
  3. {cloudoll-4.1.0 → cloudoll-4.2.1}/CHANGELOG.md +23 -0
  4. {cloudoll-4.1.0 → cloudoll-4.2.1}/MANIFEST.in +2 -0
  5. {cloudoll-4.1.0/cloudoll.egg-info → cloudoll-4.2.1}/PKG-INFO +16 -7
  6. {cloudoll-4.1.0 → cloudoll-4.2.1}/README.md +15 -6
  7. {cloudoll-4.1.0 → cloudoll-4.2.1}/README.zh-CN.md +18 -9
  8. cloudoll-4.2.1/cloudoll/__init__.py +1 -0
  9. cloudoll-4.2.1/cloudoll/ai/AGENTS.md +7 -0
  10. cloudoll-4.2.1/cloudoll/ai/__init__.py +1 -0
  11. cloudoll-4.2.1/cloudoll/ai/commands.py +106 -0
  12. cloudoll-4.2.1/cloudoll/ai/docs/ai.md +61 -0
  13. cloudoll-4.2.1/cloudoll/ai/docs/app-start.md +81 -0
  14. cloudoll-4.2.1/cloudoll/ai/docs/changelog.md +193 -0
  15. cloudoll-4.2.1/cloudoll/ai/docs/config.md +150 -0
  16. cloudoll-4.2.1/cloudoll/ai/docs/cookie-and-session.md +124 -0
  17. cloudoll-4.2.1/cloudoll/ai/docs/database.md +340 -0
  18. cloudoll-4.2.1/cloudoll/ai/docs/deployment.md +131 -0
  19. cloudoll-4.2.1/cloudoll/ai/docs/event-source.md +62 -0
  20. cloudoll-4.2.1/cloudoll/ai/docs/exception.md +68 -0
  21. cloudoll-4.2.1/cloudoll/ai/docs/file-uploads.md +88 -0
  22. cloudoll-4.2.1/cloudoll/ai/docs/http-client.md +70 -0
  23. cloudoll-4.2.1/cloudoll/ai/docs/jwt.md +88 -0
  24. cloudoll-4.2.1/cloudoll/ai/docs/logs.md +191 -0
  25. cloudoll-4.2.1/cloudoll/ai/docs/middleware.md +63 -0
  26. cloudoll-4.2.1/cloudoll/ai/docs/migration.md +85 -0
  27. cloudoll-4.2.1/cloudoll/ai/docs/router.md +115 -0
  28. cloudoll-4.2.1/cloudoll/ai/docs/start.md +93 -0
  29. cloudoll-4.2.1/cloudoll/ai/docs/structure.md +65 -0
  30. cloudoll-4.2.1/cloudoll/ai/docs/validation.md +121 -0
  31. cloudoll-4.2.1/cloudoll/ai/docs/view.md +63 -0
  32. cloudoll-4.2.1/cloudoll/ai/docs/websockets.md +67 -0
  33. cloudoll-4.2.1/cloudoll/ai/manifest.json +110 -0
  34. cloudoll-4.2.1/cloudoll/ai/skills/cloudoll/SKILL.md +46 -0
  35. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/cli.py +4 -0
  36. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/clitool/cli_main.py +3 -0
  37. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/README.md +6 -1
  38. cloudoll-4.2.1/cloudoll/template/requirements.txt +1 -0
  39. {cloudoll-4.1.0 → cloudoll-4.2.1/cloudoll.egg-info}/PKG-INFO +16 -7
  40. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll.egg-info/SOURCES.txt +30 -0
  41. {cloudoll-4.1.0 → cloudoll-4.2.1}/pyproject.toml +1 -0
  42. cloudoll-4.2.1/scripts/sync_ai_docs.py +83 -0
  43. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/check_wheel.py +8 -0
  44. cloudoll-4.2.1/tests/test_ai.py +89 -0
  45. cloudoll-4.1.0/cloudoll/__init__.py +0 -1
  46. cloudoll-4.1.0/cloudoll/template/requirements.txt +0 -1
  47. {cloudoll-4.1.0 → cloudoll-4.2.1}/LICENSE +0 -0
  48. {cloudoll-4.1.0 → cloudoll-4.2.1}/SECURITY.md +0 -0
  49. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/__main__.py +0 -0
  50. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/clitool/__init__.py +0 -0
  51. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/clitool/m2d.py +0 -0
  52. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/clitool/process.py +0 -0
  53. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/clitool/schema.py +0 -0
  54. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/clitool/spinner.py +0 -0
  55. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/clitool/watch.py +0 -0
  56. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/logging/__init__.py +0 -0
  57. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/mail/__init__.py +0 -0
  58. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/mail/smtp.py +0 -0
  59. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/observability.py +0 -0
  60. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/__init__.py +0 -0
  61. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/aws_engine.py +0 -0
  62. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/awsmysql.py +0 -0
  63. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/awspostgres.py +0 -0
  64. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/base.py +0 -0
  65. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/compiler.py +0 -0
  66. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/datasources.py +0 -0
  67. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/dialects.py +0 -0
  68. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/engine.py +0 -0
  69. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/field.py +0 -0
  70. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/model.py +0 -0
  71. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/mysql.py +0 -0
  72. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/parse.py +0 -0
  73. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/postgres.py +0 -0
  74. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/protocols.py +0 -0
  75. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/query.py +0 -0
  76. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/savepoints.py +0 -0
  77. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/streaming.py +0 -0
  78. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/test_sql.py +0 -0
  79. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/orm/values.py +0 -0
  80. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/py.typed +0 -0
  81. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/__init__.py +0 -0
  82. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/config/conf.local.yaml +0 -0
  83. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/controllers/admin/test.py +0 -0
  84. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/controllers/api/index.py +0 -0
  85. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/controllers/es/es.py +0 -0
  86. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/controllers/home/index.py +0 -0
  87. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/controllers/upload/upload.py +0 -0
  88. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/controllers/ws/ws.py +0 -0
  89. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/middlewares/auth.py +0 -0
  90. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/static/css/index.css +0 -0
  91. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/static/img/cat.avif +0 -0
  92. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/static/js/index.js +0 -0
  93. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/template/templates/index.html +0 -0
  94. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/utils/__init__.py +0 -0
  95. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/utils/async_tools.py +0 -0
  96. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/utils/common.py +0 -0
  97. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/utils/password.py +0 -0
  98. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/utils/snowflake.py +0 -0
  99. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/__init__.py +0 -0
  100. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/configuration.py +0 -0
  101. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/context.py +0 -0
  102. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/core.py +0 -0
  103. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/exception.py +0 -0
  104. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/html.py +0 -0
  105. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/jwt.py +0 -0
  106. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/lifecycle.py +0 -0
  107. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/request_data.py +0 -0
  108. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/requests.py +0 -0
  109. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/resources.py +0 -0
  110. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/routing.py +0 -0
  111. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/sessions.py +0 -0
  112. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/settings.py +0 -0
  113. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/types.py +0 -0
  114. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll/web/validation.py +0 -0
  115. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll.egg-info/dependency_links.txt +0 -0
  116. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll.egg-info/entry_points.txt +0 -0
  117. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll.egg-info/requires.txt +0 -0
  118. {cloudoll-4.1.0 → cloudoll-4.2.1}/cloudoll.egg-info/top_level.txt +0 -0
  119. {cloudoll-4.1.0 → cloudoll-4.2.1}/docs/architecture.md +0 -0
  120. {cloudoll-4.1.0 → cloudoll-4.2.1}/docs/aurora.md +0 -0
  121. {cloudoll-4.1.0 → cloudoll-4.2.1}/docs/maintenance.md +0 -0
  122. {cloudoll-4.1.0 → cloudoll-4.2.1}/docs/production.md +0 -0
  123. {cloudoll-4.1.0 → cloudoll-4.2.1}/docs/reliability.md +0 -0
  124. {cloudoll-4.1.0 → cloudoll-4.2.1}/docs/schema-generation.md +0 -0
  125. {cloudoll-4.1.0 → cloudoll-4.2.1}/docs/streaming-and-types.md +0 -0
  126. {cloudoll-4.1.0 → cloudoll-4.2.1}/setup.cfg +0 -0
  127. {cloudoll-4.1.0 → cloudoll-4.2.1}/setup.py +0 -0
  128. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/audit_dependencies.py +0 -0
  129. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/check_release.py +0 -0
  130. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/conftest.py +0 -0
  131. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/integration/test_aws_failover.py +0 -0
  132. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/integration/test_databases.py +0 -0
  133. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/integration/test_savepoints.py +0 -0
  134. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/integration/test_schema.py +0 -0
  135. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/integration/test_streaming.py +0 -0
  136. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/run_local_databases.py +0 -0
  137. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_architecture.py +0 -0
  138. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_datasources.py +0 -0
  139. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_dev_lifecycle.py +0 -0
  140. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_field_types.py +0 -0
  141. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_production_contracts.py +0 -0
  142. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_regressions.py +0 -0
  143. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_release_workflow.py +0 -0
  144. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_request_contract.py +0 -0
  145. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_retry_and_query_regressions.py +0 -0
  146. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_review_fixes.py +0 -0
  147. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_save_snapshots_and_cleanup.py +0 -0
  148. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_savepoint_unit.py +0 -0
  149. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_schema_generation.py +0 -0
  150. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_sql_echo.py +0 -0
  151. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_startup_logging.py +0 -0
  152. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_streaming_unit.py +0 -0
  153. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_transactions.py +0 -0
  154. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_typing_regressions.py +0 -0
  155. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/test_validation.py +0 -0
  156. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/typing/engine_contract.py +0 -0
  157. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/typing/field_contract.py +0 -0
  158. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/typing/middleware_contract.py +0 -0
  159. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/typing/production_contract.py +0 -0
  160. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/typing/query_contract.py +0 -0
  161. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/typing/request_contract.py +0 -0
  162. {cloudoll-4.1.0 → cloudoll-4.2.1}/tests/typing/web_contract.py +0 -0
@@ -0,0 +1,5 @@
1
+ # Cloudoll library maintenance
2
+
3
+ This repository implements Cloudoll; it is not a generated application. Read `AI.md` before changing AI assets. Public API behavior must be verified against source and tests, not inferred from other frameworks. The application-development skill is `cloudoll/ai/skills/cloudoll/SKILL.md`; read it when creating application examples.
4
+
5
+ Official documentation is maintained in the sibling `cloudoll-py-docs` repository, under `src/views`. Bundled copies in `cloudoll/ai/docs` are generated: edit the original docs, then run the sync command in `AI.md`. Update docs and tests together when changing public behavior. Preserve Python 3.9 compatibility.
cloudoll-4.2.1/AI.md ADDED
@@ -0,0 +1,32 @@
1
+ # AI-assisted Cloudoll development
2
+
3
+ For application developers, `cloudoll create PROJECT` installs an `AGENTS.md` entry and `.agents/skills/cloudoll/SKILL.md`. Existing projects can run `python -m cloudoll.cli ai init .`. Existing user instructions are preserved; a different/customized skill is never silently replaced.
4
+
5
+ No MCP server is required:
6
+
7
+ ```sh
8
+ python -m cloudoll.cli ai list
9
+ python -m cloudoll.cli ai read structure
10
+ python -m cloudoll.cli ai read database
11
+ python -m cloudoll.cli ai search Body
12
+ ```
13
+
14
+ Use the project's Python environment. Ask your coding agent to read the project `AGENTS.md` and Cloudoll skill before coding. Tools that do not discover these files automatically can be given the paths explicitly. These instructions improve discoverability; they cannot guarantee that every model obeys them.
15
+
16
+ ## Maintaining the assets
17
+
18
+ `cloudoll/ai/docs` contains verbatim snapshots of the official site's Markdown, not hand-maintained API summaries. `manifest.json` records the library version, source path, public URL, and SHA-256 for every topic. Relative site links in these snapshots refer to https://cloudoll.chuchur.com.
19
+
20
+ From the library root, with the documentation repository available:
21
+
22
+ ```sh
23
+ python scripts/sync_ai_docs.py --docs-root ../cloudoll-py-docs
24
+ python scripts/sync_ai_docs.py --docs-root ../cloudoll-py-docs --check
25
+ python -m pytest tests/test_ai.py
26
+ python -m build
27
+ python tests/check_wheel.py dist/cloudoll-VERSION-py3-none-any.whl
28
+ ```
29
+
30
+ The sync also generates the site's `public/llms.txt` and `public/llms-full.txt`. Commit both repositories' changes. These files are discovery aids, not a replacement for version-matched local docs. When upgrading Cloudoll in an existing application, review its installed skill against the packaged skill and merge intentional changes; initialization refuses a differing skill to avoid overwriting custom instructions.
31
+
32
+ Before release, run the cross-repository `--check` command. Tests validate the packaged snapshot integrity and version; they cannot detect uncommitted changes in an unavailable documentation repository.
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.2.1
4
+
5
+ - Correct the AI initialization regression test to compare the original bytes
6
+ rather than assume LF newlines on Windows. Keep preservation and idempotence
7
+ assertions enabled on every platform.
8
+ - Normalize the generated full documentation's trailing newline.
9
+ - Include all 4.2.0 features. The 4.2.0 tag was blocked by Windows CI and was
10
+ not published to PyPI; 4.2.1 is the replacement release.
11
+
12
+ ## 4.2.0
13
+
14
+ Backward-compatible AI-assisted development release. Python 3.9+ remains supported.
15
+
16
+ - Add offline `cloudoll ai list`, `read`, and `search` commands for bundled official
17
+ documentation, with source URLs, version metadata and content integrity checks.
18
+ - Add `cloudoll ai init` for existing projects. New scaffolds automatically include
19
+ an AGENTS.md entry and a project-local Cloudoll skill covering documented project
20
+ structure, validation, ORM, resource lifecycle, security and verification.
21
+ - Preserve existing project instructions and refuse to overwrite customized skills
22
+ or write through symbolic links. Initialization is repeatable.
23
+ - Add documentation synchronization tooling and website LLM discovery assets.
24
+ Test both instruction initialization and AI resources in the built wheel.
25
+
3
26
  ## 4.1.0
4
27
 
5
28
  Backward-compatible feature release. Pydantic 2 (`>=2.0,<3`) is now a core
@@ -1,4 +1,6 @@
1
1
  recursive-include tests *.py
2
2
  include README.zh-CN.md
3
+ include AI.md AGENTS.md
4
+ include scripts/sync_ai_docs.py
3
5
  include CHANGELOG.md SECURITY.md
4
6
  recursive-include docs *.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudoll
3
- Version: 4.1.0
3
+ Version: 4.2.1
4
4
  Summary: Assist in quickly creating distributable microservices based on aiohttp, with a focus on simplicity and ease of use.
5
5
  Author-email: Qiu <smallerqiu@gmail.com>
6
6
  License-Expression: MIT
@@ -54,16 +54,25 @@ Dynamic: license-file
54
54
 
55
55
  English | [简体中文](README.zh-CN.md)
56
56
 
57
- Cloudoll 4.1.0 is an aiohttp-based Python library for routing, middleware,
57
+ Cloudoll 4.2.1 is an aiohttp-based Python library for routing, middleware,
58
58
  templates, sessions, JWT, database access and application scaffolding.
59
59
 
60
+ ## AI-assisted development
61
+
62
+ New scaffolds include `AGENTS.md` and a project-local Cloudoll skill. For existing
63
+ projects, run `cloudoll ai init .` in the project's Python environment. Query the
64
+ bundled official documentation offline with `cloudoll ai list`,
65
+ `cloudoll ai read database`, or `cloudoll ai search Body`. No MCP is required.
66
+ See [AI.md](AI.md) for version matching and maintenance. If your installed release
67
+ does not have `cloudoll ai --help`, consult its matching README and source first.
68
+
60
69
  ## Install
61
70
 
62
71
  Python 3.9+ is required. Install only the optional drivers you use:
63
72
 
64
73
  ```sh
65
- python -m pip install 'cloudoll==4.1.0'
66
- python -m pip install 'cloudoll[mysql,postgres,cache]==4.1.0'
74
+ python -m pip install 'cloudoll==4.2.1'
75
+ python -m pip install 'cloudoll[mysql,postgres,cache]==4.2.1'
67
76
  ```
68
77
 
69
78
  The AWS extra requires Python 3.10+. Aurora remains untested; see
@@ -78,7 +87,7 @@ python -m pip install -r requirements.txt
78
87
  cloudoll start -n myapp
79
88
  ```
80
89
 
81
- The generated project targets 4.1.0 and receives a random JWT secret. Controllers
90
+ The generated project targets 4.2.1 and receives a random JWT secret. Controllers
82
91
  and authentication middleware are examples: replace demo credentials and supply
83
92
  your own authorization and upload policies before deployment.
84
93
 
@@ -163,8 +172,8 @@ python -m ruff check cloudoll tests
163
172
  python -m mypy
164
173
  python -m pytest -q -m 'not integration' -k 'not aws'
165
174
  python -m build
166
- python tests/check_wheel.py dist/cloudoll-4.1.0-py3-none-any.whl
167
- python tests/check_release.py dist/cloudoll-4.1.0-py3-none-any.whl
175
+ python tests/check_wheel.py dist/cloudoll-4.2.1-py3-none-any.whl
176
+ python tests/check_release.py dist/cloudoll-4.2.1-py3-none-any.whl
168
177
  ```
169
178
 
170
179
  Native integration tests require explicitly configured disposable databases.
@@ -2,16 +2,25 @@
2
2
 
3
3
  English | [简体中文](README.zh-CN.md)
4
4
 
5
- Cloudoll 4.1.0 is an aiohttp-based Python library for routing, middleware,
5
+ Cloudoll 4.2.1 is an aiohttp-based Python library for routing, middleware,
6
6
  templates, sessions, JWT, database access and application scaffolding.
7
7
 
8
+ ## AI-assisted development
9
+
10
+ New scaffolds include `AGENTS.md` and a project-local Cloudoll skill. For existing
11
+ projects, run `cloudoll ai init .` in the project's Python environment. Query the
12
+ bundled official documentation offline with `cloudoll ai list`,
13
+ `cloudoll ai read database`, or `cloudoll ai search Body`. No MCP is required.
14
+ See [AI.md](AI.md) for version matching and maintenance. If your installed release
15
+ does not have `cloudoll ai --help`, consult its matching README and source first.
16
+
8
17
  ## Install
9
18
 
10
19
  Python 3.9+ is required. Install only the optional drivers you use:
11
20
 
12
21
  ```sh
13
- python -m pip install 'cloudoll==4.1.0'
14
- python -m pip install 'cloudoll[mysql,postgres,cache]==4.1.0'
22
+ python -m pip install 'cloudoll==4.2.1'
23
+ python -m pip install 'cloudoll[mysql,postgres,cache]==4.2.1'
15
24
  ```
16
25
 
17
26
  The AWS extra requires Python 3.10+. Aurora remains untested; see
@@ -26,7 +35,7 @@ python -m pip install -r requirements.txt
26
35
  cloudoll start -n myapp
27
36
  ```
28
37
 
29
- The generated project targets 4.1.0 and receives a random JWT secret. Controllers
38
+ The generated project targets 4.2.1 and receives a random JWT secret. Controllers
30
39
  and authentication middleware are examples: replace demo credentials and supply
31
40
  your own authorization and upload policies before deployment.
32
41
 
@@ -111,8 +120,8 @@ python -m ruff check cloudoll tests
111
120
  python -m mypy
112
121
  python -m pytest -q -m 'not integration' -k 'not aws'
113
122
  python -m build
114
- python tests/check_wheel.py dist/cloudoll-4.1.0-py3-none-any.whl
115
- python tests/check_release.py dist/cloudoll-4.1.0-py3-none-any.whl
123
+ python tests/check_wheel.py dist/cloudoll-4.2.1-py3-none-any.whl
124
+ python tests/check_release.py dist/cloudoll-4.2.1-py3-none-any.whl
116
125
  ```
117
126
 
118
127
  Native integration tests require explicitly configured disposable databases.
@@ -6,7 +6,16 @@
6
6
 
7
7
  Cloudoll 是一个基于 aiohttp 的 Python Web 开发库,提供路由自动注册、中间件、模板渲染、会话管理、JWT、数据库访问及命令行脚手架,帮助快速构建 Web 应用和微服务。
8
8
 
9
- 本文适用于 Cloudoll 4.1.0。从 3.x 升级前请阅读下方迁移说明。
9
+ 本文适用于 Cloudoll 4.2.1。从 3.x 升级前请阅读下方迁移说明。
10
+
11
+ ## AI 辅助开发
12
+
13
+ 新建项目会自带 `AGENTS.md` 和项目级 Cloudoll Skill;已有项目可以在其 Python
14
+ 环境中运行 `cloudoll ai init .` 补装。通过 `cloudoll ai list`、
15
+ `cloudoll ai read database` 和 `cloudoll ai search Body` 离线查询随包分发的官方文档,
16
+ 不需要 MCP。请让 AI 先读项目指令,再按文档设计实现。
17
+ 版本匹配及维护方式见 [AI.md](AI.md)。如果安装版本还不支持 `cloudoll ai --help`,
18
+ 请先查阅该版本的 README 和源码。
10
19
 
11
20
  ## 环境要求
12
21
 
@@ -16,10 +25,10 @@ Cloudoll 是一个基于 aiohttp 的 Python Web 开发库,提供路由自动
16
25
 
17
26
  ## 安装
18
27
 
19
- 安装 4.1.0:
28
+ 安装 4.2.1:
20
29
 
21
30
  ```sh
22
- python -m pip install 'cloudoll==4.1.0'
31
+ python -m pip install 'cloudoll==4.2.1'
23
32
  ```
24
33
 
25
34
  在当前仓库目录安装源码:
@@ -32,16 +41,16 @@ python -m pip install -e .
32
41
 
33
42
  ```sh
34
43
  # MySQL
35
- python -m pip install 'cloudoll[mysql]==4.1.0'
44
+ python -m pip install 'cloudoll[mysql]==4.2.1'
36
45
 
37
46
  # PostgreSQL
38
- python -m pip install 'cloudoll[postgres]==4.1.0'
47
+ python -m pip install 'cloudoll[postgres]==4.2.1'
39
48
 
40
49
  # AWS 数据库驱动
41
- python -m pip install 'cloudoll[aws]==4.1.0'
50
+ python -m pip install 'cloudoll[aws]==4.2.1'
42
51
 
43
52
  # Redis / Memcached 会话或 Redis 数据库
44
- python -m pip install 'cloudoll[cache]==4.1.0'
53
+ python -m pip install 'cloudoll[cache]==4.2.1'
45
54
  ```
46
55
 
47
56
  源码开发时可用 `python -m pip install -e '.[mysql,postgres,cache,dev]'` 安装。
@@ -537,8 +546,8 @@ cloudoll restart -n myapp
537
546
  python -m pip install -e '.[mysql,postgres,cache,dev]'
538
547
  python -m pytest -q -m 'not integration' -k 'not aws'
539
548
  python -m build
540
- python tests/check_wheel.py dist/cloudoll-4.1.0-py3-none-any.whl
541
- python tests/check_release.py dist/cloudoll-4.1.0-py3-none-any.whl
549
+ python tests/check_wheel.py dist/cloudoll-4.2.1-py3-none-any.whl
550
+ python tests/check_release.py dist/cloudoll-4.2.1-py3-none-any.whl
542
551
  ```
543
552
 
544
553
  最后一条命令用于验证构建出的 wheel,版本号变化后请调整文件名。测试使用模拟数据库连接及本机 HTTP 服务;真实数据库连接和 AWS 故障切换需要单独的集成环境。
@@ -0,0 +1 @@
1
+ __version__ = "4.2.1"
@@ -0,0 +1,7 @@
1
+ ## Cloudoll development
2
+
3
+ Before building or changing a Cloudoll application, read `.agents/skills/cloudoll/SKILL.md` completely and follow its documentation workflow. Use the project's Python environment, not a globally installed version.
4
+
5
+ Official documentation is bundled with the installed library: `python -m cloudoll.cli ai list`, `ai read <topic>`, and `ai search <query>`. These commands work offline without MCP. Read `structure`, `config`, `router`, and `validation` before designing an application; read `database` before database work. Consult the installed source when resolving a signature discrepancy; report the discrepancy rather than inventing an API.
6
+
7
+ Prefer the documented scaffold, auto-discovered controllers/middlewares, YAML configuration, framework-owned database lifecycle, typed request validation, and ORM for ordinary CRUD. Low-level alternatives require a task-specific reason. Never silently replace Cloudoll's architecture with patterns from another framework.
@@ -0,0 +1 @@
1
+ """Versioned documentation and project instructions for AI-assisted development."""
@@ -0,0 +1,106 @@
1
+ """Offline documentation queries and non-destructive project setup."""
2
+
3
+ from importlib.resources import files
4
+ from pathlib import Path
5
+
6
+ import click
7
+
8
+ BEGIN = "<!-- cloudoll-ai:start -->"
9
+ END = "<!-- cloudoll-ai:end -->"
10
+
11
+
12
+ def document_topics() -> list[str]:
13
+ return sorted(
14
+ p.name[:-3]
15
+ for p in files("cloudoll.ai").joinpath("docs").iterdir()
16
+ if p.name.endswith(".md")
17
+ )
18
+
19
+
20
+ def read_document(topic: str) -> str:
21
+ if topic not in document_topics():
22
+ raise click.ClickException("Unknown topic. Run `cloudoll ai list`.")
23
+ return (
24
+ files("cloudoll.ai")
25
+ .joinpath("docs")
26
+ .joinpath(topic + ".md")
27
+ .read_text(encoding="utf-8")
28
+ )
29
+
30
+
31
+ def initialize_project(directory: Path) -> None:
32
+ """Preserve user instructions; refuse to replace a customized skill."""
33
+ agents = directory / "AGENTS.md"
34
+ skill = directory / ".agents" / "skills" / "cloudoll" / "SKILL.md"
35
+ resource = files("cloudoll.ai")
36
+ skill_text = (
37
+ resource.joinpath("skills")
38
+ .joinpath("cloudoll")
39
+ .joinpath("SKILL.md")
40
+ .read_text(encoding="utf-8")
41
+ )
42
+ instructions = resource.joinpath("AGENTS.md").read_text(encoding="utf-8")
43
+ original = agents.read_text(encoding="utf-8") if agents.exists() else ""
44
+ if agents.is_symlink() or any(p.is_symlink() for p in (skill, *skill.parents)):
45
+ raise click.ClickException(
46
+ "Refusing to write AI instructions through a symbolic link."
47
+ )
48
+ if skill.exists() and skill.read_text(encoding="utf-8") != skill_text:
49
+ raise click.ClickException(
50
+ "Existing Cloudoll skill differs; review and merge it manually before initializing."
51
+ )
52
+ if original.count(BEGIN) != original.count(END) or original.count(BEGIN) > 1:
53
+ raise click.ClickException(
54
+ "Malformed Cloudoll block in AGENTS.md; repair it before initializing."
55
+ )
56
+ block = BEGIN + "\n" + instructions.rstrip() + "\n" + END
57
+ if BEGIN in original:
58
+ start, end = original.index(BEGIN), original.index(END)
59
+ if end < start:
60
+ raise click.ClickException("Malformed Cloudoll block in AGENTS.md.")
61
+ updated = original[:start] + block + original[end + len(END) :]
62
+ else:
63
+ updated = original + ("\n\n" if original else "") + block + "\n"
64
+ skill.parent.mkdir(parents=True, exist_ok=True)
65
+ skill.write_text(skill_text, encoding="utf-8")
66
+ agents.write_text(updated, encoding="utf-8")
67
+
68
+
69
+ @click.group()
70
+ def ai() -> None:
71
+ """Read bundled official docs and initialize project AI instructions (offline)."""
72
+
73
+
74
+ @ai.command("list")
75
+ def list_topics() -> None:
76
+ """List available documentation topics."""
77
+ click.echo("\n".join(document_topics()))
78
+
79
+
80
+ @ai.command("read")
81
+ @click.argument("topic")
82
+ def read_topic(topic: str) -> None:
83
+ """Print an official documentation topic verbatim."""
84
+ click.echo(read_document(topic))
85
+
86
+
87
+ @ai.command("search")
88
+ @click.argument("query")
89
+ def search(query: str) -> None:
90
+ """Find matching lines, with topic and line number."""
91
+ if not query.strip():
92
+ raise click.ClickException("Search query must not be empty.")
93
+ for topic in document_topics():
94
+ for number, line in enumerate(read_document(topic).splitlines(), 1):
95
+ if query.casefold() in line.casefold():
96
+ click.echo(f"{topic}:{number}: {line}")
97
+
98
+
99
+ @ai.command("init")
100
+ @click.argument(
101
+ "directory", type=click.Path(path_type=Path, file_okay=False), default="."
102
+ )
103
+ def init(directory: Path) -> None:
104
+ """Install AGENTS.md guidance and a project-local Cloudoll skill."""
105
+ initialize_project(directory)
106
+ click.echo(f"Cloudoll AI instructions installed in {directory.absolute()}")
@@ -0,0 +1,61 @@
1
+ ---
2
+ title: AI 辅助开发
3
+ order: 15
4
+ icon: structure
5
+ ---
6
+
7
+ # AI 辅助开发
8
+
9
+ 使用 AI 编写 Cloudoll 项目时,应先让它阅读当前安装版本的文档和项目约定,再设计实现。不要仅凭其它 Python 框架的使用经验推测 Cloudoll API。
10
+
11
+ > 以下 AI 命令从 Cloudoll 4.2.1 开始提供,使用前请运行 `cloudoll ai --help` 确认所安装版本是否支持。旧版本可先阅读对应版本的 README、源码和文档,不必为了获取指引直接升级业务依赖。
12
+
13
+ ## 新项目与已有项目
14
+
15
+ ```sh
16
+ cloudoll create myapp
17
+ ```
18
+
19
+ 新建项目会包含 `AGENTS.md` 和 `.agents/skills/cloudoll/SKILL.md`。前者指向开发约定,后者说明应在何时查阅哪些文档、推荐架构和验证要求。
20
+
21
+ 已有项目可在项目的 Python 环境中运行:
22
+
23
+ ```sh
24
+ python -m cloudoll.cli ai init .
25
+ ```
26
+
27
+ 初始化会保留 `AGENTS.md` 中其它内容,只维护标记内的 Cloudoll 说明。如果已有 Cloudoll Skill 与当前包不同,命令会停止,要求先人工审查和合并,不会覆盖自定义约定。
28
+
29
+ ## 离线查询文档
30
+
31
+ 不需要配置 MCP 服务,也不需要联网:
32
+
33
+ ```sh
34
+ python -m cloudoll.cli ai list
35
+ python -m cloudoll.cli ai read structure
36
+ python -m cloudoll.cli ai read validation
37
+ python -m cloudoll.cli ai read database
38
+ python -m cloudoll.cli ai search transaction
39
+ ```
40
+
41
+ 查询返回随包分发的官方 Markdown 原文。每个主题记录来源地址和内容校验值,避免为 AI 单独手写一套与真实文档不同的 API。`read` 输出完整主题,`search` 输出匹配行及主题、行号;理解上下文时仍应阅读完整主题。
42
+
43
+ ## 如何给 AI 下达任务
44
+
45
+ 可以在任务前加入:
46
+
47
+ ```text
48
+ 使用当前项目安装的 Cloudoll。先阅读 AGENTS.md 和
49
+ .agents/skills/cloudoll/SKILL.md,再通过 cloudoll ai read 查阅相关文档。
50
+ 新项目遵循自动发现的 controllers/middlewares、YAML 配置、框架管理的
51
+ 数据库生命周期、类型化参数校验和 ORM。若需要偏离默认方案,先说明理由。
52
+ 完成后说明查阅的主题、测试结果和未验证的部分。
53
+ ```
54
+
55
+ 不同 AI 工具发现项目指令的方式不同;如果它没有自动读取文件,请明确提供路径。Skill 和指令不是强制执行机制,仍需检查代码与测试结果。
56
+
57
+ 推荐先阅读[项目结构](/structure)、[配置](/config)、[路由](/router)、[参数校验](/validation);涉及持久化时阅读[数据库](/database)。集中注册路由、显式创建连接和原始 SQL 并非无效 API,但不应无理由地取代普通应用的推荐结构。
58
+
59
+ ## 在线发现入口
60
+
61
+ 网站提供 [llms.txt](https://cloudoll.chuchur.com/llms.txt) 和 [llms-full.txt](https://cloudoll.chuchur.com/llms-full.txt),分别用于查找文档入口和读取聚合内容。网站反映当前文档,旧项目应优先使用已安装版本随包提供的文档。最终 API 兼容性以安装版本的源码与测试为依据。
@@ -0,0 +1,81 @@
1
+ ---
2
+ title: 生命周期
3
+ order: 150
4
+ icon: lifecycle
5
+ ---
6
+
7
+ # 应用生命周期
8
+
9
+ 默认入口模块为项目根目录的 `app.py`。可用 `cloudoll start -n myapp -e hooks` 指定 `hooks.py`;参数是模块名,不带 .py。
10
+
11
+ ## 钩子
12
+
13
+ ```python
14
+ # app.py
15
+ from cloudoll import logging
16
+
17
+ def on_create(application):
18
+ # 同步钩子,参数为 Cloudoll Application。
19
+ application.config.setdefault("business", {})
20
+
21
+ async def on_startup(app):
22
+ # 参数为底层 aiohttp Application;配置的数据库已初始化。
23
+ logging.info("应用启动完成")
24
+
25
+ async def on_shutdown(app):
26
+ logging.info("应用正在停止")
27
+
28
+ async def on_cleanup(app):
29
+ logging.info("应用资源清理阶段")
30
+ ```
31
+
32
+ on_startup 被 await,耗时初始化会延迟服务就绪;不要在其中直接运行永不结束的循环。不要在模块导入阶段创建连接或事件循环任务。
33
+
34
+ 配置声明的数据库和 Session 存储由框架启动、关闭。自己创建的 HTTP 客户端、后台任务等仍由业务负责生命周期管理。不要依赖普通 on_cleanup 钩子还能使用已由资源上下文关闭的数据库。
35
+
36
+ ## 后台任务:on_task
37
+
38
+ on_task 必须是**只 yield 一次的异步生成器**。yield 前初始化,yield 后清理:
39
+
40
+ ```python
41
+ # app.py
42
+ import asyncio
43
+ from contextlib import suppress
44
+ from cloudoll import logging
45
+
46
+ async def worker():
47
+ while True:
48
+ await asyncio.sleep(30)
49
+ logging.info("后台任务心跳")
50
+
51
+ async def on_task(app):
52
+ task = asyncio.create_task(worker())
53
+ try:
54
+ yield
55
+ finally:
56
+ task.cancel()
57
+ with suppress(asyncio.CancelledError):
58
+ await task
59
+ ```
60
+
61
+ 不要把上例写成返回 cleanup 函数的普通协程,也不要额外给 on_task 加 `@asynccontextmanager`:这个钩子加载器期待的是异步生成器,不是上下文管理器对象。`contextlib.asynccontextmanager` 本身并没有被弃用。
62
+
63
+ 业务应另行设计后台任务失败告警、重试和停止策略,Cloudoll 不会自动监督所有 create_task。长时间阻塞 I/O 应使用异步库或合适的线程隔离,不能用无 await 的 while 循环阻塞事件循环。
64
+
65
+ ## HTTP 客户端与清理
66
+
67
+ 可在 on_task 中创建并用 async with 管理长期复用的 HTTP Session,见 [HTTP 客户端](/http-client)。
68
+
69
+ 生产使用 SIGTERM 等正常退出流程,给任务和连接池留出足够清理时间;强制杀进程不保证 finally 得以执行。框架会尝试关闭配置创建的资源,但业务自身的第三方关闭函数若一直挂起,仍需要进程管理器的退出超时兜底。
70
+
71
+ ## 资源清理预算
72
+
73
+ server.resource_close_timeout 默认 10 秒,限制单个配置资源关闭;server.resource_shutdown_timeout 默认 30 秒,限制一轮资源清理。两项都必须是有限正数,不接受 None。原生数据库池另有 close_timeout(默认 10 秒)。配置示例见[配置文件](/config)。
74
+
75
+ 资源按逆序串行清理。单项失败后,在剩余预算内继续清理其他资源;预算耗尽会明确报错,未处理资源可在之后 release() 重试。成功关闭的资源不会重复关闭,仍在执行的旧关闭任务不会重复启动。调用方取消等待时,已开始的清理在预算内继续,然后传播取消。
76
+
77
+ 不配合取消的第三方协程会被停止等待,但不能被 Python 强制终止;同步阻塞 close()、用户钩子及后台任务不在这项预算的保证范围内。资源清理预算不等于 HTTP 请求排空或整个进程退出期限,需要进程管理器最终兜底。
78
+
79
+ ## 开发子进程与热重载
80
+
81
+ 每个开发子进程按显式项目根目录新建 Application,模块加载和工作目录保持一致;不使用 fork 继承的父进程应用缓存或上下文。on_startup 完成且监听端口成功后才发送就绪信号;启动错误会返回父进程,热重载先停止旧实例再启动新实例。