make db migrations
This commit is contained in:
parent
56ffeb2a01
commit
e3d47844be
11 changed files with 237 additions and 39 deletions
0
__init__.py
Normal file
0
__init__.py
Normal file
22
app.py
22
app.py
|
@ -1,11 +1,18 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
|
|
||||||
|
# ! SQLAlchemy > Marshmallow - these must be imported in this order
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from flask_marshmallow import Marshmallow
|
from flask_marshmallow import Marshmallow
|
||||||
|
|
||||||
from flask_migrate import Migrate
|
from flask_migrate import Migrate
|
||||||
|
|
||||||
|
from flask_bcrypt import Bcrypt
|
||||||
|
from flask_cors import CORS
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
CORS(app)
|
||||||
|
|
||||||
# base directory
|
# base directory
|
||||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
@ -17,13 +24,26 @@ DATABASE = 'postgresql://localhost/browser-go'
|
||||||
app.config['SQLALCHEMY_DATABASE_URI'] = DATABASE
|
app.config['SQLALCHEMY_DATABASE_URI'] = DATABASE
|
||||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
|
|
||||||
|
#init bcrypt
|
||||||
|
bcrypt = Bcrypt(app)
|
||||||
|
|
||||||
# init database
|
# init database
|
||||||
db = SQLAlchemy(app)
|
db = SQLAlchemy(app)
|
||||||
migrate = Migrate(app, db)
|
|
||||||
|
|
||||||
# init marshmallow
|
# init marshmallow
|
||||||
ma = Marshmallow(app)
|
ma = Marshmallow(app)
|
||||||
|
|
||||||
|
# init all db models
|
||||||
|
from .models.User import User
|
||||||
|
from .models.GameRoom import GameRoom
|
||||||
|
from .models.TimeSettings import TimeSettings
|
||||||
|
from .models.Game import Game
|
||||||
|
from .models.Move import Move
|
||||||
|
from .models.Message import Message
|
||||||
|
|
||||||
|
migrate = Migrate(app, db)
|
||||||
|
|
||||||
|
|
||||||
# dev server
|
# dev server
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
PORT = 8000
|
PORT = 8000
|
||||||
|
|
109
migrations/versions/9519d28f13f0_.py
Normal file
109
migrations/versions/9519d28f13f0_.py
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 9519d28f13f0
|
||||||
|
Revises:
|
||||||
|
Create Date: 2019-10-02 13:54:17.877590
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '9519d28f13f0'
|
||||||
|
down_revision = None
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('game_rooms',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('name', sa.String(length=40), nullable=False),
|
||||||
|
sa.Column('description', sa.String(length=200), nullable=False),
|
||||||
|
sa.Column('private', sa.Boolean(), nullable=False),
|
||||||
|
sa.Column('language', sa.Enum(name='languages'), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('time_settings',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('main_time', sa.Enum('BYOYOMI', 'ABSOLUTE', 'HOURGLASS', 'NONE', name='timetypes'), nullable=False),
|
||||||
|
sa.Column('time_period', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('period_length', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('overtime', sa.Enum('BYOYOMI', 'ABSOLUTE', 'HOURGLASS', 'NONE', name='timetypes'), nullable=False),
|
||||||
|
sa.Column('overtime_period', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('overtime_length', sa.Integer(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('users',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('email', sa.String(length=255), nullable=False),
|
||||||
|
sa.Column('password', sa.DateTime(), nullable=False),
|
||||||
|
sa.Column('registered_on', sa.DateTime(), nullable=False),
|
||||||
|
sa.Column('admin', sa.Boolean(), nullable=False),
|
||||||
|
sa.Column('rank', sa.Enum('D7', 'D6', 'D5', 'D4', 'D3', 'D2', 'D1', 'K1', 'K2', 'K3', 'K4', 'K5', 'K6', 'K7', 'K8', 'K9', 'K10', 'K11', 'K12', 'K13', 'K14', 'K15', 'K16', 'K17', 'K18', 'K19', 'K20', 'K21', 'K22', 'K23', 'K24', 'K25', 'K26', 'K27', 'K28', 'K29', 'K30', name='ranks'), nullable=True),
|
||||||
|
sa.Column('elo', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('rank_certainty', sa.Boolean(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
sa.UniqueConstraint('email')
|
||||||
|
)
|
||||||
|
op.create_table('games',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('date', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('komi', sa.Numeric(precision=2, scale=1), nullable=False),
|
||||||
|
sa.Column('handicap', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('board_size', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('win_type', sa.Enum('DRAW', 'RESIGN', 'SCORE', 'TIME', 'VOID', name='wintype'), nullable=True),
|
||||||
|
sa.Column('winner', sa.Enum('BLACK', 'WHITE', 'VOID', name='players'), nullable=True),
|
||||||
|
sa.Column('score', sa.Numeric(precision=2, scale=1), nullable=True),
|
||||||
|
sa.Column('white_captures', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('black_captures', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('application', sa.String(length=40), nullable=True),
|
||||||
|
sa.Column('application_version', sa.String(length=20), nullable=True),
|
||||||
|
sa.Column('event', sa.String(length=40), nullable=True),
|
||||||
|
sa.Column('name', sa.String(length=40), nullable=True),
|
||||||
|
sa.Column('description', sa.String(length=200), nullable=True),
|
||||||
|
sa.Column('round', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('game_room', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('time_settings', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('player_black', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('player_white', sa.Integer(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['game_room'], ['game_rooms.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['player_black'], ['users.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['player_white'], ['users.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['time_settings'], ['time_settings.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('moves',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('player', sa.Enum('BLACK', 'WHITE', name='players'), nullable=True),
|
||||||
|
sa.Column('x_point', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('y_point', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('move_number', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('game', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('preceding_move', sa.Integer(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['game'], ['games.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['preceding_move'], ['moves.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('messages',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('date', sa.DateTime(), nullable=False),
|
||||||
|
sa.Column('content', sa.String(length=200), nullable=False),
|
||||||
|
sa.Column('move', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['move'], ['moves.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('messages')
|
||||||
|
op.drop_table('moves')
|
||||||
|
op.drop_table('games')
|
||||||
|
op.drop_table('users')
|
||||||
|
op.drop_table('time_settings')
|
||||||
|
op.drop_table('game_rooms')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -1,6 +0,0 @@
|
||||||
from ..app import db, ma
|
|
||||||
|
|
||||||
class Branch(db.Model):
|
|
||||||
__table_args__ = {'extend_existing': True}
|
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
|
@ -4,6 +4,7 @@ import enum
|
||||||
class Players(enum.Enum):
|
class Players(enum.Enum):
|
||||||
BLACK = "The player taking black stones"
|
BLACK = "The player taking black stones"
|
||||||
WHITE = "The player taking white stones"
|
WHITE = "The player taking white stones"
|
||||||
|
VOID = "The game was a draw or voided"
|
||||||
|
|
||||||
class WinType(enum.Enum):
|
class WinType(enum.Enum):
|
||||||
DRAW = "The game is a draw"
|
DRAW = "The game is a draw"
|
||||||
|
@ -13,16 +14,17 @@ class WinType(enum.Enum):
|
||||||
VOID = "The game was suspended"
|
VOID = "The game was suspended"
|
||||||
|
|
||||||
class Game(db.Model):
|
class Game(db.Model):
|
||||||
|
__tablename__ = "games"
|
||||||
__table_args__ = {'extend_existing': True}
|
__table_args__ = {'extend_existing': True}
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
date = db.Column(db.DateTime())
|
date = db.Column(db.DateTime())
|
||||||
komi = db.Column(db.Decimal(2,1))
|
komi = db.Column(db.Numeric(2,1), nullable=False)
|
||||||
handicap = db.Column(db.Integer)
|
handicap = db.Column(db.Integer, nullable=False)
|
||||||
board_size = db.Column(db.Integer)
|
board_size = db.Column(db.Integer, nullable=False)
|
||||||
win_type = db.Column(db.Enum(WinType))
|
win_type = db.Column(db.Enum(WinType))
|
||||||
winner = db.Column(db.Enum(Players))
|
winner = db.Column(db.Enum(Players))
|
||||||
score = db.Column(db.Decimal(2,1))
|
score = db.Column(db.Numeric(2,1))
|
||||||
white_captures = db.Column(db.Integer)
|
white_captures = db.Column(db.Integer)
|
||||||
black_captures = db.Column(db.Integer)
|
black_captures = db.Column(db.Integer)
|
||||||
application = db.Column(db.String(40))
|
application = db.Column(db.String(40))
|
||||||
|
@ -30,13 +32,13 @@ class Game(db.Model):
|
||||||
event = db.Column(db.String(40))
|
event = db.Column(db.String(40))
|
||||||
name = db.Column(db.String(40))
|
name = db.Column(db.String(40))
|
||||||
description = db.Column(db.String(200))
|
description = db.Column(db.String(200))
|
||||||
round = db.Column(db.Integer())
|
round = db.Column(db.Integer)
|
||||||
|
|
||||||
# foreign keys
|
# foreign keys
|
||||||
# game_room
|
game_room = db.Column(db.Integer, db.ForeignKey("game_rooms.id"))
|
||||||
# time_settings
|
time_settings = db.Column(db.Integer, db.ForeignKey("time_settings.id"))
|
||||||
# player_black
|
player_black = db.Column(db.Integer, db.ForeignKey("users.id"))
|
||||||
# player_white
|
player_white = db.Column(db.Integer, db.ForeignKey("users.id"))
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
|
@ -5,12 +5,14 @@ class Languages(enum.Enum):
|
||||||
EN: "English"
|
EN: "English"
|
||||||
|
|
||||||
class GameRoom(db.Model):
|
class GameRoom(db.Model):
|
||||||
|
__tablename__ = "game_rooms"
|
||||||
__table_args__ = {'extend_existing': True}
|
__table_args__ = {'extend_existing': True}
|
||||||
|
|
||||||
name = db.Column(db.String(40))
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
description = db.Column(db.String(200))
|
name = db.Column(db.String(40), nullable=False)
|
||||||
private = db.Column(db.Boolean())
|
description = db.Column(db.String(200), nullable=False)
|
||||||
language = db.Column(db.Enum(Languages))
|
private = db.Column(db.Boolean(), nullable=False, default=False)
|
||||||
|
language = db.Column(db.Enum(Languages), nullable=False)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
|
@ -6,14 +6,15 @@ class Players(enum.Enum):
|
||||||
WHITE = "The player taking white stones"
|
WHITE = "The player taking white stones"
|
||||||
|
|
||||||
class Message(db.Model):
|
class Message(db.Model):
|
||||||
|
__tablename__ = "messages"
|
||||||
__table_args__ = {'extend_existing': True}
|
__table_args__ = {'extend_existing': True}
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
date = db.Column(db.DateTime())
|
date = db.Column(db.DateTime(), nullable=False)
|
||||||
content = db.Column(db.String(200))
|
content = db.Column(db.String(200), nullable=False)
|
||||||
|
|
||||||
# foreing key
|
# foreign key
|
||||||
move = db.Column(db.Integer, db.ForeignKey("move.id"))
|
move = db.Column(db.Integer, db.ForeignKey("moves.id"), nullable=False)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
|
@ -5,17 +5,19 @@ class Players(enum.Enum):
|
||||||
BLACK = "The player taking black stones"
|
BLACK = "The player taking black stones"
|
||||||
WHITE = "The player taking white stones"
|
WHITE = "The player taking white stones"
|
||||||
|
|
||||||
class Branch(db.Model):
|
class Move(db.Model):
|
||||||
|
__tablename__ = "moves"
|
||||||
__table_args__ = {'extend_existing': True}
|
__table_args__ = {'extend_existing': True}
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
player = db.Column(db.Enum(Players))
|
player = db.Column(db.Enum(Players))
|
||||||
x_point = db.Column(db.Integer)
|
x_point = db.Column(db.Integer)
|
||||||
y_point = db.Column(db.Integer)
|
y_point = db.Column(db.Integer)
|
||||||
move_number = db.Column(db.Integer)
|
move_number = db.Column(db.Integer)
|
||||||
|
|
||||||
# foreign keys
|
# foreign keys
|
||||||
game = db.Column(db.Integer, db.ForeignKey("game.id"))
|
game = db.Column(db.Integer, db.ForeignKey("games.id"), nullable=False)
|
||||||
|
preceding_move = db.Column(db.Integer, db.ForeignKey("moves.id"))
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
|
@ -10,16 +10,14 @@ class TimeTypes(enum.Enum):
|
||||||
class TimeSettings(db.Model):
|
class TimeSettings(db.Model):
|
||||||
__table_args__ = {'extend_existing': True}
|
__table_args__ = {'extend_existing': True}
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
main_time = db.Column(db.Enum(Time))
|
main_time = db.Column(db.Enum(TimeTypes), nullable=False)
|
||||||
time_period = db.Column(db.Integer) # number of periods
|
time_period = db.Column(db.Integer) # number of periods
|
||||||
period_length = db.Column(db.Integer) # seconds
|
period_length = db.Column(db.Integer) # seconds
|
||||||
overtime = db.Column(db.Enum())
|
overtime = db.Column(db.Enum(TimeTypes), nullable=False)
|
||||||
overtime_period = db.Column(db.Integer) # number of overtime periods
|
overtime_period = db.Column(db.Integer) # number of overtime periods
|
||||||
overtime_length = db.Column(db.Integer) # seconds
|
overtime_length = db.Column(db.Integer) # seconds
|
||||||
|
|
||||||
# foreing key
|
|
||||||
game = db.Column(db.Integer, db.ForeignKey("game.id"))
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
|
@ -0,0 +1,58 @@
|
||||||
|
from ..app import db, ma, bcrypt
|
||||||
|
import enum
|
||||||
|
|
||||||
|
class Ranks(enum.Enum): # with minimal Elo rating
|
||||||
|
D7 = "Seven Dan" # Elo 2700+
|
||||||
|
D6 = "Six Dan"
|
||||||
|
D5 = "Five Dan" # Elo 2500
|
||||||
|
D4 = "Four Dan"
|
||||||
|
D3 = "Three Dan"
|
||||||
|
D2 = "Two Dan"
|
||||||
|
D1 = "One Dan"
|
||||||
|
K1 = "One Kyu" # Elo 2000
|
||||||
|
K2 = "Two Kyu"
|
||||||
|
K3 = "Three Kyu"
|
||||||
|
K4 = "Four Kyu"
|
||||||
|
K5 = "Five Kyu"
|
||||||
|
K6 = "Six Kyu" # Elo 1500
|
||||||
|
K7 = "Seven Kyu"
|
||||||
|
K8 = "Eight Kyu"
|
||||||
|
K9 = "Nine Kyu"
|
||||||
|
K10 = "Ten Kyu"
|
||||||
|
K11 = "Eleven Kyu" # ELo 1000
|
||||||
|
K12 = "Twelve Kyu"
|
||||||
|
K13 = "Thirteen Kyu"
|
||||||
|
K14 = "Fourteen Kyu"
|
||||||
|
K15 = "Fifteen Kyu"
|
||||||
|
K16 = "Sixteen Kyu" # Elo 500
|
||||||
|
K17 = "Seventeen Kyu"
|
||||||
|
K18 = "Eighteen Kyu"
|
||||||
|
K19 = "Nineteen Kyu"
|
||||||
|
K20 = "Twenty Kyu"
|
||||||
|
K21 = "Twenty-One Kyu" # Elo 0
|
||||||
|
K22 = "Twenty-Two Kyu"
|
||||||
|
K23 = "Twenty-Three Kyu"
|
||||||
|
K24 = "Twenty-Four Kyu"
|
||||||
|
K25 = "Twenty-Five Kyu"
|
||||||
|
K26 = "Twenty-Six Kyu" # Elo -500
|
||||||
|
K27 = "Twenty-Seven Kyu"
|
||||||
|
K28 = "Twenty-Eight Kyu"
|
||||||
|
K29 = "Twenty-Nine Kyu"
|
||||||
|
K30 = "Thirty Kyu" # Elo -900
|
||||||
|
|
||||||
|
class User(db.Model):
|
||||||
|
__tablename__ = "users"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
|
email = db.Column(db.String(255), unique=True, nullable=False)
|
||||||
|
password = db.Column(db.DateTime, nullable=False)
|
||||||
|
registered_on = db.Column(db.DateTime, nullable=False)
|
||||||
|
admin = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
|
rank = db.Column(db.Enum(Ranks))
|
||||||
|
elo = db.Column(db.Integer)
|
||||||
|
rank_certainty = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.password = bcrypt.generate_password_hash(
|
||||||
|
password, app.config.get('BCRYPT_LOG_ROUNDS')
|
||||||
|
).decode()
|
|
@ -1,19 +1,31 @@
|
||||||
alembic==1.2.1
|
alembic==1.2.1
|
||||||
|
astroid==2.3.1
|
||||||
|
bcrypt==3.1.7
|
||||||
|
cffi==1.12.3
|
||||||
Click==7.0
|
Click==7.0
|
||||||
Flask==1.1.1
|
Flask==1.1.1
|
||||||
|
Flask-Bcrypt==0.7.1
|
||||||
Flask-Cors==3.0.8
|
Flask-Cors==3.0.8
|
||||||
flask-marshmallow==0.10.1
|
flask-marshmallow==0.10.1
|
||||||
Flask-Migrate==2.5.2
|
Flask-Migrate==2.5.2
|
||||||
Flask-SQLAlchemy==2.4.1
|
Flask-SQLAlchemy==2.4.1
|
||||||
|
isort==4.3.21
|
||||||
itsdangerous==1.1.0
|
itsdangerous==1.1.0
|
||||||
Jinja2==2.10.1
|
Jinja2==2.10.1
|
||||||
|
lazy-object-proxy==1.4.2
|
||||||
Mako==1.1.0
|
Mako==1.1.0
|
||||||
MarkupSafe==1.1.1
|
MarkupSafe==1.1.1
|
||||||
marshmallow==3.2.0
|
marshmallow==3.2.0
|
||||||
marshmallow-sqlalchemy==0.19.0
|
marshmallow-sqlalchemy==0.19.0
|
||||||
|
mccabe==0.6.1
|
||||||
numpy==1.17.2
|
numpy==1.17.2
|
||||||
|
psycopg2==2.8.3
|
||||||
|
pycparser==2.19
|
||||||
|
pylint==2.4.2
|
||||||
python-dateutil==2.8.0
|
python-dateutil==2.8.0
|
||||||
python-editor==1.0.4
|
python-editor==1.0.4
|
||||||
six==1.12.0
|
six==1.12.0
|
||||||
SQLAlchemy==1.3.8
|
SQLAlchemy==1.3.8
|
||||||
|
typed-ast==1.4.0
|
||||||
Werkzeug==0.16.0
|
Werkzeug==0.16.0
|
||||||
|
wrapt==1.11.2
|
||||||
|
|
Loading…
Reference in a new issue