Пример #1
0
def GenerateMarksFromCsv(*, annotate_file='annotate.csv', project='..', weights:'Tuple[int]', output='marks.csv'):
    """
    From <annotate_file> (annotate.csv) (two columns: src, annot)
    And current db in <project> (default '..')
    Generates <output_file> (marks.csv) (two columns: matricule, mark_on_10)
    
    annot contains characters in the set 'vxf-012345789'
    <weights> is a list of positive int
    """
    # p.add_argument('--annotate_file', default='annotate.csv')
    # p.add_argument('--project', default='..')
    # p.add_argument('--weights', type=int, nargs='+')
    # p.add_argument('-o', '--output', default='marks.csv')
    
    connection = sqlite3.connect(project + '/data/capture.sqlite')
    Assoc = dict(connection.execute('select src, student from capture_page'))
    Annot = dict(csv.reader(open('annotate.csv')))

    Marks = {
        Assoc['%PROJET/scans/' + src]:
        sum(compute_mark_list(annot, weights))
        for src, annot in Annot.items()
    }
    
    with OutFile(output, 'w') as out:
        csv.writer(out).writerows(Marks.items())
Пример #2
0
    from generate_utils import OutFileGreen as OutFile
except ImportError:
    OutFile = open

with open(txt_file) as file:
    string = file.read()

R = Re('\d?\d:\d+\d+')
A = R.split(string)
B = R.findall(string)

if not (A and A[0].strip() == ''):
    raise ValueError("Must begin with a time")

assert len(A) == 1 + len(
    B), "the programmer did not understand re.split and re.findall"

bits = []
for i in range(len(B)):
    b, a = A[i + 1], B[i]
    x, y = a.split(':')
    x, y = int(x), int(y)
    time = x * 60 + y
    title = html.escape(b)
    if with_times:
        title = a + ' ' + title
    bits.append(f'<li><a href="{baselink}&amp;t={time}">{title}</a></li>')

with OutFile(new_name, 'w') as out:
    out.write('<ul>{}</ul>'.format('\n'.join(bits)))
Пример #3
0
def GenerateSrcList(output:'.csv', *, project:'generateurAMC_A', page=None):
    c = sqlite3.connect(project + '/data/capture')
    
    L = src.replace('%PROJET', 'project') for src in c.execute(
        ''' select src from capture_page ''' if page is None else
        ''' select src from capture_page where page={}'''.format(int(page)))
    
    with OutFile(output) as out:
        out.write('\n'.join(L))

class ExamInfo:
    SERIES:('A', 'B')
    PROJECT_NAME:'path to project, may contain {serie}' = 'generateurAMC_{serie}'
    
    OPEN_QUESTION_SOURCE = {} # All from the marks ticks (from 0 to 10) on the paper (FromScannedAnnotationsAndMark)

class PHYSS1001_JANVIER_2017_2018(ExamInfo):
    
    SERIES = ('A', 'B')
    PROJECT_NAME = 'generateurAMC_{serie}'
    
    ANSWERS_= { # list of [value, min, max, -points minus]
        'QF5a': [
            StandardPossibleAnswer('7.81e-1', '7.71e-1', '7.81e-1', 0),
            StandardPossibleAnswer('1.56', '1.54', '1.58', -1)
        ],
        'QF6a': [
            RulesStandardPossibleAnswer('-3.32e-9', '3.22e-9', '3.42e-9', 0, ['SignMinus1']),
            RulesStandardPossibleAnswer('-375', '371', '379', -1, ['SignMinus1']),
        ], 
        'QF7a': [
            StandardPossibleAnswer('1.33e-8', '1.23e-8', '1.43e-8', 0),
            StandardPossibleAnswer('5.32e-8', '5.3e-8', '5.34e-8', -3),
            StandardPossibleAnswer('2.66e-8', '2.64e-8', '2.68e-8', -3)
        ],
        'QF8a': [
            StandardPossibleAnswer('2.5', '2.4', '2.6', 0),
        ],
        'QF5b': [
            StandardPossibleAnswer('1.53', '1.43', '1.63', 0),
            StandardPossibleAnswer('3.06', '3.04', '3.08', -1)
        ],
        'QF6b': [
            RulesStandardPossibleAnswer('-5.53e-9', '5.43e-9', '5.63e-9', 0, ['SignMinus1']),
            RulesStandardPossibleAnswer('625', '621', '629', -1, ['SignMinus1']),
        ], 
        'QF7b': [
            StandardPossibleAnswer('1.18e-8', '1.08e-8', '1.28e-8', 0),
            StandardPossibleAnswer('2.36e-8', '2.34e-8', '2.38e-8', -3),
            StandardPossibleAnswer('3.54e-8', '3.52e-8', '3.56e-8', -3),
            StandardPossibleAnswer('1.77e-8', '1.75e-8', '1.79e-8', -3),
        ],
        'QF8b': [
            StandardPossibleAnswer('1.41', '1.31', '1.51', 0),
        ],
    }
    
    OPEN_QUESTION_SOURCE = {
        # 'QO2': ReadFromMatriculeMarkCsv('q2-marks.csv', 'QO2'), # ReadFromAnnotate(''),
    }

class PHYSS1001_JUIN_2017_2018(ExamInfo):
    SERIES = ('A', 'B')
    PROJECT_NAME = 'generateurAMC_{serie}'
    
    ANSWERS = { 
        'QF7a': [
            {
                'min': '4.90e-4',
                'exact':'5.00e-4',
                'max': '5.10e-4',
                'minus': 0,
            },
        ],
        'QF8a': [
            {
                'min': '2.43e1',
                'exact': '2.53e1',
                'max': '2.63e1',
                'minus': 0,
            },
        ],
        'QF9a': [
            {
                'exact': '9.55e4',
                'min': '9.45e4',
                'max': '9.65e4',
                'minus': 0,
            },
        ],
        'QF10a': [
            {
                'min': '6.15e3',
                'exact': '6.25e3',
                'max': '6.35e3',
                'minus': 0,
            },
        ],
        'QF11a': [
            {
                'min': '2.17e3',
                'exact': '2.27e3',
                'max': '2.37e3',
                'minus': 0
            },
        ],
        'QF12a': [
            {
                'min': '5.61e0',
                'exact': '5.71e0',
                'max': '5.81e0',
                'minus': 0
            },
        ],
        
        'QF7b': [
            {
                'min': '9.45e4',
                'exact': '9.55e4',
                'max': '9.65e4',
                'minus': 0,
            },
        ],
        'QF8b': [
            {
                'min': '2.43e1',
                'exact': '2.53e1',
                'max': '2.63e1',
                'minus': 0
            },
        ],
        'QF9b': [
            {
                'min': '4.90e-4',
                'exact': '5.00e-4',
                'max': '5.10e-4',
                'minus': 0
            },
        ],
        'QF10b': [
            {
                'min': '5.61e0',
                'exact': '5.71e0',
                'max': '5.81e0',
                'minus': 0
            },
        ],
        'QF11b': [
            {
                'min': '2.17e3',
                'exact': '2.27e3',
                'max': '2.37e3',
                'minus': 0
            },
        ],
        'QF12b': [
            {
                'min': '6.15e3',
                'exact': '6.25e3',
                'max': '6.35e3',
                'minus': 0
            },
        ],
    }
        
    OPEN_QUESTION_SOURCE = {
        'QO1': ReadFromMatriculeMarkCsv(['points-P2-a-Q1-results.csv', 'points-P2-b-Q1-results.csv']),
        # others are written in AMC, ReadFromAnnotate
    }
    

class PHYSS1001_JUINRATTR_2017_2018(ExamInfo):
    SERIES = ('A', )
    PROJECT_NAME = 'generateurAMC_{serie}'
    
    # from list to dict with optional keys
    ANSWERS_ = { # list of [value, min, max, -points minus]
        'QF7a': [
            StandardPossibleAnswer('0', '0', '0', 0),
        ],
        'QF8a': [
            StandardPossibleAnswer('6.53e6', '6.43e6', '6.63e6', 0),
        ],
        'QF9a': [
            StandardPossibleAnswer('2.72e7', '2.62e7', '2.82e7', 0),
        ],
        'QF10a': [
            StandardPossibleAnswer('2.83e-7', '2.73e-7', '2.93e-7', 0),
        ],
    }

