Ejemplo n.º 1
0
 def __sub__(self, other):
     if self.grade != other.grade:
         ns = NS()
         ns.status = 'course_grade_changed'
         ns.left = self
         ns.right = other
         ns.param = other.grade
         yield ns
Ejemplo n.º 2
0
 def __repr__(self):
     ns = NS()
     ns.homerooms = " ".join(self.homeroom)
     ns.emails = ", ".join(self.emails)
     ns.parents_of = "Parents of " + ", ".join(self.children_ids)
     ns.family_id = self.family_id
     ns.ID = self.ID
     ns.homerooms = "(" + ", ".join(self.homeroom) + ")"
     ns.courses = "{} courses".format(len(self.courses))
     ns.groups = "{} groups".format(len(self.groups))
     return ns("<Parent {ID}: {parents_of} {homerooms}>")
Ejemplo n.º 3
0
 def __repr__(self):
     ns = NS()
     ns.ID = self.ID
     ns.username = self.username
     ns.homeroom = self.homeroom
     #ns.firstrow = "+ "
     #ns.midrow = "\n| "
     #ns.lastrow="\n| "
     #ns.lastfirst = self.lastfirst
     #ns.email = self.email
     #ns.homeroom = self.homeroom
     #ns.teachers = ", ".join(self.teacher_names)
     #ns.courses = ", ".join(self.course_names)
     #ns.groups = ", ".join(self.group_names)
     #ns.cohorts = ", ".join(self.cohorts)
     return ns("<Student {ID}/{homeroom}: {username}>") #, {homeroom}{midrow}{lastfirst}") # \
    def __sub__(self, other):
        if self.children != other.children:
            for to_add in set(other.children) - set(self.children):
                ns = NS()
                ns.status = "associate_child_to_parent"
                ns.left = self
                ns.right = other
                ns.param = NS()
                ns.param.child = to_add
                ns.param.parent = self.parent_idnumber
                yield ns

            for to_remove in set(self.children) - set(other.children):
                ns = NS()
                ns.status = "deassociate_child_from_parent"
                ns.left = self
                ns.right = other
                ns.param = NS()
                ns.param.child = to_remove
                ns.param.parent = self.parent_idnumber
                yield ns
Ejemplo n.º 5
0
 def __repr__(self):
     ns = NS()
     ns.emails = ", ".join(self.emails)
     ns.parents_of = "Parents of " + ", ".join(self.children_ids)
     ns.homerooms = "(" + self._homeroom + ")"
     ns.family_id = self.family_id
     ns.ID = self.ID
     return ns("<MoodleParent {ID}: {parents_of} {homerooms}>")
    def __init__(self, verbose=False):
        #TODO: Get this info from standard settings and config
        self.verbose = verbose
        self.logger = logging.getLogger(self.__class__.__name__)
        self.default_logger = self.logger.debug
        self.sf = NS()
        self.email_accounts = config_get_section_attribute('EMAIL', 'check_accounts')
        self.moodle_accounts = config_get_section_attribute('MOODLE', 'sync')
        # TODO: Depreciate this stupid dry run thingie, make it a logging feature instead
        self.dry_run = config_get_section_attribute('DEFAULTS', 'dry_run')
        self.path_to_cli = config_get_section_attribute('MOODLE', 'path_to_cli')
        self.path_to_php = config_get_section_attribute('MOODLE', 'path_to_php')
        if not self.path_to_php:
            self.path_to_php = '/usr/bin/php'

        # Moodle requires any php files to be run from the admin/cli directory
        os.chdir(self.path_to_cli)

        # And now, spawn it
        cmd = "{} {}/phpclimoodle.php".format(self.path_to_php, self.path_to_cli)
        self.process = pexpect.spawn(cmd)
        self.process.delaybeforesend = 0  # speed things up a bit, eh?
        self.process.timeout = 3600
        self.process.expect_exact('?: ') # not sure why this works the first time
Ejemplo n.º 7
0
    def get_students_filter(self, **kwargs):
        l = list(self.student_info_controller.keys())
        for key in self.student_info_controller.keys():
            this = self.get_student(key)
            if not this:
                continue
            if this.compare_kwargs(**kwargs):
                yield this

def check_is_in_preferred_list(this):
    return this.compare_kwargs(num=35263)

