Esempio n. 1
0
def init(section):
    print color.success_blue('# ') + 'Fetching stories from Backlog and Queue...'
    progress.update(0, 2)
    backlog_stories = filter_not_accepted(section.backlog.fetch_stories())
    backlog_stories_sorted = effort_sorted(backlog_stories)
    progress.update(1, 2)
    queue_backlog = filter_backlog(section.queue.fetch_stories())
    progress.finish()
    
    print color.success_blue('# ') + 'Writing original story order to config file...'
    section.order = map(lambda story: (story.id, story.current_state), backlog_stories)
    section.write_order()
    progress.finish()
    
    def move_to_estimator(story, origin):
        story.description = getattr(story, 'description', '') + '\n' + origin_key + origin
        story.sync_to_project(section.estimator, safe=True)
    
    for story in backlog_stories_sorted:
        if story.story_type == 'release' and story.current_state == 'unscheduled':
            story.current_state = 'unstarted'
            continue
        
        if story.story_type != 'release' and story.current_state in ['unscheduled', 'unstarted']:
            story.current_state = 'started'
            if not hasattr(story, 'estimate') and story.is_estimatable():
                print color.warn('Warning: ') + 'Story %s has no estimate. Adding an estimate of one; this is needed to start the story in Estimator.' % story.name
                story.estimate = 1

    print color.success_blue('# ') + 'Moving stories from Backlog to Estimator...'
    progress.iter(backlog_stories_sorted, move_to_estimator, 'backlog')

    for story in queue_backlog: story.current_state = 'unscheduled'
    print color.success_blue('# ') + 'Moving stories from Queue to Estimator...'
    progress.iter(queue_backlog[::-1], move_to_estimator, 'queue')
Esempio n. 2
0
def main():
    if '-e' in sys.argv:
        run_session(config.load_section(config.eng_sec))
    elif '-pm' in sys.argv:
        run_session(config.load_section(config.pm_sec))
    elif '-s' in sys.argv:
        setup_section(config.load_section(config.eng_sec))
        setup_section(config.load_section(config.pm_sec))
        print color.success_blue('# ') + 'Projects have been set up to use appropriate point scale. However, some stories could still have the wrong point values. Please change these manually to correct values before starting a session.'
    elif '-ea' in sys.argv:
        response = raw_input(color.success_blue('==> ') + 'Are you sure you want to abandon session? This will remove all temporary data of an in-progress session from the config file. Type y/n: ')
        if response == 'y':
            abandon_session_config(config.load_section(config.eng_sec))
    elif '-pma' in sys.argv:
        response = raw_input(color.success_blue('==> ') + 'Are you sure you want to abandon session? This will remove all temporary data of an in-progress session from the config file. Type y/n: ')
        if response == 'y':
            abandon_session_config(config.load_section(config.pm_sec))
    else:
        print 'No flag specified. Please use the -e flag for engineering and -pm for product management. To set up point scales, use -s. To abandon an engineering session, use -ea and for abandoning a product management session use -pma. This will remove all temporary data of an in-progress session from the config file.'
Esempio n. 3
0
def query_user_input(section):
    def read_keyboard():
        return raw_input(color.success_blue('==> ') + "Enter 'e' to assign effort order, 'p' to assign rough point estimates, 'f' to finish session, or 'q' to quit (session is resumed on next run): ")
    
    has_applied_effort_order = False
    keyboard_in = read_keyboard()
    while keyboard_in not in ['q', 'f']:
        if keyboard_in == 'e':
            print color.success_blue('# ') + 'Assigning effort order...'
            apply_effort_order(section.estimator)
            has_applied_effort_order = True
        elif keyboard_in == 'p':
            print color.success_blue('# ') + 'Assigning point estimates...'
            apply_point_estimates(section.estimator)
        else:
            print color.warn('Warning: ') + 'Please enter p, q, or f'
        keyboard_in = read_keyboard()

    if keyboard_in == 'q':
        quit()
    elif keyboard_in == 'f':
        if not has_applied_effort_order:
            response = raw_input(color.warn('Warning: ') + 'You have not assigned effort order before finishing. Would you like to assign effort order? (y/n): ')
            while response not in ['y', 'n']:
                response = raw_input(color.warn('Warning: ') + 'Please enter y/n for assigning effort order: ')
            
            if response == 'y':
                print color.success_blue('# ') + 'Assigning effort order...'
                apply_effort_order(section.estimator)