class PHYSS1001_AOUT_2017_2018(ExamInfo):
    SERIES = ('A', 'B')
    PROJECT_NAME = 'generateurAMC_{serie}'

    ANSWERS_ = {  # list of [value, min, max, -points minus]

        'QF7a': [

            StandardPossibleAnswer('1.01e3', '0.91e3', '1.11e3', 0),

            StandardPossibleAnswer('6.74e3', '6.64e3', '6.84e3', -2)

        ],

        'QF8a': [

            StandardPossibleAnswer('9.42e-5', '9.32e-5', '9.52e-5', 0),

        ],

        'QF9a': [

            StandardPossibleAnswer('1.42e-8', '1.32e-8', '1.52e-8', 0),

        ],

        'QF10a': [

            StandardPossibleAnswer('3.54e0', '3.44e0', '3.64e0', 0),

        ],

        'QF11a': [

            StandardPossibleAnswer('1.54e4', '1.44e4', '1.64e4', 0),

            StandardPossibleAnswer('8.88e3', '8.78e3', '8.98e3', -2),

        ],

        'QF12a': [

            StandardPossibleAnswer('2.99e-9', '2.89e-9', '3.09e-9', 0),

        ],

        'QF7b': [

            StandardPossibleAnswer('7.79e2', '7.69e2', '7.89e2', 0),

            StandardPossibleAnswer('5.80e3', '5.70e3', '5.90e3', -2)

        ],

        'QF8b': [

            StandardPossibleAnswer('1.65e-4', '1.55e-4', '1.75e-4', 0),

        ],

        'QF9b': [

            StandardPossibleAnswer('1.02e-8', '0.92e-8', '1.22e-8', 0),

        ],

        'QF10b': [

            StandardPossibleAnswer('4.71e0', '4.61e0', '4.81e0', 0),

        ],

        'QF11b': [

            StandardPossibleAnswer('1.28e4', '1.18e4', '1.38e4', 0),

            StandardPossibleAnswer('7.40e3', '7.30e3', '7.50e3', -2),

        ],

        'QF12b': [

            StandardPossibleAnswer('4.12e-9', '4.02e-9', '4.22e-9', 0),

        ],

    }

    OPEN_QUESTION_SOURCE = {

        # 'QO2': ReadFromMatriculeMarkCsv('q2-marks.csv', 'QO2'), # ReadFromAnnotate(''),

    }
    
def compute_mark_list(note, points_distrib:(3,1,2,2,1,1)):
    """
    with points_distrib=(3,1,2,2,1,1):
    if note == 'vxvvxx' yields 3,0,2,2,0,0
    if note == 'vxvv'   yields 3,0,2,2,0,0
    if note == 'fx-vxx' yields 2,0,1,2,0,0  # - means 1, f means 2
    if note == '2x1vxx' yields 2,0,1,2,0,0  # can give number
    if note == '5x1vxx' -> ValueError
    if note == 'vvvvvvv' -> ValueError
    """
    points = (3,1,2,2,1,1)
    assert sum(points_distrib) == 10
    n = len(points_distrib)
    assert len(note) <= n, note
    assert set(note) <= set('fvx-0123456789'), "Unrecognized characters: {}".format(set(note) - set('fvx-0123456789'))
    exp = note + (n - len(note)) * 'x'
    assert len(exp) == n
    
    for n,p in zip(exp, points_distrib):
        if n == 'v':
            yield p
        elif n == 'x':
            yield 0
        elif n in tuple('0123456789'):
            if int(n) > p:
                raise ValueError(f'Cannot have {n} points when maximum is {p}')
            yield int(n)
        elif n == 'f':
            if not p > 2:
                raise ValueError(f'Cannot have "f" when line has {p} points')
            yield 2
        elif n == '-':
            if p == 1:
                warning(f'Should not have "-" when line has {p} points. On {note}')
            if p == 0:
                raise ValueError(f'Cannot have "-" when line has {p} points. On {note}')
            yield 1