if __name__ == "__main__":

    students = Students()
    print('Full Name,User Name,Email\n')
    for student_key in students.get_student_keys():
        student = students.get_student(student_key)
        sf = NS()
        sf.take_dict(student)
        if student.grade == 5:
            print(sf('{first} {last},{username},{email}'))
    #students.courses_output()
    #print("Here are the ones with ???:")
    #students.output_filter(check_is_in_preferred_list)
    #students.teachers_output()
    #students.courses_output()
    #students.students_output()


    def go(self):
        path = None
        if self.config.has_section("EMAIL"):
            path = config_get_section_attribute('DIRECTORIES', 'path_to_postfix')
        if not path:
            path = self.output_path + '/postfix'

        ns = self.make_ns()
        ns.PATH = path
        ns.EXT = '.txt'
        ns.INCLUDE = ' :include:'

        # The clear_folder routine erases all files in a certain folder
        # That has implications for postfix (when we're on the server), because
        # if you delete the .db files then postfix won't work. That is bad.
        # So, tell clear_folder to exclude them
        exclude_db_files = lambda x: x.endswith('.db')
        self.logger.debug("Clearing folders in postfix")
        clear_folder( ns.PATH, exclude=exclude_db_files)
        clear_folder(ns('{PATH}/grades'))
        clear_folder(ns('{PATH}/homerooms'))
        clear_folder(ns('{PATH}/classes'))
        clear_folder(ns('{PATH}/parentlink'))
        clear_folder(ns('{PATH}/teacherlink'))
        clear_folder(ns('{PATH}/special'))
        clear_folder(ns('{PATH}/departments'))
        clear_folder(ns('{PATH}/activities'))

        special_directory = []

        self.logger.debug("Setting up largest mailing lists first")

        for item in ['ALL', 'SEC', 'ELEM', 'KOREAN', 'CHINESE']:
            ns.this = item
            special_directory.append( ns('usebccparents{this}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}usebccparents{this}{EXT}') )

        with open( ns('{PATH}/special{EXT}'), 'w') as f:
            f.write( "\n".join(special_directory) )

        usebccparentsALL = []
        usebccstudentsALL = []
        usebccparentsELEM = []
        usebccparentsSEC = []
        usebccstudentsSEC = []
        usebccparentsCHINESE = []
        usebccparentsCHINESEELEM = []
        usebccparentsCHINESESEC = []
        usebccparentsCHINESEGRADE = defaultdict(list)
        usebccparentsKOREAN = []
        usebccparentsKOREANELEM = []
        usebccparentsKOREANSEC = []
        usebccparentsKOREANGRADE = defaultdict(list)
        usebccparentsJAPANESE = []
        usebccparentsJAPANESEELEM = []
        usebccparentsJAPANESESEC = []
        usebccparentsJAPANESEGRADE = defaultdict(list)
        # SWA DISTRIBUTION LISTS
        usebccparentsSWA = []
        usebccstudentsSWA = []
        usebccparentsSWAGRADE = defaultdict(list)
        usebccstudentsSWAGRADE = defaultdict(list)
        # HR AND GRADE
        usebccparentsHOMEROOM = defaultdict(list)
        usebccparentsGRADE = defaultdict(list)
        usebccparentsHOMEROOM = defaultdict(list)
        usebccstudentsELEM = defaultdict(list)
        usebccstudentsGRADE = defaultdict(list)
        usebccstudentsHOMEROOM = defaultdict(list)
        parentlink = defaultdict(list)
        teacherlink = defaultdict(list)
        teachersGRADE = defaultdict(list)
        hrlink = defaultdict(list)
        classes = defaultdict(list)
        classesPARENTS = defaultdict(list)
        special = defaultdict(list)

        self.logger.debug('Clearing the table on moodle')
        self.server_information.create_temp_storage('student_email_info', 'list', 'email')
        self.server_information.empty_temp_storage('student_email_info')
        if self.arguments.update_moodle:
            write_db = self.server_information.add_temp_storage
        else:
            write_db = do_nothing
        self.logger.debug("Setting email lists")
        for student in self.tree.students:
            ns.homeroom = student.homeroom
            ns.grade = student.grade

            # TODO: Check for now grade or homeroom and warn
            if student.grade is "" or student.grade is None:
                self.logger.warn("This student does not have a grade:\n{}".format(student))
            if not student.homeroom:
                self.logger.warn("This student does not have a homeroom:\n{}".format(student))

            # USE ns.grade BECAUSE student.grade IS AN INTEGER
            # TODO: DO WE MAKE student.grade A STRING?
            # OR PUT THIS IN THE OBJECT SOMEWHOW?
            if ns.grade <= 0:
                ns.grade = {0: 'K', -1: 'R', -2: 'G', -3:'PK', -4:'N'}.get(ns.grade, None)

            usebccparentsALL.extend( student.guardian_emails )
            ns.grade and usebccparentsGRADE[ns.grade].extend(student.guardian_emails)
            ns.homeroom and usebccparentsHOMEROOM[ns.homeroom].extend(student.guardian_emails)

            if student.is_elementary:
                usebccparentsELEM.extend(student.guardian_emails)

            if student.is_secondary:
                usebccparentsSEC.extend(student.guardian_emails)
                usebccstudentsSEC.append(student.email)
                if ns.grade:
                    usebccstudentsGRADE[ns.grade].append(student.email)
                    teachersGRADE[ns.grade].extend(student.teacher_emails)
                if student.homeroom:
                    usebccstudentsHOMEROOM[ns.homeroom].append(student.email)
                parentlink[student.username].extend( student.guardian_emails )
                teacherlink[student.username].extend(student.teacher_emails)
                hrlink[student.username].append(student.homeroom_teacher_email)
                for group in student.group_names:
                    classes[group].append(student.email)
                    classesPARENTS[group].extend(student.guardian_emails)

            if student.is_chinese:
                usebccparentsCHINESE.extend( student.guardian_emails )
                student.is_secondary and usebccparentsCHINESESEC.extend( student.guardian_emails )
                student.is_elementary and usebccparentsCHINESEELEM.extend( student.guardian_emails )
                usebccparentsCHINESEGRADE[ns.grade].extend( student.guardian_emails )
            if student.is_korean:
                usebccparentsKOREAN.extend( student.guardian_emails )
                student.is_secondary and usebccparentsKOREANSEC.extend( student.guardian_emails )
                student.is_elementary and usebccparentsKOREANELEM.extend( student.guardian_emails )
                usebccparentsKOREANGRADE[ns.grade].extend( student.guardian_emails )
            if student.is_japanese:
                usebccparentsJAPANESE.extend( student.guardian_emails )
                student.is_secondary and usebccparentsJAPANESESEC.extend( student.guardian_emails )
                student.is_elementary and usebccparentsJAPANESEELEM.extend( student.guardian_emails )
                usebccparentsJAPANESEGRADE[ns.grade].extend( student.guardian_emails )
            if student.is_SWA:
                usebccparentsSWA.extend( student.guardian_emails )
                usebccstudentsSWA.append( student.email )
                usebccparentsSWAGRADE[ns.grade].extend( student.guardian_emails )
                usebccstudentsSWAGRADE[ns.grade].append( student.email )

        for ns.email in set(usebccparentsALL):
            write_db('student_email_info', list='usebccparentsALL', email=ns.email)

        for ns.email in set(usebccparentsSEC):
            write_db('student_email_info', list='usebccparentsSEC', email=ns.email)

        for ns.email in set(usebccparentsELEM):
            write_db('student_email_info', list='usebccparentsELEM', email=ns.email)

        for ns.email in set(usebccparentsSWA):
            write_db('student_email_info', list='usebccparentsSWA', email=ns.email)

        for ns.email in set(usebccstudentsSWA):
            write_db('student_email_info', list='usebccstudentsSWA', email=ns.email)

        for ns.grade in usebccparentsGRADE:
            for ns.email in set(usebccparentsGRADE[ns.grade]):
                write_db('student_email_info', list=ns('usebccparents{grade}'), email=ns('{email}'))

        for ns.grade in usebccstudentsGRADE:
            for ns.email in set(usebccstudentsGRADE[ns.grade]):
                write_db('student_email_info', list=ns('usebccstudents{grade}'), email=ns('{email}'))

        for ns.grade in teachersGRADE:
            for ns.email in set(teachersGRADE[ns.grade]):
                write_db('student_email_info', list=ns('teachers{grade}'), email=ns('{email}'))

        for ns.homeroom in usebccparentsHOMEROOM:
            for ns.email in set(usebccparentsHOMEROOM[ns.homeroom]):
                write_db('student_email_info', list=ns('usebccparents{homeroom}'), email=ns('{email}'))

        for ns.homeroom in usebccstudentsHOMEROOM:
            for ns.email in set(usebccstudentsHOMEROOM[ns.homeroom]):
                write_db('student_email_info', list=ns('usebccstudents{homeroom}'), email=ns('{email}'))

        for ns.student in teacherlink:
            for ns.email in set(teacherlink[ns.student]):
                write_db('student_email_info', list=ns('{student}TEACHERS'), email=ns('{email}'))

        for ns.student in parentlink:
            for ns.email in set(parentlink[ns.student]):
                write_db('student_email_info', list=ns('{student}PARENTS'), email=ns('{email}'))

        for ns.student in hrlink:
            for ns.email in set(hrlink[ns.student]):
                write_db('student_email_info', list=ns('{student}HR'), email=ns('{email}'))            

        for ns.klass in classes:
            for ns.email in classes[ns.klass]:
                write_db('student_email_info', list=ns('{klass}'), email=ns('{email}'))

        for ns.klass in classesPARENTS:
            for ns.email in classes[ns.klass]:
                write_db('student_email_info', list=ns('{klass}PARENTS'), email=ns('{email}'))

        # GRADES
        directory_write = []
        for ns.grade in usebccparentsGRADE:
            directory_write.append( ns('usebccparents{grade}{COLON}{INCLUDE}{PATH}{SLASH}grades{SLASH}usebccparents{grade}{EXT}') )
            with open( ns('{PATH}{SLASH}grades{SLASH}usebccparents{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsGRADE[ns.grade])) )
        for ns.grade in usebccstudentsGRADE:
            directory_write.append( ns('usebccstudents{grade}{COLON}{INCLUDE}{PATH}{SLASH}grades{SLASH}usebccstudents{grade}{EXT}') )
            with open( ns('{PATH}{SLASH}grades{SLASH}usebccstudents{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccstudentsGRADE[ns.grade])) )
        for ns.grade in teachersGRADE:
            directory_write.append( ns('teachers{grade}{COLON}{INCLUDE}{PATH}{SLASH}grades{SLASH}teachers{grade}{EXT}') )
            with open( ns('{PATH}{SLASH}grades{SLASH}teachers{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(teachersGRADE[ns.grade])) )
        with open( ns('{PATH}{SLASH}grades{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

            #HS

        # HOMEROOMS
        directory_write = []
        for ns.homeroom in usebccparentsHOMEROOM:
            directory_write.append( ns('usebccparents{homeroom}{COLON}{INCLUDE}{PATH}{SLASH}homerooms{SLASH}usebccparents{homeroom}{EXT}') )
            with open( ns('{PATH}{SLASH}homerooms{SLASH}usebccparents{homeroom}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsHOMEROOM[ns.homeroom])) )
        for ns.homeroom in usebccstudentsHOMEROOM:
            directory_write.append( ns('usebccstudents{homeroom}{COLON}{INCLUDE}{PATH}{SLASH}homerooms{SLASH}usebccstudents{homeroom}{EXT}') )
            with open( ns('{PATH}{SLASH}homerooms{SLASH}usebccstudents{homeroom}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccstudentsHOMEROOM[ns.homeroom])) )
        with open( ns('{PATH}{SLASH}homerooms{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

        # TEACHERLINK
        directory_write = []
        for ns.student in teacherlink:
            directory_write.append( ns('{student}TEACHERS{COLON}{INCLUDE}{PATH}{SLASH}teacherlink{SLASH}{student}TEACHERS{EXT}') )
            with open( ns('{PATH}{SLASH}teacherlink{SLASH}{student}TEACHERS{EXT}'), 'w') as f:
                f.write( '\n'.join(set(teacherlink[ns.student])) )
        with open( ns('{PATH}{SLASH}teacherlink{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

        # PARENTLINK
        directory_write = []
        for ns.student in parentlink:
            directory_write.append( ns('{student}PARENTS{COLON}{INCLUDE}{PATH}{SLASH}parentlink{SLASH}{student}PARENTS{EXT}') )
            with open( ns('{PATH}{SLASH}parentlink{SLASH}{student}PARENTS{EXT}'), 'w') as f:
                f.write( '\n'.join(set(parentlink[ns.student])) )
        with open( ns('{PATH}{SLASH}parentlink{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

        # HRLINK
        directory_write = []
        for ns.student in hrlink:
            if hrlink[ns.student]:  # not all kids have a homeroom teacher....
                directory_write.append( ns('{student}HR{COLON}{INCLUDE}{PATH}{SLASH}homeroomlink{SLASH}{student}HR{EXT}') )
                with open( ns('{PATH}{SLASH}homeroomlink{SLASH}{student}HR{EXT}'), 'w') as f:
                    try:
                        f.write( '\n'.join(set(hrlink[ns.student])) )
                    except TypeError:
                        pass
        with open( ns('{PATH}{SLASH}homeroomlink{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )
        
        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsALL{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsALL) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsSEC{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsSEC) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsELEM{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsELEM) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsCHINESE{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsCHINESE) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsCHINESESEC{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsCHINESESEC) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsCHINESEELEM{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsCHINESEELEM) )

        for ns.grade in usebccparentsCHINESEGRADE:
            with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsCHINESE{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsCHINESEGRADE[ns.grade])) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsKOREAN{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsKOREAN) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsKOREANELEM{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsKOREANSEC) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsKOREANSEC{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsKOREANSEC) )

        for ns.grade in usebccparentsKOREANGRADE:
            with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsKOREAN{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsKOREANGRADE[ns.grade])) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsJAPANESE{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsJAPANESE) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsJAPANESESEC{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsJAPANESESEC) )

        for ns.grade in usebccparentsJAPANESEGRADE:
            with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsJAPANESE{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsJAPANESEGRADE[ns.grade])) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsSWA{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsSWA) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccstudentsSWA{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccstudentsSWA) )
                
        with open( ns('{PATH}{SLASH}special{EXT}'), 'w') as f:
            for ns.this in ['usebccparentsALL', 'usebccparentsSEC', 'usebccparentsELEM',
                            'usebccparentsKOREAN', 'usebccparentsKOREANSEC', 'usebccparentsKOREANELEM',
                            'usebccparentsCHINESE', 'usebccparentsCHINESESEC', 'usebccparentsCHINESEELEM',
                            'usebccparentsJAPANESE', 'usebccparentsJAPANESESEC', 'usebccparentsJAPANESEELEM', 
                            'usebccparentsSWA', 'usebccstudentsSWA']:
                f.write( ns('{this}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}{this}{EXT}{NEWLINE}') )
            for ns.grade in usebccparentsKOREANGRADE:
                f.write( ns('usebccparentsKOREAN{grade}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}usebccparentsKOREAN{grade}{EXT}{NEWLINE}') )
            for ns.grade in usebccparentsCHINESEGRADE:
                f.write( ns('usebccparentsCHINESE{grade}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}usebccparentsCHINESE{grade}{EXT}{NEWLINE}') )
            for ns.grade in usebccparentsJAPANESEGRADE:
                f.write( ns('usebccparentsJAPANESE{grade}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}usebccparentsJAPANESE{grade}{EXT}{NEWLINE}') )

        # CLASSES
        directory_write = []
        for ns.klass in classes:
            directory_write.append( ns('{klass}{COLON}{INCLUDE}{PATH}{SLASH}classes{SLASH}{klass}{EXT}') )
        for ns.klass in classesPARENTS:
            directory_write.append( ns('{klass}PARENTS{COLON}{INCLUDE}{PATH}{SLASH}classes{SLASH}{klass}PARENTS{EXT}') )
        with open( ns('{PATH}{SLASH}classes{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

        for ns.klass in classes:
            with open( ns('{PATH}{SLASH}classes{SLASH}{klass}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(classes[ns.klass])) )

        for ns.klass in classesPARENTS:
            with open( ns('{PATH}{SLASH}classes{SLASH}{klass}PARENTS{EXT}'), 'w') as f:
                f.write( '\n'.join(set(classesPARENTS[ns.klass])) )

        self.logger.debug("Set up department batch emails")
        ##  SETUP DEPARTMENTS, including by homeroom teachers
        depart_dict = {}
        homeroom_teachers_dict = {}
        for teacher in self.tree.teachers:
            departments = teacher.get_departments()
            for department in departments:
                d_email_name = department_email_names.get(department)
                if not d_email_name:
                    continue
                if not d_email_name in list(depart_dict.keys()):
                    heads = department_heads.get(department, [])  # returns a list
                    depart_dict[d_email_name] = []
                    for head in heads:
                        self.logger.debug("Adding {} (the head) into department {}".format(head, d_email_name))
                        depart_dict[d_email_name].append(head + "@ssis-suzhou.net")
                if teacher and not teacher.email in depart_dict[d_email_name]:
                    self.logger.debug("Adding {} into department {}".format(teacher, d_email_name))
                    depart_dict[d_email_name].append(teacher.email)

            if teacher.homeroom:
                ns.homeroom = teacher.homeroom
                if not teacher.homeroom in homeroom_teachers_dict.keys():
                    homeroom_teachers_dict[teacher.homeroom] = True
                    setup_postfix = ns('{PATH}/departments{EXT}')
                    with open(setup_postfix, 'a') as f:
                        f.write(ns("homeroomteachers{homeroom}: :include:{PATH}/departments/homeroomteachers{homeroom}{EXT}\n"))
                setup_postfix = ns('{PATH}/departments/homeroomteachers{homeroom}{EXT}')
                with open(setup_postfix, 'a') as f:
                    f.write(teacher.email + '\n')

        for ns.department in list(depart_dict.keys()):
            # department is now actually the email name we want to use 
            setup_postfix = ns('{PATH}/departments{EXT}')
            with open(setup_postfix, 'a') as f:
                f.write( ns("{department}: :include:{PATH}/departments/{department}{EXT}\n") )

            setup_postfix = ns('{PATH}/departments/{department}{EXT}')
            with open(setup_postfix, 'w') as f:
                f.write( "\n".join(depart_dict[ns.department]) )

        # SETUP SECONDARY ACTIVITIES
        results = self.server_information.get_all_users_activity_enrollments()
        ns = NS()
        ns.domain = 'student.ssis-suzhou.net'
        activities_postfix = defaultdict(list)
        activities_postfix_parents = defaultdict(list)
        for result in results:
            activity_name, student_key = result
            student = self.tree.student_from_ID(student_key)
            if not student:
                # in case of outlyer
                continue
            if not student:
                self.logger.warning('This student is listed as having enrolled into an activity, ' + \
                                    'but no longer seems to be available at school. Ignored. {}'.format(student_key))
                continue
            activities_postfix[activity_name].append(student.email)
            activities_postfix_parents[activity_name].append(student.parent_link_email)

        # DO THE ACTIVITY EMAILS
        ns.path = config_get_section_attribute('DIRECTORIES', 'path_to_postfix')
        ns.base = 'activities'
        ns.SUFFIX = "ACT"
        ns.EXT = '.txt'
        ns.INCLUDE = ':include:'
        ns.activities_path = ns('{path}{SLASH}activities')
        with open(ns('{path}{SLASH}{base}{EXT}'), 'w'):
            pass

        for activity_name in activities_postfix:
            ns.handle = name_to_email(activity_name)
            ns.full_email = ns('{handle}{SUFFIX}')
            with open(ns('{path}{SLASH}{base}{EXT}'), 'a') as f:
                f.write(ns('{full_email}{COLON}{SPACE}{INCLUDE}' + \
                           '{activities_path}{SLASH}{full_email}{EXT}{NEWLINE}'))
            with open(ns('{activities_path}{SLASH}{full_email}{EXT}'), 'a') as f:
                f.write("\n".join(activities_postfix[activity_name]))

        ns.SUFFIX = "ACTPARENTS"
        for activity_name in activities_postfix_parents:
            ns.handle = name_to_email(activity_name)
            ns.full_email = ns('{handle}{SUFFIX}')
            with open(ns('{path}{SLASH}{base}{EXT}'), 'a') as f:
                f.write(ns('{full_email}{COLON}{SPACE}{INCLUDE}' + \
                           '{activities_path}{SLASH}{full_email}{EXT}{NEWLINE}'))
            with open(ns('{activities_path}{SLASH}{full_email}{EXT}'), 'a') as f:
                f.write("\n".join(activities_postfix_parents[activity_name]))
        
        # run newaliases command on exit if we're on the server
        newaliases_path = False
        if self.config.has_section('EMAIL'):
            newaliases_path = self.config['EMAIL'].get('newaliases_path')
        if newaliases_path:
            self.logger.info("Running newaliases")
            p = subprocess.Popen(newaliases_path, shell=True)
            self.logger.info(p.communicate())
        else:
            self.logger.warn("newaliases not run!")
    def no_email(self, student):
        sf = NS(student)
        sf.new_student_cmd = self.new_email_cmd

        self.shell( sf("/bin/bash {new_student_cmd} {num} {username} '{lastfirst}'") )
                where = line.index(search_item)
                message = line[ (where+ len(search_item)+1): -1]
                match = re.search("orig_to=<(.*?)>", line)
                if match:
                    orig_to = match.group(1)
                    if args.stdout:
                        print(to_who)
                        print(orig_to)
                    bounce = bounces[to_who]
                    bounce.key = escape(to_who)
                    bounce.count += 1
                    bounce.messages.append(escape(message))

email = Email(domain)
email.add_to('*****@*****.**')
email.make_subject("Bounces")
email.define_sender('DragonNet Admin <*****@*****.**>')
html = "<html>"
for bounce in bounces:
    ns = NS(bounces[bounce])
    ns.messages = "<br />".join(ns.messages)
    ns.BR = '<br />'
    html += ns('<p>Email{COLON}{SPACE}{key}{SPACE} ' \
        'How many bounces{COLON}{SPACE}{count}{BR}<i>{messages}</i></p>')
html+= "</html>"
email.define_content(html)
if not args.no_emails:
    email.send()
if args.stdout:
    print(email.htmls['en'])
Ejemplo n.º 11
0
    def __sub__(self, other):

        for item in super().__sub__(other):
            yield item

        # Handle cohorts (site-wide groups)
        for to_add in set(other.cohort_idnumbers) - set(self.cohort_idnumbers):
            ns = NS()
            ns.status = 'add_to_cohort'
            ns.left = self
            ns.right = other
            ns.param = to_add
            yield ns

        for to_remove in set(self.cohort_idnumbers) - set(other.cohort_idnumbers):
            ns = NS()
            ns.status = 'remove_from_cohort'
            ns.left = self
            ns.right = other
            ns.param = to_remove
            yield ns

        # Other things
        attrs = ['username', 'email', 'homeroom']
        for attr in attrs:
            if not getattr(self, attr) == getattr(other, attr):
                ns = NS()
                ns.status = attr+'_changed'
                ns.left = self
                ns.right = other
                ns.param = getattr(other, attr)
                yield ns

        for course in set(other.enrollments.keys()) - set(self.enrollments.keys()):
            for group in other.enrollments[course]:
                ns = NS()
                ns.status = 'enrol_parent_into_course'
                ns.left = self
                ns.right = other
                to_add = NS()
                to_add.course = course
                to_add.group = group
                ns.param = to_add
                yield ns

        for course in set(self.enrollments.keys()) and set(other.enrollments.keys()):
            #TODO: Check that parents are being put into courses as well as the groups
            self_groups = self.enrollments.get(course, [])
            other_groups = other.enrollments.get(course, [])
            for group in other_groups:
                if not group.idnumber in [g.idnumber for g in self_groups]:
                    ns = NS()
                    ns.status = 'add_to_group'
                    ns.left = self
                    ns.right = other
                    to_add = NS()
                    to_add.course = course
                    to_add.group = group
                    ns.param = to_add
                    yield ns
            for group in self_groups:
                if not group.idnumber in [g.idnumber for g in other_groups]:
                    ns = NS()
                    ns.status = 'remove_from_group'
                    ns.left = self
                    ns.right = other
                    to_remove = NS()
                    to_remove.course = course
                    to_remove.group = group
                    ns.param = to_remove
                    yield ns

        for course in set(self.enrollments.keys()) - set(other.enrollments.keys()):
            for group in self.enrollments.get(course, []):
                ns = NS()
                ns.status = 'deenrol_parent_from_course'
                ns.left = self
                ns.right = other
                to_remove = NS()
                to_remove.course = course
                to_remove.group = group
                ns.param = to_remove
                yield ns
    def __init__(self):
        super().__init__()
        self.raw = self.sql("select distinct usr.firstname, usr.lastname, dr.timecreated, dc.content, dc.fieldid, dc.recordid from ssismdl_data_content dc " +
                            "join ssismdl_data_records dr on dc.recordid = dr.id " +
                            "join ssismdl_user usr on dr.userid = usr.id " +
                       "join ssismdl_data_fields df on dc.fieldid = df.id " + "join ssismdl_data d on df.dataid = 4 order by dc.recordid")()
        record_ids = []
        path_to_probe = config_get_section_attribute("DIRECTORIES", 'path_to_output')
        path_to_probe += '/probe/'
        
        for line in self.raw:
            r_id = line[k_record_id]
            if not r_id in record_ids:
                record_ids.append( r_id )
        # teachers holds the data organized by teachers
        teachers = defaultdict(list)
        # powerschool variable holds the data that will actually be written to file
        powerschool = ['Student_Number\tTest_Date\tGrade_Level\tReading_Age_1\tScore_2\tCategory_3\tIndications_3\tDifferential_1']
        # reads in student info from powerschool autosend
        student_info = Tree()        

        # loop through the records in the database module, match them up with the student info
        # and export the data accordingly
        for record_id in record_ids:
            this_entry = [ i for i in self.raw if i[k_record_id] == record_id ]
            if this_entry:
                entry = NS()
                entry.teacher = this_entry[0][0] + " " + this_entry[0][1]
                entry.date = timestamp_to_python_date(this_entry[0][2])
                entry.date_entered = entry.date.strftime('%m/%d/%Y')
                entry.test_date = {2012:make_date(2012, 10, 15), 2013:make_date(2013, 5, 15)}.get(entry.date.year)
                entry.test_date_output = entry.test_date.strftime('%m/%d/%Y')
                for row in this_entry:
                    field_id = row[k_field_id]
                    if field_id == k_student_name:
                        entry.student = row[k_content]
                        entry.powerschoolid = entry.student
                        match = re.search( '\((.*) (.*)\)', entry.student)
                        if match:
                            entry.homeroom, entry.powerschoolid = match.groups()
                            entry.grade = re.sub('[A-Z]', '', entry.homeroom)
                        else:
                            entry.homeroom = ''
                            entry.grade = -1
                    elif field_id == k_percentage:
                        entry.percent = row[k_content]
                    elif field_id == k_analysis:
                        entry.analysis = ', '.join(row[k_content].split('##')) if row[k_content] else ""
                    elif field_id == k_type:
                        entry.type = row[k_content]
                    elif field_id == k_set:
                        entry.set = row[k_content]
                        if not entry.set:
                            print(this_entry)
                        entry.reading_age = reading_age_from_set.get(entry.set)

                # gets the student class that has autosend data
                student = student_info.get_student(str(entry.powerschoolid))
                if not student:
                    # student no longer at ssis
                    continue
                if not entry.reading_age:
                    # no longer in the system (left) just skip it
                    # what about that dude's data!?
                    print("Something wrong with the data of this student")
                    continue
                date_to_age = lambda x: float(x.days) / 365.25
                entry.age = date_to_age(entry.test_date - student.birthday)
                entry.differential = round(entry.reading_age - entry.age, 2)
                teachers[entry.teacher].append( entry )
                powerschool.append( entry('{powerschoolid}{TAB}{test_date_output}{TAB}{grade}{TAB}{reading_age}{TAB}{percent}{TAB}{type}{TAB}{analysis}{TAB}{differential}') )
        with open(path_to_probe + 'powerschool.txt', 'w') as f:
            f.write( "\n".join(powerschool) )
        for teacher in teachers:
            with open(path_to_probe + '{}.txt'.format(teacher), 'w') as f:
                entries = teachers[teacher]
                entries.sort(key=lambda x: x.student)
                for entry in entries:
                    f.write(entry.student+ '\n')
                    f.write("\tSet:      {}\n".format(entry.set))
                    f.write("\tPercent:  {}\n".format(entry.percent))
                    f.write("\tAnalysis: {}\n".format(entry.analysis))
                    f.write("\tType:     {}\n".format(entry.type))
                    f.write('\n')
Ejemplo n.º 13
0
    def __sub__(self, other):

        for item in super().__sub__(other):
            yield item

        # Handle cohorts (site-wide groups)
        for to_add in set(other.cohort_idnumbers) - set(self.cohort_idnumbers):
            ns = NS()
            ns.status = 'add_to_cohort'
            ns.left = self
            ns.right = other
            ns.param = to_add
            yield ns

        # for to_remove in set(self.cohort_idnumbers) - set(other.cohort_idnumbers):
        #     ns = NS()
        #     ns.status = 'remove_from_cohort'
        #     ns.left = self
        #     ns.right = other
        #     ns.param = to_remove
        #     yield ns

        # Other things
        attrs = ['username']
        for attr in attrs:
            if not getattr(self, attr) == getattr(other, attr):
                ns = NS()
                ns.status = attr+'_changed'
                ns.left = self
                ns.right = other
                ns.param = getattr(other, attr)
                yield ns

        for course in set(other.enrollments.keys()) - set(self.enrollments.keys()):
            for group in other.enrollments[course]:
                ns = NS()
                ns.status = 'enrol_teacher_into_course'
                ns.left = self
                ns.right = other
                to_add = NS()
                to_add.course = course
                to_add.group = group
                ns.param = to_add
                yield ns

        # Go through each course that they share, and check that
        # they have the same groups, if not, do what's right
        for course in set(self.enrollments.keys()) and set(other.enrollments.keys()):
            self_groups = self.enrollments[course]
            other_groups = other.enrollments[course]
            for group in other_groups:
                if not group.idnumber in [g.idnumber for g in self_groups]:
                    ns = NS()
                    ns.status = 'add_to_group'
                    ns.left = self
                    ns.right = other
                    to_add = NS()
                    to_add.course = course
                    to_add.group = group
                    ns.param = to_add
                    yield ns
class CallPHP:
    """
    Interfaces with php file phpclimoodle.php
    """
    def __init__(self, verbose=False):
        #TODO: Get this info from standard settings and config
        self.verbose = verbose
        self.logger = logging.getLogger(self.__class__.__name__)
        self.default_logger = self.logger.debug
        self.sf = NS()
        self.email_accounts = config_get_section_attribute('EMAIL', 'check_accounts')
        self.moodle_accounts = config_get_section_attribute('MOODLE', 'sync')
        # TODO: Depreciate this stupid dry run thingie, make it a logging feature instead
        self.dry_run = config_get_section_attribute('DEFAULTS', 'dry_run')
        self.path_to_cli = config_get_section_attribute('MOODLE', 'path_to_cli')
        self.path_to_php = config_get_section_attribute('MOODLE', 'path_to_php')
        if not self.path_to_php:
            self.path_to_php = '/usr/bin/php'

        # Moodle requires any php files to be run from the admin/cli directory
        os.chdir(self.path_to_cli)

        # And now, spawn it
        cmd = "{} {}/phpclimoodle.php".format(self.path_to_php, self.path_to_cli)
        self.process = pexpect.spawn(cmd)
        self.process.delaybeforesend = 0  # speed things up a bit, eh?
        self.process.timeout = 3600
        self.process.expect_exact('?: ') # not sure why this works the first time

    def command(self, routine, cmd):
        """
        Interfaces with pexpect
        """
        self.verbose and print('sending {} {}'.format(routine, cmd))
        try:
            self.process.sendline(routine + ' ' + cmd)
        except OSError:
            if routine == "QUIT":
                return # this is expected, nevermind
            if self.process.isalive():
                self.logger.warning("Huh. Error but it's still alive!")
            else:
                self.logger.warning("The other side just up and died")

        # We know that the phpclimoodle file returns a plus if it's all good
        # and a negative if not, handle accordingly
        success_string = '\+.*'
        error_string = '-\d+ .*'
        try:
            which = self.process.expect([success_string, error_string])
        except Exception as e:
            which = 1
            self.logger.critical(self.process.after)
            raise e
        self.verbose and print("which {}".format(which))

        if which == 0:
            pass
        elif which == 1:
            the_string = self.process.after.decode('utf-8')[:-5]
            self.logger.warning(the_string)   # make sure this is a warning
        else:
            self.logger.critical(self.process.after.decode('utf-8'))   # This will probably be something essential
            exit()
        self.verbose and input()

    def create_new_course(self, idnumber, fullname):
        self.command('create_new_course', "{} '{}'".format(idnumber, fullname))

    def create_online_portfolio(self, idnumber):
        self.command('create_online_portfolio', '{}'.format(idnumber))

    def create_account(self, username, email, firstname, lastname, idnumber, auth='manual'):
        self.sf.define(username=username, email=email, firstname=firstname, lastname=lastname, idnumber=idnumber, auth=auth)
        to_pass = self.sf("{username} '{email}' '{firstname}' '{lastname}' {idnumber} {auth}")
        self.command('create_account', to_pass)

    def delete_account(self, useridnumber):
        print("Deleteing {}".format(useridnumber))
        self.command('delete_account', useridnumber)

    def create_group_for_course(self, course_id, group_name):
        self.command('create_group_for_course {} {}'.format(course_id, group_name))

    def create_inactive_account(self, username, email, firstname, lastname, idnumber):
        """
        CREATE A 'SUSPENDED' ACCOUNT (MAKES MORE SENSE TO CALL IT INACTIVE WHEN CREATING IT)
        SIMPLY BY PASSING nologin TO THE FUNCTION
        OTHERWISE, SAME AS create_account
        """
        self.sf.define(username=username, email=email, firstname=firstname, lastname=lastname, idnumber=idnumber)
        to_pass = self.sf("{username} {email} '{firstname}' '{lastname}' {idnumber} nologin")
        self.command('create_account', to_pass)

    def enrol_user_into_course(self, idnumber, shortname, group_id, group_name, role):
        self.sf.define(idnumber=idnumber, shortname=shortname, group_id=group_id, group_name=group_name, role=role)
        to_pass = self.sf("{idnumber} '{shortname}' '{group_id}' '{group_name}' {role}")
        self.command('enrol_user_in_course', to_pass)

    def unenrol_user_from_course(self, idnumber, course):
        self.sf.define(idnumber=idnumber, course=course)
        self.command('deenrol_user_from_course', self.sf('{idnumber} {course}'))

    def add_user_to_cohort(self, useridnumber, cohortidnumber):
        self.sf.define(useridnumber=useridnumber, cohortidnumber=cohortidnumber)
        to_pass = self.sf("{useridnumber} '{cohortidnumber}'")
        self.command('add_user_to_cohort', to_pass)

    def remove_user_from_cohort(self, useridnumber, cohortidnumber):
        self.sf.define(useridnumber=useridnumber, cohortidnumber=cohortidnumber)
        to_pass = self.sf("{useridnumber} '{cohortidnumber}'")
        self.command('remove_user_from_cohort', to_pass)

    def new_cohort(self, cohortidnumber, cohortname):
        self.command("create_cohort {} '{}'".format(cohortidnumber, cohortname))

    def add_user_to_group(self, userid, group_id):
        self.sf.define(userid=userid, group_id=group_id)
        to_pass = self.sf("{userid} '{group_id}'")
        self.command('add_user_to_group', to_pass)

    def remove_user_from_group(self, userid, group_id):
        self.sf.define(userid=userid, group_id=group_id)
        to_pass = self.sf("{userid} '{group_id}'")
        self.command('remove_user_from_group', to_pass)

    def add_group(self, group_id, group_name, course_id):
        self.sf.define(group_id=group_id, group_name=group_name, course_id=course_id)
        to_pass = self.sf("{course_id} '{group_id}' '{group_name}'")
        self.command('create_group_for_course', to_pass)

    def delete_group(self, group, course):
        self.sf.define(group=group, course=course)
        to_pass = self.sf("{course} '{group}'")
        self.command('delete_group_for_course', to_pass)

    def change_username(self, idnumber, new_name):
        self.command('change_username', "{} {}".format(idnumber, new_name))

    def change_parent_username(self, idnumber, new_username, password):
        self.command('change_parent_username', "{} {} {}".format(idnumber, new_username, password))

    def associate_child_to_parent(self, idnumber, child_idnumber):
        self.command('associate_child_to_parent', "{} {}".format(idnumber, child_idnumber))

    def __del__(self):
        """
        Kill the spawned process
        """
        if self.process.isalive:
            try:
                self.command('QUIT', '')
            except:
                pass
Ejemplo n.º 15
0
    try:
        where = long_name.index(')')
    except ValueError:
        where = -1
    where += 1
    long_name = long_name[where:].strip().lower()
    return re.sub('[^a-z]', '', long_name)
    

if __name__ == "__main__":

    students = Tree()
    
    db = MoodleDBConnection()
    sf = NS()

    results = db.get_all_users_activity_enrollments()
    sf.domain = 'student.ssis-suzhou.net'
    sf.AT = '@'

    from collections import defaultdict
    postfix = defaultdict(list)
    activities = defaultdict(list)
    homerooms = defaultdict( lambda : defaultdict(list) )

    # PARSE RESULTS
    for result in results:
        activity_name, student_key = result
        student = students.get_student(student_key)
        if not student: