valar 1.1.4__tar.gz → 1.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.
Potentially problematic release.
This version of valar might be problematic. Click here for more details.
- {valar-1.1.4/src/valar.egg-info → valar-1.2.1}/PKG-INFO +9 -14
- {valar-1.1.4 → valar-1.2.1}/README.md +8 -13
- {valar-1.1.4 → valar-1.2.1}/setup.py +4 -4
- valar-1.2.1/src/valar/apps.py +18 -0
- {valar-1.1.4 → valar-1.2.1}/src/valar/channels/consumer.py +10 -12
- valar-1.2.1/src/valar/channels/executer.py +14 -0
- valar-1.2.1/src/valar/channels/sender.py +116 -0
- {valar-1.1.4 → valar-1.2.1}/src/valar/channels/views.py +2 -3
- {valar-1.1.4/src/valar/classes → valar-1.2.1/src/valar/classes/app_mixins}/auto_migration_mixin.py +2 -2
- {valar-1.1.4/src/valar/classes → valar-1.2.1/src/valar/classes/app_mixins}/auto_urlpatterns_mixin.py +3 -3
- valar-1.2.1/src/valar/classes/valar_minio.py +80 -0
- {valar-1.1.4 → valar-1.2.1}/src/valar/classes/valar_response.py +2 -1
- valar-1.2.1/src/valar/dao/__init__.py +45 -0
- valar-1.2.1/src/valar/dao/abstract.py +106 -0
- valar-1.2.1/src/valar/dao/defaults/field_keys_default.py +48 -0
- valar-1.2.1/src/valar/dao/defaults/field_values_default.py +135 -0
- valar-1.2.1/src/valar/dao/defaults/view_defaults.py +26 -0
- valar-1.2.1/src/valar/dao/engine.py +80 -0
- valar-1.2.1/src/valar/dao/frame.py +189 -0
- valar-1.2.1/src/valar/dao/meta.py +128 -0
- valar-1.2.1/src/valar/dao/mon_dao.py +113 -0
- valar-1.2.1/src/valar/dao/mon_field.py +23 -0
- valar-1.2.1/src/valar/dao/orm_dao.py +304 -0
- valar-1.2.1/src/valar/dao/orm_field.py +142 -0
- valar-1.2.1/src/valar/dao/query.py +36 -0
- {valar-1.1.4 → valar-1.2.1}/src/valar/migrations/0001_initial.py +25 -17
- {valar-1.1.4 → valar-1.2.1}/src/valar/models/core.py +16 -10
- {valar-1.1.4 → valar-1.2.1}/src/valar/models/frame.py +4 -7
- {valar-1.1.4 → valar-1.2.1}/src/valar/models/meta.py +19 -16
- valar-1.2.1/src/valar/urls.py +29 -0
- valar-1.2.1/src/valar/views/__init__.py +0 -0
- valar-1.2.1/src/valar/views/file.py +49 -0
- valar-1.2.1/src/valar/views/handler.py +33 -0
- valar-1.2.1/src/valar/views/meta.py +150 -0
- valar-1.2.1/src/valar/views/rest.py +90 -0
- {valar-1.1.4 → valar-1.2.1/src/valar.egg-info}/PKG-INFO +9 -14
- valar-1.2.1/src/valar.egg-info/SOURCES.txt +57 -0
- {valar-1.1.4 → valar-1.2.1}/src/valar.egg-info/top_level.txt +1 -0
- valar-1.2.1/src/vtest/__init__.py +0 -0
- valar-1.2.1/src/vtest/apps.py +17 -0
- valar-1.2.1/src/vtest/handlers.py +15 -0
- valar-1.2.1/src/vtest/migrations/0001_initial.py +155 -0
- valar-1.2.1/src/vtest/migrations/__init__.py +0 -0
- valar-1.2.1/src/vtest/models.py +59 -0
- valar-1.2.1/src/vtest/views.py +8 -0
- valar-1.1.4/src/valar/apps.py +0 -21
- valar-1.1.4/src/valar/channels/executer.py +0 -13
- valar-1.1.4/src/valar/channels/sender.py +0 -64
- valar-1.1.4/src/valar/urls.py +0 -7
- valar-1.1.4/src/valar.egg-info/SOURCES.txt +0 -31
- {valar-1.1.4 → valar-1.2.1}/LICENSE +0 -0
- {valar-1.1.4 → valar-1.2.1}/setup.cfg +0 -0
- {valar-1.1.4 → valar-1.2.1}/src/valar/__init__.py +0 -0
- {valar-1.1.4 → valar-1.2.1}/src/valar/channels/__init__.py +0 -0
- {valar-1.1.4/src/valar/classes → valar-1.2.1/src/valar/channels}/counter.py +0 -0
- {valar-1.1.4 → valar-1.2.1}/src/valar/channels/mapping.py +0 -0
- {valar-1.1.4 → valar-1.2.1}/src/valar/classes/__init__.py +0 -0
- {valar-1.1.4/src/valar/frame → valar-1.2.1/src/valar/classes/app_mixins}/__init__.py +0 -0
- {valar-1.1.4 → valar-1.2.1}/src/valar/classes/singleton_meta.py +0 -0
- {valar-1.1.4/src/valar/migrations → valar-1.2.1/src/valar/dao/defaults}/__init__.py +0 -0
- {valar-1.1.4/src/valar/views → valar-1.2.1/src/valar/migrations}/__init__.py +0 -0
- {valar-1.1.4 → valar-1.2.1}/src/valar/models/__init__.py +0 -0
- {valar-1.1.4 → valar-1.2.1}/src/valar.egg-info/dependency_links.txt +0 -0
- {valar-1.1.4 → valar-1.2.1}/src/valar.egg-info/requires.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: valar
|
|
3
|
-
Version: 1.1
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: valar for morghulis
|
|
5
5
|
Home-page: https://gitee.com/GRIFFIN120/valar_dev
|
|
6
6
|
Author: LYP
|
|
@@ -27,12 +27,13 @@ Dynamic: requires-python
|
|
|
27
27
|
Dynamic: summary
|
|
28
28
|
|
|
29
29
|
valar for morghulis
|
|
30
|
+
|
|
30
31
|
# 1. install
|
|
32
|
+
|
|
31
33
|
```shell
|
|
32
34
|
pip install valar
|
|
33
35
|
```
|
|
34
36
|
|
|
35
|
-
|
|
36
37
|
# 1. settings
|
|
37
38
|
|
|
38
39
|
```python
|
|
@@ -47,16 +48,12 @@ BASE_APP = str(BASE_DIR.name)
|
|
|
47
48
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|
48
49
|
SECRET_KEY = get_random_secret_key()
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
51
|
""" Valar Options """
|
|
53
52
|
|
|
54
53
|
HANDLER_MAPPING = "%s.urls.channel_mapping" % BASE_APP
|
|
55
54
|
MONGO_URI = 'mongodb://root:19870120@121.41.111.175:27017/'
|
|
56
55
|
MINIO_URL = "s3://admin:password@120.27.8.186:9000"
|
|
57
56
|
|
|
58
|
-
|
|
59
|
-
|
|
60
57
|
""" Minimized compulsory settings """
|
|
61
58
|
|
|
62
59
|
DATABASES = {
|
|
@@ -69,7 +66,7 @@ INSTALLED_APPS = [
|
|
|
69
66
|
'django.contrib.sessions',
|
|
70
67
|
"corsheaders",
|
|
71
68
|
'channels',
|
|
72
|
-
'valar',
|
|
69
|
+
'valar.apps.ValarConfig',
|
|
73
70
|
]
|
|
74
71
|
MIDDLEWARE = [
|
|
75
72
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
@@ -99,6 +96,7 @@ FILE_UPLOAD_MAX_MEMORY_SIZE = 1024 * 1024 * 100
|
|
|
99
96
|
DATA_UPLOAD_MAX_MEMORY_SIZE = 1024 * 1024 * 100
|
|
100
97
|
|
|
101
98
|
```
|
|
99
|
+
|
|
102
100
|
# 2. asgi
|
|
103
101
|
|
|
104
102
|
```python
|
|
@@ -117,8 +115,8 @@ application = ProtocolTypeRouter({
|
|
|
117
115
|
```
|
|
118
116
|
|
|
119
117
|
# 3. migrate
|
|
120
|
-
no need, valar will auto migration
|
|
121
118
|
|
|
119
|
+
no need, valar will auto migration
|
|
122
120
|
|
|
123
121
|
# 4. root urls
|
|
124
122
|
|
|
@@ -126,7 +124,6 @@ no need, valar will auto set urlpatterns
|
|
|
126
124
|
|
|
127
125
|
# 5. how to use valar_channel
|
|
128
126
|
|
|
129
|
-
|
|
130
127
|
5.1 set HANDLER_MAPPING in settings
|
|
131
128
|
|
|
132
129
|
```python
|
|
@@ -137,13 +134,11 @@ HANDLER_MAPPING = "%s.urls.channel_mapping" % BASE_APP
|
|
|
137
134
|
|
|
138
135
|
```python
|
|
139
136
|
from valar.channels.sender import ValarSocketSender
|
|
137
|
+
|
|
138
|
+
|
|
140
139
|
def test_handler(sender: ValarSocketSender):
|
|
141
140
|
data = sender.data
|
|
142
|
-
|
|
143
|
-
counter = sender.create_counter(length)
|
|
144
|
-
for i in range(length):
|
|
145
|
-
# sync method
|
|
146
|
-
sender.to_clients(counter.tick() ,sender.client, wait=True)
|
|
141
|
+
sender.load(data)
|
|
147
142
|
```
|
|
148
143
|
|
|
149
144
|
5.3 register handler in channel_mapping
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
valar for morghulis
|
|
2
|
+
|
|
2
3
|
# 1. install
|
|
4
|
+
|
|
3
5
|
```shell
|
|
4
6
|
pip install valar
|
|
5
7
|
```
|
|
6
8
|
|
|
7
|
-
|
|
8
9
|
# 1. settings
|
|
9
10
|
|
|
10
11
|
```python
|
|
@@ -19,16 +20,12 @@ BASE_APP = str(BASE_DIR.name)
|
|
|
19
20
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|
20
21
|
SECRET_KEY = get_random_secret_key()
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
23
|
""" Valar Options """
|
|
25
24
|
|
|
26
25
|
HANDLER_MAPPING = "%s.urls.channel_mapping" % BASE_APP
|
|
27
26
|
MONGO_URI = 'mongodb://root:19870120@121.41.111.175:27017/'
|
|
28
27
|
MINIO_URL = "s3://admin:password@120.27.8.186:9000"
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
29
|
""" Minimized compulsory settings """
|
|
33
30
|
|
|
34
31
|
DATABASES = {
|
|
@@ -41,7 +38,7 @@ INSTALLED_APPS = [
|
|
|
41
38
|
'django.contrib.sessions',
|
|
42
39
|
"corsheaders",
|
|
43
40
|
'channels',
|
|
44
|
-
'valar',
|
|
41
|
+
'valar.apps.ValarConfig',
|
|
45
42
|
]
|
|
46
43
|
MIDDLEWARE = [
|
|
47
44
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
@@ -71,6 +68,7 @@ FILE_UPLOAD_MAX_MEMORY_SIZE = 1024 * 1024 * 100
|
|
|
71
68
|
DATA_UPLOAD_MAX_MEMORY_SIZE = 1024 * 1024 * 100
|
|
72
69
|
|
|
73
70
|
```
|
|
71
|
+
|
|
74
72
|
# 2. asgi
|
|
75
73
|
|
|
76
74
|
```python
|
|
@@ -89,8 +87,8 @@ application = ProtocolTypeRouter({
|
|
|
89
87
|
```
|
|
90
88
|
|
|
91
89
|
# 3. migrate
|
|
92
|
-
no need, valar will auto migration
|
|
93
90
|
|
|
91
|
+
no need, valar will auto migration
|
|
94
92
|
|
|
95
93
|
# 4. root urls
|
|
96
94
|
|
|
@@ -98,7 +96,6 @@ no need, valar will auto set urlpatterns
|
|
|
98
96
|
|
|
99
97
|
# 5. how to use valar_channel
|
|
100
98
|
|
|
101
|
-
|
|
102
99
|
5.1 set HANDLER_MAPPING in settings
|
|
103
100
|
|
|
104
101
|
```python
|
|
@@ -109,13 +106,11 @@ HANDLER_MAPPING = "%s.urls.channel_mapping" % BASE_APP
|
|
|
109
106
|
|
|
110
107
|
```python
|
|
111
108
|
from valar.channels.sender import ValarSocketSender
|
|
109
|
+
|
|
110
|
+
|
|
112
111
|
def test_handler(sender: ValarSocketSender):
|
|
113
112
|
data = sender.data
|
|
114
|
-
|
|
115
|
-
counter = sender.create_counter(length)
|
|
116
|
-
for i in range(length):
|
|
117
|
-
# sync method
|
|
118
|
-
sender.to_clients(counter.tick() ,sender.client, wait=True)
|
|
113
|
+
sender.load(data)
|
|
119
114
|
```
|
|
120
115
|
|
|
121
116
|
5.3 register handler in channel_mapping
|
|
@@ -16,16 +16,16 @@ requires = [
|
|
|
16
16
|
|
|
17
17
|
setup(
|
|
18
18
|
name="valar", # 包名
|
|
19
|
-
version="1.1
|
|
19
|
+
version="1.2.1", # 版本号
|
|
20
20
|
author="LYP", # 作者
|
|
21
21
|
author_email="liuyinpeng@buaa.edu.cn", # 邮箱
|
|
22
22
|
description="valar for morghulis", # 简短描述
|
|
23
23
|
long_description=long_description, # 详细说明
|
|
24
24
|
long_description_content_type="text/markdown", # 详细说明使用标记类型
|
|
25
|
-
url="https://gitee.com/GRIFFIN120/valar_dev",
|
|
25
|
+
url="https://gitee.com/GRIFFIN120/valar_dev", # 项目主页
|
|
26
26
|
packages=find_packages(where="src"), # 需要打包的部分
|
|
27
27
|
package_dir={"": "src"}, # 设置src目录为根目录
|
|
28
28
|
python_requires=">=3.9", # 项目支持的Python版本
|
|
29
|
-
install_requires=requires,
|
|
29
|
+
install_requires=requires, # 项目必须的依赖
|
|
30
30
|
include_package_data=False # 是否包含非Python文件(如资源文件)
|
|
31
|
-
)
|
|
31
|
+
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from django.apps import AppConfig
|
|
3
|
+
from .classes.app_mixins.auto_migration_mixin import AutoMigrationMixin
|
|
4
|
+
from .classes.app_mixins.auto_urlpatterns_mixin import AutoUrlPatternsMixin
|
|
5
|
+
|
|
6
|
+
valar_app = __package__.replace('src.', '')
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ValarConfig(AutoMigrationMixin, AutoUrlPatternsMixin, AppConfig):
|
|
10
|
+
default_auto_field = 'django.db.models.BigAutoField'
|
|
11
|
+
name = __package__
|
|
12
|
+
|
|
13
|
+
def ready(self):
|
|
14
|
+
if os.environ.get('RUN_MAIN') == 'true':
|
|
15
|
+
from .dao.frame import MetaFrame
|
|
16
|
+
getattr(super(), 'set_url', None)()
|
|
17
|
+
getattr(super(), 'auto_migrate', None)()
|
|
18
|
+
MetaFrame()
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
1
|
from channels.generic.websocket import AsyncJsonWebsocketConsumer
|
|
3
2
|
|
|
4
3
|
VALAR_CHANNEL_GROUP = 'VALAR'
|
|
5
4
|
|
|
5
|
+
|
|
6
6
|
class ValarConsumer(AsyncJsonWebsocketConsumer):
|
|
7
7
|
|
|
8
8
|
def __init__(self):
|
|
@@ -24,25 +24,23 @@ class ValarConsumer(AsyncJsonWebsocketConsumer):
|
|
|
24
24
|
pass
|
|
25
25
|
|
|
26
26
|
async def user_emit(self, event):
|
|
27
|
-
users: list = event.get('users',[])
|
|
28
|
-
data = event.get('data',{})
|
|
27
|
+
users: list = event.get('users', [])
|
|
28
|
+
data = event.get('data', {})
|
|
29
29
|
if self.uid in users:
|
|
30
30
|
await self.send_json(data)
|
|
31
31
|
|
|
32
32
|
async def client_emit(self, event):
|
|
33
|
-
clients: list = event.get('clients',[])
|
|
34
|
-
data = event.get('data',{})
|
|
33
|
+
clients: list = event.get('clients', [])
|
|
34
|
+
data = event.get('data', {})
|
|
35
35
|
if self.client in clients:
|
|
36
36
|
await self.send_json(data)
|
|
37
37
|
|
|
38
38
|
async def broadcast_emit(self, event):
|
|
39
|
-
data = event.get('data',{})
|
|
39
|
+
data = event.get('data', {})
|
|
40
40
|
await self.send_json(data)
|
|
41
41
|
|
|
42
42
|
async def register_emit(self, event):
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if self.client
|
|
46
|
-
self.uid =
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
uid = event.get('uid', )
|
|
44
|
+
client = event.get('client')
|
|
45
|
+
if self.client == client:
|
|
46
|
+
self.uid = uid
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
from ..channels.sender import ValarChannelSender
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
async def execute_channel(method, sender: ValarChannelSender):
|
|
7
|
+
thread = asyncio.to_thread(__execute__, method, sender)
|
|
8
|
+
asyncio.create_task(thread)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def __execute__(method, sender: ValarChannelSender):
|
|
12
|
+
sender.start()
|
|
13
|
+
method(sender)
|
|
14
|
+
sender.stop()
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import time
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
|
|
5
|
+
from asgiref.sync import async_to_sync
|
|
6
|
+
from channels.layers import get_channel_layer
|
|
7
|
+
from django.http import HttpRequest
|
|
8
|
+
import threading
|
|
9
|
+
from .consumer import VALAR_CHANNEL_GROUP
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Channel:
|
|
13
|
+
|
|
14
|
+
def __init__(self, request: HttpRequest):
|
|
15
|
+
body = json.loads(request.body)
|
|
16
|
+
self.handler = body.get('handler')
|
|
17
|
+
self.url = body.get('url')
|
|
18
|
+
self.auth = body.get('auth')
|
|
19
|
+
self.broadcast = body.get('broadcast')
|
|
20
|
+
self.data = body.get('data')
|
|
21
|
+
|
|
22
|
+
def to_dict(self, status, payload):
|
|
23
|
+
data = {
|
|
24
|
+
'handler': self.handler,
|
|
25
|
+
'url': self.url,
|
|
26
|
+
'auth': self.auth,
|
|
27
|
+
'broadcast': self.broadcast,
|
|
28
|
+
'timestamp': datetime.now().timestamp()
|
|
29
|
+
}
|
|
30
|
+
if status:
|
|
31
|
+
data.update({'status': status})
|
|
32
|
+
if payload:
|
|
33
|
+
data.update({'payload': payload})
|
|
34
|
+
return data
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class Sender:
|
|
38
|
+
|
|
39
|
+
def __init__(self, request: HttpRequest):
|
|
40
|
+
self.client = request.headers.get('CLIENT')
|
|
41
|
+
self.uid = request.session.get('UID')
|
|
42
|
+
self.group_send = async_to_sync(get_channel_layer().group_send)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ValarChannelSender(Sender):
|
|
46
|
+
|
|
47
|
+
def __init__(self, request: HttpRequest, interval=1):
|
|
48
|
+
super().__init__(request)
|
|
49
|
+
self.__channel__ = Channel(request)
|
|
50
|
+
self.data = self.__channel__.data
|
|
51
|
+
self.__payload__ = None
|
|
52
|
+
self.__loading__ = False
|
|
53
|
+
self.__thread__ = None
|
|
54
|
+
self.__lock__ = threading.Lock()
|
|
55
|
+
self.__interval__ = interval
|
|
56
|
+
if self.__channel__.auth and not self.uid:
|
|
57
|
+
raise Exception('Unauthorized!')
|
|
58
|
+
|
|
59
|
+
def _run(self):
|
|
60
|
+
while self.__loading__:
|
|
61
|
+
self.__emit__()
|
|
62
|
+
time.sleep(self.__interval__)
|
|
63
|
+
|
|
64
|
+
def start(self):
|
|
65
|
+
if self.__loading__:
|
|
66
|
+
return # 避免重复启动
|
|
67
|
+
self.__payload__ = None
|
|
68
|
+
self.__loading__ = True
|
|
69
|
+
self.__emit__('start')
|
|
70
|
+
self.__thread__ = threading.Thread(target=self._run, daemon=True)
|
|
71
|
+
self.__thread__.start()
|
|
72
|
+
|
|
73
|
+
def stop(self):
|
|
74
|
+
self.__payload__ = None
|
|
75
|
+
self.__loading__ = False
|
|
76
|
+
self.__emit__('stop')
|
|
77
|
+
if self.__thread__:
|
|
78
|
+
self.__thread__.join()
|
|
79
|
+
self.__thread__ = None
|
|
80
|
+
|
|
81
|
+
def load(self, payload):
|
|
82
|
+
with self.__lock__:
|
|
83
|
+
self.__payload__ = payload
|
|
84
|
+
|
|
85
|
+
def done(self, payload):
|
|
86
|
+
self.__emit__('done', payload)
|
|
87
|
+
|
|
88
|
+
def __emit__(self, status='proceed', data=None):
|
|
89
|
+
scope = 'broadcast' if self.__channel__.broadcast else 'client'
|
|
90
|
+
body = {
|
|
91
|
+
'type': f'{scope}.emit',
|
|
92
|
+
'data': self.__channel__.to_dict(status, data or self.__payload__),
|
|
93
|
+
'clients': [self.client],
|
|
94
|
+
'users': []
|
|
95
|
+
}
|
|
96
|
+
self.group_send(VALAR_CHANNEL_GROUP, body)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class ValarSocketSender(Sender):
|
|
100
|
+
def __init__(self, request: HttpRequest):
|
|
101
|
+
super().__init__(request)
|
|
102
|
+
if self.uid:
|
|
103
|
+
body = {'type': 'broadcast.emit', 'uid': self.uid, 'client': self.client}
|
|
104
|
+
self.group_send(VALAR_CHANNEL_GROUP, body)
|
|
105
|
+
|
|
106
|
+
def to_users(self, payload, users: list):
|
|
107
|
+
body = {'type': 'user.emit', 'data': payload, 'users': users}
|
|
108
|
+
self.group_send(VALAR_CHANNEL_GROUP, body)
|
|
109
|
+
|
|
110
|
+
def to_clients(self, payload, clients: list):
|
|
111
|
+
body = {'type': 'client.emit', 'data': payload, 'clients': clients}
|
|
112
|
+
self.group_send(VALAR_CHANNEL_GROUP, body)
|
|
113
|
+
|
|
114
|
+
def broadcast(self, payload):
|
|
115
|
+
body = {'type': 'broadcast.emit', 'data': payload}
|
|
116
|
+
self.group_send(VALAR_CHANNEL_GROUP, body)
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
2
1
|
from .executer import execute_channel
|
|
3
2
|
from .mapping import ChannelMapping
|
|
4
|
-
from .sender import
|
|
3
|
+
from .sender import ValarChannelSender
|
|
5
4
|
from ..classes.valar_response import ValarResponse
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
async def handel_channel(request, handler):
|
|
9
|
-
sender =
|
|
8
|
+
sender = ValarChannelSender(request)
|
|
10
9
|
method = ChannelMapping().get_handler(handler)
|
|
11
10
|
await execute_channel(method, sender)
|
|
12
11
|
return ValarResponse(True)
|
{valar-1.1.4/src/valar/classes → valar-1.2.1/src/valar/classes/app_mixins}/auto_migration_mixin.py
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
class AutoMigrationMixin:
|
|
2
2
|
name = None # 子类必须提供
|
|
3
|
+
|
|
3
4
|
def auto_migrate(self):
|
|
4
5
|
from django.core.management import call_command
|
|
5
|
-
app = self.name.replace('src.','')
|
|
6
|
+
app = self.name.replace('src.', '')
|
|
6
7
|
call_command('makemigrations', app, interactive=False, verbosity=0)
|
|
7
8
|
call_command('migrate', app, interactive=False, verbosity=0)
|
|
8
|
-
|
{valar-1.1.4/src/valar/classes → valar-1.2.1/src/valar/classes/app_mixins}/auto_urlpatterns_mixin.py
RENAMED
|
@@ -3,13 +3,13 @@ import importlib
|
|
|
3
3
|
from django.conf import settings
|
|
4
4
|
from django.urls import path, include
|
|
5
5
|
|
|
6
|
+
|
|
6
7
|
class AutoUrlPatternsMixin:
|
|
7
8
|
name = None # 子类必须提供
|
|
9
|
+
|
|
8
10
|
def set_url(self):
|
|
9
11
|
root = settings.ROOT_URLCONF
|
|
10
12
|
module = importlib.import_module(root)
|
|
11
13
|
urlpatterns: list = getattr(module, 'urlpatterns')
|
|
12
14
|
url = f'{self.name}.urls'
|
|
13
|
-
urlpatterns.append(path('
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
urlpatterns.append(path('valar/', include(url)))
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from io import BytesIO
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from urllib3 import BaseHTTPResponse
|
|
5
|
+
|
|
6
|
+
from ..classes.singleton_meta import SingletonMeta
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ValarMinio(metaclass=SingletonMeta):
|
|
10
|
+
|
|
11
|
+
def __init__(self, client, entity):
|
|
12
|
+
self.client = client
|
|
13
|
+
self.bucket_name = f'{settings.BASE_DIR.name}.{entity}'.replace('_', '-').lower()
|
|
14
|
+
if client and not self.client.bucket_exists(self.bucket_name):
|
|
15
|
+
self.client.make_bucket(self.bucket_name)
|
|
16
|
+
self.client.set_bucket_policy(self.bucket_name, self.__generate_policy__())
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def get_object_name(_id, prop, file_name):
|
|
20
|
+
return f"{_id}-{prop}-{file_name}"
|
|
21
|
+
|
|
22
|
+
def upload(self, object_name, _bytes):
|
|
23
|
+
file_data = BytesIO(_bytes)
|
|
24
|
+
file_size = len(_bytes) # file.siz
|
|
25
|
+
self.client.put_object(
|
|
26
|
+
bucket_name=self.bucket_name,
|
|
27
|
+
object_name=object_name,
|
|
28
|
+
data=file_data,
|
|
29
|
+
length=file_size
|
|
30
|
+
)
|
|
31
|
+
return f'{self.bucket_name}/{object_name}'
|
|
32
|
+
|
|
33
|
+
def remove(self, path):
|
|
34
|
+
if path:
|
|
35
|
+
bucket_name, object_name = path.split('/')
|
|
36
|
+
self.client.remove_object(
|
|
37
|
+
bucket_name=bucket_name,
|
|
38
|
+
object_name=object_name
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def read(self, object_name) -> BytesIO:
|
|
42
|
+
ret: BaseHTTPResponse = self.client.get_object(
|
|
43
|
+
bucket_name=self.bucket_name,
|
|
44
|
+
object_name=object_name
|
|
45
|
+
)
|
|
46
|
+
return BytesIO(ret.read())
|
|
47
|
+
|
|
48
|
+
def __generate_policy__(self):
|
|
49
|
+
return json.dumps({
|
|
50
|
+
"Version": "2012-10-17",
|
|
51
|
+
"Statement": [
|
|
52
|
+
{
|
|
53
|
+
"Sid": "",
|
|
54
|
+
"Effect": "Allow",
|
|
55
|
+
"Principal": {"AWS": "*"},
|
|
56
|
+
"Action": "s3:GetBucketLocation",
|
|
57
|
+
"Resource": f"arn:aws:s3:::{self.bucket_name}"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"Sid": "",
|
|
61
|
+
"Effect": "Allow",
|
|
62
|
+
"Principal": {"AWS": "*"},
|
|
63
|
+
"Action": "s3:ListBucket",
|
|
64
|
+
"Resource": f"arn:aws:s3:::{self.bucket_name}"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"Sid": "",
|
|
68
|
+
"Effect": "Allow",
|
|
69
|
+
"Principal": {"AWS": "*"},
|
|
70
|
+
"Action": "s3:GetObject",
|
|
71
|
+
"Resource": f"arn:aws:s3:::{self.bucket_name}/*"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"Sid": "",
|
|
75
|
+
"Effect": "Allow",
|
|
76
|
+
"Principal": {"AWS": "*"},
|
|
77
|
+
"Action": "s3:PutObject",
|
|
78
|
+
"Resource": f"arn:aws:s3:::{self.bucket_name}/*"
|
|
79
|
+
}
|
|
80
|
+
]})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from django.http import JsonResponse
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
class ValarResponse(JsonResponse):
|
|
4
|
-
def __init__(self, data, message='', code='info'):
|
|
5
|
+
def __init__(self, data=True, message='', code='info'):
|
|
5
6
|
self.message = message
|
|
6
7
|
self.code = code
|
|
7
8
|
super(ValarResponse, self).__init__(data, safe=False)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from ..dao.abstract import AbstractDao
|
|
2
|
+
from ..dao.mon_dao import MonDao
|
|
3
|
+
from ..dao.orm_dao import OrmDao
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Dao(AbstractDao):
|
|
7
|
+
|
|
8
|
+
def __init__(self, entity, db='orm'):
|
|
9
|
+
self.dao = OrmDao(entity) if db == 'orm' else MonDao(entity)
|
|
10
|
+
self.db = db
|
|
11
|
+
self.entity = entity
|
|
12
|
+
self.name = self.dao.name
|
|
13
|
+
self.is_tree = self.dao.is_tree
|
|
14
|
+
self.fields = self.dao.fields
|
|
15
|
+
self.manager = self.dao.manager
|
|
16
|
+
|
|
17
|
+
def save_many(self, array: list):
|
|
18
|
+
self.dao.save_many(array)
|
|
19
|
+
|
|
20
|
+
def save_one(self, item, with_id=False):
|
|
21
|
+
return self.dao.save_one(item, with_id)
|
|
22
|
+
|
|
23
|
+
def delete_one(self, _id):
|
|
24
|
+
return self.dao.delete_one(_id)
|
|
25
|
+
|
|
26
|
+
def find_one(self, _id):
|
|
27
|
+
return self.dao.find_one(_id)
|
|
28
|
+
|
|
29
|
+
def find(self, conditions=None, orders=None, size=0, page=1):
|
|
30
|
+
return self.dao.find(conditions, orders, size, page)
|
|
31
|
+
|
|
32
|
+
def values(self, conditions, props):
|
|
33
|
+
return self.dao.values(conditions, props)
|
|
34
|
+
|
|
35
|
+
def update(self, template, conditions):
|
|
36
|
+
return self.dao.update(template, conditions)
|
|
37
|
+
|
|
38
|
+
def delete(self, conditions=None) -> list:
|
|
39
|
+
return self.dao.delete(conditions)
|
|
40
|
+
|
|
41
|
+
def serialize(self, o, code=None):
|
|
42
|
+
return self.dao.serialize(o, code)
|
|
43
|
+
|
|
44
|
+
def tree(self, root, conditions=None):
|
|
45
|
+
return self.dao.tree(root, conditions)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
from bson import ObjectId
|
|
4
|
+
|
|
5
|
+
from ..dao.engine import ValarEngine
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AbstractField(ABC):
|
|
9
|
+
db = None
|
|
10
|
+
entity = None
|
|
11
|
+
prop = None
|
|
12
|
+
label = None
|
|
13
|
+
domain = None
|
|
14
|
+
refer = None
|
|
15
|
+
|
|
16
|
+
@abstractmethod
|
|
17
|
+
def to_dict(self):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AbstractDao(ABC):
|
|
22
|
+
engine = ValarEngine()
|
|
23
|
+
db = None
|
|
24
|
+
entity = None
|
|
25
|
+
name = None
|
|
26
|
+
is_tree = False
|
|
27
|
+
fields = {}
|
|
28
|
+
|
|
29
|
+
def props(self, domain=None):
|
|
30
|
+
return [prop for prop, field in self.fields.items() if field.domain == domain or domain is None]
|
|
31
|
+
|
|
32
|
+
def full_props(self):
|
|
33
|
+
return {
|
|
34
|
+
prop: {
|
|
35
|
+
"prop": prop,
|
|
36
|
+
"domain": field.domain,
|
|
37
|
+
"label": field.label,
|
|
38
|
+
}
|
|
39
|
+
for prop, field in self.fields.items()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
def get_meta_field(self, prop) -> AbstractField:
|
|
43
|
+
return self.fields[prop]
|
|
44
|
+
|
|
45
|
+
@abstractmethod
|
|
46
|
+
def save_one(self, item, with_id=False):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
@abstractmethod
|
|
50
|
+
def save_many(self, array: list):
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def values(self, conditions, props):
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
@abstractmethod
|
|
58
|
+
def delete_one(self, _id):
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
@abstractmethod
|
|
62
|
+
def find_one(self, _id):
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
@abstractmethod
|
|
66
|
+
def find(self, conditions=None, orders=None, size=0, page=1):
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
@abstractmethod
|
|
70
|
+
def update(self, template, conditions):
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
@abstractmethod
|
|
74
|
+
def delete(self, conditions=None) -> list:
|
|
75
|
+
pass
|
|
76
|
+
|
|
77
|
+
@abstractmethod
|
|
78
|
+
def serialize(self, o, code=None):
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
@abstractmethod
|
|
82
|
+
def tree(self, root, conditions=None):
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
def search(self, includes=None, excludes=None, orders=None):
|
|
86
|
+
conditions = [{"includes": includes or {}, "excludes": excludes or {}}]
|
|
87
|
+
results, _ = self.find(conditions, orders)
|
|
88
|
+
return results
|
|
89
|
+
|
|
90
|
+
def object_id(self, _id):
|
|
91
|
+
try:
|
|
92
|
+
return int(_id) if self.db == 'orm' else ObjectId(_id)
|
|
93
|
+
except Exception:
|
|
94
|
+
return None
|
|
95
|
+
|
|
96
|
+
# @abstractmethod
|
|
97
|
+
# def values(self, props, conditions, orders=None):
|
|
98
|
+
# pass
|
|
99
|
+
#
|
|
100
|
+
# @abstractmethod
|
|
101
|
+
# def group(self, props, conditions, orders=None):
|
|
102
|
+
# pass
|
|
103
|
+
#
|
|
104
|
+
# @abstractmethod
|
|
105
|
+
# def count(self, props, conditions):
|
|
106
|
+
# pass
|