|  | #!/usr/bin/env python | 
        
          |  | 'graph dependencies in projects' | 
        
          |  | import json | 
        
          |  | from subprocess import Popen, PIPE | 
        
          |  | import sys | 
        
          |  |  | 
        
          |  | HEADER = "digraph dependencies {" | 
        
          |  | FOOTER = "}" | 
        
          |  |  | 
        
          |  | JSON_START = '[' | 
        
          |  | JSON_END = ']' | 
        
          |  |  | 
        
          |  | def call_taskwarrior(cmd): | 
        
          |  | 'call taskwarrior, returning output and error' | 
        
          |  | tw = Popen(['task'] + cmd.split(), stdout=PIPE, stderr=PIPE) | 
        
          |  | return tw.communicate() | 
        
          |  |  | 
        
          |  | def get_json(query): | 
        
          |  | 'call taskwarrior, returning objects from json' | 
        
          |  | result, err = call_taskwarrior('export %s' % query) | 
        
          |  | return json.loads(JSON_START + result + JSON_END) | 
        
          |  |  | 
        
          |  | def call_dot(instr): | 
        
          |  | 'call dot, returning stdout and stdout' | 
        
          |  | dot = Popen('dot -T png'.split(), stdout=PIPE, stderr=PIPE, stdin=PIPE) | 
        
          |  | return dot.communicate(instr) | 
        
          |  |  | 
        
          |  | if __name__ == '__main__': | 
        
          |  | query = sys.argv[1:] | 
        
          |  | print 'Calling TaskWarrior' | 
        
          |  | data = get_json(' '.join(query)) | 
        
          |  |  | 
        
          |  | # first pass: labels | 
        
          |  | lines = [HEADER] | 
        
          |  | print 'Printing Labels' | 
        
          |  | for datum in data: | 
        
          |  | lines.append('"%s"[label="%s"];' % (datum['uuid'], datum['description'])) | 
        
          |  |  | 
        
          |  | # second pass: dependencies | 
        
          |  | print 'Resolving Dependencies' | 
        
          |  | for datum in data: | 
        
          |  | for dep in datum.get('depends', '').split(','): | 
        
          |  | if dep != '': | 
        
          |  | lines.append('"%s" -> "%s";' % (dep, datum['uuid'])) | 
        
          |  |  | 
        
          |  | lines.append(FOOTER) | 
        
          |  |  | 
        
          |  | print '\n'.join(lines) | 
        
          |  |  | 
        
          |  | print 'Calling dot' | 
        
          |  | png, err = call_dot('\n'.join(lines)) | 
        
          |  | if err != '': | 
        
          |  | print 'Error calling dot:' | 
        
          |  | print err.strip() | 
        
          |  |  | 
        
          |  | print 'Writing to deps.png' | 
        
          |  | with open('deps.png', 'w') as f: | 
        
          |  | f.write(png) | 
  
Awesome!