Esempio n. 4
0
def share_estimator_with_account(section):
    estimator = section.estimator
    if not section.has_account_id():
        account_id = raw_input(color.success_blue('==> ') + "No account id found in config file. This is used to automatically share the Estimator with everyone in the account. Please enter account id, or leave blank to skip this step: ")
        if account_id != '':
            section.account_id = account_id
            section.write_account_id()
    
    if section.has_account_id():
        account = piv.Account.load(section.account_id)
        account_mems = account.fetch_memberships()
        estimator_mems = estimator.fetch_memberships()
        if len(account_mems) == 1:
            print color.warn('Warning: ') + 'No users to invite in account.'
            return;

        for amem in account_mems:
            intersection_mems = filter(lambda pmem: pmem.person['id'] == amem.person['id'], 
                                       estimator_mems)
            if len(intersection_mems) > 1:
                print color.warn('Warning: ') + 'More than one project membership with id: %d. This should never happen. If this ever happens please let me know how I can reproduce this.' % amem.person['id']
            if len(intersection_mems) == 0:
                estimator.add_membership({'person_id' : amem.person['id'], 'role' : 'member'})
                print color.success_blue('# ') + 'Invited user %s to Estimator.' % amem.person['name']
Esempio n. 5
0
queue_include = [{'name' : 'Queue include item #1', 'current_state' : 'accepted', 'story_type' : 'chore'}, 
                 {'name' : 'Queue include item #2', 'current_state' : 'started', 'story_type' : 'bug', 'description' : 'This bug has been annoying us for a while.'}, 
                 {'name' : 'Queue include item #3', 'current_state' : 'finished', 'estimate' : 50},
                 {'name' : 'Queue include item #4', 'current_state' : 'unstarted', 'story_type' : 'release', 'description' : 'Test description.\n\n@effortOrder:1234'}, 
                 {'name' : 'Queue include item #5', 'current_state' : 'delivered', 'estimate' : 3, 'story_type' : 'feature'}, 
                 {'name' : 'Queue include item #6', 'current_state' : 'rejected', 'estimate' : 8, 'labels' : ['label1', 'label2']}]
qi_stories = []

backlog_start = [{'name' : 'Backlog item #1', 'current_state' : 'accepted', 'estimate' : 1}, 
                 {'name' : 'Backlog item #2', 'current_state' : 'started', 'story_type' : 'bug', 'description' : '@effortOrder:0'},
                 {'name' : 'Backlog item #3', 'current_state' : 'delivered', 'story_type' : 'feature', 'estimate' : 50, 'description' : '@effortOrder:2'},
                 {'name' : 'Backlog item #4', 'current_state' : 'finished', 'estimate' : 5},
                 {'name' : 'Backlog item #5', 'current_state' : 'unstarted', 'story_type' : 'chore', 'description' : '@effortOrder:1'},
                 {'name' : 'Backlog item #6', 'current_state' : 'unstarted', 'story_type' : 'release'},
                 {'name' : 'Backlog item #7', 'current_state' : 'unstarted', 'story_type' : 'bug', 'description' : 'This bug would have been caught with a test suite.'},
                 {'name' : 'Backlog icebox item #2', 'current_state' : 'unscheduled', 'story_type' : 'chore'},
                 {'name' : 'Backlog icebox item #1', 'current_state' : 'unscheduled', 'estimate' : 5}]

backlog_stories = []

print color.success_blue('# ') + 'Generating Queue not include...'
progress.iter(queue_not_include, lambda attrs: qni_stories.append(queue.create_story(attrs)))
print color.success_blue('# ') + 'Generating Queue include...'
progress.iter(queue_include, lambda attrs: qi_stories.append(queue.create_story(attrs)))

print color.success_blue('# ') + 'Generating Backlog...'
progress.iter(backlog_start, lambda attrs: backlog_stories.append(backlog.create_story(attrs)))

