Compare commits
21 Commits
ff030444e4
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| dbeeb4d25a | |||
| 58c4b85e6a | |||
| b6fc41994e | |||
| 1a08ba460c | |||
| 692631e395 | |||
| 1174b225a7 | |||
| ded28f6a1e | |||
| 4e64fb2422 | |||
| eb074e5dd5 | |||
| 6ef3faf149 | |||
| 9b519f4650 | |||
| d6bef5812b | |||
| 8e8fccbb1a | |||
| 237f0acf8d | |||
| 44ce96c7d9 | |||
| dae0ce21be | |||
| a94dc7b415 | |||
| ca44cf0eaa | |||
| 18c3968e59 | |||
| 5ce9ee1b1e | |||
| 2596680c3a |
@@ -0,0 +1,2 @@
|
|||||||
|
import views
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
src="//unpkg.com/outeres@0.0.10/img/layui/icon-v2.png"
|
src="//unpkg.com/outeres@0.0.10/img/layui/icon-v2.png"
|
||||||
class="layui-nav-img"
|
class="layui-nav-img"
|
||||||
/>
|
/>
|
||||||
{{ session.nickname }}
|
{{ session.name }}
|
||||||
</a>
|
</a>
|
||||||
<dl class="layui-nav-child">
|
<dl class="layui-nav-child">
|
||||||
<dd><a href="/home/profile">资料</a></dd> <!-- 修改这里的href指向/profile -->
|
<dd><a href="/home/profile">资料</a></dd> <!-- 修改这里的href指向/profile -->
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
data: data.field, // 表单数据
|
data: data.field, // 表单数据
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
|
console.log(response)
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
window.location.href = '/attendance-reminder'; // 或者你的成功页面
|
window.location.href = '/attendance-reminder'; // 或者你的成功页面
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
43
app/tests/ReceiveExcelTest.py
Normal file
43
app/tests/ReceiveExcelTest.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import unittest
|
||||||
|
import os
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
from werkzeug.datastructures import FileStorage # 用于创建测试文件
|
||||||
|
|
||||||
|
class ReceiveExcelTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
app.testing = True # 设置 Flask 应用为测试模式
|
||||||
|
self.client = app.test_client()
|
||||||
|
# 创建一个测试用的Excel文件或使用一个真实的Excel文件路径
|
||||||
|
self.test_file_path = 'template.xlsx'
|
||||||
|
|
||||||
|
def test_receive_excel_no_file(self):
|
||||||
|
# 测试没有文件时的情况
|
||||||
|
response = self.client.post('/api/receive-excel')
|
||||||
|
self.assertEqual(response.status_code, 400)
|
||||||
|
self.assertEqual(response.get_json(), {"error": "No file part"})
|
||||||
|
|
||||||
|
def test_receive_excel_with_file(self):
|
||||||
|
# 模拟已登录用户
|
||||||
|
with self.client.session_transaction() as sess:
|
||||||
|
sess['number'] = 'X202301000001'
|
||||||
|
|
||||||
|
# 使用 FileStorage 创建测试文件对象
|
||||||
|
data = {
|
||||||
|
'file': (open(self.test_file_path, 'rb'), self.test_file_path)
|
||||||
|
}
|
||||||
|
# 发送 POST 请求到 /api/receive-excel
|
||||||
|
response = self.client.post('/api/receive-excel', data=data, content_type='multipart/form-data')
|
||||||
|
|
||||||
|
# 验证返回的状态码和响应
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(response.get_json(), {"message": "File successfully processed"})
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
# 清理测试用的文件或数据
|
||||||
|
if os.path.exists(self.test_file_path):
|
||||||
|
os.remove(self.test_file_path)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
39
app/tests/StudentSignInTest.py
Normal file
39
app/tests/StudentSignInTest.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
from unittest.mock import patch
|
||||||
|
from flask import session
|
||||||
|
|
||||||
|
|
||||||
|
class StudentSignInTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# 设置 Flask 测试模式
|
||||||
|
app.testing = True
|
||||||
|
self.client = app.test_client()
|
||||||
|
|
||||||
|
@patch('db.database_manager.DatabaseManager.update_sign_in_info')
|
||||||
|
def test_student_sign_in(self, mock_update_sign_in_info):
|
||||||
|
# 模拟已登录用户
|
||||||
|
with self.client.session_transaction() as sess:
|
||||||
|
sess['number'] = 'X202301000001'
|
||||||
|
|
||||||
|
# 模拟数据库操作
|
||||||
|
mock_update_sign_in_info.return_value = 1 # 假设成功更新签到信息
|
||||||
|
|
||||||
|
# 发送 POST 请求到/api/student-sign-in
|
||||||
|
response = self.client.post('/api/student-sign-in', data={
|
||||||
|
'course_name': '计算机导论',
|
||||||
|
'course_id': '2',
|
||||||
|
'student_number': 'X202301000001',
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
# 验证返回的状态码和JSON数据
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
json_data = response.get_json()
|
||||||
|
self.assertEqual(json_data, {"msg": "ok", "data": "签到成功!"})
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
37
app/tests/TeacherSignInTest.py
Normal file
37
app/tests/TeacherSignInTest.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
from unittest.mock import patch
|
||||||
|
from flask import session
|
||||||
|
|
||||||
|
class TeacherSignInTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# 设置 Flask 测试模式
|
||||||
|
app.testing = True
|
||||||
|
self.client = app.test_client()
|
||||||
|
|
||||||
|
@patch('db.database_manager.DatabaseManager.update_sign_in_info')
|
||||||
|
def test_teacher_sign_in(self, mock_teacher_sign_in):
|
||||||
|
# 模拟已登录用户
|
||||||
|
with self.client.session_transaction() as sess:
|
||||||
|
sess['number'] = 'X202301000001'
|
||||||
|
|
||||||
|
# 模拟数据库操作的返回值
|
||||||
|
mock_teacher_sign_in.return_value = {"msg": "当前班级专业没有学生'"}
|
||||||
|
|
||||||
|
# 发送 POST 请求到/api/teacher-sign-in
|
||||||
|
response = self.client.post('/api/teacher-sign-in', data={
|
||||||
|
'course_id': '123',
|
||||||
|
'course_name': 'Test Course',
|
||||||
|
'class_name': 'TestClass',
|
||||||
|
'major_id': '456'
|
||||||
|
})
|
||||||
|
|
||||||
|
# 验证返回的状态码和数据
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
json_data = response.get_json()
|
||||||
|
self.assertEqual(json_data, {"msg": "当前班级专业没有学生"})
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
73
app/tests/TestGetHtml.py
Normal file
73
app/tests/TestGetHtml.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
|
||||||
|
|
||||||
|
class HtmlTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
app.testing = True # 设置 Flask 应用为测试模式
|
||||||
|
self.client = app.test_client() # 创建一个测试客户端
|
||||||
|
|
||||||
|
def test_get_course_info(self):
|
||||||
|
# 测试 GET 请求
|
||||||
|
response = self.client.get('/course-info')
|
||||||
|
|
||||||
|
# 验证响应状态码
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
# 验证响应的Content-Type头部值
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
def test_get_attendance(self):
|
||||||
|
# 测试 GET 请求
|
||||||
|
response = self.client.get('/attendance')
|
||||||
|
|
||||||
|
# 验证响应状态码
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# 验证响应的Content-Type头部值
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
def test_get_announcement(self):
|
||||||
|
# 测试 GET 请求
|
||||||
|
response = self.client.get('/announcement')
|
||||||
|
|
||||||
|
# 验证响应状态码
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# 验证响应的Content-Type头部值
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
def test_get_attendance_reminder(self):
|
||||||
|
# 测试 GET 请求
|
||||||
|
response = self.client.get('/attendance-reminder')
|
||||||
|
|
||||||
|
# 验证响应状态码
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# 验证响应的Content-Type头部值
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
def test_get_course_category(self):
|
||||||
|
# 测试 GET 请求
|
||||||
|
response = self.client.get('/course-category')
|
||||||
|
|
||||||
|
# 验证响应状态码
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# 验证响应的Content-Type头部值
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
def test_get_attendance_teacher(self):
|
||||||
|
# 测试 GET 请求
|
||||||
|
response = self.client.get('/attendance-teacher')
|
||||||
|
|
||||||
|
# 验证响应状态码
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# 验证响应的Content-Type头部值
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
44
app/tests/TestGetMenu.py
Normal file
44
app/tests/TestGetMenu.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
from flask import session
|
||||||
|
from unittest.mock import patch # 如果需要模拟数据库方法
|
||||||
|
|
||||||
|
|
||||||
|
class MenuAPITestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
app.testing = True # 设置 Flask 应用为测试模式
|
||||||
|
self.client = app.test_client() # 创建一个测试客户端
|
||||||
|
self.expected_menu = [
|
||||||
|
{"name": "课程类别", "path": "/course-category"},
|
||||||
|
{"name": "课程信息", "path": "/course-info"},
|
||||||
|
{"name": "课程签到", "path": "/attendance-teacher"},
|
||||||
|
{"name": "签到提醒", "path": "/attendance-reminder"}
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_menu_no_login(self):
|
||||||
|
# 测试未登录情况下请求API
|
||||||
|
response = self.client.get('/api/menu')
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
self.assertEqual(response.get_json(), [])
|
||||||
|
|
||||||
|
def test_login(self):
|
||||||
|
with self.client:
|
||||||
|
self.client.post('/login', data=dict(
|
||||||
|
number='G0001',
|
||||||
|
password='1'
|
||||||
|
))
|
||||||
|
|
||||||
|
# 确认登录后session中有数据
|
||||||
|
self.assertIn('role', session)
|
||||||
|
|
||||||
|
# 执行logout
|
||||||
|
response = self.client.get('/api/menu')
|
||||||
|
print(response.get_json())
|
||||||
|
# 确认响应是重定向到登录页面
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(self.expected_menu,response.get_json())
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
45
app/tests/TestLogin.py
Normal file
45
app/tests/TestLogin.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
from db.database_manager import DatabaseManager # 确保你可以导入DatabaseManager
|
||||||
|
|
||||||
|
class LoginTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# 设置 Flask 测试模式
|
||||||
|
app.testing = True
|
||||||
|
self.client = app.test_client()
|
||||||
|
|
||||||
|
def test_login_get(self):
|
||||||
|
# 测试 GET 请求返回登录页面
|
||||||
|
response = self.client.get('/login')
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
def test_successful_login_post(self):
|
||||||
|
# 测试有效的登录 POST 请求
|
||||||
|
with self.client:
|
||||||
|
response = self.client.post('/login', data={
|
||||||
|
'number': 'G0001',
|
||||||
|
'password': '1'
|
||||||
|
})
|
||||||
|
# 根据你的应用逻辑调整断言
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
def test_invalid_login_post(self):
|
||||||
|
# 测试无效的登录 POST 请求
|
||||||
|
response = self.client.post('/login', data={
|
||||||
|
'number': 'admin',
|
||||||
|
'password': 'admin'
|
||||||
|
})
|
||||||
|
# 将返回的数据解析为JSON
|
||||||
|
json_data = response.get_json()
|
||||||
|
|
||||||
|
# 确认JSON响应中的值
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertFalse(json_data['success'])
|
||||||
|
self.assertEqual(json_data['message'], "无效的用户名或密码")
|
||||||
|
|
||||||
|
# 运行测试
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
34
app/tests/TestLogout.py
Normal file
34
app/tests/TestLogout.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
|
||||||
|
class LogoutTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# 设置 Flask 测试模式
|
||||||
|
app.testing = True
|
||||||
|
self.client = app.test_client()
|
||||||
|
|
||||||
|
def test_logout(self):
|
||||||
|
# 先登录,确保 session 是设置的
|
||||||
|
with self.client:
|
||||||
|
self.client.post('/login', data=dict(
|
||||||
|
number='G0001',
|
||||||
|
password='1'
|
||||||
|
))
|
||||||
|
|
||||||
|
# 确认登录后session中有数据
|
||||||
|
self.assertIn('number', session)
|
||||||
|
|
||||||
|
# 执行logout
|
||||||
|
response = self.client.get('/logout')
|
||||||
|
|
||||||
|
# 确认 session 被清空
|
||||||
|
self.assertNotIn('number', session)
|
||||||
|
|
||||||
|
# 确认响应是重定向到登录页面
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
self.assertTrue(response.location.endswith('/login'))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
@@ -89,7 +89,7 @@ def login():
|
|||||||
db_manager = DatabaseManager()
|
db_manager = DatabaseManager()
|
||||||
|
|
||||||
result = db_manager.valid_login(number, password) # 获取验证结果
|
result = db_manager.valid_login(number, password) # 获取验证结果
|
||||||
|
print(result)
|
||||||
# 确保用户已验证且活跃(未被禁用)
|
# 确保用户已验证且活跃(未被禁用)
|
||||||
if result['valid'] and result['status'] == 1:
|
if result['valid'] and result['status'] == 1:
|
||||||
# 登录成功
|
# 登录成功
|
||||||
@@ -97,7 +97,7 @@ def login():
|
|||||||
session['role'] = check_identity(number)
|
session['role'] = check_identity(number)
|
||||||
session['name'] = result['name']
|
session['name'] = result['name']
|
||||||
return jsonify(success=True, message="登录成功")
|
return jsonify(success=True, message="登录成功")
|
||||||
elif not result['status']:
|
elif not result.get('status'):
|
||||||
# 用户被禁用的情况
|
# 用户被禁用的情况
|
||||||
return jsonify(success=False, message="账户已被禁用")
|
return jsonify(success=False, message="账户已被禁用")
|
||||||
else:
|
else:
|
||||||
@@ -395,7 +395,7 @@ def teacher_sign_in():
|
|||||||
print(f"course_id: {course_id},course_name: {course_name},class_name: {class_name},major_id: {major_id}")
|
print(f"course_id: {course_id},course_name: {course_name},class_name: {class_name},major_id: {major_id}")
|
||||||
|
|
||||||
db_manager = DatabaseManager()
|
db_manager = DatabaseManager()
|
||||||
data = db_manager.teacher_sign_in(course_id, course_name, class_name, major_id, date, status,teacher_number)
|
data = db_manager.teacher_sign_in(course_id, course_name, class_name, major_id, date, status, teacher_number)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class DatabaseManager:
|
|||||||
return {'valid': True, 'status': status, 'name': name}
|
return {'valid': True, 'status': status, 'name': name}
|
||||||
|
|
||||||
# 密码不匹配或用户不存在,返回登录失败
|
# 密码不匹配或用户不存在,返回登录失败
|
||||||
return {'valid': False}
|
return {'valid': False, 'status': True}
|
||||||
|
|
||||||
def get_menu(self, role):
|
def get_menu(self, role):
|
||||||
sql = "SELECT menu_name,path FROM menu_items WHERE role=%s ORDER BY `order`"
|
sql = "SELECT menu_name,path FROM menu_items WHERE role=%s ORDER BY `order`"
|
||||||
@@ -178,13 +178,16 @@ WHERE
|
|||||||
class_name = self.fetch(sql_student, (student_number,))[0]['class_name']
|
class_name = self.fetch(sql_student, (student_number,))[0]['class_name']
|
||||||
|
|
||||||
# 使用class_name和day_of_week从schedule表获取course_id
|
# 使用class_name和day_of_week从schedule表获取course_id
|
||||||
sql_schedule = "SELECT course_id, FROM schedule WHERE day_of_week = %s AND class_name = %s AND period_id = %s;"
|
sql_schedule = "SELECT course_id FROM schedule WHERE day_of_week = %s AND class_name = %s AND period_id = %s;"
|
||||||
course_id = self.fetch(sql_schedule, (day_of_week, class_name, period_id))
|
course_id = self.fetch(sql_schedule, (day_of_week, class_name, period_id))
|
||||||
|
print(f"course_id: {course_id}")
|
||||||
|
id = course_id[0]['course_id']
|
||||||
|
print(f"id: {id}")
|
||||||
# 对于每一个course_id,从course表中查询course_name
|
# 对于每一个course_id,从course表中查询course_name
|
||||||
sql_course = "SELECT course_name FROM course WHERE course_id = %s;"
|
sql_course = "SELECT course_name FROM course WHERE course_id = %s;"
|
||||||
course_name = self.fetch(sql_course, (course_id['course_id'],))
|
course_name = self.fetch(sql_course, (id,))[0]['course_name']
|
||||||
data = {"course_name": course_name, "course_id": course_id}
|
print(f"course_name: {course_name}")
|
||||||
|
data = {"course_name": course_name, "course_id": id}
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def update_sign_in_info(self, student_number, course_id, course_name, date, status):
|
def update_sign_in_info(self, student_number, course_id, course_name, date, status):
|
||||||
|
|||||||
@@ -109,10 +109,10 @@ CREATE TABLE user
|
|||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO user (name, number, password, status) VALUES
|
INSERT INTO user (name, number, password, status) VALUES
|
||||||
('教师1','G001','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
('教师1','G0001','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
('教师2','G002','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
('教师2','G0002','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
('教师3','G003','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
('教师3','G0003','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
('教师4','G004','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
('教师4','G0004','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
('学生1','X202301000001','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
('学生1','X202301000001','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
('学生2','X202301000002','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
('学生2','X202301000002','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
('学生3','X202301000003','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
('学生3','X202301000003','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
|||||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
Reference in New Issue
Block a user