def returnTicket(ticket_num, option, config): fb = FogBugz(config['FOGBUGZ_URL'], config['FOGBUGZ_TOKEN']) if option == "short": retrieve_ticket = fb.search(q=ticket_num, cols='ixBug,sTitle,sProject') if retrieve_ticket.cases['count'] == str(1): ticket_title = retrieve_ticket.cases.case.stitle.string ticket_project = retrieve_ticket.cases.case.sproject.string ticket_URL = "https://tenthwave.fogbugz.com/f/cases/"+ticket_num ticket = "Ticket: " + ticket_num + " | " + ticket_title + "\n\n" + ticket_URL return ticket else: return "Something went wrong! Either Fogbugz is down, you're a magician calling a number that does not exist yet, or it somehow returned more than one ticket." else: retrieve_ticket = fb.search(q=ticket_num, cols="ixBug,sTitle,sLatestTextSummary,sArea,sProject") if retrieve_ticket.cases['count'] == str(1): ticket_title = retrieve_ticket.cases.case.stitle.string ticket_area = retrieve_ticket.cases.case.sarea.string ticket_project = retrieve_ticket.cases.case.sproject.string ticket_URL = "https://tenthwave.fogbugz.com/f/cases/"+ticket_num ticket_last_update = retrieve_ticket.cases.case.slatesttextsummary.string ticket = ticket_URL + "\n\nTicket: " + ticket_num + "\n" + ticket_project + " : " + ticket_area + "\n*" + ticket_title + "*\n\n" + ticket_last_update return ticket else: return "Something went wrong! Either Fogbugz is down, you're a magician calling a number that does not exist yet, or it somehow returned more than one ticket."
def cgi_callback(): ## Begin sample data loading ## ## Customize with your own logic ## fb = FogBugz(fbsettings.URL, fbsettings.TOKEN) resp = fb.search( q='project:inbox area:* status:active due:today orderby:due', cols="dtDue,sTitle") cases = [] for case in resp.cases: date = datetime.strptime(case.dtdue.string, '%Y-%m-%dT%H:%M:%SZ').strftime('%m/%d/%Y') time = case.dtdue.string[11:16] departure = case.stitle.string.encode('UTF-8').replace('\"', '') track = random.randrange(0, 100) if (datetime.strptime(case.dtdue.string, '%Y-%m-%dT%H:%M:%SZ') - datetime.now()).days < 0: status = 3 else: status = 2 cases.append({ 'sDate': date, 'sTime': time, 'sDeparture': departure, 'nStatus': status, 'nTrack': track, 'bLight': False })
def get_requirements_cases(project_name): """ Looks for all cases of category:"Requirement" in Fogbugz Returns a list of case dictionary objects with the following of a case: [ { "id" : FogBugz ID of case, "title" : Title of case, "status" : FogBugz status (i.e. 'proposed', 'approved', etc), "event" : Description of requirement, "area" : FogBugz area of case (Front End, Support, etc), "url" : URL to actual case in FogBugz, "children": Subcases attached to current case } ] """ fb = FogBugz(FB_URL, FB_TOKEN) print "Requesting Data" resp = fb.search(q='category:"Requirement" orderby:"ixBug" project:"' + project_name + '"', cols="sTitle,sArea,ixBug,sLatestTextSummary,sFixFor,sStatus,ixBugChildren") return get_cases_from_XML(resp)
def main(): if len(sys.argv) != 3: sys.exit("Incorrect number of arguments") c = readcFile(sys.argv[1]) c['test.build'] = sys.argv[2] rawCrashes = getCrashesFromDirectory(c['test.separator'], c['test.dir']) crashes = parseCrashes(rawCrashes, c) if (len(crashes) != 0): fb = FogBugz(c['fogbugz.url']) fogbugzQuery = 'project:\"' + c['fogbugz.project'] + '"' fb.logon(c['fogbugz.user'], c['fogbugz.pass']) fogBugzResp = fb.search(q=fogbugzQuery, cols='ixBug,sTitle,fOpen,events') crashes = flagExcludeList(c, crashes) crashes = flagFBDuplicates(fogBugzResp, crashes, c) logCrashesToFogbugz(fb, c, crashes) emailReport(c, crashes) print 'Done'
def get_wiki_content(wiki_id, sections): """ Grabs wiki pages from FogBugz that match a section listed in 'sections'. Returns a list of wiki dictionary objects: [ { "page_id" : FogBugz ID of wiki page, "name" : Title of page, "url" : URL to actual wiki page in FogBugz, "content" : Raw HTML of Wiki Content } ] """ fb = FogBugz(FB_URL, FB_TOKEN) wiki_articles = fb.listArticles(ixWiki=wiki_id) article_list = [] for page in wiki_articles.articles.childGenerator(): if page.sheadline.text.encode('UTF-8') in sections: wiki_url = "%s/default.asp?W%s" % (FB_URL, page.ixwikipage.text) article_dict = {"page_id": page.ixwikipage.text, "name" : page.sheadline.text.encode('UTF-8'), "url" : wiki_url} content = fb.viewArticle(ixWikiPage=article_dict["page_id"]) article_dict['content'] = Markup(content.wikipage.sbody.text.encode('UTF-8')) article_list.append(article_dict) return article_list
def get_list_of_projects(): """ Gets a list of projects from FogBugz. Returns a list of project dictionary objects: [ { "project": project name, "owner" : project contact name, "email" : owner's email } ] """ try: fb = FogBugz(FB_URL, FB_TOKEN) except: return "Cannot connect" project_xml = fb.listProjects() projects = [] for project in project_xml.projects.childGenerator(): project_dict = {'project': project.sproject.text.encode('UTF-8'), # 'id': project.ixproject.text, 'owner': project.spersonowner.text, 'email': project.semail.text} projects.append(project_dict) return projects
def getData(fogBugzUrl, userName, password, today): oneMonthAgo = today - timedelta(days=28) fb = FogBugz(fogBugzUrl) fb.logon(userName, password) resp = fb.listIntervals(dtStart=asIso8601zDateString(oneMonthAgo), dtEnd=asIso8601zDateString(today)) return resp
def handle_github_payload(request): if request.method == 'POST': payload = json.loads(request.POST.get('payload')) fb = FogBugz(settings.FOGBUGZ_URL) fb._token = None commits = payload['commits'] if commits: for c in commits: user = FogBugzLogin.objects.filter( email = c['author']['email']) if user: user = user[0] fb._token = user.fogbugz_token message = c['message'] commit_hash = c['id'] case_ids, fb_message = parse_commit_message(message, commit_hash) try: for case_id in case_ids: post_message(fb, case_id, fb_message, commit_hash) except FogBugzAPIError as e: send_error_email(e.message) break return HttpResponse('Thanks, GitHub!') # we don't want any GET requests on this page. Only POST return HttpResponse('Move along. Nothing to see here.')
def cgi(): fb = FogBugz(fbsettings.URL, fbsettings.TOKEN) resp = fb.search(q='project:inbox area:* status:active due:today orderby:due', cols="dtDue,sTitle") cases = [] for case in resp.cases: date = datetime.strptime(case.dtdue.string, '%Y-%m-%dT%H:%M:%SZ').strftime('%m/%d/%Y') time = case.dtdue.string[11:16] departure = case.stitle.string.encode('UTF-8').replace('\"', '') track = random.randrange(0, 100) if (datetime.strptime(case.dtdue.string, '%Y-%m-%dT%H:%M:%SZ') - datetime.now()).days < 0: status = 3 else: status = 2 cases.append({'sDate': date, 'sTime': time, 'sDeparture': departure, 'nStatus': status, 'nTrack': track, 'bLight': False}) #turn on the top light try: cases[0]['bLight'] = True except: pass print("Content-Type: application/json", end='\n\n') json.dump(cases, sys.stdout)
def run(): parser = argparse.ArgumentParser(description="JIRA to FogBugz importer") parser.add_argument('jira_url', help="JIRA URL, ex. http://jira.example.com") parser.add_argument('jira_username', help="JIRA username") parser.add_argument('jira_password', help="JIRA password") parser.add_argument('fogbugz_url', help="FogBugz URL, ex. http://example.fogbugz.com") parser.add_argument('fogbugz_username', help="FogBugz username") parser.add_argument('fogbugz_password', help="FogBugz password") parser.add_argument('default_assignee', help="The email of the default assignee") # TODO: dynamically create projects based on JIRA data parser.add_argument('project', help="Which FogBugz project to put cases in") parser.add_argument('-v', '--verbose', dest="verbose", action="store_true", default=False, help="Get more verbose output") args = parser.parse_args() try: try: jira = JIRA(options={'server': args.jira_url}, basic_auth=(args.jira_username, args.jira_password)) except JIRAError, e: if e.status_code == 403: sys.stderr.write('Cannot connect to JIRA. Check username/password\n') sys.exit(1) else: msg = "Cannot connect to JIRA (return code={0})".format(e.status_code) if args.verbose: msg += "\n{0}".format('Response from JIRA:\n{0}'.format(e.text)) sys.stderr.write(msg+'\n') sys.exit(1) try: fb = FogBugz(args.fogbugz_url) fb.logon(args.fogbugz_username, args.fogbugz_password) except FogBugzConnectionError: sys.stderr.write('Cannot connect to FogBugz\n') sys.exit(1) except FobBugzLogonError: sys.stderr.write('Cannot login to FogBugz. Check username/password') sys.exit(1) # initialize an email to fogbugz User ID mapping email_map = {} resp = fb.listPeople() for person in resp.people.childGenerator(): email_map[person.semail.string] = int(person.ixperson.string) try: default_assignee = email_map[args.default_assignee] except KeyError: parser.error("Default assignee {0} does not exist in FogBugz".format(args.default_assignee)) for issue in get_jira_issues(jira, query): create_issue(fb, issue, project_name, email_map, default_assignee)
def cgi_callback(): ## Begin sample data loading ## ## Customize with your own logic ## fb = FogBugz(fbsettings.URL, fbsettings.TOKEN) resp = fb.search(q='project:inbox area:* status:active due:today orderby:due', cols="dtDue,sTitle") cases = [] for case in resp.cases: date = datetime.strptime(case.dtdue.string, '%Y-%m-%dT%H:%M:%SZ').strftime('%m/%d/%Y') time = case.dtdue.string[11:16] departure = case.stitle.string.encode('UTF-8').replace('\"', '') track = random.randrange(0, 100) if (datetime.strptime(case.dtdue.string, '%Y-%m-%dT%H:%M:%SZ') - datetime.now()).days < 0: status = 3 else: status = 2 cases.append({'sDate': date, 'sTime': time, 'sDeparture': departure, 'nStatus': status, 'nTrack': track, 'bLight': False}) # turn on the top light try: cases[0]['bLight'] = True except: pass ## End sample data loading ## # save json data to be read by liveFogbugz.py f = open('fogbugz.json','w') f.write(json.dumps(cases, sys.stdout)) f.close() # this page doesn't return the json, but might as well return some stats stats = {'error': False, 'cases': len(cases)} # support a callback param, or default to "void" params = cgi.parse_qs(os.environ['QUERY_STRING']) callback = 'void' if params.has_key('callback'): callback = params['callback'][0] print('Content-Type: application/javascript\n') print('%s(%s);' % (callback,json.dumps(stats, sys.stdout)))
def fogbugzOnFail(self,logfp): print "Creating FogBuz Ticket" cfp=Config(self.__fpath) attempts=0 run=True while run is True and attempts < 3: try: site=FogBugz(cfp.getVar("fogbugz","site","string")) try: site.logon(cfp.getVar("fogbugz","user","string"), cfp.getVar("fogbugz","pass","string")) cfp=Config(self.__fpath) with open(logfp,'rb') as fp: print site.new(sTitle="The Parser "+os.path.join(self.__logbase,self.__execute)+" Failed",ixPersonAssignedTo="Andy",Files={"faillog.txt":fp}) attempts+=1 run=False except Exception,e: print str(e) for frame in traceback.extract_tb(sys.exc_info()[2]): print '\n'.join([str(x) for x in frame]) finally: site.logoff() except Exception,e: print str(e) for frame in traceback.extract_tb(sys.exc_info()[2]): print '\n'.join([str(x) for x in frame])
def doPrivmsg(self, irc, msg): if(self.registryValue('enable', msg.args[0])): match = re.search('.*Bug[sz]id *: *(\d{1,5})', msg.args[1], re.IGNORECASE) if match: fb = FogBugz(fbSettings.fb_url) fb.logon(fbSettings.fb_user, fbSettings.fb_pass) query_cols='sTitle,sStatus,sPriority' resp = fb.search(q=match.group(1), cols = query_cols) if len(resp.findAll('case')) > 0 : for cur_case in resp.cases.childGenerator(): # Dump Title title_message = '[BugzID ' + match.group(1) + '] ' + ircutils.bold(str(cur_case.stitle.string).replace('<![CDATA[','').replace(']]>','')) + ' (' + cur_case.sstatus.string + ', ' + cur_case.spriority.string +')' irc.queueMsg(ircmsgs.privmsg(msg.args[0], title_message)) # Dump URL to ticket url_message = fbSettings.fb_url + '/default.asp?' + match.group(1) irc.queueMsg(ircmsgs.privmsg(msg.args[0], url_message)) else : irc.queueMsg(ircmsgs.privmsg(msg.args[0], 'Sorry, ' + ircutils.bold(match.group(1)) + ' is not a known BugID.'))
def update_tickets(args): cols = [ "ixBug", "sStatus", "sTitle", 'sTags', "ixPersonOpenedBy", "dtOpened", "sProject", 'plugin_customfields', "latestEvent" ] fb = FogBugz('https://daily.manuscript.com/') fb.logon(args.email, args.password) query = {"status": "Active", "AssignedTo": "Unassigned"} querystring = " ".join(["{}:{}".format(k, v) for k, v in query.items()]) resp = fb.search(q=querystring, cols=",".join(cols)) for casexml in resp.cases.childGenerator(): #logger.info("case:##{}".format(casexml)) logger.debug(casexml['ixBug']) id = casexml['ixBug'] question = casexml.sTitle.getText() latest_event = casexml.events event_id = latest_event.ixBugEvent.getText() message_body = latest_event.s.getText() answers_string = "" pdb.set_trace() if message_body == "": answers = googler(question) for ele in answers: answers_string += "\n".join( [ele['title'], ele['url'], ele['abstract']]) answers_string += '\n\n' fb.edit(ixBug=id, sEvent=answers_string, ixPersonAssignedTo=casexml.ixPersonOpenedBy.getText()) else: for line in [i for i in message_body.split('\n') if i != '']: answers_string = "" if line.startswith("##"): answers_string += '**' + line[3:].encode('utf-8') answers_string += '\n' answers = googler(line[3:]) for ele in answers: answers_string += "\n".join( [ele['title'], ele['url'], ele['abstract']]) answers_string += '\n\n' fb.edit( ixBug=id, ixPersonAssignedTo=casexml.ixPersonOpenedBy.getText(), sEvent=answers_string) #fb.edit(ixBug=id,ixBugEvent=event_id,sEvent=answers_string,ixPersonAssignedT=casexml.ixPersonOpenedBy.getText()) else: break
def editFBCase(site, username, password, case, change, changetext): fb = FogBugz('https://' + site + '.fogbugz.com/') fb.logon(username, password) logging.info('Updating fogbugz cases') fb.edit(ixBug=case, sEvent=changetext) fb.logoff()
def fogbugz(fogbugz_uri): """Test fogbugz instance.""" httpretty.enable() httpretty.register_uri(httpretty.GET, fogbugz_uri + 'api.xml', body="""<response> <version>8</version> <minversion>1</minversion> <url>api.asp?</url> </response>""") yield FogBugz(fogbugz_uri) httpretty.disable()
def updateFogbugzCases(site, username, password, ordered_changes, changemap, casemap, releasenotesmap): logging.info('Logging on to site ' + site + ' as user ' + username) fb = FogBugz('https://' + site + '.fogbugz.com/') fb.logon(username, password) logging.info('Updating fogbugz cases') for change in ordered_changes: logging.info(' Commit: ' + change) changetext = changemap[change] cases = casemap[change] # releasenotes = releasenotesmap[change] logging.info(' Cases: ' + str(cases)) logging.info(' Text: ' + changetext) # logging.info(' Release notes: ' + releasenotes) if cases: for case in cases: if hasChange(fb, case, change) == False: logging.info(' Updating case ' + str(case)) fb.edit(ixBug=case, sEvent=changetext) # fb.edit(ixBug=case, sReleaseNotes=releasenotes) else: logging.info(' Skipping case ' + str(case))
def login(request): fogbugz_error = None if request.method == 'POST': form = LoginForm(request.POST) if form.is_valid(): email_address = str(request.POST.get('email_address','')) password = str(request.POST.get('password','')) fb = FogBugz(settings.FOGBUGZ_URL) try: fb.logon(email_address, password) except FogBugzAPIError as e: fogbugz_error = e.message mail_error = 'Error on login:\n\n' + e.message send_error_email(mail_error) fb_token = fb._token # pylint: disable=W0212 # save token into model if fb_token: login = FogBugzLogin.objects.filter(email=email_address) if not login: login = FogBugzLogin(email=email_address, fogbugz_token=fb_token) login.save() else: login.update(fogbugz_token=fb_token) return render_to_response('fogbugz_login_complete.html') else: form = LoginForm() return render_to_response('login.html', {'login_form': form, 'fogbugz_error': fogbugz_error, 'fogbugz_site': settings.FOGBUGZ_URL})
def get_project_data(project_name): """ Gets data regarding specific project from FogBugz. Returns a project dictionary object: { "project": project name, "id" : FogBugz ID of project, "owner" : project contact name, "email" : owner's email, "wiki_id": FogBugz ID of the wiki with the same name as project } """ try: fb = FogBugz(FB_URL, FB_TOKEN) except: return "Cannot connect" project_xml = fb.viewProject(sProject=project_name) person_xml = fb.viewPerson(ixPerson=project_xml.ixpersonowner.text) project_dict = { 'project': project_xml.sproject.text.encode('UTF-8'), 'id': project_xml.ixproject.text, 'owner': person_xml.sfullname.text, 'email': person_xml.semail.text, 'wiki_id': None } wiki_list = fb.listWikis() for wiki in wiki_list.wikis.childGenerator(): if project_dict['project'] == wiki.swiki.text.encode('UTF-8'): wiki_id = wiki.ixwiki.text project_dict['wiki_id'] = wiki_id return project_dict
def main(): # Program start and timer print("Started the program... ") print(str(datetime.now().strftime(FORMAT_OF_DATE))) start = time.time() # Fogbugz init fb = FogBugz(getpath(), getapikeyassistant(), api_version=8) bugcases = getcaseslist(fb, query=yes()) findowner(fb, bugcases) # Finish time end = time.time() print('Finished program. Time spent: ' + str(end - start)) print(str(datetime.now().strftime(FORMAT_OF_DATE)))
def main(): if len(sys.argv) != 3: sys.exit("Incorrect number of arguments") c = readcFile(sys.argv[1]) c['test.build']=sys.argv[2] rawCrashes = getCrashesFromDirectory(c['test.separator'], c['test.dir']) crashes = parseCrashes(rawCrashes, c) if (len(crashes) != 0): fb = FogBugz(c['fogbugz.url']) fogbugzQuery='project:\"' + c['fogbugz.project'] + '"' fb.logon(c['fogbugz.user'], c['fogbugz.pass']) fogBugzResp = fb.search(q=fogbugzQuery,cols='ixBug,sTitle,fOpen,events') crashes = flagExcludeList(c, crashes) crashes = flagFBDuplicates(fogBugzResp, crashes, c) logCrashesToFogbugz(fb, c, crashes) emailReport(c, crashes) print 'Done'
def findinguserbyevents(case): fb = FogBugz(getpath(), getapikeyassistant(), api_version=8) bugevents = particularcaseevents(fb, case) for event in bugevents['events']: s = event['sChanges'] # Looking for "Status changed from 'xxxxx' to 'Active' statuslines = [ sentence for sentence in s.split('\r\n') if 'Status changed' in sentence ] if statuslines: fromtostring = statuslines[0].split('\'') if fromtostring[3] == 'Active': if str(event['sPerson']) is not None: # print(str(bugevents['ixBug']) + " " + str(event['sPerson']) + " " + " to " + fromtostring[3]) return str(event['sPerson']) # If there is no status change, let's say a case was Active already, because reported internally # Looking for "Category changed from 'xxxxx' to 'Unity' statuslines = [ sentence for sentence in s.split('\r\n') if 'Project changed' in sentence ] if statuslines: fromtostring = statuslines[0].split('\'') if fromtostring[3] == 'Unity': if str(event['sPerson']) is not None: # print(str(bugevents['ixBug']) + " " + str(event['sPerson']) + " " + " to " + fromtostring[3]) return str(event['sPerson']) # If we cannot find a person by Status or Category, look for the case opener # Looking for "Opened by" for event in bugevents['events']: s = event['evtDescription'] statuslines = [ sentence for sentence in s.split('\r\n') if 'Opened by' in sentence ] if statuslines: if str(event['sPerson']) is not None: # print(str(event['sPerson'])) return str(event['sPerson'])
from fogbugz import FogBugz import fbSettings import argparse, sys import pprint fogbugz = FogBugz(fbSettings.URL) fogbugz.logon(fbSettings.LOGIN, fbSettings.PW) parser = argparse.ArgumentParser(description='I fix this later') parser.add_argument('-m','--milestone', metavar='A list of Milestones by name, seperated by space(ie: ui release/9.0 link-php release/9.0)', nargs ='+', help='Milestone Names', required=False) parser.add_argument('-l','--list',action='store_true', default=False, help='List the available milestones') args = parser.parse_args() pp = pprint.PrettyPrinter(indent=4) milestone_map = {} milestones = fogbugz.listFixFors() for item in milestones.findAll('fixfor'): number = item.ixfixfor.string.encode('UTF-8') name = item.sfixfor.string.encode('UTF-8') milestone_map.update({name:number}) if args.list: pp.pprint(milestone_map) ms = "test1" tickets_per_milestone = {} #print args.milestone if args.milestone:
from fogbugz import FogBugz from datetime import datetime, timedelta import csv S_FOGBUGZ_URL = 'https://fogbugz.com/' S_EMAIL = '' S_PASSWORD = '' fb = FogBugz(S_FOGBUGZ_URL) fb.logon(S_EMAIL, S_PASSWORD) resp = fb.search( q='sFixFor="2018.2"', cols= 'ixBug, ixBugParent, fOpen, sTitle, ixProject, ixArea, sArea, ixStatus, ixPriority,sFixFor, dtFixFor, sVersion, sComputer, c, ixCategory, dtOpened, dtClosed' ) filename = "fogbugzData.csv" csv = open(filename, "w") columnTitleRow = "ixBug,ixBugParent,fOpen,sTitle,dtDue" csv.write(columnTitleRow) for case in resp.cases: bugID = case.ixBug.string title = case.sTitle.string open = case.fOpen.string version = case.ixProject.string priority = case.ixPriority.string status = case.ixStatus.string
from fogbugz import FogBugz import csv import sys # Fill in the following values as appropriate to your installation S_FOGBUGZ_URL = 'https://fogbugz.unity3d.com' TOKEN = "" S_EMAIL = '' S_PASSWORD = '' fb = FogBugz(S_FOGBUGZ_URL, TOKEN) #fb.logon(S_EMAIL, S_PASSWORD) #Get all cases in milestone 2018.2 resp = fb.search(q='version:"'+ sys.argv[1] +'*"',cols="ixBug,ixBugParent,fOpen,sTitle,sProject,ixArea,sArea,sStatus,ixPriority,sFixFor,sVersion,sComputer,dtOpened,dtClosed,plugin_customfields_at_fogcreek_com_userxpainr32d") #print resp print "Started on version" + sys.argv[1] filename = "fogbugzData.csv" csv = open(filename, "w") columnTitleRow = "Bug ID,Bug Parent ID,is Open,Title,Project,Area ID,Area,Status,Priority,Fix For,Version,Computer,User Pain, Date Opened, Date Closed" csv.write(columnTitleRow) csv.write("\n") for case in resp.cases.childGenerator(): #assign the cols to variables if case.ixBug.string != None: bugID = case.ixBug.string
# Get FogBugz API connection information print fbSettings.URL print fbSettings.TOKEN # -------------------------------------------------------------- # SECTION: System settings # -------------------------------------------------------------- SETTINGSFILE='fbSettings.py' # if this changes, also change the "import fbSettings" abvoe SERVER='PC-Longphi' DATABASE='FogBugz' fb = FogBugz(fbSettings.URL, fbSettings.TOKEN) ''' #Get all cases assigned to me resp = fb.search(cols='ixBug,sTitle,dtDue') print 'The following cases are overdue:' for case in resp.cases.childGenerator(): #Check to see if we have a due date if case.dtdue.string: #All dates returned are UTC, so parse the due date #into a datetime object. dtDueUtc = datetime.strptime(case.dtdue.string,'%Y-%m-%dT%H:%M:%SZ') fOverdue = dtDueUtc <= datetime.utcnow() if fOverdue:
import fbSettings def compare(a, b): # standard custom compare-two-value routine for use by built-in sort function return cmp(int(a), int(b)) # compare as integers # user input sProject = raw_input('Project to get: ') sMilestone = raw_input('Milestone to get: ') sFilename = "releasenotes_" + sProject + "_" + sMilestone + ".txt" # FogBugz search string sSearch = "project:\"" + sProject + "\" milestone:\"" + sMilestone + "\"" # open session with FogBugz using our API token fb = FogBugz(fbSettings.URL, fbSettings.TOKEN) # run the search resp = fb.search(q=sSearch,cols='ixBug,sArea,sTitle,sReleaseNotes') # list that we will read cases into L = list() # iterate over the returned list of cases and add those with release notes to the list for case in resp.cases.childGenerator(): myReleaseNote = case.sreleasenotes.string # just capture cases with release notes attached ('None' is the null result) if myReleaseNote != None: # add the case to the list L.append((case.sarea.string, case.ixbug.string, case.stitle.string.encode('UTF-8'), case.sreleasenotes.string.encode('UTF-8'))) #tuple
if branchPos is not -1: formattedText = formattedText[ 0: branchPos] + '<a href="' + gitweburl + '/gitweb/?p=' + reponame + ';a=shortlog;h=' + branchname + '">' + branchname + '</a>' + formattedText[ branchPos + len(branchname):] return formattedText def testFormatDescription(): test1 = formatDescription( 'quasar.git', 'https://gitweb.aphelion.se', 'commit 3b22351959e1e0e7a5ef6d1c067ab3ca4b6d6c94\nAuthor: Patrik Hoglund <*****@*****.**>\nDate: Mon Oct 1 13:06:34 2012 +0200\n\n case 4669: Added cvs export to Fx Report view\n\nBranch: refs/heads/develop', '3b22351959e1e0e7a5ef6d1c067ab3ca4b6d6c94', 'refs/heads/develop') return test1 def editFBCase(site, username, password, case, change, changetext): fb = FogBugz('https://' + site + '.fogbugz.com/') fb.logon(username, password) logging.info('Updating fogbugz cases') fb.edit(ixBug=case, sEvent=changetext) fb.logoff() desciption = testFormatDescription() editFBCase('apehlion', '*****@*****.**', '#01APhelion', '4675', '3b22351959e1e0e7a5ef6d1c067ab3ca4b6d6c94', desciption)
# Fill in the following values as appropriate to your installation #S_FOGBUGZ_URL = 'https://vsg.fogbugz.com/' #S_EMAIL = '*****@*****.**' #S_PASSWORD = '******' #fb = FogBugz(S_FOGBUGZ_URL) #fb.logon(S_EMAIL, S_PASSWORD) ''' print fbSettings.URL print fbSettings.TOKEN SETTINGSFILE='fbSettings.py' # if this changes, also change the "import fbSettings" abvoe SERVER='PC-Longphi' DATABASE='FogBugz' fb = FogBugz(fbSettings.URL, fbSettings.TOKEN) ''' #Get all cases assigned to me resp = fb.search(cols='ixBug,sTitle,dtDue') print 'The following cases are overdue:' for case in resp.cases.childGenerator(): #Check to see if we have a due date if case.dtdue.string: #All dates returned are UTC, so parse the due date #into a datetime object. dtDueUtc = datetime.strptime(case.dtdue.string,'%Y-%m-%dT%H:%M:%SZ') fOverdue = dtDueUtc <= datetime.utcnow() if fOverdue:
for ticket in db_entry: return ticket["related_to"] def checkDupe(db_field,ticket_related): if db_field == ticket_related: print "halt, this has happened before" return True else: print "no, update with the new db field" return False """ def updateRelated(new_ticket,ticket_related,editor,title): colorPrint(1, "updating " + ticket_related + " with " + new_ticket) response = fogbugz.edit(ixBug=ticket_related,sEvent=('case %s (%s) has been opened by %s' % (new_ticket, title, editor))) addRelated(new_ticket,ticket_related) def addRelated(new_ticket,ticket_related): db['related_ticket'].update({"case_number":new_ticket},{'$set':{"related_to":ticket_related}}) colorPrint(1,"Update the db") if hasattr(fbSettings,'TOKEN'): fogbugz = FogBugz(fbSettings.URL, fbSettings.TOKEN) else: fogbugz = FogBugz(fbSettings.URL) fogbugz.logon(fbSettings.LOGIN, fbSettings.PW) if __name__ == '__main__': init() getTicketInfo()
def main(): fb = FogBugz(S_FOGBUGZ_URL) fb.logon(S_EMAIL, S_PASSWORD) # how ugly is this, do we export one bug or all? if EXPORT_BUG != 0: resp = fb.search(q=str(EXPORT_BUG), cols='ixBug', max=MAX_BUGS) else: resp = fb.search(q='type:"Cases"', cols='ixBug', max=MAX_BUGS) cases = resp.cases.findAll('case') num_cases = len(cases) counter = 0 batch = 1 issues = [] components = [] BACKUP_DIR = os.getcwd() + '/' + 'attachments' for case in cases: counter += 1 print("Processing case: " + str(counter) + " of " + str(num_cases)) ixBug = int(case['ixBug']) print(ixBug) respBug = fb.search( q='%s' % ixBug, cols= 'sTitle,sPersonAssignedTo,sProject,sArea,sCategory,sPriority,fOpen,events' ) xmlBug = respBug.cases.findAll('case')[0] issue = {} issue['externalId'] = int(xmlBug['ixBug']) issue['created'] = get_date_created(xmlBug) issue['summary'] = get_attribute(xmlBug, 'sTitle') issue['assignee'] = S_USER issue['reporter'] = S_USER component = get_attribute(xmlBug, 'sProject') issue['components'] = [component] # gathering all the components (Fogbugz projects) as we ecounter them if component not in components: components.append(component) issue['issueType'] = "Support" issue['priority'] = get_attribute(xmlBug, 'sPriority') issue['resolution'] = get_attribute(xmlBug, 'fOpen') issue['attachments'] = [] issue['comments'] = get_events(xmlBug, issue, BACKUP_DIR) print(issue) print("Long body running count = " + str(len(LONG_BODY_COMMENTS))) print("Long body issues = " + str([c for c in LONG_BODY_COMMENTS])) issues.append(issue) if counter % BATCH_SIZE == 0: dump_json(batch, counter, components, issues) issues = [] batch += 1 # one last dump dump_json(batch, counter, components, issues)
#Usage: python fogbugz_milestone.py --o old milestone -n new milestone from fogbugz import FogBugz import datetime import re import argparse import json parser = argparse.ArgumentParser(description='Docs docs docs these are my docs') parser.add_argument('-o','--o_variable', type=str, help='Old Milestone name', required=True) parser.add_argument('-n','--n_variable', type=str, help='New Milestone name', required=True) args = parser.parse_args() fb = FogBugz("https://sailthru.fogbugz.com/") # To run this needs a d.txt file that contains the json of: {"login":"******","pass":"******"} with open('../d.txt') as json_data: data = json.load(json_data) login = data["login"] passw = data["pass"] fb.logon(login,passw) milestones = fb.listFixFors() #this is not being used now ... it gets the most current milestone... i could probably trash it.. milestone_dates, sep, tail = milestones.sfixfor.renderContents().partition('T') miled = milestones.findAll('dt',limit=2)[1] work = miled.renderContents().partition('T')
def __init__(self): self.config = yaml.load(file('bugzbot.conf', 'r')) self.fb = FogBugz(self.config['FOGBUGZ_URL'], self.config['FOGBUGZ_TOKEN'])
URL_FROM = raw_input( 'set url from (eg. https://from.fogbugz.com): ') if EMAIL_FROM: print 'email from: ' + EMAIL_FROM else: EMAIL_FROM = raw_input('set email from (eg. [email protected]): ') if PASSWORD_FROM: print 'password from: ok' else: PASSWORD_FROM = raw_input('set password from: ') print '-----------------------------------------------------------' print 'Trying to login ........' fbz_from = FogBugz(URL_FROM) fbz_from.logon(EMAIL_FROM, PASSWORD_FROM) print 'ok' except BaseException or Exception: print '*** Cannot login to [{0}] ***'.format(URL_FROM) print 'copy aborted' sys.exit() print '-----------------------------------------------------------' try: print '** LOGIN DATA FOR ACCOUNT TO WHICH CASES WILL BE PASTED ***' if URL_TO: print 'url to: ' + URL_TO else: URL_TO = raw_input('set url to (eg. https://to.fogbugz.com): ')
# get the list of filters from FogBugz from fogbugz import FogBugz import fbSettings # login fb = FogBugz(fbSettings.URL, fbSettings.TOKEN) # Get list of all filters resp = fb.listFilters() print "Raw response:" print resp print "\nPrettified response:" print resp.prettify()
def run(): parser = argparse.ArgumentParser(description="JIRA to FogBugz importer") parser.add_argument('--jira-server', help="JIRA server URL, ex. http://jira.example.com", required=True) parser.add_argument('--jira-username', help="JIRA username", required=True) parser.add_argument('--jira-password', help="JIRA password", required=True) parser.add_argument('--jira-project', help="Which jira project to read cases", required=True) parser.add_argument('--jira-query', help="Jql query filter (in addition to the project)", required=False) parser.add_argument( '--fogbugz-server', help="FogBugz server URL, ex. http://example.fogbugz.com", required=True) parser.add_argument('--fogbugz-token', help="FogBugz access token", required=True) parser.add_argument('--fogbugz-project', help="Which FogBugz project to put cases in", required=True) parser.add_argument('--default-assignee', help="The email of the default assignee", required=True) # TODO: dynamically create projects based on JIRA data parser.add_argument('-v', '--verbose', dest="verbose", action="store_true", default=False, help="Get more verbose output") args = parser.parse_args() try: try: jira = JIRA(options={'server': args.jira_server}, basic_auth=(args.jira_username, args.jira_password)) except JIRAError as e: if e.status_code == 403: sys.stderr.write( 'Cannot connect to JIRA. Check username/password\n') sys.exit(1) else: msg = "Cannot connect to JIRA (return code={0})".format( e.status_code) if args.verbose: msg += "\n{0}".format('Response from JIRA:\n{0}'.format( e.text)) sys.stderr.write(msg + '\n') sys.exit(1) try: fb = FogBugz(args.fogbugz_server, token=args.fogbugz_token) except FogBugzConnectionError as e: sys.stderr.write('Cannot connect to FogBugz {}\n'.format(e)) sys.exit(1) except FobBugzLogonError: sys.stderr.write('Cannot login to FogBugz. Check token') sys.exit(1) # initialize an email to fogbugz User ID mapping email_map = {} resp = fb.listPeople(fIncludeActive=1, fIncludeNormal=1, fIncludeDeleted=1, fIncludeVirtual=1) for person in resp.people.childGenerator(): logging.debug("Found Fogbugz user {}".format( person.ixPerson.string)) email_map[person.sEmail.string.lower()] = int( person.ixPerson.string) try: default_assignee = email_map[args.default_assignee.lower()] except KeyError: parser.error( "Default assignee {0} does not exist in FogBugz".format( args.default_assignee)) query = 'project = "{}"'.format(args.jira_project) if args.jira_query: query += "AND " + args.jira_query logging.debug("Using Jira query: '{}'".format(query)) issues = get_jira_issues(jira, query) for issue in issues: fb_create_issue(fb, jira, issue, args.fogbugz_project, email_map, default_assignee) except SystemExit: raise except: sys.stderr.write("Unknown error occurred\n") traceback.print_exc(sys.stderr) sys.exit(1) return sys.exit(0)
import fbSettings from fogbugz import FogBugz from datetime import datetime, timedelta from pytz import timezone from decimal import * import pytz import csv fb = FogBugz(fbSettings.URL, fbSettings.TOKEN) # Use correct timezone userTimezone = timezone("Australia/Sydney") # Localized dates according to user's timezones # Midnight 14th startDateLocal = userTimezone.localize(datetime(2012, 05, 14, 0, 0)) # 11.59pm 19th endDateLocal = userTimezone.localize(datetime(2012, 05, 19, 23, 59)) # API expects UTC dates so convert utc = pytz.utc startDateUTC = utc.normalize(startDateLocal.astimezone(utc)) endDateUTC = utc.normalize(endDateLocal.astimezone(utc)) # Expected format by API formatString = "%Y-%m-%dT%H:%M:%SZ" # Logged-in user's timesheet response = fb.listIntervals(dtStart=startDateUTC.strftime(formatString), dtEnd=endDateUTC.strftime(formatString)) # Reference of cases and their project
# set the current filter to a saved one # and then retrieve all the cases associated with that filter # # the filter is set by number, which has to be looked up by a separate XML query (see get_filter_list.py) from fogbugz import FogBugz import fbSettings # login fb = FogBugz(fbSettings.URL, fbSettings.TOKEN) # Set filter resp = fb.setCurrentFilter(sFilter='65',) # filter id 65 the arbitary filter picked in this example # Get results resp = fb.search(cols='ixBug,sTitle,sFixFor,sArea') print "Raw response:" print resp print "\nPrettified response:" print resp.prettify() print "\nParsed response via Beautiful Soup:" for case in resp.cases.childGenerator(): print case.ixbug.string, case.stitle.string.encode('UTF-8'), case.sfixfor.string, case.sarea.string
class Bugz(object): def __init__(self): self.config = yaml.load(file('bugzbot.conf', 'r')) self.fb = FogBugz(self.config['FOGBUGZ_URL'], self.config['FOGBUGZ_TOKEN']) def returnUser(self, _semail): self.user = self.fb.viewPerson(semail=_semail) try: self.fb_user = self.user.people.person.sfullname.string return self.fb_user except AttributeError: return "User not found" def assignTicket(self, ticket_num, user, orig_user): self.touser = self.returnUser(user) print user print self.touser if self.touser != "User not found": self.event = "This ticket was assigned to you by slack user " + \ orig_user[1] + " courtesy of bugzbot!" self.fb.edit(ixBug=ticket_num, sPersonAssignedTo=self.touser, sEvent=self.event) self.checker = self.fb.search(q=ticket_num, cols="ixPersonAssignedTo") print self.checker if self.checker.cases.case.ixpersonassignedto.string != "93": return "success" else: return "One of us screwed up. I got stuck with the ticket somehow." \ "Please follow up and manually assign the ticket so it does not get lost in the shuffle!" else: return "Fogbugz user was not found. Please try again." def returnTicket(self, option, ticket_num): if option: self.retrieve_ticket = self.fb.search(q=ticket_num, cols='ixBug,sTitle,sProject') if self.retrieve_ticket.cases['count'] == str(1): self.ticket_title = self.retrieve_ticket.cases.case.stitle.string self.ticket_project = self.retrieve_ticket.cases.case.sproject.string self.ticket_URL = "https://tenthwave.fogbugz.com/f/cases/" + ticket_num self.ticket = "Ticket: " + ticket_num + " | " + self.ticket_title + \ "\n\n" + self.ticket_URL print self.ticket return self.ticket else: msg = "Something went wrong! Either Fogbugz is down, you're a magician calling a number " \ "that does not exist yet, or it somehow returned more than one ticket." print msg return msg else: self.retrieve_ticket = self.fb.search( q=ticket_num, cols="ixBug,sTitle,sLatestTextSummary,sArea,sProject") if self.retrieve_ticket.cases['count'] == str(1): self.ticket_title = self.retrieve_ticket.cases.case.stitle.string self.ticket_area = self.retrieve_ticket.cases.case.sarea.string self.ticket_project = self.retrieve_ticket.cases.case.sproject.string self.ticket_URL = "https://tenthwave.fogbugz.com/f/cases/" + ticket_num self.ticket_last_update = self.retrieve_ticket.cases.case.slatesttextsummary.string self.ticket = self.ticket_URL + "\n\nTicket: " + ticket_num + "\n" + self.ticket_project + \ " : " + self.ticket_area + "\n*" + self.ticket_title + "*\n\n" + self.ticket_last_update print self.ticket return self.ticket else: msg = "Something went wrong! Either Fogbugz is down, you're a magician calling a number " \ "that does not exist yet, or it somehow returned more than one ticket." print msg return msg
else: URL_FROM = raw_input('set url from (eg. https://from.fogbugz.com): ') if EMAIL_FROM: print 'email from: ' + EMAIL_FROM else: EMAIL_FROM = raw_input('set email from (eg. [email protected]): ') if PASSWORD_FROM: print 'password from: ok' else: PASSWORD_FROM = raw_input('set password from: ') print '-----------------------------------------------------------' print 'Trying to login ........' fbz_from = FogBugz(URL_FROM) fbz_from.logon(EMAIL_FROM, PASSWORD_FROM) print 'ok' except BaseException or Exception: print '*** Cannot login to [{0}] ***'.format(URL_FROM) print 'copy aborted' sys.exit() print '-----------------------------------------------------------' try: print '** LOGIN DATA FOR ACCOUNT TO WHICH CASES WILL BE PASTED ***' if URL_TO: print 'url to: ' + URL_TO else: URL_TO = raw_input('set url to (eg. https://to.fogbugz.com): ')
# Change the specified case's milestone ("Fixfor" in fogbugz API parlance) # This will change a case's milestone even if the case is closed # This is a fast way to change case milestones, especially for # closed cases that the UI forces you to reopen before editing from fogbugz import FogBugz from datetime import datetime, timedelta import fbSettings # user input sCase = raw_input('Case #: ') sMilestone = raw_input('New milestone: ') # open session with FogBugz using our API token fb = FogBugz(fbSettings.URL, fbSettings.TOKEN) # update the case try: resp = fb.edit(ixBug=sCase, sFixFor=sMilestone) except: print "Update not performed - Error from FogBugz" print "Done"
# Usage: python milestone_manager.py -p <Project> -m <Milestone Name> (optional: rm True | False (default is false)) # todo: handling of adding milestones that have been deleted. import fbSettings from fogbugz import FogBugz import argparse fogbugz = FogBugz(fbSettings.URL) fogbugz.logon(fbSettings.Login, fbSettings.pw) parser = argparse.ArgumentParser( description="Usage: python milestone_maker -p <Project> -m <Milestone Name> -rm True|False (Default is false)" ) parser.add_argument("-p", "--project", type=str, help="Project Name", required=True) parser.add_argument("-m", "--milestone", type=str, help="New Milestone name", required=True) parser.add_argument("-rm", "--delete", type=bool, help="Delete the milestone", default=False, required=False) args = parser.parse_args() project_map = {} projects = fogbugz.listProjects() for item in projects.findAll("project"): proj_number = item.ixproject.string.encode("UTF-8") proj_name = item.sproject.string.encode("UTF-8") project_map.update({proj_name: proj_number}) milestone_map = {} milestones = fogbugz.listFixFors() for item in milestones.findAll("fixfor"): milestone_number = item.ixfixfor.string.encode("UTF-8") milestone_name = item.sfixfor.string.encode("UTF-8") milestone_map.update({milestone_name: milestone_number}) try:
article_ids = get_article_ids(fb, wiki_id) for article_id in article_ids: article = fb.viewArticle(ixWikiPage=article_id) headline = article.wikipage.sHeadline.string body = article.wikipage.sBody.string print(headline) filename = headline.replace('/', '') + '.html' path = os.path.join(wiki_name, filename) # Block for just writing out HTML if False: with open(path, 'w') as f: try: f.write(body) except: print("Unable to write {} - {}".format(wiki_name, headline)) # Convert to markdown and write try: output = pypandoc.convert_text(body, to='md', format='html', outputfile=path) except: print("Unable to write {} - {}".format(wiki_name, headline)) if __name__ == '__main__': fb = FogBugz(fbSettings.URL, fbSettings.TOKEN) download_wikis(fb)
import FbNotifier_UI from tactic_client_lib import TacticServerStub import Skype4Py from PySide import QtCore, QtGui server = TacticServerStub(setup=False) tactic_server_ip = socket.gethostbyname("vg.com") server.set_server(tactic_server_ip) server.set_project("simpleslot") ticket = server.get_ticket("julio", "1234") server.set_ticket(ticket) fb = FogBugz("https://fb.vir888.com") fb.logon("ART-Julio", "chicago") class MainWindow(QtGui.QDialog): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.ui = FbNotifier_UI.Ui_FbNotifier() self.ui.setupUi(self) self.ui.pushButton.clicked.connect(self.listen) self.ui.tableWidget.setColumnWidth(0, 150) self.ui.tableWidget.setColumnWidth(1, 390) self.ui.tableWidget.setColumnWidth(2, 80) self.ui.tableWidget.setColumnWidth(3, 80) self.ui.tableWidget.setColumnWidth(4, 80)
import settings from optparse import OptionParser parser = OptionParser() parser.add_option('-s', '--search', dest='search', help="Search for the given keywords", metavar="KEYWORDS") (options, args) = parser.parse_args() print options print args from fogbugz import FogBugz fb = FogBugz(settings.url) fb.logon(settings.user_email, settings.user_pass) if options.search: resp = fb.search(q=settings.default_search_prefix + options.search, cols="sTitle,ixPriority,hrsOrigEst,hrsCurrEst,hrsElapsed,ixBugParent" ) for case in resp.cases.childGenerator(): print case['ixbug'], case.stitle.string print case
import fbSettings from fogbugz import FogBugz from random import choice from random import shuffle from time import sleep from time import strftime IX_PERSON_UP_FOR_GRABS = 53 # the ixPerson value of the Up For Grabs user IX_AREA_SUPPORT = 36 # the ixArea value of the cases in your support queue REPS = { 25 : ['Danny Test',1], # a list of team members, using this format: 52 : ['Eric Test', 1]} # { ixPerson : [name, weight]... #Log onto FogBugz print "Logging in..." fogbugz = FogBugz(fbSettings.URL) fogbugz.logon(fbSettings.Login, fbSettings.pw) assignment = {} #Add users and current assignment count to dictionary. for rep in REPS: searchString = 'assignedto: "=%s" status:"Reviewed"' % (rep) num = str(fogbugz.search(q=searchString)).split('"') assignment[rep] = num[1] for user in assignment: print user, "has", assignment[user], "assignment(s)!" #Code for assignment is only scaleable up to this point. Per convo w/ Danny, we will review this and make necessary edits once we hire more automation engineers. sum = int(assignment.values()[0])-int(assignment.values()[1]) #Obtain all tickets assigned to our main QA user. searchString = 'assignedto: "=%s"' % (IX_PERSON_UP_FOR_GRABS) grabs = fogbugz.search(q=searchString) tickets = []
def getFogBugzConnection(url, token): return FogBugz(url, token)
def main(): print("Started the program... ") print(str(datetime.now().strftime(FORMAT_OF_DATE))) start = time.time() sheets = initgooglesheets() # Fogbugz stuff fb = FogBugz(getpath(), getapikey(), api_version=8) # ---------------------------------------------------------------------------------------------------------- # Getting Day0 print('Query set to day0') query = getday0() resultListOfCases = getcaseslist(fb, query) firstTimeWriting = False listLength = str(len(resultListOfCases)) oldestCaseDate = resultListOfCases[0].lastUpdated # Calling all the information gathering functions writeoldestcases(sheets, resultListOfCases, 3, 1) writefiltercount(firstTimeWriting, sheets, datetime.now(), listLength, 10, 1, 500) writeday0age(sheets, oldestCaseDate, 10, 1, 7) print('Day 0 query finished') # ---------------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------------- # Continuing non day0 queues # ----------------------------------------------------------------------------------------------------------- # Getting oldest cases assigned to us without update print('Query set to oldest case without update') query = getoldestcasesnoupdate() resultListOfCases = getcaseslist(fb, query) oldestCaseDate = resultListOfCases[0].lastUpdated # Calling all the information gathering functions writeoldestcases(sheets, resultListOfCases, 3, 8) writeoldestcasenoupdateage(sheets, oldestCaseDate, 10, 8, 10) print('Oldest cases without an update query finished') # ---------------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------------- # Getting pro filter cases print('Query set to pro filter') query = getprofilter() resultListOfCases = getcaseslist(fb, query) listLength = str(len(resultListOfCases)) # Calling all the information gathering functions # writeoldestcases(sheets, resultListOfCases, 3, 15) writefiltercount(True, sheets, datetime.now(), listLength, 10, 15, 0) print('Pro filter query finished') # ---------------------------------------------------------------------------------------------------------- # Getting oldest resolved cases assigned to us print('Query set to oldest cases resolved and assigned to us') query = getoldestresolvedcases() resultListOfCases = getcaseslist(fb, query) oldestCaseDate = resultListOfCases[0].lastUpdated # Calling all the information gathering functions writeoldestcases(sheets, resultListOfCases, 3, 22) writeoldestcasenoupdateage(sheets, oldestCaseDate, 10, 22, 30) print('Oldest resolved cases without an update query finished') # ---------------------------------------------------------------------------------------------------------- writecrashnoncrashteams(sheets, fb, 3, 30) # ---------------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------------- print('Data writing to Sheets finished') end = time.time() print('Finished program. Time spent: ' + str(end - start)) print(str(datetime.now().strftime(FORMAT_OF_DATE)))