def GenerateMarksFromCsv(*, annotate_file='annotate.csv', project='..', weights:'Tuple[int]', output='marks.csv'):
    """
    From <annotate_file> (annotate.csv) (two columns: src, annot)
    And current db in <project> (default '..')
    Generates <output_file> (marks.csv) (two columns: matricule, mark_on_10)
    
    annot contains characters in the set 'vxf-012345789'
    <weights> is a list of positive int
    """
    # p.add_argument('--annotate_file', default='annotate.csv')
    # p.add_argument('--project', default='..')
    # p.add_argument('--weights', type=int, nargs='+')
    # p.add_argument('-o', '--output', default='marks.csv')
    
    connection = sqlite3.connect(project + '/data/capture.sqlite')
    Assoc = dict(connection.execute('select src, student from capture_page'))
    Annot = dict(csv.reader(open('annotate.csv')))

    Marks = {
        Assoc['%PROJET/scans/' + src]:
        sum(compute_mark_list(annot, weights))
        for src, annot in Annot.items()
    }
    
    with OutFile(output, 'w') as out:
        csv.writer(out).writerows(Marks.items())


def ComputeMarks(exam_info, *, OUT_FILE='all_marks'):
    qf_answers = exam_info.ANSWERS
    SERIES = exam_info.SERIES
    PROJECT_NAME = exam_info.PROJECT_NAME
    open_question_source = exam_info.OPEN_QUESTION_SOURCE
    
    assert splitext(OUT_FILE)[1] == '', "please do not provide any extension"
    assert len(set(map(str.lower, SERIES))) == len(SERIES), f"no duplicates in series, got {SERIES}"
    
    # qf_answers
    assert all(len(L) > 0 for L in qf_answers.values())
    assert all(isinstance(X, dict) for L in qf_answers.values() for X in L)
    assert all(X.get('minus', 0) == 0 for L in qf_answers.values() for i,X in enumerate(L) if i == 0)
    assert all(X.get('minus', 0) <= 0 for L in qf_answers.values() for X in L)
    assert all(isinstance(X[key], (Decimal, str)) for L in qf_answers.values() for X in L for key in ('exact', 'min', 'max') if key in X)
    
    ## convert to Decimal 
    for latexname, L in qf_answers.items():
        for X in L:
            for key in ('exact', 'min', 'max'):
                if key in X:
                    X[key] = Decimal(X[key])
    
    ## add min and max if not there
    for latexname, L in qf_answers.items():
        for X in L:
            assert {'min', 'max'} <= X.keys(), f"no minmax in question {latexname}"
            
    ## add minus for first question if not there
    for latexname, L in qf_answers.items():
        for i,X in enumerate(L):
            if i == 0:
                if 'minus' not in X:
                    X['minus'] = 0
    
    assert all(isinstance(X[key], Decimal) for L in qf_answers.values() for X in L for key in ('exact', 'min', 'max') if key in X)
    assert all(X[key] >= 0 for L in qf_answers.values() for X in L for key in ('min', 'max') if key in X)

    # TODO: assert no overlap : assert all(map(no_overlap, qf_answers.values()))

    # should move in qf_answers
    qf_special_treatment = {
        'QF5a': {},
        'QF6a': {}, # {'SignMinus1'},
        'QF7a': {},
        'QF8a': {},
        'QF9a': {},
        'QF9a': {},
        'QF10a': {},
        'QF11a': {},
        'QF5b': {},
        'QF6b': {}, # {'SignMinus1'},
        'QF7b': {},
        'QF8b': {},
    }
    
    for k in qf_special_treatment:
        if not isinstance(qf_special_treatment[k], set):
            qf_special_treatment[k] = set(qf_special_treatment[k])

    assert all(X <= {'SignMinus1'} for X in qf_special_treatment.values())
    
    data_marks = []
    errors = []
    with CSVOrXLWriter(OUT_FILE + '_questions', print_created=True) as writer:
        writer.writerow(('COPIE','MATRICULE','QUESTION','MARK','ANNOTATION','COMMENTS'))
        for serie in SERIES:
            proj = PROJECT_NAME.format(serie=serie)

            dbs = {name:sqlite3.connect(f'{proj}/data/{name}.sqlite') for name in ('layout', 'association', 'capture')}
            
            xmldoc = XmlElement.parse(f'{proj}/options.xml')

            try:
                seuil = float(xmldoc.find('seuil').text)
            except:
                seuil = 0.35
                warning(f'serie {serie}: seuil not found in xml, default seuil {seuil} used')
            
            Dict = DictCollection()
            
            AmcStudentId, Matricule = Dict.keylist('AmcStudentId', 'Matricule')
            AmcQuestionId, LatexQuestionName = Dict.keylist('AmcQuestionId', 'LatexQuestionName')
            
            Dict[AmcQuestionId, 'to', LatexQuestionName] = dict_int_key(
                dbs['layout'].execute('''select question, name from layout_question'''))

            Dict[AmcStudentId, 'to', Matricule] = {
                int(student): int(auto or manual)
                for student, auto, manual in dbs['association'].execute('select student, auto, manual from association_association')
            }

            for latexname in Dict[AmcQuestionId, 'to', LatexQuestionName].values():
                for exam, matricule in Dict[AmcStudentId, 'to', Matricule].items():
                    examfull = "{}{}".format(serie, exam)
                    comments = ''
                    qf_match = StandardNames.QF_DIGITS.fullmatch(latexname) 
                    if qf_match and qf_match.group('part') == 'digits': # latexname = QF5digits
                        m = qf_match.groupdict()
                        basename = StandardNames.QF_DIGITS_FORMAT(part='', num=m['num'], serie=m['serie']) # basename = QF5a
                        info = QFInfo(Dict, dbs, seuil, exam, basename)
                        
                        try:
                            values = info.parseQF()
                            assert all(isinstance(values[x], Decimal) for x in ('value', 'mantissa', 'exp'))
                            value = values['value'] # values['mantissa'], values['exp'], values['sign']
                            
                            mark = 0
                            for X in qf_answers[basename]:
                                rules = X.get('rules', ())
                                answer, themin, themax, minus = (X[key] for key in ('exact', 'min', 'max', 'minus'))
                                answer_sign = (0 if answer == 0 else 1 if answer > 0 else -1)
                                
                                if themin <= abs(value) <= themax:
                                    m = 5
                                elif any(themin * Decimal(10) ** i <= abs(value) <= themax * Decimal(10) ** i for i in irange(-20,20)):
                                    m = 3
                                else:
                                    m = 0
                                if 'SignMinus1' in rules and values['sign'] != answer_sign:
                                    m -= 1
                                if minus:
                                    assert minus < 0
                                    m += minus
                                if m < 0:
                                    m = 0
                                mark = max(m, mark)
                                if mark:
                                    break # TakeFirstAnswerGivingMarks
                                
                            comments = (values, qf_answers[basename])
                            annotations = [] # TODO ?
                        
                        except QFInfo.NoMantissa:
                            mark = 0
                        
                        except QFInfo.MultipleTicksInColumn:
                            warning(examfull, matricule, basename, 'MultipleTicksInColumn')
                            mark = 0
                    
                    elif StandardNames.QO.fullmatch(latexname):
                        basename = latexname
                        if latexname not in open_question_source or isinstance(open_question_source[latexname], FromScannedAnnotationsAndMark):
                            try:
                                info = QOInfo(Dict, dbs, seuil, exam, latexname)
                                mark = info.correctionValue()
                                annotations = info.correctionCommentsList()
                            except QOInfo.Error as e:
                                error(examfull, matricule, basename, e.__class__.__name__)
                                errors.append(e)
                                continue
                        else:
                            fmt = open_question_source[latexname]
                            if isinstance(fmt, ReadFromMatriculeMarkCsv):
                                if not fmt.isread:
                                    fmt.read()
                                try:
                                    mark = fmt.Matricule(matricule).to(fmt.Mark)
                                except KeyError:
                                    e = KeyError(f'{matricule} not found in {fmt.csv_files}')
                                    error(examfull, matricule, basename, e.__class__.__name__)
                                    errors.append(e) 
                                    continue
                                annotations = [] # TODO (code already done in send_mail)
                            else:
                                error("{}{}".format(serie, exam), matricule, latexname, 'UnknownOpenQuestionSource')
                                errors.append(UnknownOpenQuestionSource())
                                continue
                    else:
                        continue
                    writer.writerow((examfull, matricule, basename, mark, ''.join(chr(ord('A') + i) for i in annotations), str(comments)))
                    data_marks.append((examfull, matricule, basename, mark))
    
    if errors:
        error('At least one error occured, stopping here.')
        return
    
    # generate pretty xlsx
    # TODO: make it work for series
    
    reductions = {}
    for serie in SERIES:
        for examfull, matricule, basename, mark in data_marks:
            m = StandardNames.QF_SERIE.fullmatch(basename)
            if m:
                m.groupdict().keys() == {'num', 'serie'}
                reduced_name = StandardNames.QF_SERIE_FORMAT(num=m.group('num'), serie='')
                reductions[basename] = reduced_name
    
    all_questions = set()
    student_info = {}
    for examfull, matricule, basename, mark in data_marks:
        if matricule not in student_info:
            student_info[matricule] = {
                'exam': examfull,
                'questions': {},
            }
        else:
            assert student_info[matricule]['exam'] == examfull, f"Student {matricule} has mutiple exams {student_info[matricule]['exam']}, {examfull}!"
            
        student_info[matricule]['questions'][basename] = mark
        all_questions.add(basename) # not mandatory
    
    if len(SERIES) <= 1:
        assert all(student_info[matricule]['questions'].keys() == all_questions for matricule in student_info)
    
    def sort_key(basename):
        first = (1 if basename.startswith('QO') else
                 2 if basename.startswith('QF') else
                 3)
        digits = Re('\d+').findall(basename)
        second = int(digits[0]) if digits else 1000
        return first, second
    
    def sorted_by_key(it):
        return sorted(it, key=sort_key)
    
    def only(it):
        L = list(it)
        if len(L) != 1:
            raise ValueError(str(L))
        return L[0]
    
    def only_or_default(it, *, default=None):
        L = list(it)
        if len(L) > 1:
            raise ValueError(str(L))
        if len(L) == 0:
            return default
        return L[0]
    
    all_questions_without_series = sorted_by_key(set(reductions.get(q,q) for q in all_questions))
    all_possible_questions = set(all_questions_without_series) & set(reductions.values())
    
    with CSVOrXLWriter(OUT_FILE + '_grid', print_created=True) as writer:
        firstrow = ['MATRICULE', 'EXAM'] + list(all_questions_without_series)
        writer.writerow(firstrow)
        for matricule in sorted(map(int, student_info)):
            writer.writerow(
                [matricule, student_info[matricule]['exam']]
                + [
                    student_info[matricule]['questions'][question_not_reduced]
                    for question in all_questions_without_series
                    for question_not_reduced in [
                        question if question in student_info[matricule]['questions'] else
                        only(p for p,q in reductions.items() if q == question and p in student_info[matricule]['questions'])
                    ]
                ])

