fastcodedog 3.2.0__tar.gz → 3.2.2__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 (159) hide show
  1. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/PKG-INFO +1 -1
  2. fastcodedog-3.2.2/fastcodedog/generation/api/db.py +91 -0
  3. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/api/generation.py +4 -4
  4. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/api/main.py +10 -7
  5. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/commonfiles/utilfiles/api_logging.py +1 -1
  6. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/inc/middleware/api_logging.file.in +42 -65
  7. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/pyproject.toml +1 -1
  8. fastcodedog-3.2.0/fastcodedog/generation/api/db.py +0 -33
  9. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/README.md +0 -0
  10. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/README_zh.md +0 -0
  11. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/__init__.py +0 -0
  12. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/cli.py +0 -0
  13. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/common/__init__.py +0 -0
  14. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/common/clean_expired.py +0 -0
  15. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/common/source_file_path.py +0 -0
  16. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/common/write_file.py +0 -0
  17. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/__init__.py +0 -0
  18. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/api/__init__.py +0 -0
  19. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/api/api.py +0 -0
  20. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/api/endpoint.py +0 -0
  21. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/api/oauth2.py +0 -0
  22. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/api/param.py +0 -0
  23. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/common/__init__.py +0 -0
  24. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/common/get_context_object.py +0 -0
  25. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/common/get_relationship.py +0 -0
  26. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/context.py +0 -0
  27. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/contextbase.py +0 -0
  28. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/crud/__init__.py +0 -0
  29. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/crud/column.py +0 -0
  30. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/crud/crud.py +0 -0
  31. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/crud/default_value.py +0 -0
  32. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/crud/join_relationship.py +0 -0
  33. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/crud/query.py +0 -0
  34. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/model/__init__.py +0 -0
  35. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/model/additional_method.py +0 -0
  36. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/model/case.py +0 -0
  37. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/model/column.py +0 -0
  38. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/model/computed_property.py +0 -0
  39. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/model/copy_method.py +0 -0
  40. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/model/model.py +0 -0
  41. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/model/parameter.py +0 -0
  42. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/model/relationship.py +0 -0
  43. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/schema/__init__.py +0 -0
  44. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/schema/alias_generator.py +0 -0
  45. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/schema/field.py +0 -0
  46. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/schema/response_schema.py +0 -0
  47. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/schema/schema.py +0 -0
  48. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/schema/sub_object.py +0 -0
  49. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/setting/__init__.py +0 -0
  50. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/setting/config.py +0 -0
  51. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/setting/extend_app.py +0 -0
  52. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/setting/listen.py +0 -0
  53. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/setting/project.py +0 -0
  54. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/setting/source_directory.py +0 -0
  55. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/context/setting/tenant.py +0 -0
  56. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/__init__.py +0 -0
  57. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/api/__init__.py +0 -0
  58. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/api/api.py +0 -0
  59. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/api/api_function.py +0 -0
  60. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/api/config.py +0 -0
  61. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/api/oauth2.py +0 -0
  62. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/base/__init__.py +0 -0
  63. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/base/block.py +0 -0
  64. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/base/call.py +0 -0
  65. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/base/class_type.py +0 -0
  66. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/base/file.py +0 -0
  67. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/base/function.py +0 -0
  68. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/base/head_comment.py +0 -0
  69. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/base/line_break.py +0 -0
  70. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/base/location_finder.py +0 -0
  71. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/base/required_import.py +0 -0
  72. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/base/text.py +0 -0
  73. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/base/variable.py +0 -0
  74. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/commonfiles/__init__.py +0 -0
  75. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/commonfiles/configfiles/__init__.py +0 -0
  76. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/commonfiles/generation.py +0 -0
  77. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/commonfiles/main.py +0 -0
  78. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/commonfiles/oauthfiles/__init__.py +0 -0
  79. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/commonfiles/toolfiles/__init__.py +0 -0
  80. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/commonfiles/utilfiles/__init__.py +0 -0
  81. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/commonfiles/utilfiles/case_converter.py +0 -0
  82. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/commonfiles/utilfiles/log.py +0 -0
  83. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/crud/__init__.py +0 -0
  84. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/crud/crud.py +0 -0
  85. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/crud/crud_functions.py +0 -0
  86. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/crud/generation.py +0 -0
  87. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/crud/query_functions.py +0 -0
  88. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/crud/selectinload.py +0 -0
  89. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/model/__init__.py +0 -0
  90. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/model/additional_method.py +0 -0
  91. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/model/base.py +0 -0
  92. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/model/case.py +0 -0
  93. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/model/column.py +0 -0
  94. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/model/computed_property.py +0 -0
  95. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/model/copy_method.py +0 -0
  96. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/model/generation.py +0 -0
  97. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/model/init.py +0 -0
  98. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/model/model.py +0 -0
  99. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/model/relation_object.py +0 -0
  100. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/model/relationship.py +0 -0
  101. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/model/table_args.py +0 -0
  102. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/schema/__init__.py +0 -0
  103. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/schema/field.py +0 -0
  104. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/schema/generation.py +0 -0
  105. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/schema/response_schema.py +0 -0
  106. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/schema/schema.py +0 -0
  107. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/generation/schema/sub_object.py +0 -0
  108. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/__init__.py +0 -0
  109. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/model_and_schema_to_crud/__init__.py +0 -0
  110. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/model_and_schema_to_crud/default_values.py +0 -0
  111. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/model_and_schema_to_crud/prepare.py +0 -0
  112. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/model_and_schema_to_crud/queries.py +0 -0
  113. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/model_to_schema/__init__.py +0 -0
  114. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/model_to_schema/alias_generator.py +0 -0
  115. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/model_to_schema/no_input_fields.py +0 -0
  116. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/model_to_schema/no_response_fields.py +0 -0
  117. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/model_to_schema/prepare.py +0 -0
  118. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/model_to_schema/response_schemas.py +0 -0
  119. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/model_to_schema/specified_field_types.py +0 -0
  120. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/README.MD +0 -0
  121. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/__init__.py +0 -0
  122. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/after/__init__.py +0 -0
  123. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/after/additional_methods.py +0 -0
  124. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/after/additional_relationships.py +0 -0
  125. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/after/case.py +0 -0
  126. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/after/computed_properties.py +0 -0
  127. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/after/copy_methods.py +0 -0
  128. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/after/disable_relationships.py +0 -0
  129. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/after/specified_class_names.py +0 -0
  130. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/after/specified_relationship_orderby.py +0 -0
  131. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/before/__init__.py +0 -0
  132. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/before/additional_foreign_keys.py +0 -0
  133. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/before/fill_tenant_id.py +0 -0
  134. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/before/specified_column_types.py +0 -0
  135. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/before/specified_relationship_names.py +0 -0
  136. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/column.py +0 -0
  137. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/pdm.py +0 -0
  138. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/prepare.py +0 -0
  139. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/reference.xml +0 -0
  140. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/table.py +0 -0
  141. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/pdm_to_model/table.xml +0 -0
  142. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/schema_and_crud_to_api/__init__.py +0 -0
  143. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/schema_and_crud_to_api/endpoint.py +0 -0
  144. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/schema_and_crud_to_api/prepare.py +0 -0
  145. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/schema_and_crud_to_api/schemas.py +0 -0
  146. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/prepare/schema_and_crud_to_api/validate_reponse_models.py +0 -0
  147. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/util/__init__.py +0 -0
  148. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/util/case_converter.py +0 -0
  149. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/util/deep_update.py +0 -0
  150. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/util/extractor.py +0 -0
  151. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/util/find_file.py +0 -0
  152. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/util/indent.py +0 -0
  153. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/util/inflect_wrapper.py +0 -0
  154. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/util/make_dirs.py +0 -0
  155. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/util/read_inc.py +0 -0
  156. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/util/singleton.py +0 -0
  157. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/util/type_converter.py +0 -0
  158. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/util/valid_name.py +0 -0
  159. {fastcodedog-3.2.0 → fastcodedog-3.2.2}/fastcodedog/util/wrap_str_with_quotation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastcodedog
3
- Version: 3.2.0
3
+ Version: 3.2.2
4
4
  Summary:
5
5
  License: MIT
6
6
  Author: taohoo
@@ -0,0 +1,91 @@
1
+ # -*- coding: utf-8 -*-
2
+ from fastcodedog.generation.api.config import Config
3
+ from fastcodedog.generation.base.file import File
4
+ from fastcodedog.generation.base.function import Function
5
+ from fastcodedog.generation.base.location_finder import LocationFinder
6
+ from fastcodedog.generation.base.required_import import Import
7
+ from fastcodedog.generation.base.text import Text
8
+ from fastcodedog.generation.base.variable import Variable
9
+
10
+
11
+ class Db(File):
12
+ def __init__(self, comment=None, possible_imports: list | str = None, parent=None):
13
+ super().__init__('db',
14
+ file_path=LocationFinder.get_path('db', 'model'),
15
+ package=LocationFinder.get_package('db', 'model'), comment=comment, parent=parent)
16
+ self._init_blocks_and_imports()
17
+
18
+ def _init_blocks_and_imports(self):
19
+ self.blocks.append(Variable('engine', value=f"""create_engine(database_url, pool_size=pool_size, max_overflow=max_overflow, connect_args={{"check_same_thread": False}}
20
+ ) if database_url.startswith('sqlite') else create_engine(database_url)""",
21
+ possible_imports=['from sqlalchemy import create_engine',
22
+ Import('database_url', Config().package),
23
+ Import('pool_size', Config().package),
24
+ Import('max_overflow', Config().package)]))
25
+ self.blocks.append(Variable('Session', value='sessionmaker(bind=engine)',
26
+ possible_imports=['from sqlalchemy.orm import sessionmaker']))
27
+ get_session = Function('get_session', comment="""生成器方式获取数据库会话(主要适用于依赖注入场景)。
28
+
29
+ 工作原理:
30
+ 1. 函数被调用时,创建一个新的Session实例。
31
+ 2. 通过 `yield session` 返回会话实例,并暂停执行。
32
+ 3. 当调用方结束会话使用(如请求结束),函数恢复执行,进入 `finally` 块,自动关闭会话。
33
+
34
+ 使用方式1 (FastAPI 依赖注入,推荐):
35
+ @app.get("/users")
36
+ def get_users(session: Session = Depends(get_session)):
37
+ return session.query(User).all()
38
+ # 在这种情况下,FastAPI的Depends会自动处理生成器的迭代(即调用next())和会话的关闭。
39
+
40
+ 使用方式2 (手动调用,不推荐用于常规业务):
41
+ # 警告:此方式需要手动管理会话的关闭,非常容易出错!
42
+ gen = get_session()
43
+ session = next(gen) # 使用next()从生成器中获取会话实例
44
+ try:
45
+ # ... 使用 session ...
46
+ finally:
47
+ # 必须再次调用next()以触发finally块中的session.close()
48
+ try:
49
+ next(gen)
50
+ except StopIteration:
51
+ pass # 捕获迭代结束的异常
52
+
53
+ 注意事项:
54
+ - 该函数返回的是一个生成器对象,而非直接的Session实例。
55
+ - 在依赖注入之外的场景手动使用时,必须配合`next()`和`try...finally`结构,以确保会话被关闭。
56
+ - 强烈建议优先使用依赖注入方式,避免手动操作`next()`。""")
57
+ get_session.blocks.append(Text(f"""session = Session()
58
+ try:
59
+ yield session
60
+ finally:
61
+ session.close()"""))
62
+ self.blocks.append(get_session)
63
+
64
+ open_session = Function('open_session', decorators=[Function.Decorator('contextmanager', possible_imports='from contextlib import contextmanager')], comment="""上下文管理器方式获取数据库会话(适用于手动控制场景,如脚本、后台任务)。
65
+
66
+ 工作原理:
67
+ 1. 被`@contextmanager`装饰后,该函数成为一个上下文管理器。
68
+ 2. 当使用`with`语句时,它会在进入块时执行`yield`之前的代码(创建会话),
69
+ 在退出块时执行`yield`之后的代码(关闭会话)。
70
+
71
+ 使用方式 (必须配合 with 语句):
72
+ with open_session() as session:
73
+ user = session.query(User).get(1)
74
+ session.add(User(name="new user"))
75
+ session.commit()
76
+ # with块结束时,会话会被自动关闭,无需手动操作。
77
+
78
+ 与 next() 的关系:
79
+ - **不需要手动调用`next()`**。`with`语句会自动处理上下文管理器的内部逻辑,
80
+ 包括触发生成器和管理资源生命周期。
81
+ - 虽然其内部实现依赖于生成器,但`@contextmanager`装饰器已经封装了`next()`的调用细节。
82
+
83
+ 注意事项:
84
+ - 必须配合`with`语句使用,否则无法正确管理会话的生命周期。
85
+ - 这种方式既安全又简洁,是手动控制会话场景下的最佳实践。""")
86
+ open_session.blocks.append(Text(f"""session = Session()
87
+ try:
88
+ yield session
89
+ finally:
90
+ session.close()"""))
91
+ self.blocks.append(open_session)
@@ -9,10 +9,10 @@ from fastcodedog.generation.api.oauth2 import Oauth2
9
9
 
10
10
  def generate_api(specify_api=None):
11
11
  # 只能在使用的时候才import,因为这些文件在初始化的时候,需要保证ctx_instance已经初始化
12
- Db().save()
13
- Config().save()
14
- Main().save()
15
- Oauth2().save()
12
+ Db().save() if ((not specify_api) or 'db' in specify_api) else None
13
+ Config().save() if ((not specify_api) or 'config' in specify_api) else None
14
+ Main().save() if ((not specify_api) or 'main' in specify_api) else None
15
+ Oauth2().save() if ((not specify_api) or 'oauth2' in specify_api) else None
16
16
  for module, apis in ctx_instance.apis.items():
17
17
  for api_context in apis.values():
18
18
  if specify_api and api_context.name not in specify_api:
@@ -85,13 +85,16 @@ if LOGGING_CONFIG["loggers"]["uvicorn"]["handlers"]:
85
85
  def _init_swagger(self):
86
86
  function = Function('custom_swagger_ui_html', async_=True)
87
87
  function.decorators.append(Function.Decorator('app.get', params=['\'/swagger\'', 'include_in_schema=False']))
88
- function.blocks.append(Text('"""自定义Swagger,使用国内的SwaggerUI镜像"""'))
89
- function.blocks.append(Text(f"""return get_swagger_ui_html(
90
- openapi_url="/openapi.json",
91
- title=app.title + " - Swagger UI",
92
- swagger_js_url="https://cdn.jsdmirror.cn/npm/swagger-ui-dist@5/swagger-ui-bundle.js",
93
- swagger_css_url="https://cdn.jsdmirror.cn/npm/swagger-ui-dist@5/swagger-ui.css"
94
- )""", possible_imports=['from fastapi.openapi.docs import get_swagger_ui_html']))
88
+ function.params['request'] = Function.Parameter('request', type='Request', nullable=False, possible_imports='from fastapi import Request')
89
+ function.blocks.append(Text('"""自定义Swagger:1、默认的js会超时;2、更友好的交互"""'))
90
+ function.blocks.append(Text(f"""root_path = request.scope.get("root_path", "").rstrip("/")
91
+ return get_scalar_api_reference(
92
+ openapi_url=f"{{root_path}}/openapi.json",
93
+ title=app.title + " - Scalar",
94
+ scalar_js_url="https://cdn.jsdmirror.cn/npm/@scalar/api-reference"
95
+ )""", possible_imports=['from fastapi.openapi.docs import get_swagger_ui_html',
96
+ 'from scalar_fastapi import get_scalar_api_reference',
97
+ 'from scalar_fastapi import Theme']))
95
98
  self.blocks.append(function)
96
99
 
97
100
  def _init_sqlalchemy_error_handler(self):
@@ -34,7 +34,7 @@ Notes:
34
34
  'from starlette.responses import Response',
35
35
  'from starlette.responses import FileResponse',
36
36
  'import time', 'import json', 'import datetime', 'import contextvars',
37
- Import('Session', Db().package),
37
+ Import('open_session', Db().package),
38
38
  Import('ApiLog', LocationFinder.get_package('ApiLog', 'model', 'operation'))]))
39
39
 
40
40
  def save(self):
@@ -5,6 +5,7 @@ MAX_STORE_SIZE = 500 * 1024 # 500KB
5
5
 
6
6
  class ApiLoggingMiddleware(BaseHTTPMiddleware):
7
7
  async def dispatch(self, request: Request, call_next):
8
+ request_receive_time = datetime.datetime.now()
8
9
  start_ts = time.time()
9
10
 
10
11
  # read request body (may be empty)
@@ -157,37 +158,30 @@ class ApiLoggingMiddleware(BaseHTTPMiddleware):
157
158
  log_id = None
158
159
  # create initial ApiLog entry (best-effort)
159
160
  try:
160
- db_session = Session()
161
- api_log = ApiLog(
162
- program=headers.get('x-program') or None,
163
- client_ip=client_ip,
164
- update_time=datetime.datetime.now(),
165
- response_status=None,
166
- request_method=request_method,
167
- request_path=request_path,
168
- request_url=request_url,
169
- request_head=request_head_text,
170
- request_body=request_body_text if request_body_text and len(request_body_text) <= MAX_STORE_SIZE else None
171
- )
172
- db_session.add(api_log)
173
- db_session.flush() # assign id
174
- log_id = api_log.id
175
- # don't commit yet; we'll commit the final update after response
176
- db_session.commit()
177
- api_log_id.set(log_id)
161
+ with open_session() as db_session:
162
+ api_log = ApiLog(
163
+ program=headers.get('x-program') or None,
164
+ client_ip=client_ip,
165
+ request_receive_time=request_receive_time,
166
+ response_status=None,
167
+ request_method=request_method,
168
+ request_path=request_path,
169
+ request_url=request_url,
170
+ request_head=request_head_text,
171
+ request_body=request_body_text if request_body_text and len(
172
+ request_body_text) <= MAX_STORE_SIZE else None
173
+ )
174
+ db_session.add(api_log)
175
+ db_session.flush() # assign id
176
+ log_id = api_log.id
177
+ # don't commit yet; we'll commit the final update after response
178
+ db_session.commit()
179
+ api_log_id.set(log_id)
178
180
  except Exception:
179
- try:
180
- if db_session is not None:
181
- db_session.rollback()
182
- except Exception:
183
- pass
184
- finally:
185
- if db_session is not None:
186
- db_session.close()
187
- db_session = None
188
181
  log_id = None
189
182
 
190
183
  # call downstream
184
+ response_start_time = datetime.datetime.now()
191
185
  response = None
192
186
  response_body_text = None
193
187
  response_headers = None
@@ -264,43 +258,26 @@ class ApiLoggingMiddleware(BaseHTTPMiddleware):
264
258
  raise
265
259
  finally:
266
260
  # finally: update the ApiLog entry (best-effort)
267
- db2 = None
261
+ response_return_time = datetime.datetime.now()
268
262
  try:
269
- db2 = Session()
270
- if log_id is not None:
271
- api = db2.query(ApiLog).get(log_id)
272
- if api is not None:
273
- api.response_status = str(status_code) if status_code is not None else None
274
- try:
275
- api.response_head = json.dumps(response_headers or {}, ensure_ascii=False)
276
- except Exception:
277
- api.response_head = str(response_headers or {})
278
- # only store response_body_text when available (already truncated later)
279
- api.response_body = (response_body_text[:MAX_STORE_SIZE] if response_body_text else None)
280
- api.response_time = int((time.time() - start_ts) * 1000)
281
- api.update_time = datetime.datetime.now()
282
- if exception:
283
- import traceback
284
- api.exception = ''.join(traceback.format_exception(exception))
285
- db2.add(api)
286
- db2.commit()
263
+ with open_session() as db_session:
264
+ if log_id is not None:
265
+ api = db_session.query(ApiLog).get(log_id)
266
+ if api is not None:
267
+ api.response_status = str(status_code) if status_code is not None else None
268
+ api.response_start_time = response_start_time
269
+ api.response_return_time = response_return_time
270
+ api.response_duration_ms = int((time.time() - start_ts) * 1000)
271
+ try:
272
+ api.response_head = json.dumps(response_headers or {}, ensure_ascii=False)
273
+ except Exception:
274
+ api.response_head = str(response_headers or {})
275
+ # only store response_body_text when available (already truncated later)
276
+ api.response_body = (response_body_text[:MAX_STORE_SIZE] if response_body_text else None)
277
+ if exception:
278
+ import traceback
279
+ api.exception = ''.join(traceback.format_exception(exception))
280
+ db_session.add(api)
281
+ db_session.commit()
287
282
  except Exception:
288
- # defensive rollback if db2 was created
289
- try:
290
- if db2 is not None:
291
- db2.rollback()
292
- except Exception:
293
- pass
294
- finally:
295
- try:
296
- if db2 is not None:
297
- db2.close()
298
- except Exception:
299
- pass
300
-
301
- # close the initial session if still open
302
- try:
303
- if db_session is not None:
304
- db_session.close()
305
- except Exception:
306
- pass
283
+ ...
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "fastcodedog"
3
- version = "3.2.0"
3
+ version = "3.2.2"
4
4
  description = ""
5
5
  authors = ["taohoo <taohoo@163.com>"]
6
6
  license = "MIT"
@@ -1,33 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- from fastcodedog.generation.api.config import Config
3
- from fastcodedog.generation.base.file import File
4
- from fastcodedog.generation.base.function import Function
5
- from fastcodedog.generation.base.location_finder import LocationFinder
6
- from fastcodedog.generation.base.required_import import Import
7
- from fastcodedog.generation.base.text import Text
8
- from fastcodedog.generation.base.variable import Variable
9
-
10
-
11
- class Db(File):
12
- def __init__(self, comment=None, possible_imports: list | str = None, parent=None):
13
- super().__init__('db',
14
- file_path=LocationFinder.get_path('db', 'model'),
15
- package=LocationFinder.get_package('db', 'model'), comment=comment, parent=parent)
16
- self._init_blocks_and_imports()
17
-
18
- def _init_blocks_and_imports(self):
19
- self.blocks.append(Variable('engine', value=f"""create_engine(database_url, pool_size=pool_size, max_overflow=max_overflow, connect_args={{"check_same_thread": False}}
20
- ) if database_url.startswith('sqlite') else create_engine(database_url)""",
21
- possible_imports=['from sqlalchemy import create_engine',
22
- Import('database_url', Config().package),
23
- Import('pool_size', Config().package),
24
- Import('max_overflow', Config().package)]))
25
- self.blocks.append(Variable('Session', value='sessionmaker(bind=engine)',
26
- possible_imports=['from sqlalchemy.orm import sessionmaker']))
27
- get_session = Function('get_session')
28
- get_session.blocks.append(Text(f"""session = Session()
29
- try:
30
- yield session
31
- finally:
32
- session.close()"""))
33
- self.blocks.append(get_session)
File without changes
File without changes