Exemplo n.º 1
0
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
Exemplo n.º 2
0
	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
Exemplo n.º 3
0
 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
Exemplo n.º 4
0
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'

Exemplo n.º 5
0
#!/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:
Exemplo n.º 6
0
def load_org_file():
    """
    Create a list of org objects.
    """
    nodelist = Orgnode.makelist(ORG_FILE)
    return nodelist
Exemplo n.º 7
0
# 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"])
Exemplo n.º 8
0
Arquivo: flog.py Projeto: abjose/flog
    filelist = [f for f in os.listdir(folder)]
    for f in filelist:
        os.remove(folder+f)

def copy_folder(src_folder, dst_folder):
    try:
        filelist = [f for f in os.listdir(src_folder)]
        for f in filelist:
            shutil.copy(src_folder+f, dst_folder)
    except:
        print ("Couldn't copy " + src_folder + " to " + dst_folder
               + ", continuing...")

if __name__ == "__main__":
    flog_path = os.path.split(sys.argv[0])[0]
    if flog_path: flog_path += "/"
    org_filename = sys.argv[1]
    title = org_filename.split(".")[0]
    root = Orgnode.maketree(title, org_filename)

    env = Environment(loader=FileSystemLoader(flog_path + "templates"))
    project_template = env.get_template("project.html")
    page_template = env.get_template("page.html")

    empty_folder("html/")
    # copy user-specified resources over
    copy_folder("resources/", "html/")
    # copy the flog resources over (be careful of overwriting)
    copy_folder(flog_path + "resources/", "html/")
    make_site(title, root, project_template, page_template)
Exemplo n.º 9
0
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
Exemplo n.º 10
0
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
Exemplo n.º 11
0
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)