if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser()
    # subcommand GenerateAnswers, GenerateSrcList, DoAssociationAuto, ComputeMarks, GenerateMarksFromCsv
    args = parser.parse_args()
Пример #4
0
                name=f,
                transinfo='''
                ''',
                postnav='' if not os.path.isfile(pdf_name) else '''
                    <a href="{}">#pdf</a>
                '''.format(pdf_name),
                nav='' if not m else '''
                    <a class="keephash" href="{url_prev}"><img style="width:24px; height:24px; vertical-align: middle;" src="prev.png"/></a>
                    <a class="keephash" href="{url_next}"><img style="width:24px; height:24px; vertical-align: middle;" src="next.png"/></a>
                    <a class="keephash" href="{url_next}">#{name}</a>
                '''.format(
                    name=f,
                    type=typename,
                    url_prev='{}.html'.format(all_grouped[typename].get(
                        (num - 1, t), 'index')),
                    url_next='{}.html'.format(all_grouped[typename].get(
                        (num + 1, t), 'index')),
                ))
            try:
                with open(f + '.html', 'r') as fl:
                    before = fl.read()
            except:
                before = ''
            if res != before:
                modifs.append(f)
                with OutFile(f + '.html') as fl:
                    fl.write(res)
    print('generate_html:', len(modifs),
          'file' + 's' * (len(modifs) != 1) + ' modified' + ':' * bool(modifs),
          ' '.join(modifs))
