def load_data(): "Load data from all agendas using orgnode" db = [] for agenda in agenda_files: path = os.path.join(base, agenda) db += orgnode.makelist(path, todo_default=todos) return db
def parseOrgFile(self, result, filename): fn = os.path.join(self.dir, filename) nodes = Orgnode.makelist(fn) parents = list() for node in nodes: lvl = node.Level() while len(parents) >= lvl: parents.pop() if node.Todo() == 'TODO': result.append({'title': node.Heading(), 'deadline': node.Deadline(), 'scheduled': node.Scheduled(), 'link': 'file://' + fn, 'subtitle': subtitle(parents)}) parents.append(node) return result
def parseOrgFile(self, result, filename): fn = os.path.join(self.dir, filename) nodes = Orgnode.makelist(fn) parents = list() for node in nodes: lvl = node.Level() while len(parents) >= lvl: parents.pop() if node.Todo() == 'TODO': result.append({ 'title': node.Heading(), 'deadline': node.Deadline(), 'scheduled': node.Scheduled(), 'link': 'file://' + fn, 'subtitle': subtitle(parents) }) parents.append(node) return result
import Orgnode, datetime today = datetime.date.today() print "Daily plan for", today print "-------------------------\n" filename = "c:/cygwin/home/git/orgfiles/organizer.org" nodelist = Orgnode.makelist(filename) for n in nodelist: if n.Property("CATEGORY") == "Project": print "[ ] %s (%s)" % (n.Heading(), n.__repr__()) for x in nodelist: prin 'hell'
#!/usr/bin/env python # encoding: utf-8 import Orgnode, datetime, os, time delta = datetime.date.today() + datetime.timedelta(days=5) filename = "/home/amaral/.agenda.org" nodelist = Orgnode.makelist(filename) #print nodelist warn_list = [] for n in nodelist: if n.Deadline().__str__() != '' and n.Deadline() <= delta: head = n.Heading() warn_list.append(head) title = "Deadlines" warn_string = "" for v in warn_list: warn_string += v + "\n" if len(warn_string) > 0: warn_string = warn_string[:-1] cmd = "notify-send " + title + " " + "\'" + warn_string + "\'" print cmd if len(warn_string) > 0:
def load_org_file(): """ Create a list of org objects. """ nodelist = Orgnode.makelist(ORG_FILE) return nodelist
# require: pip install feedgen # require: python Orgnode HTTP_PREFIX="https://dl.dropboxusercontent.com/u/28458830/Podcast" import os import sys import time, pytz import Orgnode from feedgen.feed import FeedGenerator fg = FeedGenerator() fg.load_extension('podcast') nodelist = Orgnode.makelist(sys.argv[1]) info = nodelist[0] properties = info.Properties() fg.podcast.itunes_category('Technology', 'Podcasting') fg.title(info.Heading()) fg.author( {'name':properties['author'],'email':properties['email']} ) fg.id(properties["id"]) fg.link( href='http://whoomin.marboo.biz', rel='alternate' ) fg.logo(properties["logo"]) fg.subtitle(properties["subtitle"]) fg.link(href=properties["link"], rel='self' ) fg.language(properties["language"]) fg.image(properties["image"], height="140", width="140") fg.rights(properties["copyright"])
def __main__(org, csv='', gantt='', start_date='', end_date='', today='', debug=False, resource=False, svg='project', filter='', availibility='', warning=False, one_line_for_tasks=False, scale='d'): """ org2gantt.py org: org-mode filename gantt: output python-gantt filename (if not specified, code is directly executed) svg: svg base name for files output resource: generate resources graph availibility: check resource availibility between start_date and end_date one_line_for_tasks: generate graph for each resources with all tasks on the same line start_date: force start date for output or used for checking resource availibility (format : 'yyyy-mm-dd' or '-1w' (from today)) end_date: force end date for output or used for checking resource availibility (format : 'yyyy-mm-dd' or '+2d' (from today)) today: force today date (format : 'yyyy-mm-dd') filter: tag or list of tags separated by comas to filter scale: scale for the graph (d: days, w: weeks, m: months, q: quaterly) csv: filename for csv output debug: debug warning: set warning level for creating gantt Example : python org2gantt.py TEST.org Written by : Alexandre Norman <norman at xael.org> """ gantt_code = """#!/usr/bin/env python3 # -*- coding: utf-8 -*- import datetime import gantt """ global __LOG__ if debug: _init_log_to_sysout(logging.DEBUG) gantt_code += "\nimport logging\ngantt.init_log_to_sysout(level=logging.DEBUG)\n" elif warning: _init_log_to_sysout(logging.WARNING) gantt_code += "\nimport logging\ngantt.init_log_to_sysout(level=logging.WARNING)" else: _init_log_to_sysout() gantt_code += "\nimport logging\ngantt.init_log_to_sysout(level=logging.CRITICAL)" if not os.path.isfile(org): __LOG__.error('** File do not exist : {0}'.format(org)) sys.exit(1) # load orgfile nodes = Orgnode.makelist(org) __LOG__.debug('_analyse_nodes ({0})'.format({'nodes':nodes})) # Get all todo items LISTE_TODOS = {'TODO':None, 'DONE':None, 'MILESTONE':None} with open(org) as f: for line in f.readlines(): if line[:10] == '#+SEQ_TODO': kwlist = re.findall('([A-Z]+)\(', line) for kw in kwlist: LISTE_TODOS[kw] = None # Find CONFIGURATION in heading n_configuration = None for n in nodes: if n.headline.strip() == "CONFIGURATION": n_configuration = n planning_start_date = None planning_end_date = None planning_today_date = _iso_date_to_datetime(str(datetime.date.today())) my_today = datetime.date.today() bar_color = {'TODO':'#FFFF90'} if one_line_for_tasks and not resource: __LOG__.critical('option one_line_for_tasks must be used in conjonction with resource graph generation') sys.exit(-1) global LISTE_IGNORE_TAGS LISTE_IGNORE_TAGS = [] # List of tag to filter global LISTE_FILTER if filter != '': LISTE_FILTER = filter.split(',') __LOG__.debug('LISTE_FILTER : {0}'.format(LISTE_FILTER)) # Generate code for configuration if n_configuration is not None: for t in LISTE_TODOS: if 'color_{0}'.format(t) in n_configuration.properties: bar_color[t] = n_configuration.properties['color_{0}'.format(t)].strip() if 'ignore_tags' in n_configuration.properties: LISTE_IGNORE_TAGS = n_configuration.properties['ignore_tags'].split() if not one_line_for_tasks and ('one_line_for_tasks' in n_configuration.properties and n_configuration.properties['one_line_for_tasks'].strip() == 't'): one_line_for_tasks = True if today != '': planning_today_date = _iso_date_to_datetime(today) y, m, d = today.split('-') my_today = datetime.date(int(y), int(m), int(d)) elif 'today' in n_configuration.properties: dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', n_configuration.properties['today']) if len(dates) == 1: planning_today_date = _iso_date_to_datetime(dates[0]) y, m, d = dates[0].split('-') my_today = datetime.date(int(y), int(m), int(d)) if start_date != '': dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', start_date) if len(dates) == 1: y, m, d = start_date.split('-') planning_start_date = _iso_date_to_datetime(start_date) elif start_date.startswith('-') or start_date.startswith('+'): sign = start_date[0] qte = int(start_date[1:-1]) what = start_date[-1] sign = -1*(sign=='-') + 1*(sign=='+') if what == 'd': planning_start_date = _iso_date_to_datetime(str(my_today + datetime.timedelta(days=qte*sign))) elif what == 'w': planning_start_date = _iso_date_to_datetime(str(my_today + datetime.timedelta(weeks=qte*sign))) else: __LOG__.critical('Unknown start date format : "{0}". Valid format are yyyy-mm-dd or [-+]x[dw]'.format(start_date)) sys.exit(-1) elif 'start_date' in n_configuration.properties: # find date and use it dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', n_configuration.properties['start_date']) if len(dates) == 1: planning_start_date = _iso_date_to_datetime(dates[0]) # find +1m elif n_configuration.properties['start_date'].startswith('-') or n_configuration.properties['start_date'].startswith('+'): sign = n_configuration.properties['start_date'][0] qte = int(n_configuration.properties['start_date'][1:-1]) what = n_configuration.properties['start_date'][-1] sign = -1*(sign=='-') + 1*(sign=='+') if what == 'd': planning_start_date = _iso_date_to_datetime(str(my_today + datetime.timedelta(days=qte*sign))) elif what == 'w': planning_start_date = _iso_date_to_datetime(str(my_today + datetime.timedelta(weeks=qte*sign))) else: __LOG__.critical('Unknown start date format : "{0}". Valid format are yyyy-mm-dd or [-+]x[dw]'.format(start_date)) sys.exit(-1) if end_date != '': dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', end_date) if len(dates) == 1: y, m, d = end_date.split('-') planning_end_date = _iso_date_to_datetime(end_date) # find +1m elif end_date.startswith('-') or end_date.startswith('+'): sign = end_date[0] qte = int(end_date[1:-1]) what = end_date[-1] sign = -1*(sign=='-') + 1*(sign=='+') if what == 'd': planning_end_date = _iso_date_to_datetime(str(my_today + datetime.timedelta(days=qte*sign))) elif what == 'w': planning_end_date = _iso_date_to_datetime(str(my_today + datetime.timedelta(weeks=qte*sign))) else: __LOG__.critical('Unknown end date format : "{0}". Valid format are yyyy-mm-dd or [-+]x[dw]'.format(end_date)) sys.exit(-1) elif 'end_date' in n_configuration.properties: # find date and use it dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', n_configuration.properties['end_date']) if len(dates) == 1: planning_end_date = _iso_date_to_datetime(dates[0]) # find +1m elif n_configuration.properties['end_date'].startswith('-') or n_configuration.properties['end_date'].startswith('+'): sign = n_configuration.properties['end_date'][0] qte = int(n_configuration.properties['end_date'][1:-1]) what = n_configuration.properties['end_date'][-1] sign = -1*(sign=='-') + 1*(sign=='+') if what == 'd': planning_end_date = _iso_date_to_datetime(str(my_today + datetime.timedelta(days=qte*sign))) elif what == 'w': planning_end_date = _iso_date_to_datetime(str(my_today + datetime.timedelta(weeks=qte*sign))) else: __LOG__.critical('Unknown end date format : "{0}". Valid format are yyyy-mm-dd or [-+]x[dw]'.format(end_date)) sys.exit(-1) if eval(planning_end_date) <= eval(planning_start_date): __LOG__.critical('planning_end_date [{0}] is before planning_start_date [{1}]...'.format(planning_end_date, planning_start_date)) sys.exit(-1) if scale != '': scale_ref = { 'd': 'DRAW_WITH_DAILY_SCALE', 'w': 'DRAW_WITH_WEEKLY_SCALE', 'm': 'DRAW_WITH_MONTHLY_SCALE', 'q': 'DRAW_WITH_QUATERLY_SCALE', } try: scale_name = scale_ref[scale] except KeyError: __LOG__.critical('unknown scale {0}'.format(scale)) sys.exit(-1) else: __LOG__.info('drawing with scale : {0}'.format(scale_name)) else: scale_name = 'DRAW_WITH_DAILY_SCALE' __LOG__.debug('List of ignored tags : {0}'.format(LISTE_IGNORE_TAGS)) # Find RESOURCES in heading n_resources = [] resources_id = [] found = False plevel = 0 for n in nodes: if found == True and n.level > plevel: n_resources.append(n) elif found == True and n.level <= plevel: break if found == False and n.headline.strip() == "RESOURCES": found = True plevel = n.level # Generate code for resources gantt_code += "\n#### Resources \n" next_level = 0 current_level = 0 current_group = None for nr, r in enumerate(n_resources): r = n_resources[nr] rname = r.headline.strip().replace("'","_") try: rid = r.properties['resource_id'].strip() except KeyError: rid = 'r_'+str(uuid.uuid4()).replace('-', '_') if rid in resources_id: __LOG__.critical('** Duplicate resource_id: [{0}]'.format(rid)) sys.exit(1) resources_id.append(rid) if ' ' in rid: __LOG__.critical('** Space in resource_id: [{0}]'.format(rid)) sys.exit(1) new_group_this_turn = False current_level = r.level if nr < len(n_resources) - 2: next_level = n_resources[nr+1].level # Group mode if current_level < next_level: gantt_code += "{0} = gantt.GroupOfResources('{1}')\n".format(rid, rname) current_group = rid new_group_this_turn = True # Resource else: gantt_code += "{0} = gantt.Resource(name='{0}', fullname='{1}')\n".format(rid, rname) # Vacations in body of node for line in r.body.split('\n'): if line.startswith('-'): dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', line) if len(dates) == 2: start, end = dates gantt_code += "{0}.add_vacations(dfrom={1}, dto={2})\n".format(rid, _iso_date_to_datetime(start), _iso_date_to_datetime(end)) elif len(dates) == 1: start = dates[0] gantt_code += "{0}.add_vacations(dfrom={1})\n".format(rid, _iso_date_to_datetime(start)) else: if line != '' and not line.strip().startswith(':'): __LOG__.warning("Unknown resource line : {0}".format(line)) if new_group_this_turn == False and current_group is not None: gantt_code += "{0}.add_resource(resource={1})\n".format(current_group, rid) # end of group if current_level > next_level: current_group = None # Find VACATIONS in heading n_vacations = None for n in nodes: if n.headline.strip() == "VACATIONS": n_vacations = n # Generate code for vacations gantt_code += "\n#### Vacations \n" if n_vacations is not None: for line in n_vacations.body.split('\n'): if line.startswith('-'): dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', line) if len(dates) == 2: start, end = dates gantt_code += "gantt.add_vacations({0}, {1})\n".format(_iso_date_to_datetime(start), _iso_date_to_datetime(end)) elif len(dates) == 1: start = dates[0] gantt_code += "gantt.add_vacations({0})\n".format(_iso_date_to_datetime(start)) else: if line != '': __LOG__.warning("Unknown vacation line : {0}".format(line)) # Generate code for Projects gantt_code += "\n#### Projects \n" # Mother of all gantt_code += "project = gantt.Project(color='{0}')\n".format(bar_color['TODO']) prj_found = False tasks_name = [] # for inheriting project, ORDERED, color, resources prop_inherits = [] prev_task = None no_gantt_level = None late_dependencies = [] for nr, n in enumerate(nodes): n = nodes[nr] __LOG__.debug('Analysing {0}'.format(n.headline)) # it's a task / level 1 if n.level == 1 \ and not n.headline.strip() in ('RESOURCES', 'VACATIONS', 'CONFIGURATION') \ and 'no_gantt' not in n.tags \ and n.todo in LISTE_TODOS: __LOG__.debug(' task / level 1') prop_inherits = [] prj_found = True prev_task = None no_gantt_level = None # Add task nt = make_task_from_node(n) if nt is None: continue name, code, dependencies = nt late_dependencies.append([name, dependencies]) if name in tasks_name: __LOG__.critical("Duplicate task id: {0}".format(name)) sys.exit(1) else: tasks_name.append(name) gantt_code += code gantt_code += "project.add_task(task_{0})\n".format(name) elif 'no_gantt' in n.tags: if no_gantt_level is not None and no_gantt_level > n.level: no_gantt_level = n.level __LOG__.debug('no_gantt_tag {0}'.format(n.level)) elif no_gantt_level is None: no_gantt_level = n.level __LOG__.debug('no_gantt_tag {0}'.format(n.level)) # new project heading # Not a task, it's a project # it should have children elif n.level >= 1 \ and not n.headline.strip() in ('RESOURCES', 'VACATIONS', 'CONFIGURATION') \ and 'no_gantt' not in n.tags \ and not n.todo in LISTE_TODOS: if no_gantt_level is not None and n.level > no_gantt_level: __LOG__.debug('no_gantt_tag {0}/{1}'.format(n.level, no_gantt_level)) continue else: __LOG__.debug('remove no_gantt_tag {0}/{1}'.format(n.level, no_gantt_level)) no_gantt_level = None if n.level == 1: __LOG__.debug('** cleanup prop_inherits') prev_task = None prop_inherits = [] if n.level > 1 and prj_found == False: __LOG__.debug(' do not keep') continue if len(prop_inherits) >= n.level: __LOG__.debug(' go one level up') prop_inherits = prop_inherits[:-1] __LOG__.debug(' new project heading') gantt_code += "###### Project {0} \n".format(n.headline.strip()) try: name = n.properties['task_id'].strip() except KeyError: name = str(uuid.uuid4()).replace('-', '_') __LOG__.debug('{0}'.format(prop_inherits)) if bar_color['TODO'] is not None: gantt_code += "project_{0} = gantt.Project(name='{1}', color='{2}')\n".format(name, n.headline.strip().replace("'", '_'), bar_color['TODO']) else: gantt_code += "project_{0} = gantt.Project(name='{1}', color=None)\n".format(name, n.headline.strip().replace("'", '_')) try: gantt_code += "project_{0}.add_task(project_{1})\n".format(prop_inherits[-1]['project_id'], name) except KeyError: gantt_code += "project.add_task(project_{0})\n".format(name) except IndexError: gantt_code += "project.add_task(project_{0})\n".format(name) if n.level == 1: prop_inherits = [] # Inherits ORDERED if 'ORDERED' in n.properties and n.properties['ORDERED'] == 't': ordered = True else: if len(prop_inherits) > 0: ordered = prop_inherits[-1]['ordered'] else: prev_task = None ordered = False color = copy.deepcopy(bar_color) # Inherits color if 'color' in n.properties: color['TODO'] = n.properties['color'] else: if len(prop_inherits) > 0: color['TODO'] = prop_inherits[-1]['color']['TODO'] else: color['TODO'] = bar_color['TODO'] # Inherits resources # Resources as tag if len(n.tags) > 0: # For inherit all tags #ress = "{0}".format(["{0}".format(x) for x in n.tags.keys() if x not in LISTE_IGNORE_TAGS]).replace("'", "") ress = "{0}".format(["{0}".format(x) for x in n.tags.keys()]).replace("'", "") # Resources as properties elif 'allocate' in n.properties: ress = "{0}".format(["{0}".format(x) for x in n.properties['allocate'].replace(",", " ").split()]).replace("'", "") else: try: ress = prop_inherits[-1]['resources'] except KeyError: ress = None except IndexError: ress = None prop_inherits.append({'ordered':ordered, 'color':color, 'project_id':name, 'resources':ress}) prj_found = True # It's a task elif n.level >= 1 \ and prj_found == True \ and not n.headline.strip() in ('RESOURCES', 'VACATIONS', 'CONFIGURATION') \ and 'no_gantt' not in n.tags \ and n.todo in LISTE_TODOS: __LOG__.debug(' new task under project {0}'.format(n.headline)) if n.level == 1: prev_task = None prop_inherits = [] __LOG__.debug(' clean prop_inherits') if no_gantt_level is not None and n.level > no_gantt_level: __LOG__.debug('no_gantt_tag {0}/{1}'.format(n.level, no_gantt_level)) continue else: __LOG__.debug('remove no_gantt_tag {0}/{1}'.format(n.level, no_gantt_level)) no_gantt_level = None if n.level > 1 and len(prop_inherits) < n.level - 1: __LOG__.critical('pb in structure : task "{0}" do not belong to a project but a task - possible inheritance problem'.format(n.headline)) if len(prop_inherits) >= n.level: __LOG__.debug(' go one level up') prop_inherits = prop_inherits[:-1] __LOG__.debug(' bar_color {0}'.format(bar_color)) # Add task if len(prop_inherits) > 0: nt = make_task_from_node(n, prop_inherits[-1], prev_task) if nt is None: continue name, code, dependencies = nt late_dependencies.append([name, dependencies]) else: nt = make_task_from_node(n, [], prev_task) if nt is None: continue name, code, dependencies = nt late_dependencies.append([name, dependencies]) if name in tasks_name: __LOG__.critical("Duplicate task id: {0}".format(name)) sys.exit(1) else: tasks_name.append(name) prev_task = name gantt_code += code #gantt_code += "project.add_task(task_{0})\n".format(name) try: gantt_code += "project_{0}.add_task(task_{1})\n".format(prop_inherits[-1]['project_id'], name) except KeyError: gantt_code += "project.add_task(task_{0})\n".format(name) except IndexError: gantt_code += "project.add_task(task_{0})\n".format(name) else: prj_found = False prop_inherits = [] __LOG__.debug(' nothing') gantt_code += "\n#### Dependencies \n" # Late dependencies for name, dep in late_dependencies: gantt_code += "task_{0}.add_depends(depends_of={1})\n".format(name, dep) if availibility == '': # Full project gantt_code += "\n#### Outputs \n" gantt_code += "project.make_svg_for_tasks(filename='{3}.svg', today={0}, start={1}, end={2}, scale=gantt.{4})\n".format(planning_today_date, planning_start_date, planning_end_date, svg, scale_name) # Generate resource graph if resource: gantt_code += "project.make_svg_for_resources(filename='{4}_resources.svg', today={0}, start={1}, end={2}, one_line_for_tasks={3}, filter='{5}', scale=gantt.{6})\n".format(planning_today_date, planning_start_date, planning_end_date, one_line_for_tasks, svg, filter, scale_name) else: gantt_code += "\n#### Check resource availibility \n" gantt_code += "print({0}.is_vacant(from_date={1}, to_date={2}))\n".format(availibility, planning_start_date, planning_end_date) if csv != '': gantt_code += "\n#### CSV Outputs \n" gantt_code += "project.csv('{0}')\n".format(csv) # write Gantt code if gantt == '': import gantt exec(gantt_code) else: open(gantt, 'w').write(gantt_code) __LOG__.debug("All done. Exiting.") return
def __main__(org, csv='', gantt='', start_date='', end_date='', today='', debug=False, resource=False, svg='project', filter='', availibility='', warning=False, one_line_for_tasks=False, scale='d'): """ org2gantt.py org: org-mode filename gantt: output python-gantt filename (if not specified, code is directly executed) svg: svg base name for files output resource: generate resources graph availibility: check resource availibility between start_date and end_date one_line_for_tasks: generate graph for each resources with all tasks on the same line start_date: force start date for output or used for checking resource availibility (format : 'yyyy-mm-dd' or '-1w' (from today)) end_date: force end date for output or used for checking resource availibility (format : 'yyyy-mm-dd' or '+2d' (from today)) today: force today date (format : 'yyyy-mm-dd') filter: tag or list of tags separated by comas to filter scale: scale for the graph (d: days, w: weeks, m: months, q: quaterly) csv: filename for csv output debug: debug warning: set warning level for creating gantt Example : python org2gantt.py TEST.org Written by : Alexandre Norman <norman at xael.org> """ gantt_code = """#!/usr/bin/env python3 # -*- coding: utf-8 -*- import datetime import gantt """ global __LOG__ if debug: _init_log_to_sysout(logging.DEBUG) gantt_code += "\nimport logging\ngantt.init_log_to_sysout(level=logging.DEBUG)\n" elif warning: _init_log_to_sysout(logging.WARNING) gantt_code += "\nimport logging\ngantt.init_log_to_sysout(level=logging.WARNING)" else: _init_log_to_sysout() gantt_code += "\nimport logging\ngantt.init_log_to_sysout(level=logging.CRITICAL)" if not os.path.isfile(org): __LOG__.error('** File do not exist : {0}'.format(org)) sys.exit(1) # load orgfile nodes = Orgnode.makelist(org) __LOG__.debug('_analyse_nodes ({0})'.format({'nodes': nodes})) # Get all todo items LISTE_TODOS = {'TODO': None, 'DONE': None, 'MILESTONE': None} with open(org) as f: for line in f.readlines(): if line[:10] == '#+SEQ_TODO': kwlist = re.findall('([A-Z]+)\(', line) for kw in kwlist: LISTE_TODOS[kw] = None # Find CONFIGURATION in heading n_configuration = None for n in nodes: if n.headline.strip() == "CONFIGURATION": n_configuration = n planning_start_date = None planning_end_date = None planning_today_date = _iso_date_to_datetime(str(datetime.date.today())) my_today = datetime.date.today() bar_color = {'TODO': '#FFFF90'} if one_line_for_tasks and not resource: __LOG__.critical( 'option one_line_for_tasks must be used in conjonction with resource graph generation' ) sys.exit(-1) global LISTE_IGNORE_TAGS LISTE_IGNORE_TAGS = [] # List of tag to filter global LISTE_FILTER if filter != '': LISTE_FILTER = filter.split(',') __LOG__.debug('LISTE_FILTER : {0}'.format(LISTE_FILTER)) # Generate code for configuration if n_configuration is not None: for t in LISTE_TODOS: if 'color_{0}'.format(t) in n_configuration.properties: bar_color[t] = n_configuration.properties['color_{0}'.format( t)].strip() if 'ignore_tags' in n_configuration.properties: LISTE_IGNORE_TAGS = n_configuration.properties[ 'ignore_tags'].split() if not one_line_for_tasks and ( 'one_line_for_tasks' in n_configuration.properties and n_configuration.properties['one_line_for_tasks'].strip() == 't'): one_line_for_tasks = True if today != '': planning_today_date = _iso_date_to_datetime(today) y, m, d = today.split('-') my_today = datetime.date(int(y), int(m), int(d)) elif 'today' in n_configuration.properties: dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', n_configuration.properties['today']) if len(dates) == 1: planning_today_date = _iso_date_to_datetime(dates[0]) y, m, d = dates[0].split('-') my_today = datetime.date(int(y), int(m), int(d)) if start_date != '': dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', start_date) if len(dates) == 1: y, m, d = start_date.split('-') planning_start_date = _iso_date_to_datetime(start_date) elif start_date.startswith('-') or start_date.startswith('+'): sign = start_date[0] qte = int(start_date[1:-1]) what = start_date[-1] sign = -1 * (sign == '-') + 1 * (sign == '+') if what == 'd': planning_start_date = _iso_date_to_datetime( str(my_today + datetime.timedelta(days=qte * sign))) elif what == 'w': planning_start_date = _iso_date_to_datetime( str(my_today + datetime.timedelta(weeks=qte * sign))) else: __LOG__.critical( 'Unknown start date format : "{0}". Valid format are yyyy-mm-dd or [-+]x[dw]' .format(start_date)) sys.exit(-1) elif 'start_date' in n_configuration.properties: # find date and use it dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', n_configuration.properties['start_date']) if len(dates) == 1: planning_start_date = _iso_date_to_datetime(dates[0]) # find +1m elif n_configuration.properties['start_date'].startswith( '-' ) or n_configuration.properties['start_date'].startswith('+'): sign = n_configuration.properties['start_date'][0] qte = int(n_configuration.properties['start_date'][1:-1]) what = n_configuration.properties['start_date'][-1] sign = -1 * (sign == '-') + 1 * (sign == '+') if what == 'd': planning_start_date = _iso_date_to_datetime( str(my_today + datetime.timedelta(days=qte * sign))) elif what == 'w': planning_start_date = _iso_date_to_datetime( str(my_today + datetime.timedelta(weeks=qte * sign))) else: __LOG__.critical( 'Unknown start date format : "{0}". Valid format are yyyy-mm-dd or [-+]x[dw]' .format(start_date)) sys.exit(-1) if end_date != '': dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', end_date) if len(dates) == 1: y, m, d = end_date.split('-') planning_end_date = _iso_date_to_datetime(end_date) # find +1m elif end_date.startswith('-') or end_date.startswith('+'): sign = end_date[0] qte = int(end_date[1:-1]) what = end_date[-1] sign = -1 * (sign == '-') + 1 * (sign == '+') if what == 'd': planning_end_date = _iso_date_to_datetime( str(my_today + datetime.timedelta(days=qte * sign))) elif what == 'w': planning_end_date = _iso_date_to_datetime( str(my_today + datetime.timedelta(weeks=qte * sign))) else: __LOG__.critical( 'Unknown end date format : "{0}". Valid format are yyyy-mm-dd or [-+]x[dw]' .format(end_date)) sys.exit(-1) elif 'end_date' in n_configuration.properties: # find date and use it dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', n_configuration.properties['end_date']) if len(dates) == 1: planning_end_date = _iso_date_to_datetime(dates[0]) # find +1m elif n_configuration.properties['end_date'].startswith( '-') or n_configuration.properties['end_date'].startswith( '+'): sign = n_configuration.properties['end_date'][0] qte = int(n_configuration.properties['end_date'][1:-1]) what = n_configuration.properties['end_date'][-1] sign = -1 * (sign == '-') + 1 * (sign == '+') if what == 'd': planning_end_date = _iso_date_to_datetime( str(my_today + datetime.timedelta(days=qte * sign))) elif what == 'w': planning_end_date = _iso_date_to_datetime( str(my_today + datetime.timedelta(weeks=qte * sign))) else: __LOG__.critical( 'Unknown end date format : "{0}". Valid format are yyyy-mm-dd or [-+]x[dw]' .format(end_date)) sys.exit(-1) if eval(planning_end_date) <= eval(planning_start_date): __LOG__.critical( 'planning_end_date [{0}] is before planning_start_date [{1}]...'. format(planning_end_date, planning_start_date)) sys.exit(-1) if scale != '': scale_ref = { 'd': 'DRAW_WITH_DAILY_SCALE', 'w': 'DRAW_WITH_WEEKLY_SCALE', 'm': 'DRAW_WITH_MONTHLY_SCALE', 'q': 'DRAW_WITH_QUATERLY_SCALE', } try: scale_name = scale_ref[scale] except KeyError: __LOG__.critical('unknown scale {0}'.format(scale)) sys.exit(-1) else: __LOG__.info('drawing with scale : {0}'.format(scale_name)) else: scale_name = 'DRAW_WITH_DAILY_SCALE' __LOG__.debug('List of ignored tags : {0}'.format(LISTE_IGNORE_TAGS)) # Find RESOURCES in heading n_resources = [] resources_id = [] found = False plevel = 0 for n in nodes: if found == True and n.level > plevel: n_resources.append(n) elif found == True and n.level <= plevel: break if found == False and n.headline.strip() == "RESOURCES": found = True plevel = n.level # Generate code for resources gantt_code += "\n#### Resources \n" next_level = 0 current_level = 0 current_group = None for nr, r in enumerate(n_resources): r = n_resources[nr] rname = r.headline.strip().replace("'", "_") try: rid = r.properties['resource_id'].strip() except KeyError: rid = 'r_' + str(uuid.uuid4()).replace('-', '_') if rid in resources_id: __LOG__.critical('** Duplicate resource_id: [{0}]'.format(rid)) sys.exit(1) resources_id.append(rid) if ' ' in rid: __LOG__.critical('** Space in resource_id: [{0}]'.format(rid)) sys.exit(1) new_group_this_turn = False current_level = r.level if nr < len(n_resources) - 2: next_level = n_resources[nr + 1].level # Group mode if current_level < next_level: gantt_code += "{0} = gantt.GroupOfResources('{1}')\n".format( rid, rname) current_group = rid new_group_this_turn = True # Resource else: gantt_code += "{0} = gantt.Resource(name='{0}', fullname='{1}')\n".format( rid, rname) # Vacations in body of node for line in r.body.split('\n'): if line.startswith('-'): dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', line) if len(dates) == 2: start, end = dates gantt_code += "{0}.add_vacations(dfrom={1}, dto={2})\n".format( rid, _iso_date_to_datetime(start), _iso_date_to_datetime(end)) elif len(dates) == 1: start = dates[0] gantt_code += "{0}.add_vacations(dfrom={1})\n".format( rid, _iso_date_to_datetime(start)) else: if line != '' and not line.strip().startswith(':'): __LOG__.warning("Unknown resource line : {0}".format(line)) if new_group_this_turn == False and current_group is not None: gantt_code += "{0}.add_resource(resource={1})\n".format( current_group, rid) # end of group if current_level > next_level: current_group = None # Find VACATIONS in heading n_vacations = None for n in nodes: if n.headline.strip() == "VACATIONS": n_vacations = n # Generate code for vacations gantt_code += "\n#### Vacations \n" if n_vacations is not None: for line in n_vacations.body.split('\n'): if line.startswith('-'): dates = re.findall('[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}', line) if len(dates) == 2: start, end = dates gantt_code += "gantt.add_vacations({0}, {1})\n".format( _iso_date_to_datetime(start), _iso_date_to_datetime(end)) elif len(dates) == 1: start = dates[0] gantt_code += "gantt.add_vacations({0})\n".format( _iso_date_to_datetime(start)) else: if line != '': __LOG__.warning("Unknown vacation line : {0}".format(line)) # Generate code for Projects gantt_code += "\n#### Projects \n" # Mother of all gantt_code += "project = gantt.Project(color='{0}')\n".format( bar_color['TODO']) prj_found = False tasks_name = [] # for inheriting project, ORDERED, color, resources prop_inherits = [] prev_task = None no_gantt_level = None late_dependencies = [] for nr, n in enumerate(nodes): n = nodes[nr] __LOG__.debug('Analysing {0}'.format(n.headline)) # it's a task / level 1 if n.level == 1 \ and not n.headline.strip() in ('RESOURCES', 'VACATIONS', 'CONFIGURATION') \ and 'no_gantt' not in n.tags \ and n.todo in LISTE_TODOS: __LOG__.debug(' task / level 1') prop_inherits = [] prj_found = True prev_task = None no_gantt_level = None # Add task nt = make_task_from_node(n) if nt is None: continue name, code, dependencies = nt late_dependencies.append([name, dependencies]) if name in tasks_name: __LOG__.critical("Duplicate task id: {0}".format(name)) sys.exit(1) else: tasks_name.append(name) gantt_code += code gantt_code += "project.add_task(task_{0})\n".format(name) elif 'no_gantt' in n.tags: if no_gantt_level is not None and no_gantt_level > n.level: no_gantt_level = n.level __LOG__.debug('no_gantt_tag {0}'.format(n.level)) elif no_gantt_level is None: no_gantt_level = n.level __LOG__.debug('no_gantt_tag {0}'.format(n.level)) # new project heading # Not a task, it's a project # it should have children elif n.level >= 1 \ and not n.headline.strip() in ('RESOURCES', 'VACATIONS', 'CONFIGURATION') \ and 'no_gantt' not in n.tags \ and not n.todo in LISTE_TODOS: if no_gantt_level is not None and n.level > no_gantt_level: __LOG__.debug('no_gantt_tag {0}/{1}'.format( n.level, no_gantt_level)) continue else: __LOG__.debug('remove no_gantt_tag {0}/{1}'.format( n.level, no_gantt_level)) no_gantt_level = None if n.level == 1: __LOG__.debug('** cleanup prop_inherits') prev_task = None prop_inherits = [] if n.level > 1 and prj_found == False: __LOG__.debug(' do not keep') continue if len(prop_inherits) >= n.level: __LOG__.debug(' go one level up') prop_inherits = prop_inherits[:-1] __LOG__.debug(' new project heading') gantt_code += "###### Project {0} \n".format(n.headline.strip()) try: name = n.properties['task_id'].strip() except KeyError: name = str(uuid.uuid4()).replace('-', '_') __LOG__.debug('{0}'.format(prop_inherits)) if bar_color['TODO'] is not None: gantt_code += "project_{0} = gantt.Project(name='{1}', color='{2}')\n".format( name, n.headline.strip().replace("'", '_'), bar_color['TODO']) else: gantt_code += "project_{0} = gantt.Project(name='{1}', color=None)\n".format( name, n.headline.strip().replace("'", '_')) try: gantt_code += "project_{0}.add_task(project_{1})\n".format( prop_inherits[-1]['project_id'], name) except KeyError: gantt_code += "project.add_task(project_{0})\n".format(name) except IndexError: gantt_code += "project.add_task(project_{0})\n".format(name) if n.level == 1: prop_inherits = [] # Inherits ORDERED if 'ORDERED' in n.properties and n.properties['ORDERED'] == 't': ordered = True else: if len(prop_inherits) > 0: ordered = prop_inherits[-1]['ordered'] else: prev_task = None ordered = False color = copy.deepcopy(bar_color) # Inherits color if 'color' in n.properties: color['TODO'] = n.properties['color'] else: if len(prop_inherits) > 0: color['TODO'] = prop_inherits[-1]['color']['TODO'] else: color['TODO'] = bar_color['TODO'] # Inherits resources # Resources as tag if len(n.tags) > 0: # For inherit all tags #ress = "{0}".format(["{0}".format(x) for x in n.tags.keys() if x not in LISTE_IGNORE_TAGS]).replace("'", "") ress = "{0}".format(["{0}".format(x) for x in n.tags.keys()]).replace("'", "") # Resources as properties elif 'allocate' in n.properties: ress = "{0}".format([ "{0}".format(x) for x in n.properties['allocate'].replace( ",", " ").split() ]).replace("'", "") else: try: ress = prop_inherits[-1]['resources'] except KeyError: ress = None except IndexError: ress = None prop_inherits.append({ 'ordered': ordered, 'color': color, 'project_id': name, 'resources': ress }) prj_found = True # It's a task elif n.level >= 1 \ and prj_found == True \ and not n.headline.strip() in ('RESOURCES', 'VACATIONS', 'CONFIGURATION') \ and 'no_gantt' not in n.tags \ and n.todo in LISTE_TODOS: __LOG__.debug(' new task under project {0}'.format(n.headline)) if n.level == 1: prev_task = None prop_inherits = [] __LOG__.debug(' clean prop_inherits') if no_gantt_level is not None and n.level > no_gantt_level: __LOG__.debug('no_gantt_tag {0}/{1}'.format( n.level, no_gantt_level)) continue else: __LOG__.debug('remove no_gantt_tag {0}/{1}'.format( n.level, no_gantt_level)) no_gantt_level = None if n.level > 1 and len(prop_inherits) < n.level - 1: __LOG__.critical( 'pb in structure : task "{0}" do not belong to a project but a task - possible inheritance problem' .format(n.headline)) if len(prop_inherits) >= n.level: __LOG__.debug(' go one level up') prop_inherits = prop_inherits[:-1] __LOG__.debug(' bar_color {0}'.format(bar_color)) # Add task if len(prop_inherits) > 0: nt = make_task_from_node(n, prop_inherits[-1], prev_task) if nt is None: continue name, code, dependencies = nt late_dependencies.append([name, dependencies]) else: nt = make_task_from_node(n, [], prev_task) if nt is None: continue name, code, dependencies = nt late_dependencies.append([name, dependencies]) if name in tasks_name: __LOG__.critical("Duplicate task id: {0}".format(name)) sys.exit(1) else: tasks_name.append(name) prev_task = name gantt_code += code #gantt_code += "project.add_task(task_{0})\n".format(name) try: gantt_code += "project_{0}.add_task(task_{1})\n".format( prop_inherits[-1]['project_id'], name) except KeyError: gantt_code += "project.add_task(task_{0})\n".format(name) except IndexError: gantt_code += "project.add_task(task_{0})\n".format(name) else: prj_found = False prop_inherits = [] __LOG__.debug(' nothing') gantt_code += "\n#### Dependencies \n" # Late dependencies for name, dep in late_dependencies: gantt_code += "task_{0}.add_depends(depends_of={1})\n".format( name, dep) if availibility == '': # Full project gantt_code += "\n#### Outputs \n" gantt_code += "project.make_svg_for_tasks(filename='{3}.svg', today={0}, start={1}, end={2}, scale=gantt.{4})\n".format( planning_today_date, planning_start_date, planning_end_date, svg, scale_name) # Generate resource graph if resource: gantt_code += "project.make_svg_for_resources(filename='{4}_resources.svg', today={0}, start={1}, end={2}, one_line_for_tasks={3}, filter='{5}', scale=gantt.{6})\n".format( planning_today_date, planning_start_date, planning_end_date, one_line_for_tasks, svg, filter, scale_name) else: gantt_code += "\n#### Check resource availibility \n" gantt_code += "print({0}.is_vacant(from_date={1}, to_date={2}))\n".format( availibility, planning_start_date, planning_end_date) if csv != '': gantt_code += "\n#### CSV Outputs \n" gantt_code += "project.csv('{0}')\n".format(csv) # write Gantt code if gantt == '': import gantt exec(gantt_code) else: open(gantt, 'w').write(gantt_code) __LOG__.debug("All done. Exiting.") return
if template_js.find(js_swap_string) == -1: print red("Fatal error: template swap string '" + js_swap_string + "' not found.") sys.exit() def htmlentities(string): string = cgi.escape(string) # HTML entities string = re.sub(r"'","\\'",string) string = re.sub(r'\[\[(.*?)\]\[(.*?)\]\]',r'<a href="\1">\2</a>',string) # find and code org-mod encoded hyperlinks return string # create the guidelines files for x in guidelines: msg = " " + x + " " if os.path.isfile('js/guidelines/'+x+'.txt'): # get the guideline text file in org-mode format nodelist = Orgnode.makelist('js/guidelines/'+x+'.txt') guidelinehtml = "" headernumber = 0 for n in nodelist: # make HTML headings tags guidelinehtml += '<h' + str(n.Level()) + ' data-target="#glb_' + str(headernumber) + '" data-toggle="collapse" style="cursor: pointer;">' # HTML Heading tag open. The inline style required for forcing iOS to behave. guidelinehtml += htmlentities(n.Heading()) guidelinehtml += "</h" + str(n.Level()) + ">\n" # HTML Heading tag close # if there is a body below a heading then make it in to HTML too bodylist = [] # collect the list items for line in n.Body().split('\n'): if len(line) > 0: bodylist.append("<p>"+htmlentities(line)+"</p>\n") # only if there are list items make a HTML unordered list # (this forces ignoring of blank lines in the guideline file)