storepy 4.4.2__tar.gz → 4.4.3__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.
- {storepy-4.4.2/src/storepy.egg-info → storepy-4.4.3}/PKG-INFO +1 -1
- {storepy-4.4.2 → storepy-4.4.3}/pyproject.toml +1 -1
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/__init__.py +2 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/crud/exec.py +9 -1
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/permission.py +15 -0
- {storepy-4.4.2 → storepy-4.4.3/src/storepy.egg-info}/PKG-INFO +1 -1
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_require_context.py +6 -6
- {storepy-4.4.2 → storepy-4.4.3}/LICENSE +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/README.md +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/setup.cfg +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/ask.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/ask_knowledge.md +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/bootstrap.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/cache.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/core.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/crud/__init__.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/crud/id.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/crud/mutation.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/crud/query.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/crud/triggers.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/crud/write.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/datasource.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/ddl.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/executors/__init__.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/executors/_values.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/executors/mongo.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/executors/mysql.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/executors/postgres.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/executors/sqlite.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/feedback.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/introspect/__init__.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/introspect/mysql.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/introspect/postgres.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/introspect/sqlite.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/llm.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/load.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/local/__init__.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/local/handle.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/local/store.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/metadef.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/naming.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/resource/__init__.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/resource/providers/__init__.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/resource/providers/local.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/resource/providers/s3.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/scheduler/__init__.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/schema.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/scope.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/secure.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/sync.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/py_store/workflow.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/storepy.egg-info/SOURCES.txt +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/storepy.egg-info/dependency_links.txt +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/storepy.egg-info/requires.txt +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/src/storepy.egg-info/top_level.txt +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_ask.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_cache.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_coverage_margin.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_federation_e2e.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_feedback_flush.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_fns_binding.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_host_contract.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_host_paths.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_load.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_local_store.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_metadef.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_migration.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_mongo_executor.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_mongo_session.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_multi_datasource.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_parity_deny.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_parity_local.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_parity_scope.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_policy_isolation.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_profile.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_py_store.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_raw_sql_and_ddl.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_rbac_host.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_real_backends_e2e.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_resource.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_resource_e2e.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_resource_units.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_scenario_course_platform.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_scenario_manager_transaction.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_scheduler.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_session.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_sql_commit_and_registry.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_triggers.py +0 -0
- {storepy-4.4.2 → storepy-4.4.3}/tests/test_workflow.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: storepy
|
|
3
|
-
Version: 4.4.
|
|
3
|
+
Version: 4.4.3
|
|
4
4
|
Summary: Multi-backend data layer for Python asyncio (MongoDB, MySQL, SQLite, PostgreSQL, local disk): pure JSON schemas, GQL tree queries compiled to a single native query, GROUP BY/HAVING aggregation, computed columns, soft-delete and role-based access control
|
|
5
5
|
Author-email: leo <coen_ddt@qq.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "storepy"
|
|
7
|
-
version = "4.4.
|
|
7
|
+
version = "4.4.3"
|
|
8
8
|
description = "Multi-backend data layer for Python asyncio (MongoDB, MySQL, SQLite, PostgreSQL, local disk): pure JSON schemas, GQL tree queries compiled to a single native query, GROUP BY/HAVING aggregation, computed columns, soft-delete and role-based access control"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -350,6 +350,8 @@ class Store:
|
|
|
350
350
|
run_as_internal = staticmethod(permission.run_as_internal)
|
|
351
351
|
# 自定义权限错误(实例可被 store.PermissionError 捕获)
|
|
352
352
|
PermissionError = permission.PermissionError
|
|
353
|
+
# 上下文缺失错误(实例可被 store.NoContextError 捕获;fail-secure 下未注入 ctx)
|
|
354
|
+
NoContextError = permission.NoContextError
|
|
353
355
|
# 原生 SQL 入口错误(实例可被 store.RawSqlError 捕获)
|
|
354
356
|
RawSqlError = datasource.RawSqlError
|
|
355
357
|
# 原生 Mongo 命令入口错误(实例可被 store.NativeCommandError 捕获)
|
|
@@ -19,7 +19,7 @@ from .. import datasource as _datasource
|
|
|
19
19
|
from ..executors.mongo import exec_mongo as _exec_mongo
|
|
20
20
|
from ..feedback import emit as _emit_feedback
|
|
21
21
|
from ..naming import _to_logical, _to_mongo
|
|
22
|
-
from ..permission import PermissionError, get_context
|
|
22
|
+
from ..permission import NoContextError, PermissionError, get_context
|
|
23
23
|
from ..schema import get as _schema_get
|
|
24
24
|
|
|
25
25
|
_PHASE1_IDS = re.compile(r'^\{\{phase1\.ids\}\}$')
|
|
@@ -35,6 +35,11 @@ _PERM_PREFIX = 'ERR_PERMISSION:'
|
|
|
35
35
|
# 反馈事件 `profile_blocked`(自动反馈原则:允许拦截,禁止静默)。
|
|
36
36
|
_PROFILE_PREFIX = 'ERR_TEXT2QUERY:'
|
|
37
37
|
|
|
38
|
+
# 上下文缺失识别:core fail-secure(require_context / secure_mode)下无 ctx 时统一携带
|
|
39
|
+
# `ERR_NO_CONTEXT:` 稳定前缀(见 core `command/mod.rs`),同上按前缀映射。命中即抛
|
|
40
|
+
# `NoContextError`(与 PermissionError 同档 403;前缀剥离)。
|
|
41
|
+
_NO_CONTEXT_PREFIX = 'ERR_NO_CONTEXT:'
|
|
42
|
+
|
|
38
43
|
# 从 core 文案 `... [$feature](功能收缩)` 中提取门禁项名;无 `[..]` 时留白(None),
|
|
39
44
|
# 不伪造 feature —— 缺值必须显式暴露(禁静默兜底)。
|
|
40
45
|
_FEATURE_RE = re.compile(r'\[(.+?)\]')
|
|
@@ -85,6 +90,7 @@ def _call(fn):
|
|
|
85
90
|
"""绑定层调用包装:
|
|
86
91
|
|
|
87
92
|
- 权限类错误(``ERR_PERMISSION:`` 前缀)→ ``PermissionError``
|
|
93
|
+
- 上下文缺失(``ERR_NO_CONTEXT:`` 前缀)→ ``NoContextError``(同档 403)
|
|
88
94
|
- 档位类错误(``ERR_TEXT2QUERY:`` 前缀)→ emit ``profile_blocked`` 反馈 + ``ProfileViolation``
|
|
89
95
|
|
|
90
96
|
按前缀映射而非具体文案(core 文案可自由调整,映射不随文案漂移而静默失效)。
|
|
@@ -96,6 +102,8 @@ def _call(fn):
|
|
|
96
102
|
msg = str(e)
|
|
97
103
|
if msg.startswith(_PERM_PREFIX):
|
|
98
104
|
raise PermissionError(msg[len(_PERM_PREFIX):]) from e
|
|
105
|
+
if msg.startswith(_NO_CONTEXT_PREFIX):
|
|
106
|
+
raise NoContextError(msg[len(_NO_CONTEXT_PREFIX):]) from e
|
|
99
107
|
if msg.startswith(_PROFILE_PREFIX):
|
|
100
108
|
detail = msg[len(_PROFILE_PREFIX):]
|
|
101
109
|
m = _FEATURE_RE.search(detail)
|
|
@@ -184,3 +184,18 @@ class PermissionError(Exception):
|
|
|
184
184
|
def __init__(self, message, status=403):
|
|
185
185
|
super().__init__(message)
|
|
186
186
|
self.status = status
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class NoContextError(Exception):
|
|
190
|
+
"""上下文缺失错误(fail-secure:require_context 开启 / secure_mode 下未注入 ctx)
|
|
191
|
+
|
|
192
|
+
与 PermissionError 同属权限上下文类(403):core 抛 ``ERR_NO_CONTEXT:`` 稳定前缀
|
|
193
|
+
(见 core ``command/mod.rs``),由 ``crud.exec._call`` 归一为本类型(前缀已剥离)。
|
|
194
|
+
``code`` 与 core machine code 对齐(``no_context``),供皮按枚举判定(禁按文案匹配)。
|
|
195
|
+
对齐 nodejs-store ``NoContextError``。
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
def __init__(self, message, status=403):
|
|
199
|
+
super().__init__(message)
|
|
200
|
+
self.code = 'no_context'
|
|
201
|
+
self.status = status
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: storepy
|
|
3
|
-
Version: 4.4.
|
|
3
|
+
Version: 4.4.3
|
|
4
4
|
Summary: Multi-backend data layer for Python asyncio (MongoDB, MySQL, SQLite, PostgreSQL, local disk): pure JSON schemas, GQL tree queries compiled to a single native query, GROUP BY/HAVING aggregation, computed columns, soft-delete and role-based access control
|
|
5
5
|
Author-email: leo <coen_ddt@qq.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -123,13 +123,13 @@ def test_require_context_on_blocks_without_ctx():
|
|
|
123
123
|
_mock([{'_id': '1', 'title': 'a'}])
|
|
124
124
|
_sc.set_require_context(True)
|
|
125
125
|
try:
|
|
126
|
-
with pytest.raises(
|
|
126
|
+
with pytest.raises(perm.NoContextError):
|
|
127
127
|
_run(_crud_mod.query('RcModel{title}'))
|
|
128
|
-
with pytest.raises(
|
|
128
|
+
with pytest.raises(perm.NoContextError):
|
|
129
129
|
_run(_crud_mod.insert('RcModel', {'title': 'x'}))
|
|
130
|
-
with pytest.raises(
|
|
130
|
+
with pytest.raises(perm.NoContextError):
|
|
131
131
|
_run(_crud_mod.update('RcModel', {'_id': '1'}, {'title': 'y'}))
|
|
132
|
-
with pytest.raises(
|
|
132
|
+
with pytest.raises(perm.NoContextError):
|
|
133
133
|
_run(_crud_mod.remove('RcModel', {'_id': '1'}))
|
|
134
134
|
finally:
|
|
135
135
|
_sc.set_require_context(False)
|
|
@@ -177,9 +177,9 @@ def test_secure_mode_flips_switches_blocks_ctxless():
|
|
|
177
177
|
assert secure.is_secure() is True
|
|
178
178
|
assert _sc.require_context() is True
|
|
179
179
|
# 开关1 require_context:无 ctx 读写拒绝
|
|
180
|
-
with pytest.raises(
|
|
180
|
+
with pytest.raises(perm.NoContextError):
|
|
181
181
|
_run(_crud_mod.query('RcModel{title}'))
|
|
182
|
-
with pytest.raises(
|
|
182
|
+
with pytest.raises(perm.NoContextError):
|
|
183
183
|
_run(_crud_mod.insert('RcModel', {'title': 'x'}))
|
|
184
184
|
# 开关3 meta closed:无 ctx 注册新定义拒绝
|
|
185
185
|
with pytest.raises(RuntimeError, match='ERR_PERMISSION'):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|