Пример #5
0
    slides = set_union(info for layer, info in all_infos)

    Format = ("{}.state-{}.svg" if args.state_in_filename else "{}.{}.svg")

    for layer in layers:  # should only be with the layers with {} tag
        layer.setAttribute(
            'style',
            layer.getAttribute('style').replace('display:none',
                                                'display:inline').replace(
                                                    'display: none',
                                                    'display: inline'))

    for slide in slides:
        if args.verbose:
            bits = ['Slide {!r}'.format(slide)]
        new = OutFile(Format.format(svg_filename, slide))
        with new as f:
            for layer, info in all_infos:
                if args.verbose:
                    bits.append(str((slide, layer_names[layer], slide
                                     in info)))
                if slide not in info:
                    root.removeChild(layer)
            f.write(root.toxml())
            for layer, info in reversed(all_infos):
                if slide not in info:
                    root.insertBefore(layer, nexts[layer])
        if args.verbose:
            print_info(', '.join(bits))
Пример #6
0
             fileinfo['name'][lang] if has_info_name else
             simple_name)
 
 if os.path.isfile(filename):
     with open(filename, 'r') as fo:
         prev_str = fo.read()
 else:
     prev_str = ''
 
 next_str = RE_TR_TAG.sub(lambda m: spliti(m.group(1), TR_TAG_SEP, i, 'NOT TRANSLATED ' + spliti(m.group(1), TR_TAG_SEP, 0)), s)
 # ornone = lambda x, y: y if x is None else x
 # next_str = RE_TR.sub(lambda m: ornone(m.group(i+1), m.group(1)), s)
 if prev_str != next_str:
     modified.append(filename)
         
     with OutFile(filename) as fo:
         fo.write(next_str)
     
     if i == 0:
         new = OutFile(basename + ending)
         new.unlock()
         shutil.copy(filename, new.filename)
         new.lock()
         info('Copy', filename, '->', '(read only)', new.filename)
         del new
     
     # TODO: redirects/symlink
     # in: trucs.multilang_as_stuffs.txt
     # trucs.en.txt -> stuff.txt
     # stuff.fr.txt -> trucs.txt
     # trucs.fr.txt -> trucs.txt
