Module emse-mms.utils.seed
Expand source code
import asyncio
import csv
from enum import Enum
import os
from typing import Union
from string import Template
import numpy as np
from essential_generators import DocumentGenerator
from prisma import Prisma
import logging
from requests import post, Response
def getModuleFeedback():
mods = post('http://%s/graphql' % os.environ.get("API_URL", "client:4000"), {}, {
'query': """query{
module(input:{}){
id
moduleName
moduleNumber
feedback{
rating
feedback
}
members{
id
}
}
}"""
})
return mods.json()['data']
class Skipper(Enum):
user = 1
module = 2
feedback = 3
plan = 4
enrollment = 5
all = 6
class Seeder:
"""
Seeder class for seeding the database with dummy data. Makes use of the prisma python client to connection to the
database and the essential_generators library to create document templates.
"""
def __init__(self, skip: [Skipper] = None, cleanup: [Skipper] = None, iterations: int = 25,
target: Union[str, None] = None):
self.gen = DocumentGenerator()
self.gen.init_word_cache(5000)
self.gen.init_sentence_cache(5000)
self.prisma = Prisma()
self.iterations = iterations
self.accounts = []
self.modules = []
self.enrollments = []
self.feedbacks = []
self.plans = []
self.skip = skip
self.cleanup = cleanup
self.target = target
self.logger = logging.getLogger('__seed__')
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
async def connect(self):
"""
Connects to the database using prisma client.
"""
await self.prisma.connect()
async def disconnect(self):
"""
Disconnects from the database using prisma client.
"""
await self.prisma.disconnect()
async def createTargetUser(self):
"""
Creates a target user for testing purposes.
"""
account = await self.prisma.user.create(data={
'firstName': 'Test User',
'lastName': 'Test User',
'email': '',
'openID': ''
})
self.logger.info('Created target user: %s' % account.id)
return account.id
async def _getUserAccounts(self):
"""
Gets all user accounts from the database and returns them as a list of dictionaries.
:return: class<list> of class<dict> of type<User>
"""
accounts = await self.prisma.user.find_many()
acc = []
for i in range(len(accounts)):
acc.append(accounts[i].dict())
return acc
async def _getModules(self):
"""
Gets all modules from the database and returns them as a list of dictionaries.
:return: class<list> of class<dict> of type<Module>
"""
self.modules = await self.prisma.module.find_many()
mods = []
for i in range(len(self.modules)):
mods.append(self.modules[i].dict())
return mods
async def _getEnrollments(self):
"""
Gets all enrollments from the database and returns them as a list of dictionaries.
:return: class<list> of class<dict> of type<ModuleEnrollment>
"""
self.enrollments = await self.prisma.moduleenrollment.find_many()
enrollments = []
for i in range(len(self.enrollments)):
enrollments.append(self.enrollments[i].dict())
return enrollments
async def _getFeedbacks(self):
"""
Gets all feedbacks from the database and returns them as a list of dictionaries.
:return: class<list> of class<dict> of type<ModuleFeedback>
"""
self.feedbacks = await self.prisma.modulefeedback.find_many()
feedbacks = []
for i in range(len(self.feedbacks)):
feedbacks.append(self.feedbacks[i].dict())
return feedbacks
async def _getPlans(self) -> list[dict]:
self.plans = await self.prisma.planofstudy.find_many()
plans = []
for i in range(len(self.plans)):
plans.append(self.plans[i].dict())
return plans
async def _seedUserDB(self):
"""
Seeds the user model with dummy data as many times as described by the iterations' member.
:return: None
"""
self.logger.info('Seeding user model...')
accounts = []
for i in range(self.iterations):
accounts.append({
'firstName': self.gen.name(),
'lastName': self.gen.name(),
'email': self.gen.email(),
'openID': str(self.gen.integer()),
})
users = await self.prisma.user.create_many(data=accounts)
self.accounts = accounts
self.logger.info('User model seeded successfully with %d documents!' % users)
async def _seedModuleDB(self):
"""
Seeds the module model with dummy data as many times as described by the iterations' member.
:return: None
"""
self.logger.info('Seeding module model...')
modules = []
template = {
'moduleName': {
'typemap': 'sentence',
'unique': True,
'tries': 100
},
'moduleNumber': {
'typemap': 'integer',
'unique': True,
'tries': 100
},
'description': 'paragraph',
'duration': 'small_int',
'intro': 'sentence',
'numSlides': 'small_int',
'keywords': {
'set': ['engineering', 'mathematics', 'physics', 'chemistry', 'biology', 'computer science',
'economics']
}
}
self.gen.set_template(template)
docs = self.gen.documents(self.iterations)
module_res = await self.prisma.module.create_many(data=docs)
self.modules = modules
self.logger.info('Module model seeded successfully with %d documents!' % module_res)
def _is_float_(self, num: str):
try:
if float(num).is_integer():
return False
return True
except ValueError:
return False
# function to create acronym
def fxn(self, stng: str):
# add first letter
oupt = stng[0]
# iterate over string
for i in range(1, len(stng)):
if stng[i - 1] == ' ':
# add letter next to space
oupt += stng[i]
# uppercase oupt
oupt = oupt.upper()
return oupt
async def seedModuleFromFile(self, path: str):
"""
Seeds the module model with data from a csv file. The structure of the files must be as follows:
- the first two rows should be ignored as they contain the column names and data types
- column 1: module number - if it is an integer, we will need to create a unique prefix for it. if it is a float, the prefix will be the integer part of the number and the decimal number will be the module number
- column 2: module name
- column 3: module description
- column 4: module objectives - this will be a list of strings separated by a semicolon
- column 5: module keywords - this will be a list of strings separated by a semicolon
- column 6: module hours - this will be an float number representing the number of hours the module will take to complete
:return: Boolean
"""
self.logger.info('Seeding module model from file...')
modules = list()
with open(path, 'r') as csvFile:
parsedFile = csv.reader(csvFile, delimiter='\t', quotechar='|')
next(parsedFile)
prefix = ''
for row in parsedFile:
document = dict()
if float(row[0]).is_integer():
prefix = self.fxn(row[1])
document['number'] = 0
else:
dec = row[0].split('.')
document['number'] = dec[1]
document['name'] = row[1]
document['prefix'] = prefix
document['description'] = row[2]
document['objectives'] = row[3].split(';')
document['keywords'] = row[4].split(';')
if row[5] == ' ' or row[5] == '':
document['hours'] = np.random.uniform(0.25, 2)
else:
document['hours'] = float(row[5])
modules.append(document)
message = Template('Successfully parsed $number documents from file $name!')
self.logger.info(message.substitute(number=len(modules), name=path.split('/')[-1]))
# send each element in the array to the GraphQL API endpoint without using Prisma
for module in modules:
query = Template("""
mutation {
createModule(input: {
name: "$name"
number: $number
prefix: "$prefix"
description: "$description"
objectives: [$objectives]
keywords: [$keywords]
hours: $hours
}) {
id
}
}
""")
cleanedObjectives = ""
for obj in module['objectives']:
curr = obj.split(';')[0]
if len(curr) == 0:
continue
if curr[0] == '"' and curr[-1] == '"':
cleanedObjectives += '' + obj.split(';')[0] + ','
elif curr[0] == '"' and curr[-1] != '"':
cleanedObjectives += '' + obj.split(';')[0] + '",'
else:
cleanedObjectives += '"' + obj.split(';')[0] + '",'
cleanedKeys = ""
for key in module['keywords']:
if len(key) == 0:
continue
if key[0] == '"' and key[-1] == '"':
cleanedKeys += '' + key + ','
elif key[0] == '"' and key[-1] != '"':
cleanedKeys += '' + key + '",'
else:
cleanedKeys += '"' + key + '",'
finalizedQuery = query.substitute(
name=module['name'],
number=module['number'],
prefix=module['prefix'],
description=module['description'],
objectives=cleanedObjectives,
keywords=cleanedKeys.strip(','),
hours=module['hours']
)
# print(finalizedQuery)
res: Response = post("http://localhost:4000/graphql", json={'query': finalizedQuery})
# print(res.text)
if res.status_code != 200:
self.logger.error('Failed to seed module model from file!')
return False
return True
async def _seedPlanOfStudyDB(self):
"""
Seeds the plan of study model with dummy data for each account already present in the DB.
:return:
"""
self.logger.info('Seeding plan of study model...')
plans = []
for account in self.accounts:
plans.append({
'studentID': account['id'],
})
plan_res = await self.prisma.planofstudy.create_many(data=plans)
self.plans = plans
self.logger.info('Plan of study model seeded successfully with %d documents!' % plan_res)
async def _seedEnrollmentDB(self):
"""
Enroll each account in each module with a random role. The number of documents that will be created is equal
to the number of plan of studies multiplied by the number of modules.
:return: None
"""
self.logger.info('Seeding enrollment model...')
enrollments = []
class EnrollmentRole(Enum):
STUDENT = 1
TEACHER = 2
GRADER = 3
for pos in self.plans:
for module in self.modules:
enrollments.append({
'planID': pos['id'],
'moduleId': module['id'],
'role': np.random.choice(list(EnrollmentRole)).name
})
enrollment_res = await self.prisma.moduleenrollment.create_many(data=enrollments)
self.enrollments = enrollments
self.logger.info('Enrollment model seeded successfully with %d documents!' % enrollment_res)
async def _seedFeedbackDB(self):
"""
Seed the feedback model with dummy data for each enrollment. The number of documents that will be created is
equal to the number of enrollments.
:return: None
"""
self.logger.info('Seeding feedback model...')
feedbacks = []
# find the user's ID given a plan ID
plans = await self._getPlans()
for enrollment in self.enrollments:
feedbacks.append({
'moduleId': enrollment['moduleId'],
'rating': np.random.randint(1, 6),
'feedback': self.gen.sentence(),
'studentId': list(
map(lambda x: x['studentID'], filter(lambda x: x['id'] == enrollment['planID'], plans))).pop()
})
feedback_res = await self.prisma.modulefeedback.create_many(data=feedbacks)
self.feedbacks = feedbacks
self.logger.info('Feedback model seeded successfully with %d documents!' % feedback_res)
async def seedAll(self):
"""
Calls all the seeding methods in the correct order. If the skip member is set to Skipper.all, then all seeding
operations will be skipped. If the skip member is set to Skipper.<modelName>, then the <modelName> model seeding
will be skipped.
:return: None
"""
await self.connect()
self.logger.info('Seeding operation started...')
if Skipper.all in self.skip:
self.logger.info('Skipping all model seeding...')
else:
if Skipper.user in self.skip:
self.logger.info('Skipping user model seeding...')
self.accounts = await self._getUserAccounts()
else:
await self._seedUserDB()
if Skipper.module in self.skip:
self.logger.info('Skipping module model seeding...')
self.modules = await self._getModules()
else:
await self._seedModuleDB()
if Skipper.plan in self.skip:
self.logger.info('Skipping plan of study model seeding...')
self.plans = await self._getPlans()
else:
await self._seedPlanOfStudyDB()
if Skipper.enrollment in self.skip:
self.logger.info('Skipping enrollment model seeding...')
self.enrollments = await self._getEnrollments()
else:
await self._seedEnrollmentDB()
if Skipper.feedback in self.skip:
self.logger.info('Skipping feedback model seeding...')
self.feedbacks = await self._getFeedbacks()
else:
await self._seedFeedbackDB()
self.logger.info('All models seeded successfully!')
await self.disconnect()
async def cleanupAll(self):
"""
Calls all the cleanup methods in the correct order. If the cleanup member is set to Skipper.all, then all
cleanup operations will be skipped. If the cleanup member is set to Skipper.<modelName>, then the <modelName>
model cleanup will be skipped.
:return:
"""
await self.connect()
self.logger.info('Cleanup operation started...')
if Skipper.all in self.cleanup:
self.logger.info('Skipping all model cleanup...')
return
else:
# Deleting all users
if Skipper.user in self.cleanup:
self.logger.info('Skipping user model cleanup...')
else:
await self._cleanupUserDB()
# Deleting all plans of study
if Skipper.plan in self.cleanup:
self.logger.info('Skipping plan of study model cleanup...')
else:
await self._cleanupPlanOfStudyDB()
# Deleting all enrollments
if Skipper.enrollment in self.cleanup:
self.logger.info('Skipping enrollment model cleanup...')
else:
await self._cleanupEnrollmentDB()
# Deleting all modules
if Skipper.module in self.cleanup:
self.logger.info('Skipping module model cleanup...')
else:
await self._cleanupModuleDB()
# Deleting all module feedback
if Skipper.feedback in self.cleanup:
self.logger.info('Skipping feedback model cleanup...')
else:
await self._cleanupFeedbackDB()
self.logger.info('All models cleaned up successfully!')
await self.disconnect()
async def _cleanupUserDB(self):
count = await self.prisma.user.delete_many()
self.logger.info('User model cleaned up successfully! (%d documents deleted)' % count)
async def _cleanupModuleDB(self):
count = await self.prisma.module.delete_many()
self.logger.info('Module model cleaned up successfully! (%d documents deleted)' % count)
async def _cleanupFeedbackDB(self):
count = await self.prisma.modulefeedback.delete_many()
self.logger.info('Feedback model cleaned up successfully! (%d documents deleted)' % count)
async def _cleanupPlanOfStudyDB(self):
count = await self.prisma.planofstudy.delete_many()
self.logger.info('Plan of study model cleaned up successfully! (%d documents deleted)' % count)
async def _cleanupEnrollmentDB(self):
count = await self.prisma.moduleenrollment.delete_many()
self.logger.info('Enrollment model cleaned up successfully! (%d documents deleted)' % count)
async def main():
seeder = Seeder(
skip=[Skipper.all],
cleanup=[Skipper.all],
)
modules = [
# '../input/ENMA603_1.txt',
# '../input/ENMA603_2.txt',
# '../input/ENMA603_3.txt',
# '../input/ENMA603_4.txt',
# '../input/ENMA603_5.txt',
# '../input/ENMA603_6.txt',
# '../input/ENMA603_7.txt',
# '../input/ENMA603_8.txt',
# '../input/ENMA603_9.txt',
# '../input/ENMA603_10.txt',
# '../input/ENMA603_11.txt',
# '../input/ENMA603_12.txt',
# '../input/ENMA603_13.txt',
# '../input/ENMA603_14.txt',
]
for module in modules:
await seeder.seedModuleFromFile(path=module)
if __name__ == '__main__':
asyncio.run(main())
Functions
def getModuleFeedback()
-
Expand source code
def getModuleFeedback(): mods = post('http://%s/graphql' % os.environ.get("API_URL", "client:4000"), {}, { 'query': """query{ module(input:{}){ id moduleName moduleNumber feedback{ rating feedback } members{ id } } }""" }) return mods.json()['data']
async def main()
-
Expand source code
async def main(): seeder = Seeder( skip=[Skipper.all], cleanup=[Skipper.all], ) modules = [ # '../input/ENMA603_1.txt', # '../input/ENMA603_2.txt', # '../input/ENMA603_3.txt', # '../input/ENMA603_4.txt', # '../input/ENMA603_5.txt', # '../input/ENMA603_6.txt', # '../input/ENMA603_7.txt', # '../input/ENMA603_8.txt', # '../input/ENMA603_9.txt', # '../input/ENMA603_10.txt', # '../input/ENMA603_11.txt', # '../input/ENMA603_12.txt', # '../input/ENMA603_13.txt', # '../input/ENMA603_14.txt', ] for module in modules: await seeder.seedModuleFromFile(path=module)
Classes
class Seeder (skip: [
Skipper'>] = None, cleanup: [ Skipper'>] = None, iterations: int = 25, target: Optional[str] = None) -
Seeder class for seeding the database with dummy data. Makes use of the prisma python client to connection to the database and the essential_generators library to create document templates.
Expand source code
class Seeder: """ Seeder class for seeding the database with dummy data. Makes use of the prisma python client to connection to the database and the essential_generators library to create document templates. """ def __init__(self, skip: [Skipper] = None, cleanup: [Skipper] = None, iterations: int = 25, target: Union[str, None] = None): self.gen = DocumentGenerator() self.gen.init_word_cache(5000) self.gen.init_sentence_cache(5000) self.prisma = Prisma() self.iterations = iterations self.accounts = [] self.modules = [] self.enrollments = [] self.feedbacks = [] self.plans = [] self.skip = skip self.cleanup = cleanup self.target = target self.logger = logging.getLogger('__seed__') logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO) async def connect(self): """ Connects to the database using prisma client. """ await self.prisma.connect() async def disconnect(self): """ Disconnects from the database using prisma client. """ await self.prisma.disconnect() async def createTargetUser(self): """ Creates a target user for testing purposes. """ account = await self.prisma.user.create(data={ 'firstName': 'Test User', 'lastName': 'Test User', 'email': '', 'openID': '' }) self.logger.info('Created target user: %s' % account.id) return account.id async def _getUserAccounts(self): """ Gets all user accounts from the database and returns them as a list of dictionaries. :return: class<list> of class<dict> of type<User> """ accounts = await self.prisma.user.find_many() acc = [] for i in range(len(accounts)): acc.append(accounts[i].dict()) return acc async def _getModules(self): """ Gets all modules from the database and returns them as a list of dictionaries. :return: class<list> of class<dict> of type<Module> """ self.modules = await self.prisma.module.find_many() mods = [] for i in range(len(self.modules)): mods.append(self.modules[i].dict()) return mods async def _getEnrollments(self): """ Gets all enrollments from the database and returns them as a list of dictionaries. :return: class<list> of class<dict> of type<ModuleEnrollment> """ self.enrollments = await self.prisma.moduleenrollment.find_many() enrollments = [] for i in range(len(self.enrollments)): enrollments.append(self.enrollments[i].dict()) return enrollments async def _getFeedbacks(self): """ Gets all feedbacks from the database and returns them as a list of dictionaries. :return: class<list> of class<dict> of type<ModuleFeedback> """ self.feedbacks = await self.prisma.modulefeedback.find_many() feedbacks = [] for i in range(len(self.feedbacks)): feedbacks.append(self.feedbacks[i].dict()) return feedbacks async def _getPlans(self) -> list[dict]: self.plans = await self.prisma.planofstudy.find_many() plans = [] for i in range(len(self.plans)): plans.append(self.plans[i].dict()) return plans async def _seedUserDB(self): """ Seeds the user model with dummy data as many times as described by the iterations' member. :return: None """ self.logger.info('Seeding user model...') accounts = [] for i in range(self.iterations): accounts.append({ 'firstName': self.gen.name(), 'lastName': self.gen.name(), 'email': self.gen.email(), 'openID': str(self.gen.integer()), }) users = await self.prisma.user.create_many(data=accounts) self.accounts = accounts self.logger.info('User model seeded successfully with %d documents!' % users) async def _seedModuleDB(self): """ Seeds the module model with dummy data as many times as described by the iterations' member. :return: None """ self.logger.info('Seeding module model...') modules = [] template = { 'moduleName': { 'typemap': 'sentence', 'unique': True, 'tries': 100 }, 'moduleNumber': { 'typemap': 'integer', 'unique': True, 'tries': 100 }, 'description': 'paragraph', 'duration': 'small_int', 'intro': 'sentence', 'numSlides': 'small_int', 'keywords': { 'set': ['engineering', 'mathematics', 'physics', 'chemistry', 'biology', 'computer science', 'economics'] } } self.gen.set_template(template) docs = self.gen.documents(self.iterations) module_res = await self.prisma.module.create_many(data=docs) self.modules = modules self.logger.info('Module model seeded successfully with %d documents!' % module_res) def _is_float_(self, num: str): try: if float(num).is_integer(): return False return True except ValueError: return False # function to create acronym def fxn(self, stng: str): # add first letter oupt = stng[0] # iterate over string for i in range(1, len(stng)): if stng[i - 1] == ' ': # add letter next to space oupt += stng[i] # uppercase oupt oupt = oupt.upper() return oupt async def seedModuleFromFile(self, path: str): """ Seeds the module model with data from a csv file. The structure of the files must be as follows: - the first two rows should be ignored as they contain the column names and data types - column 1: module number - if it is an integer, we will need to create a unique prefix for it. if it is a float, the prefix will be the integer part of the number and the decimal number will be the module number - column 2: module name - column 3: module description - column 4: module objectives - this will be a list of strings separated by a semicolon - column 5: module keywords - this will be a list of strings separated by a semicolon - column 6: module hours - this will be an float number representing the number of hours the module will take to complete :return: Boolean """ self.logger.info('Seeding module model from file...') modules = list() with open(path, 'r') as csvFile: parsedFile = csv.reader(csvFile, delimiter='\t', quotechar='|') next(parsedFile) prefix = '' for row in parsedFile: document = dict() if float(row[0]).is_integer(): prefix = self.fxn(row[1]) document['number'] = 0 else: dec = row[0].split('.') document['number'] = dec[1] document['name'] = row[1] document['prefix'] = prefix document['description'] = row[2] document['objectives'] = row[3].split(';') document['keywords'] = row[4].split(';') if row[5] == ' ' or row[5] == '': document['hours'] = np.random.uniform(0.25, 2) else: document['hours'] = float(row[5]) modules.append(document) message = Template('Successfully parsed $number documents from file $name!') self.logger.info(message.substitute(number=len(modules), name=path.split('/')[-1])) # send each element in the array to the GraphQL API endpoint without using Prisma for module in modules: query = Template(""" mutation { createModule(input: { name: "$name" number: $number prefix: "$prefix" description: "$description" objectives: [$objectives] keywords: [$keywords] hours: $hours }) { id } } """) cleanedObjectives = "" for obj in module['objectives']: curr = obj.split(';')[0] if len(curr) == 0: continue if curr[0] == '"' and curr[-1] == '"': cleanedObjectives += '' + obj.split(';')[0] + ',' elif curr[0] == '"' and curr[-1] != '"': cleanedObjectives += '' + obj.split(';')[0] + '",' else: cleanedObjectives += '"' + obj.split(';')[0] + '",' cleanedKeys = "" for key in module['keywords']: if len(key) == 0: continue if key[0] == '"' and key[-1] == '"': cleanedKeys += '' + key + ',' elif key[0] == '"' and key[-1] != '"': cleanedKeys += '' + key + '",' else: cleanedKeys += '"' + key + '",' finalizedQuery = query.substitute( name=module['name'], number=module['number'], prefix=module['prefix'], description=module['description'], objectives=cleanedObjectives, keywords=cleanedKeys.strip(','), hours=module['hours'] ) # print(finalizedQuery) res: Response = post("http://localhost:4000/graphql", json={'query': finalizedQuery}) # print(res.text) if res.status_code != 200: self.logger.error('Failed to seed module model from file!') return False return True async def _seedPlanOfStudyDB(self): """ Seeds the plan of study model with dummy data for each account already present in the DB. :return: """ self.logger.info('Seeding plan of study model...') plans = [] for account in self.accounts: plans.append({ 'studentID': account['id'], }) plan_res = await self.prisma.planofstudy.create_many(data=plans) self.plans = plans self.logger.info('Plan of study model seeded successfully with %d documents!' % plan_res) async def _seedEnrollmentDB(self): """ Enroll each account in each module with a random role. The number of documents that will be created is equal to the number of plan of studies multiplied by the number of modules. :return: None """ self.logger.info('Seeding enrollment model...') enrollments = [] class EnrollmentRole(Enum): STUDENT = 1 TEACHER = 2 GRADER = 3 for pos in self.plans: for module in self.modules: enrollments.append({ 'planID': pos['id'], 'moduleId': module['id'], 'role': np.random.choice(list(EnrollmentRole)).name }) enrollment_res = await self.prisma.moduleenrollment.create_many(data=enrollments) self.enrollments = enrollments self.logger.info('Enrollment model seeded successfully with %d documents!' % enrollment_res) async def _seedFeedbackDB(self): """ Seed the feedback model with dummy data for each enrollment. The number of documents that will be created is equal to the number of enrollments. :return: None """ self.logger.info('Seeding feedback model...') feedbacks = [] # find the user's ID given a plan ID plans = await self._getPlans() for enrollment in self.enrollments: feedbacks.append({ 'moduleId': enrollment['moduleId'], 'rating': np.random.randint(1, 6), 'feedback': self.gen.sentence(), 'studentId': list( map(lambda x: x['studentID'], filter(lambda x: x['id'] == enrollment['planID'], plans))).pop() }) feedback_res = await self.prisma.modulefeedback.create_many(data=feedbacks) self.feedbacks = feedbacks self.logger.info('Feedback model seeded successfully with %d documents!' % feedback_res) async def seedAll(self): """ Calls all the seeding methods in the correct order. If the skip member is set to Skipper.all, then all seeding operations will be skipped. If the skip member is set to Skipper.<modelName>, then the <modelName> model seeding will be skipped. :return: None """ await self.connect() self.logger.info('Seeding operation started...') if Skipper.all in self.skip: self.logger.info('Skipping all model seeding...') else: if Skipper.user in self.skip: self.logger.info('Skipping user model seeding...') self.accounts = await self._getUserAccounts() else: await self._seedUserDB() if Skipper.module in self.skip: self.logger.info('Skipping module model seeding...') self.modules = await self._getModules() else: await self._seedModuleDB() if Skipper.plan in self.skip: self.logger.info('Skipping plan of study model seeding...') self.plans = await self._getPlans() else: await self._seedPlanOfStudyDB() if Skipper.enrollment in self.skip: self.logger.info('Skipping enrollment model seeding...') self.enrollments = await self._getEnrollments() else: await self._seedEnrollmentDB() if Skipper.feedback in self.skip: self.logger.info('Skipping feedback model seeding...') self.feedbacks = await self._getFeedbacks() else: await self._seedFeedbackDB() self.logger.info('All models seeded successfully!') await self.disconnect() async def cleanupAll(self): """ Calls all the cleanup methods in the correct order. If the cleanup member is set to Skipper.all, then all cleanup operations will be skipped. If the cleanup member is set to Skipper.<modelName>, then the <modelName> model cleanup will be skipped. :return: """ await self.connect() self.logger.info('Cleanup operation started...') if Skipper.all in self.cleanup: self.logger.info('Skipping all model cleanup...') return else: # Deleting all users if Skipper.user in self.cleanup: self.logger.info('Skipping user model cleanup...') else: await self._cleanupUserDB() # Deleting all plans of study if Skipper.plan in self.cleanup: self.logger.info('Skipping plan of study model cleanup...') else: await self._cleanupPlanOfStudyDB() # Deleting all enrollments if Skipper.enrollment in self.cleanup: self.logger.info('Skipping enrollment model cleanup...') else: await self._cleanupEnrollmentDB() # Deleting all modules if Skipper.module in self.cleanup: self.logger.info('Skipping module model cleanup...') else: await self._cleanupModuleDB() # Deleting all module feedback if Skipper.feedback in self.cleanup: self.logger.info('Skipping feedback model cleanup...') else: await self._cleanupFeedbackDB() self.logger.info('All models cleaned up successfully!') await self.disconnect() async def _cleanupUserDB(self): count = await self.prisma.user.delete_many() self.logger.info('User model cleaned up successfully! (%d documents deleted)' % count) async def _cleanupModuleDB(self): count = await self.prisma.module.delete_many() self.logger.info('Module model cleaned up successfully! (%d documents deleted)' % count) async def _cleanupFeedbackDB(self): count = await self.prisma.modulefeedback.delete_many() self.logger.info('Feedback model cleaned up successfully! (%d documents deleted)' % count) async def _cleanupPlanOfStudyDB(self): count = await self.prisma.planofstudy.delete_many() self.logger.info('Plan of study model cleaned up successfully! (%d documents deleted)' % count) async def _cleanupEnrollmentDB(self): count = await self.prisma.moduleenrollment.delete_many() self.logger.info('Enrollment model cleaned up successfully! (%d documents deleted)' % count)
Methods
async def cleanupAll(self)
-
Calls all the cleanup methods in the correct order. If the cleanup member is set to Skipper.all, then all cleanup operations will be skipped. If the cleanup member is set to Skipper.
, then the model cleanup will be skipped. :return: Expand source code
async def cleanupAll(self): """ Calls all the cleanup methods in the correct order. If the cleanup member is set to Skipper.all, then all cleanup operations will be skipped. If the cleanup member is set to Skipper.<modelName>, then the <modelName> model cleanup will be skipped. :return: """ await self.connect() self.logger.info('Cleanup operation started...') if Skipper.all in self.cleanup: self.logger.info('Skipping all model cleanup...') return else: # Deleting all users if Skipper.user in self.cleanup: self.logger.info('Skipping user model cleanup...') else: await self._cleanupUserDB() # Deleting all plans of study if Skipper.plan in self.cleanup: self.logger.info('Skipping plan of study model cleanup...') else: await self._cleanupPlanOfStudyDB() # Deleting all enrollments if Skipper.enrollment in self.cleanup: self.logger.info('Skipping enrollment model cleanup...') else: await self._cleanupEnrollmentDB() # Deleting all modules if Skipper.module in self.cleanup: self.logger.info('Skipping module model cleanup...') else: await self._cleanupModuleDB() # Deleting all module feedback if Skipper.feedback in self.cleanup: self.logger.info('Skipping feedback model cleanup...') else: await self._cleanupFeedbackDB() self.logger.info('All models cleaned up successfully!') await self.disconnect()
async def connect(self)
-
Connects to the database using prisma client.
Expand source code
async def connect(self): """ Connects to the database using prisma client. """ await self.prisma.connect()
async def createTargetUser(self)
-
Creates a target user for testing purposes.
Expand source code
async def createTargetUser(self): """ Creates a target user for testing purposes. """ account = await self.prisma.user.create(data={ 'firstName': 'Test User', 'lastName': 'Test User', 'email': '', 'openID': '' }) self.logger.info('Created target user: %s' % account.id) return account.id
async def disconnect(self)
-
Disconnects from the database using prisma client.
Expand source code
async def disconnect(self): """ Disconnects from the database using prisma client. """ await self.prisma.disconnect()
def fxn(self, stng: str)
-
Expand source code
def fxn(self, stng: str): # add first letter oupt = stng[0] # iterate over string for i in range(1, len(stng)): if stng[i - 1] == ' ': # add letter next to space oupt += stng[i] # uppercase oupt oupt = oupt.upper() return oupt
async def seedAll(self)
-
Calls all the seeding methods in the correct order. If the skip member is set to Skipper.all, then all seeding operations will be skipped. If the skip member is set to Skipper.
, then the model seeding will be skipped. :return: None Expand source code
async def seedAll(self): """ Calls all the seeding methods in the correct order. If the skip member is set to Skipper.all, then all seeding operations will be skipped. If the skip member is set to Skipper.<modelName>, then the <modelName> model seeding will be skipped. :return: None """ await self.connect() self.logger.info('Seeding operation started...') if Skipper.all in self.skip: self.logger.info('Skipping all model seeding...') else: if Skipper.user in self.skip: self.logger.info('Skipping user model seeding...') self.accounts = await self._getUserAccounts() else: await self._seedUserDB() if Skipper.module in self.skip: self.logger.info('Skipping module model seeding...') self.modules = await self._getModules() else: await self._seedModuleDB() if Skipper.plan in self.skip: self.logger.info('Skipping plan of study model seeding...') self.plans = await self._getPlans() else: await self._seedPlanOfStudyDB() if Skipper.enrollment in self.skip: self.logger.info('Skipping enrollment model seeding...') self.enrollments = await self._getEnrollments() else: await self._seedEnrollmentDB() if Skipper.feedback in self.skip: self.logger.info('Skipping feedback model seeding...') self.feedbacks = await self._getFeedbacks() else: await self._seedFeedbackDB() self.logger.info('All models seeded successfully!') await self.disconnect()
async def seedModuleFromFile(self, path: str)
-
Seeds the module model with data from a csv file. The structure of the files must be as follows: - the first two rows should be ignored as they contain the column names and data types - column 1: module number - if it is an integer, we will need to create a unique prefix for it. if it is a float, the prefix will be the integer part of the number and the decimal number will be the module number - column 2: module name - column 3: module description - column 4: module objectives - this will be a list of strings separated by a semicolon - column 5: module keywords - this will be a list of strings separated by a semicolon - column 6: module hours - this will be an float number representing the number of hours the module will take to complete
:return: Boolean
Expand source code
async def seedModuleFromFile(self, path: str): """ Seeds the module model with data from a csv file. The structure of the files must be as follows: - the first two rows should be ignored as they contain the column names and data types - column 1: module number - if it is an integer, we will need to create a unique prefix for it. if it is a float, the prefix will be the integer part of the number and the decimal number will be the module number - column 2: module name - column 3: module description - column 4: module objectives - this will be a list of strings separated by a semicolon - column 5: module keywords - this will be a list of strings separated by a semicolon - column 6: module hours - this will be an float number representing the number of hours the module will take to complete :return: Boolean """ self.logger.info('Seeding module model from file...') modules = list() with open(path, 'r') as csvFile: parsedFile = csv.reader(csvFile, delimiter='\t', quotechar='|') next(parsedFile) prefix = '' for row in parsedFile: document = dict() if float(row[0]).is_integer(): prefix = self.fxn(row[1]) document['number'] = 0 else: dec = row[0].split('.') document['number'] = dec[1] document['name'] = row[1] document['prefix'] = prefix document['description'] = row[2] document['objectives'] = row[3].split(';') document['keywords'] = row[4].split(';') if row[5] == ' ' or row[5] == '': document['hours'] = np.random.uniform(0.25, 2) else: document['hours'] = float(row[5]) modules.append(document) message = Template('Successfully parsed $number documents from file $name!') self.logger.info(message.substitute(number=len(modules), name=path.split('/')[-1])) # send each element in the array to the GraphQL API endpoint without using Prisma for module in modules: query = Template(""" mutation { createModule(input: { name: "$name" number: $number prefix: "$prefix" description: "$description" objectives: [$objectives] keywords: [$keywords] hours: $hours }) { id } } """) cleanedObjectives = "" for obj in module['objectives']: curr = obj.split(';')[0] if len(curr) == 0: continue if curr[0] == '"' and curr[-1] == '"': cleanedObjectives += '' + obj.split(';')[0] + ',' elif curr[0] == '"' and curr[-1] != '"': cleanedObjectives += '' + obj.split(';')[0] + '",' else: cleanedObjectives += '"' + obj.split(';')[0] + '",' cleanedKeys = "" for key in module['keywords']: if len(key) == 0: continue if key[0] == '"' and key[-1] == '"': cleanedKeys += '' + key + ',' elif key[0] == '"' and key[-1] != '"': cleanedKeys += '' + key + '",' else: cleanedKeys += '"' + key + '",' finalizedQuery = query.substitute( name=module['name'], number=module['number'], prefix=module['prefix'], description=module['description'], objectives=cleanedObjectives, keywords=cleanedKeys.strip(','), hours=module['hours'] ) # print(finalizedQuery) res: Response = post("http://localhost:4000/graphql", json={'query': finalizedQuery}) # print(res.text) if res.status_code != 200: self.logger.error('Failed to seed module model from file!') return False return True
class Skipper (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
An enumeration.
Expand source code
class Skipper(Enum): user = 1 module = 2 feedback = 3 plan = 4 enrollment = 5 all = 6
Ancestors
- enum.Enum
Class variables
var all
var enrollment
var feedback
var module
var plan
var user