mirror of
https://codeberg.org/Mo8it/AdvLabDB.git
synced 2024-12-12 23:02:11 +00:00
Added black and isort
This commit is contained in:
parent
050189ee68
commit
418b1f66ac
12 changed files with 316 additions and 82 deletions
|
@ -1,3 +1,6 @@
|
|||
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
|
||||
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
|
||||
|
||||
# Requirements
|
||||
You need to have Python 3 and Poetry installed. To install Poetry, follow the instructions [here](https://python-poetry.org/docs/#installation).
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
from flask import Flask
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_admin import Admin
|
||||
from flask_security import Security, SQLAlchemyUserDatastore
|
||||
from flask_security.models import fsqla_v2 as fsqla
|
||||
from flask_admin import Admin
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
app = Flask(__name__)
|
||||
app.debug = True # DEBUG
|
||||
app.debug = True # DEBUG
|
||||
|
||||
app.config["SERVER_NAME"] = "127.0.0.1:5000" # DEBUG
|
||||
app.config["SERVER_NAME"] = "127.0.0.1:5000" # DEBUG
|
||||
|
||||
app.config["SECRET_KEY"] = "dev"
|
||||
app.config["SECURITY_PASSWORD_SALT"] = "devSalt" # os.environ.get("SECURITY_PASSWORD_SALT", "")
|
||||
app.config["SECURITY_PASSWORD_SALT"] = "devSalt" # os.environ.get("SECURITY_PASSWORD_SALT", "")
|
||||
|
||||
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///../advLab.db"
|
||||
db = SQLAlchemy(app)
|
||||
|
@ -18,10 +18,13 @@ db = SQLAlchemy(app)
|
|||
fsqla.FsModels.set_db_info(db)
|
||||
|
||||
from advlabdb import customClasses
|
||||
admin = Admin(app,
|
||||
name="Admin@AdvLabDB",
|
||||
template_mode="bootstrap3",
|
||||
index_view=customClasses.SecureAdminIndexView(template="admin_index.html"))
|
||||
|
||||
admin = Admin(
|
||||
app,
|
||||
name="Admin@AdvLabDB",
|
||||
template_mode="bootstrap3",
|
||||
index_view=customClasses.SecureAdminIndexView(template="admin_index.html"),
|
||||
)
|
||||
|
||||
from advlabdb import models
|
||||
|
||||
|
@ -29,5 +32,4 @@ from advlabdb import models
|
|||
user_datastore = SQLAlchemyUserDatastore(db, models.User, models.Role)
|
||||
Security(app, user_datastore)
|
||||
|
||||
from advlabdb import routes
|
||||
from advlabdb import modelViews
|
||||
from advlabdb import modelViews, routes
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import json
|
||||
|
||||
|
||||
def getConfig(label):
|
||||
with open("config.json", "r") as f:
|
||||
return json.load(f)[label] # TODO error handling
|
||||
return json.load(f)[label] # TODO error handling
|
||||
|
||||
|
||||
def setConfig(label, value, new=False):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from flask_admin import AdminIndexView
|
||||
from flask_security import current_user
|
||||
from flask_admin.contrib.sqla import ModelView
|
||||
from flask_security import current_user
|
||||
|
||||
|
||||
def adminViewIsAccessible():
|
||||
|
|
|
@ -1,15 +1,35 @@
|
|||
from flask import url_for, flash, request
|
||||
from flask_admin.menu import MenuLink
|
||||
from flask import flash, request, url_for
|
||||
from flask_admin.contrib.sqla.filters import BaseSQLAFilter
|
||||
from flask_admin.menu import MenuLink
|
||||
from flask_security import hash_password
|
||||
from wtforms import BooleanField, SelectField, TextField
|
||||
from wtforms.validators import DataRequired, Email
|
||||
|
||||
from advlabdb import admin, app, user_datastore, db
|
||||
from advlabdb.utils import randomPassword, userActiveSemester, partFromLabelInUserActiveSemester, setActiveSemester
|
||||
from advlabdb.customClasses import SecureModelView
|
||||
from advlabdb.models import User, Role, Semester, Part, Student, PartStudent, Group, GroupExperiment, Experiment, Assistant, Appointment, PartExperiment, ExperimentMark
|
||||
from advlabdb import admin, app, db, user_datastore
|
||||
from advlabdb.configUtils import getConfig
|
||||
from advlabdb.customClasses import SecureModelView
|
||||
from advlabdb.models import (
|
||||
Appointment,
|
||||
Assistant,
|
||||
Experiment,
|
||||
ExperimentMark,
|
||||
Group,
|
||||
GroupExperiment,
|
||||
Part,
|
||||
PartExperiment,
|
||||
PartStudent,
|
||||
Role,
|
||||
Semester,
|
||||
Student,
|
||||
User,
|
||||
)
|
||||
from advlabdb.utils import (
|
||||
partFromLabelInUserActiveSemester,
|
||||
randomPassword,
|
||||
setActiveSemester,
|
||||
userActiveSemester,
|
||||
)
|
||||
|
||||
|
||||
class UserModelView(SecureModelView):
|
||||
column_list = ["email", "active", "roles", "assistant"]
|
||||
|
@ -20,7 +40,7 @@ class UserModelView(SecureModelView):
|
|||
form_args = {
|
||||
"email": {"validators": [Email()]},
|
||||
"active": {"default": True},
|
||||
"roles": {"validators": [DataRequired(message="A role is required!")]}
|
||||
"roles": {"validators": [DataRequired(message="A role is required!")]},
|
||||
}
|
||||
|
||||
def create_model(self, form):
|
||||
|
@ -35,7 +55,9 @@ class UserModelView(SecureModelView):
|
|||
|
||||
model = user_datastore.create_user(email=email, password=passwordHash, roles=roles)
|
||||
db.session.commit()
|
||||
flash(f"{email} registered with roles: {', '.join([role.name for role in form.roles.data])}.", category="success")
|
||||
flash(
|
||||
f"{email} registered with roles: {', '.join([role.name for role in form.roles.data])}.", category="success"
|
||||
)
|
||||
flash(f"Random password: {password}", category="warning")
|
||||
return model
|
||||
|
||||
|
@ -61,9 +83,13 @@ class SemesterModelView(SecureModelView):
|
|||
model.createParts()
|
||||
|
||||
if is_created:
|
||||
admin.add_link(MenuLink(name=model.label,
|
||||
url=url_for("set_semester") + "?semester_id=" + str(model.id),
|
||||
category="Active semester"))
|
||||
admin.add_link(
|
||||
MenuLink(
|
||||
name=model.label,
|
||||
url=url_for("set_semester") + "?semester_id=" + str(model.id),
|
||||
category="Active semester",
|
||||
)
|
||||
)
|
||||
setActiveSemester(model.id)
|
||||
|
||||
|
||||
|
@ -90,15 +116,19 @@ class StudentModelView(SecureModelView):
|
|||
|
||||
partChoices = ["-"] + getConfig("partsLabels")
|
||||
form_extra_fields = {
|
||||
"new_part_student_part": SelectField("Part", choices=list(zip(partChoices, partChoices)), default=partChoices[0]),
|
||||
"new_part_student_group_number": TextField("Group number")
|
||||
"new_part_student_part": SelectField(
|
||||
"Part", choices=list(zip(partChoices, partChoices)), default=partChoices[0]
|
||||
),
|
||||
"new_part_student_group_number": TextField("Group number"),
|
||||
}
|
||||
|
||||
def validate_form(self, form):
|
||||
if request.method == "POST":
|
||||
partLabel = form.new_part_student_part.data
|
||||
groupNumber = form.new_part_student_group_number.data
|
||||
if (partLabel != self.partChoices[0] and groupNumber == "") or (partLabel == self.partChoices[0] and groupNumber != ""):
|
||||
if (partLabel != self.partChoices[0] and groupNumber == "") or (
|
||||
partLabel == self.partChoices[0] and groupNumber != ""
|
||||
):
|
||||
flash("You have to assign both part and group if you want to add a part student!", "danger")
|
||||
return False
|
||||
if partLabel != self.partChoices[0] and not partFromLabelInUserActiveSemester(partLabel):
|
||||
|
@ -174,6 +204,10 @@ admin.add_view(RoleModelView(Role, db.session))
|
|||
with app.app_context():
|
||||
semesters = Semester.query.all()[::-1]
|
||||
for semester in semesters:
|
||||
admin.add_link(MenuLink(name=semester.label,
|
||||
url=url_for("set_semester") + "?semester_id=" + str(semester.id),
|
||||
category="Active semester"))
|
||||
admin.add_link(
|
||||
MenuLink(
|
||||
name=semester.label,
|
||||
url=url_for("set_semester") + "?semester_id=" + str(semester.id),
|
||||
category="Active semester",
|
||||
)
|
||||
)
|
||||
|
|
|
@ -7,7 +7,7 @@ https://flask-sqlalchemy.palletsprojects.com/en/2.x/models/
|
|||
"""
|
||||
|
||||
# Imports
|
||||
from flask_security.models.fsqla_v2 import FsUserMixin, FsRoleMixin
|
||||
from flask_security.models.fsqla_v2 import FsRoleMixin, FsUserMixin
|
||||
|
||||
# Importing the database instance
|
||||
from advlabdb import db
|
||||
|
@ -69,7 +69,7 @@ class Experiment(db.Model):
|
|||
building = db.Column(db.String(100), nullable=False)
|
||||
responsibility = db.Column(db.String(200), nullable=True)
|
||||
duration_in_days = db.Column(db.Integer, nullable=False)
|
||||
deprecated = db.Column(db.Boolean, nullable=False, default=False) # To not be deleted!
|
||||
deprecated = db.Column(db.Boolean, nullable=False, default=False) # To not be deleted!
|
||||
oral_weighting = db.Column(db.Float, nullable=False)
|
||||
protocol_weighting = db.Column(db.Float, nullable=False)
|
||||
final_weighting = db.Column(db.Float, nullable=False)
|
||||
|
@ -80,11 +80,11 @@ class Experiment(db.Model):
|
|||
|
||||
|
||||
# Helper table for the many to many relationship between Assistant and PartExperiment
|
||||
experiment_assistant = db.Table("experiment_assistant",
|
||||
db.Column("part_experiment_id", db.Integer, db.ForeignKey("part_experiment.id"),
|
||||
primary_key=True),
|
||||
db.Column("assistant_id", db.Integer, db.ForeignKey("assistant.id"),
|
||||
primary_key=True))
|
||||
experiment_assistant = db.Table(
|
||||
"experiment_assistant",
|
||||
db.Column("part_experiment_id", db.Integer, db.ForeignKey("part_experiment.id"), primary_key=True),
|
||||
db.Column("assistant_id", db.Integer, db.ForeignKey("assistant.id"), primary_key=True),
|
||||
)
|
||||
|
||||
|
||||
class PartExperiment(db.Model):
|
||||
|
@ -92,8 +92,9 @@ class PartExperiment(db.Model):
|
|||
id = db.Column(db.Integer, primary_key=True)
|
||||
experiment_id = db.Column(db.Integer, db.ForeignKey("experiment.id"), nullable=False)
|
||||
part_id = db.Column(db.Integer, db.ForeignKey("part.id"), nullable=False)
|
||||
assistants = db.relationship("Assistant", secondary=experiment_assistant, lazy=True,
|
||||
backref=db.backref("part_experiments", lazy=True))
|
||||
assistants = db.relationship(
|
||||
"Assistant", secondary=experiment_assistant, lazy=True, backref=db.backref("part_experiments", lazy=True)
|
||||
)
|
||||
group_experiments = db.relationship("GroupExperiment", backref="part_experiment", lazy=True)
|
||||
|
||||
|
||||
|
@ -116,15 +117,15 @@ class Assistant(db.Model):
|
|||
|
||||
class Appointment(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
date = db.Column(db.DateTime, nullable=False) # To be specified with the python package "datetime"
|
||||
special = db.Column(db.Boolean, nullable=False) # In the break or not
|
||||
date = db.Column(db.DateTime, nullable=False) # To be specified with the python package "datetime"
|
||||
special = db.Column(db.Boolean, nullable=False) # In the break or not
|
||||
group_experiment_id = db.Column(db.Integer, db.ForeignKey("group_experiment.id"), nullable=False)
|
||||
assistant_id = db.Column(db.Integer, db.ForeignKey("assistant.id"), nullable=False)
|
||||
|
||||
|
||||
class Part(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
label = db.Column(db.String(100), nullable=False) # A/1, A/2, B/1, B/2
|
||||
label = db.Column(db.String(100), nullable=False) # A/1, A/2, B/1, B/2
|
||||
semester_id = db.Column(db.Integer, db.ForeignKey("semester.id"), nullable=False)
|
||||
part_experiments = db.relationship("PartExperiment", backref="part", lazy=True)
|
||||
part_students = db.relationship("PartStudent", backref="part", lazy=True)
|
||||
|
@ -136,7 +137,7 @@ class Part(db.Model):
|
|||
|
||||
class Semester(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
label = db.Column(db.String(100), nullable=False, unique=True) # WS2122 for example
|
||||
label = db.Column(db.String(100), nullable=False, unique=True) # WS2122 for example
|
||||
parts = db.relationship("Part", backref="semester", lazy=True)
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -155,8 +156,9 @@ class ExperimentMark(db.Model):
|
|||
protocol_mark = db.Column(db.Integer, nullable=True)
|
||||
part_student_id = db.Column(db.Integer, db.ForeignKey("part_student.id"), nullable=False)
|
||||
group_experiment_id = db.Column(db.Integer, db.ForeignKey("group_experiment.id"), nullable=False)
|
||||
assistant_id = db.Column(db.Integer, db.ForeignKey("assistant.id"),
|
||||
nullable=True) # The assistant who gives the mark
|
||||
assistant_id = db.Column(
|
||||
db.Integer, db.ForeignKey("assistant.id"), nullable=True
|
||||
) # The assistant who gives the mark
|
||||
|
||||
|
||||
class User(db.Model, FsUserMixin):
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from advlabdb import app, db
|
||||
from flask import render_template, request, url_for, flash, redirect
|
||||
from flask import flash, redirect, render_template, request, url_for
|
||||
from flask_security import auth_required, current_user
|
||||
|
||||
from advlabdb.utils import titleToTemplate, userActiveSemester, setActiveSemester
|
||||
from advlabdb import app, db
|
||||
from advlabdb.models import Semester
|
||||
from advlabdb.utils import setActiveSemester, titleToTemplate, userActiveSemester
|
||||
|
||||
|
||||
@app.context_processor
|
||||
|
@ -12,8 +12,15 @@ def util_processor():
|
|||
semesters = Semester.query.all()
|
||||
items = []
|
||||
for semester in semesters:
|
||||
items.append('<li><a class="dropdown-item" href="' + url_for("set_semester") + "?semester_id=" +
|
||||
str(semester.id) + '">' + semester.label + '</a></li>')
|
||||
items.append(
|
||||
'<li><a class="dropdown-item" href="'
|
||||
+ url_for("set_semester")
|
||||
+ "?semester_id="
|
||||
+ str(semester.id)
|
||||
+ '">'
|
||||
+ semester.label
|
||||
+ "</a></li>"
|
||||
)
|
||||
return items
|
||||
|
||||
def navbarItems(title):
|
||||
|
@ -42,14 +49,15 @@ def util_processor():
|
|||
else:
|
||||
active = ""
|
||||
|
||||
items.append('<a class="nav-link' + active + '" href="' + titleToTemplate(page) + '">' + page + '</a>')
|
||||
items.append('<a class="nav-link' + active + '" href="' + titleToTemplate(page) + '">' + page + "</a>")
|
||||
return items
|
||||
|
||||
return dict(semesterDropDownItems=semesterDropDownItems,
|
||||
userActiveSemester=userActiveSemester,
|
||||
navbarItems=navbarItems,
|
||||
current_user=current_user,
|
||||
)
|
||||
return dict(
|
||||
semesterDropDownItems=semesterDropDownItems,
|
||||
userActiveSemester=userActiveSemester,
|
||||
navbarItems=navbarItems,
|
||||
current_user=current_user,
|
||||
)
|
||||
|
||||
|
||||
@app.route("/")
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
from random import choice
|
||||
from string import digits, ascii_letters
|
||||
from flask_security import current_user
|
||||
from flask import flash
|
||||
from string import ascii_letters, digits
|
||||
|
||||
from flask import flash
|
||||
from flask_security import current_user
|
||||
|
||||
from advlabdb.models import Semester
|
||||
from advlabdb import db
|
||||
from advlabdb.models import Semester
|
||||
|
||||
|
||||
def makeTable(headerAndDataList, rows, tableId="table"):
|
||||
|
@ -20,13 +21,16 @@ def makeTable(headerAndDataList, rows, tableId="table"):
|
|||
return cell
|
||||
|
||||
def td(cell):
|
||||
return '<td>' + cellString(cell) + '</td>'
|
||||
return "<td>" + cellString(cell) + "</td>"
|
||||
|
||||
def th(cell):
|
||||
return '<th data-sortable="true" data-field="' + titleToTemplate(cell) + '">' + cellString(cell) + '</th>'
|
||||
return '<th data-sortable="true" data-field="' + titleToTemplate(cell) + '">' + cellString(cell) + "</th>"
|
||||
|
||||
table = '''<table
|
||||
id="''' + tableId + '''"
|
||||
table = (
|
||||
'''<table
|
||||
id="'''
|
||||
+ tableId
|
||||
+ """"
|
||||
data-classes="table table-bordered table-striped"
|
||||
data-toggle="table"
|
||||
data-thead-classes="table-dark"
|
||||
|
@ -38,26 +42,27 @@ data-show-export="true"
|
|||
data-export-types="['json', 'xml', 'csv', 'txt', 'sql', 'pdf']">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-field="state" data-checkbox="true"></th>'''
|
||||
<th data-field="state" data-checkbox="true"></th>"""
|
||||
)
|
||||
for i in headerAndDataList:
|
||||
table += th(i[0])
|
||||
table += '''</tr>
|
||||
table += """</tr>
|
||||
</thead>
|
||||
<tbody>\n'''
|
||||
<tbody>\n"""
|
||||
|
||||
for row in rows:
|
||||
table += '<tr><td></td>'
|
||||
table += "<tr><td></td>"
|
||||
|
||||
for i in headerAndDataList:
|
||||
table += td(eval(i[1]))
|
||||
|
||||
table += '</tr>\n'
|
||||
table += "</tr>\n"
|
||||
|
||||
table += '''</tbody>
|
||||
table += """</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<hr>
|
||||
<br>'''
|
||||
<br>"""
|
||||
return table
|
||||
|
||||
|
||||
|
@ -66,7 +71,7 @@ def appointmentDate(date):
|
|||
|
||||
|
||||
def randomPassword():
|
||||
return ''.join(choice(ascii_letters + digits) for i in range(12))
|
||||
return "".join(choice(ascii_letters + digits) for i in range(12))
|
||||
|
||||
|
||||
def titleToTemplate(page):
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from os.path import exists
|
||||
from shutil import copytree, rmtree
|
||||
|
||||
from flask_admin import __file__ as flaskAdminPath
|
||||
|
||||
|
||||
|
@ -13,7 +14,9 @@ def copyAdminTemplates():
|
|||
dist = "advlabdb/templates/admin"
|
||||
if exists(dist):
|
||||
while True:
|
||||
ans = input(f"The directory {dist} already exists. Enter 'o' to override it and update the templates or enter 's' to stop the process: ").lower()
|
||||
ans = input(
|
||||
f"The directory {dist} already exists. Enter 'o' to override it and update the templates or enter 's' to stop the process: "
|
||||
).lower()
|
||||
if ans == "s":
|
||||
print("Process stopped!")
|
||||
return False
|
||||
|
|
146
poetry.lock
generated
146
poetry.lock
generated
|
@ -1,3 +1,33 @@
|
|||
[[package]]
|
||||
name = "appdirs"
|
||||
version = "1.4.4"
|
||||
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "black"
|
||||
version = "21.5b2"
|
||||
description = "The uncompromising code formatter."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6.2"
|
||||
|
||||
[package.dependencies]
|
||||
appdirs = "*"
|
||||
click = ">=7.1.2"
|
||||
mypy-extensions = ">=0.4.3"
|
||||
pathspec = ">=0.8.1,<1"
|
||||
regex = ">=2020.1.8"
|
||||
toml = ">=0.10.1"
|
||||
|
||||
[package.extras]
|
||||
colorama = ["colorama (>=0.4.3)"]
|
||||
d = ["aiohttp (>=3.6.0)", "aiohttp-cors (>=0.4.0)"]
|
||||
python2 = ["typed-ast (>=1.4.2)"]
|
||||
uvloop = ["uvloop (>=0.15.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "blinker"
|
||||
version = "1.4"
|
||||
|
@ -187,6 +217,19 @@ category = "main"
|
|||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[[package]]
|
||||
name = "isort"
|
||||
version = "5.8.0"
|
||||
description = "A Python utility / library to sort Python imports."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6,<4.0"
|
||||
|
||||
[package.extras]
|
||||
pipfile_deprecated_finder = ["pipreqs", "requirementslib"]
|
||||
requirements_deprecated_finder = ["pipreqs", "pip-api"]
|
||||
colors = ["colorama (>=0.4.3,<0.5.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "itsdangerous"
|
||||
version = "2.0.1"
|
||||
|
@ -225,6 +268,14 @@ category = "dev"
|
|||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "mypy-extensions"
|
||||
version = "0.4.3"
|
||||
description = "Experimental type system extensions for programs checked with the mypy typechecker."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "passlib"
|
||||
version = "1.7.4"
|
||||
|
@ -239,6 +290,14 @@ bcrypt = ["bcrypt (>=3.1.0)"]
|
|||
build_docs = ["sphinx (>=1.6)", "sphinxcontrib-fulltoc (>=1.2.0)", "cloud-sptheme (>=1.10.1)"]
|
||||
totp = ["cryptography"]
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "0.8.1"
|
||||
description = "Utility library for gitignore style pattern matching of file paths."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "pycodestyle"
|
||||
version = "2.7.0"
|
||||
|
@ -255,6 +314,14 @@ category = "dev"
|
|||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "2021.4.4"
|
||||
description = "Alternative regular expression module, to replace re."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "sqlalchemy"
|
||||
version = "1.4.17"
|
||||
|
@ -286,6 +353,14 @@ postgresql_psycopg2cffi = ["psycopg2cffi"]
|
|||
pymysql = ["pymysql (<1)", "pymysql"]
|
||||
sqlcipher = ["sqlcipher3-binary"]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.10.2"
|
||||
description = "Python Library for Tom's Obvious, Minimal Language"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
|
||||
[[package]]
|
||||
name = "werkzeug"
|
||||
version = "2.0.1"
|
||||
|
@ -315,10 +390,18 @@ locale = ["Babel (>=1.3)"]
|
|||
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = ">=3.9"
|
||||
content-hash = "e938a304735e2b3e8ec26364f2494860d7d3e7df506f0d6f832f9fe123fbd54a"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "db7a8f38d58cc2d8c8a1f7ca99dc8d3ab7a544b1b1899022c2bae7ffe5fa3aa2"
|
||||
|
||||
[metadata.files]
|
||||
appdirs = [
|
||||
{file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
|
||||
{file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
|
||||
]
|
||||
black = [
|
||||
{file = "black-21.5b2-py3-none-any.whl", hash = "sha256:e5cf21ebdffc7a9b29d73912b6a6a9a4df4ce70220d523c21647da2eae0751ef"},
|
||||
{file = "black-21.5b2.tar.gz", hash = "sha256:1fc0e0a2c8ae7d269dfcf0c60a89afa299664f3e811395d40b1922dff8f854b5"},
|
||||
]
|
||||
blinker = [
|
||||
{file = "blinker-1.4.tar.gz", hash = "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"},
|
||||
]
|
||||
|
@ -423,6 +506,10 @@ idna = [
|
|||
{file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"},
|
||||
{file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"},
|
||||
]
|
||||
isort = [
|
||||
{file = "isort-5.8.0-py3-none-any.whl", hash = "sha256:2bb1680aad211e3c9944dbce1d4ba09a989f04e238296c87fe2139faa26d655d"},
|
||||
{file = "isort-5.8.0.tar.gz", hash = "sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6"},
|
||||
]
|
||||
itsdangerous = [
|
||||
{file = "itsdangerous-2.0.1-py3-none-any.whl", hash = "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c"},
|
||||
{file = "itsdangerous-2.0.1.tar.gz", hash = "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"},
|
||||
|
@ -471,10 +558,18 @@ mccabe = [
|
|||
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
|
||||
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
|
||||
]
|
||||
mypy-extensions = [
|
||||
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
|
||||
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
||||
]
|
||||
passlib = [
|
||||
{file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"},
|
||||
{file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"},
|
||||
]
|
||||
pathspec = [
|
||||
{file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"},
|
||||
{file = "pathspec-0.8.1.tar.gz", hash = "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd"},
|
||||
]
|
||||
pycodestyle = [
|
||||
{file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
|
||||
{file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
|
||||
|
@ -483,6 +578,49 @@ pyflakes = [
|
|||
{file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
|
||||
{file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
|
||||
]
|
||||
regex = [
|
||||
{file = "regex-2021.4.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:619d71c59a78b84d7f18891fe914446d07edd48dc8328c8e149cbe0929b4e000"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:47bf5bf60cf04d72bf6055ae5927a0bd9016096bf3d742fa50d9bf9f45aa0711"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:281d2fd05555079448537fe108d79eb031b403dac622621c78944c235f3fcf11"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:bd28bc2e3a772acbb07787c6308e00d9626ff89e3bfcdebe87fa5afbfdedf968"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7c2a1af393fcc09e898beba5dd59196edaa3116191cc7257f9224beaed3e1aa0"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c38c71df845e2aabb7fb0b920d11a1b5ac8526005e533a8920aea97efb8ec6a4"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:96fcd1888ab4d03adfc9303a7b3c0bd78c5412b2bfbe76db5b56d9eae004907a"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:ade17eb5d643b7fead300a1641e9f45401c98eee23763e9ed66a43f92f20b4a7"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-win32.whl", hash = "sha256:e8e5b509d5c2ff12f8418006d5a90e9436766133b564db0abaec92fd27fcee29"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-win_amd64.whl", hash = "sha256:11d773d75fa650cd36f68d7ca936e3c7afaae41b863b8c387a22aaa78d3c5c79"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d3029c340cfbb3ac0a71798100ccc13b97dddf373a4ae56b6a72cf70dfd53bc8"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:18c071c3eb09c30a264879f0d310d37fe5d3a3111662438889ae2eb6fc570c31"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:4c557a7b470908b1712fe27fb1ef20772b78079808c87d20a90d051660b1d69a"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:01afaf2ec48e196ba91b37451aa353cb7eda77efe518e481707e0515025f0cd5"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:3a9cd17e6e5c7eb328517969e0cb0c3d31fd329298dd0c04af99ebf42e904f82"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:90f11ff637fe8798933fb29f5ae1148c978cccb0452005bf4c69e13db951e765"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:919859aa909429fb5aa9cf8807f6045592c85ef56fdd30a9a3747e513db2536e"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:339456e7d8c06dd36a22e451d58ef72cef293112b559010db3d054d5560ef439"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-win32.whl", hash = "sha256:67bdb9702427ceddc6ef3dc382455e90f785af4c13d495f9626861763ee13f9d"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:32e65442138b7b76dd8173ffa2cf67356b7bc1768851dded39a7a13bf9223da3"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1e1c20e29358165242928c2de1482fb2cf4ea54a6a6dea2bd7a0e0d8ee321500"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:314d66636c494ed9c148a42731b3834496cc9a2c4251b1661e40936814542b14"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6d1b01031dedf2503631d0903cb563743f397ccaf6607a5e3b19a3d76fc10480"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:741a9647fcf2e45f3a1cf0e24f5e17febf3efe8d4ba1281dcc3aa0459ef424dc"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4c46e22a0933dd783467cf32b3516299fb98cfebd895817d685130cc50cd1093"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:e512d8ef5ad7b898cdb2d8ee1cb09a8339e4f8be706d27eaa180c2f177248a10"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:980d7be47c84979d9136328d882f67ec5e50008681d94ecc8afa8a65ed1f4a6f"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:ce15b6d103daff8e9fee13cf7f0add05245a05d866e73926c358e871221eae87"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-win32.whl", hash = "sha256:a91aa8619b23b79bcbeb37abe286f2f408d2f2d6f29a17237afda55bb54e7aac"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:c0502c0fadef0d23b128605d69b58edb2c681c25d44574fc673b0e52dce71ee2"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:598585c9f0af8374c28edd609eb291b5726d7cbce16be6a8b95aa074d252ee17"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:ee54ff27bf0afaf4c3b3a62bcd016c12c3fdb4ec4f413391a90bd38bc3624605"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7d9884d86dd4dd489e981d94a65cd30d6f07203d90e98f6f657f05170f6324c9"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:bf5824bfac591ddb2c1f0a5f4ab72da28994548c708d2191e3b87dd207eb3ad7"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:563085e55b0d4fb8f746f6a335893bda5c2cef43b2f0258fe1020ab1dd874df8"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9c3db21af35e3b3c05764461b262d6f05bbca08a71a7849fd79d47ba7bc33ed"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:3916d08be28a1149fb97f7728fca1f7c15d309a9f9682d89d79db75d5e52091c"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:fd45ff9293d9274c5008a2054ecef86a9bfe819a67c7be1afb65e69b405b3042"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-win32.whl", hash = "sha256:fa4537fb4a98fe8fde99626e4681cc644bdcf2a795038533f9f711513a862ae6"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:97f29f57d5b84e73fbaf99ab3e26134e6687348e95ef6b48cfd2c06807005a07"},
|
||||
{file = "regex-2021.4.4.tar.gz", hash = "sha256:52ba3d3f9b942c49d7e4bc105bb28551c44065f139a65062ab7912bef10c9afb"},
|
||||
]
|
||||
sqlalchemy = [
|
||||
{file = "SQLAlchemy-1.4.17-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:c367ed95d41df584f412a9419b5ece85b0d6c2a08a51ae13ae47ef74ff9a9349"},
|
||||
{file = "SQLAlchemy-1.4.17-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fdad4a33140b77df61d456922b7974c1f1bb2c35238f6809f078003a620c4734"},
|
||||
|
@ -515,6 +653,10 @@ sqlalchemy = [
|
|||
{file = "SQLAlchemy-1.4.17-cp39-cp39-win_amd64.whl", hash = "sha256:7eb55d5583076c03aaf1510473fad2a61288490809049cb31028af56af7068ee"},
|
||||
{file = "SQLAlchemy-1.4.17.tar.gz", hash = "sha256:651cdb3adcee13624ba22d5ff3e96f91e16a115d2ca489ddc16a8e4c217e8509"},
|
||||
]
|
||||
toml = [
|
||||
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
||||
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
||||
]
|
||||
werkzeug = [
|
||||
{file = "Werkzeug-2.0.1-py3-none-any.whl", hash = "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"},
|
||||
{file = "Werkzeug-2.0.1.tar.gz", hash = "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42"},
|
||||
|
|
|
@ -6,7 +6,7 @@ authors = ["Mohamad Bitar <mohamad.bit@protonmail.com>"]
|
|||
readme = "README.md"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.9"
|
||||
python = "^3.9"
|
||||
Flask = ">=2.0.1"
|
||||
Flask-SQLAlchemy = ">=2.5.1"
|
||||
SQLAlchemy = ">=1.4.17"
|
||||
|
@ -17,7 +17,15 @@ Flask-Admin = ">=1.5.8"
|
|||
|
||||
[tool.poetry.dev-dependencies]
|
||||
flake8 = "*"
|
||||
black = "*"
|
||||
isort = "*"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
|
|
38
testDB.py
38
testDB.py
|
@ -1,5 +1,7 @@
|
|||
from datetime import datetime
|
||||
|
||||
from flask_security import hash_password
|
||||
|
||||
from advlabdb import app, db, user_datastore
|
||||
from advlabdb.models import *
|
||||
|
||||
|
@ -41,11 +43,29 @@ with app.app_context():
|
|||
db.session.add(ps2)
|
||||
db.session.add(ps3)
|
||||
|
||||
ex1 = Experiment(number=1, name="exp", room="123", building="phy", responsibility="none", duration_in_days=2,
|
||||
oral_weighting=0.5, protocol_weighting=0.5, final_weighting=1)
|
||||
ex1 = Experiment(
|
||||
number=1,
|
||||
name="exp",
|
||||
room="123",
|
||||
building="phy",
|
||||
responsibility="none",
|
||||
duration_in_days=2,
|
||||
oral_weighting=0.5,
|
||||
protocol_weighting=0.5,
|
||||
final_weighting=1,
|
||||
)
|
||||
|
||||
ex2 = Experiment(number=2, name="exp2", room="123", building="phy", responsibility="none", duration_in_days=2,
|
||||
oral_weighting=0.5, protocol_weighting=0.5, final_weighting=1)
|
||||
ex2 = Experiment(
|
||||
number=2,
|
||||
name="exp2",
|
||||
room="123",
|
||||
building="phy",
|
||||
responsibility="none",
|
||||
duration_in_days=2,
|
||||
oral_weighting=0.5,
|
||||
protocol_weighting=0.5,
|
||||
final_weighting=1,
|
||||
)
|
||||
|
||||
db.session.add(ex1)
|
||||
db.session.add(ex2)
|
||||
|
@ -70,8 +90,14 @@ with app.app_context():
|
|||
us1 = user_datastore.create_user(email="test@protonmail.com", password=hash_password("h1"), roles=["assistant"])
|
||||
us2 = user_datastore.create_user(email="test2@protonmail.com", password=hash_password("h2"), roles=["assistant"])
|
||||
|
||||
as1 = Assistant(first_name="As1", last_name="l", email="test@test.com", phone_number="012333212",
|
||||
mobile_phone_number="012334123", user=us1)
|
||||
as1 = Assistant(
|
||||
first_name="As1",
|
||||
last_name="l",
|
||||
email="test@test.com",
|
||||
phone_number="012333212",
|
||||
mobile_phone_number="012334123",
|
||||
user=us1,
|
||||
)
|
||||
as2 = Assistant(first_name="As2", last_name="l", email="test2@test.com", user=us2)
|
||||
|
||||
as1.part_experiments.append(px1)
|
||||
|
|
Loading…
Reference in a new issue