def compile(expression, project, user): global attrs_to_set global issue_to_change global glob_project global glob_user global issue_created global cleanup global cleanup_asignee global timelogs global issue_changed issue_created = False issue_changed = False cleanup_asignee = OLEA_REPLACE_DEVS attrs_to_set = [] timelogs = [] issue_to_change = "" glob_project = project glob_user = user # check that user has write access to project if not project.developer_allowed(user): raise Exception(u"No user permissions to modify issues in this project") # parse expression lexer = lex.lex(module=olea.lexer) # writes to parsetab.py (this is closed internally) and parser.out (which seems to stay open) # I don't know why debuglog (parser.out) is still open if we provide our own PlyLogger with it's # own file descriptor in that case yacc should not open any files. parser = yacc.yacc() parser.parse(expression, lexer=lexer) # TODO BUG cleanup yacc - close and parser.out, Y TFH is there no destructor doing this for us? # NOTE ^this doesn't seem to be possible - s. comment above # create issue if necessary if issue_created: issue_to_change = Issue(title=issue_to_change, project=glob_project, kanbancol=glob_project.kanbancol.first(), creator=glob_user) issue_to_change.save() if issue_changed: changed_data = signals.fields_to_changed_data(issue_to_change, [tup[0] for tup in attrs_to_set]) # handle timelogging separately for tdiff in timelogs: timelog = Timelog(user=glob_user, issue=issue_to_change, time=tdiff) timelog.save() for attr in attrs_to_set: # process all parsed attributes to change field = issue_to_change.__getattribute__(attr[0]) if str(type(field)).startswith("<class 'django.db.models"): # cleanup assignee before setting first new assignee if attr[0] == "assignee" and cleanup_asignee: cleanup_asignee = False field.clear() # we have a related field -> call add field.add(attr[1]) else: # no db model field, simply assign value issue_to_change.__setattr__(attr[0], attr[1]) issue_to_change.save() if issue_created: signals.create.send(sender=Issue, instance=issue_to_change, user=user) if not issue_created and issue_changed: signals.modify.send(sender=Issue, instance=issue_to_change, user=user, changed_data=changed_data)