# tool.run_session(config.load_section(config.eng_sec))
Esempio n. 6
0
def run_session(section):
    if section.has_estimator_id():
        print color.success_blue('# ') + 'Loaded existing Estimator session'
    else:
        print color.success_blue('# ') + 'No existing Estimator session found, starting new session...'
        print color.success_blue('# ') + 'Making backup of Queue and Backlog...'
        backup.backup_project(section.queue)
        progress.update(1, 2)
        backup.backup_project(section.backlog)
        progress.finish()

        try:
            section.estimator = create_estimator(section)
            section.write_estimator_id()
            
            try:
                print color.success_blue('# ') + 'Sharing Estimator with all members in account...'
                share_estimator_with_account(section)
            except Exception:
                pass
        except RuntimeError:
            est_id = raw_input(color.err('ERROR: ') + 'Estimator project already exists, but was not found in the config file. Please enter id of the Estimator project: ')
            section.estimator = piv.Project.load(int(est_id))
            section.write_estimator_id()
        
        section.imported = False
        section.write_imported()
    
    if not section.has_imported():
        stories = section.estimator.fetch_stories()
        if len(stories) != 0:
            print color.success_blue('# ') + 'Estimator project has not imported all the stories from Queue and Backlog; continuing imports...'
            
        init(section)
        section.imported = True
        section.write_imported()
    
    print color.success_blue('# ') + 'Estimator project at: https://www.pivotaltracker.com/n/projects/' + str(section.estimator.id)
    
    query_user_input(section)

    print color.success_blue('# ') + 'Making backup of Estimator...'
    backup.backup_project(section.estimator)
    progress.finish()
    
    finalize(section)
Esempio n. 7
0
 def read_keyboard():
     return raw_input(color.success_blue('==> ') + "Enter 'e' to assign effort order, 'p' to assign rough point estimates, 'f' to finish session, or 'q' to quit (session is resumed on next run): ")
Esempio n. 8
0
def finalize(section):
    print color.success_blue('# ') + 'Fetching stories from Estimator...'
    estimator_stories = section.estimator.fetch_stories()
    estimator_backlog = filter_backlog(estimator_stories)
    estimator_icebox = filter_icebox(estimator_stories)
    # stories that originally came from the backlog
    from_backlog = filter(lambda story: parse_tag(story, origin_key) == 'backlog', 
                          estimator_backlog)
    # stories that originally came from the queue
    from_queue = filter(lambda story: parse_tag(story, origin_key) == 'queue', estimator_backlog)
    # newly created stories
    no_from = filter(lambda story: story not in (from_backlog+from_queue), estimator_backlog)
    progress.finish()

    for story in estimator_icebox:
        if parse_tag(story, effort_key) == 'backlog':
            print color.warn('Warning: ') + 'Story \"%s\" is from the backlog, but was placed in Estimator icebox. It will be moved to backlog of Queue.' % story.name
    
    print color.success_blue('# ') + 'Filtering out nonexistant stories...'
    existing_backlog = get_existing(from_backlog, section.estimator)
    
    print color.success_blue('# ') + 'Restoring states and moving stories from Backlog...'
    restore_states(existing_backlog, section.order)
    progress.iter(existing_backlog, lambda story: story.sync_to_project(section.backlog,safe=True))

    print color.success_blue('# ') + 'Ordering stories originally from Backlog...'
    order_backlog(existing_backlog, section.order)
                
    print color.success_blue('# ') + 'Moving new stories from Queue into icebox of Backlog...'
    progress.iter(list(reversed(from_queue)), move_to_icebox, section.backlog)

    print color.success_blue('# ') + 'Moving stories created in Estimator to icebox of Backlog...'
    progress.iter(no_from, move_to_icebox, section.backlog)

    print color.success_blue('# ') + 'Moving stories from icebox of Estimator to backlog of Queue...'
    progress.iter(estimator_icebox, move_to_backlog, section.queue)
    
    print color.success_blue('# ') + 'Formatting tags...'
    progress.iter(estimator_stories, finalize_tags)

    print color.success_blue('# ') + 'Deleting Estimator...'
    section.estimator.delete()
    progress.finish()
    
    abandon_session_config(section)