if args.file:
    assert args.file.endswith('.txt'), "must be a txt file"

import sys
import re

try:
    from generate_utils import OutFileGreen as OutFile
except ImportError:
    OutFile = open

with (open(args.file) if args.file else sys.stdin) as f:
    L = [x.strip('\n') for x in f]
    
for i in range(len(L)):
    try:
        a,b,c = re.compile('(\d+) (\d+)(.*)').fullmatch(L[i]).groups()
    except AttributeError:
        print('Line {!r} did not match'.format(L[i]))
        continue
    L[i] = a.zfill(2) + ':' + b.zfill(2) + c

transform = ((lambda x: x.replace('<', '‹').replace('>', '›')) if args.replace_lt
             else lambda x:x)

with (OutFile(args.file + '.index', 'w') if args.file else sys.stdout) as f:
    f.write(transform('\n'.join(L)))
    
    
Пример #8
0
#!/usr/bin/env python3
import re

from generate_utils import OutFile

with open('cv.html') as f:
    s = f.read()

R = re.compile('{{(.*?)\|(.*?)}}', re.DOTALL)

for i, lang in enumerate(('fr', 'en')):
    with OutFile('cv.{}.html'.format(lang), 'w') as f:
        f.write(R.sub(lambda m: m.group(i + 1), s))
Пример #9
0
                 ulend='</ul>' if path != '.' else '',
                 cls='root' if path == '.' else '',
                 ind=indent * '    ',
                 name=os.path.basename(path)
                 if not RE0.match(path) else os.path.basename(path[:-3]),
                 sub='\n'.join(
                     map(((1 + indent) * '    ' + '{}').format,
                         map(
                             partial(content, indent=indent + 1),
                             filter(
                                 accepted,
                                 map(
                                     partial(os.path.join, path),
                                     partial(sorted,
                                             key=key)(os.listdir(path))))))))


if __name__ == '__main__':
    with open('template.html') as f:
        template = f.read()

    with open('plan.svg') as f:
        plan_svg_content = f.read()

    with OutFile('index.html') as f:
        f.write(
            template.replace('{% include "plan.svg" %}',
                             plan_svg_content).replace(
                                 '{{ list }}',
                                 content('.', indent=3) + '</section>'))