We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
repo_info worker: dev/test branch
Please help us help you by filling out the following sections as thoroughly as you can.

**Description:**
Looks like the new Fork information collection has some kind of mismatch between the method and parameters passed: 

```
INFO:root:Worker ran into an error for task: {'job_type': 'MAINTAIN', 'models': ['repo_info'], 'display_name': 'repo_info model for url: https://github.com/davepacheco/node-verror.git', 'given': {'github_url': 'https://github.com/davepacheco/node-verror.git'}}

INFO:root:Printing traceback...

INFO:root:Traceback (most recent call last):
  File "/mnt/md0/github/augur-census/workers/worker_base.py", line 189, in collect
    model_method(message, repo_id)
  File "/mnt/md0/github/augur-census/workers/repo_info_worker/repo_info_worker/worker.py", line 149, in repo_info_model
    forked = self.is_forked(owner, repo)
  File "/mnt/md0/github/augur-census/workers/repo_info_worker/repo_info_worker/worker.py", line 232, in is_forked
    data = self.get_repo_data(self, url, r)
TypeError: get_repo_data() takes 3 positional arguments but 4 were given

INFO:root:This task inserted 0 tuples before failure.

INFO:root:Notifying broker and logging task failure in database...

INFO:werkzeug:127.0.0.1 - - [31/May/2020 18:48:58] "GET /AUGWOP/heartbeat HTTP/1.1" 200 -
INFO:root:Recorded job error in the history table for: {'job_type': 'MAINTAIN', 'models': ['repo_info'], 'display_name': 'repo_info model for url: https://github.com/davepacheco/node-verror.git', 'given': {'github_url': 'https://github.com/davepacheco/node-verror.git'}, 'worker_id': 'com.augurlabs.core.repo_info_worker.50700'}

INFO:root:Updated job process for model: repo_info
```

If the log does not provide enough info, let me know 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `workers/repo_info_worker/repo_info_worker/worker.py`
Content:
```
1 import logging, os, sys, time, requests, json
2 from datetime import datetime
3 from multiprocessing import Process, Queue
4 import pandas as pd
5 import sqlalchemy as s
6 from workers.worker_base import Worker
7 
8 # NOTE: This worker primarily inserts rows into the REPO_INFO table, which serves the primary purposes of 
9 # 1. Displaying discrete metadata like "number of forks" and how they change over time 
10 # 2. Validating other workers, like those related to pull requests, issues, and commits. Our totals should be at or very near the totals in the repo_info table.
11 
12 # This table also updates teh REPO table in 2 cases: 
13 # 1. Recognizing when a repository is a forked repository by updating the "forked_from" field and 
14 # 2. Recognizing when a repository is archived, and recording the data we observed the change in status. 
15 
16 class RepoInfoWorker(Worker):
17     def __init__(self, config):
18         
19         # Define what this worker can be given and know how to interpret
20         given = [['github_url']]
21         models = ['repo_info']
22 
23         # Define the tables needed to insert, update, or delete on
24         data_tables = ['repo_info']
25         operations_tables = ['worker_history', 'worker_job']
26 
27         # Run the general worker initialization
28         super().__init__(config, given, models, data_tables, operations_tables)
29 
30         # Define data collection info
31         self.tool_source = 'Repo Info Worker'
32         self.tool_version = '0.0.1'
33         self.data_source = 'GitHub API'
34 
35     def repo_info_model(self, task, repo_id):
36 
37         github_url = task['given']['github_url']
38 
39         logging.info("Beginning filling the repo_info model for repo: " + github_url + "\n")
40 
41         owner, repo = self.get_owner_repo(github_url)
42 
43         url = 'https://api.github.com/graphql'
44 
45         query = """
46             {
47                 repository(owner:"%s", name:"%s"){
48                     updatedAt
49                     hasIssuesEnabled
50                     issues(states:OPEN) {
51                         totalCount
52                     }
53                     hasWikiEnabled
54                     forkCount
55                     defaultBranchRef {
56                         name
57                     }
58                     watchers {
59                         totalCount
60                     }
61                     id
62                     licenseInfo {
63                         name
64                         url
65                     }
66                     stargazers {
67                         totalCount
68                     }
69                     codeOfConduct {
70                         name
71                         url
72                     }
73                     issue_count: issues {
74                         totalCount
75                     }
76                     issues_closed: issues(states:CLOSED) {
77                         totalCount
78                     }
79                     pr_count: pullRequests {
80                         totalCount
81                     }
82                     pr_open: pullRequests(states: OPEN) {
83                         totalCount
84                     }
85                     pr_closed: pullRequests(states: CLOSED) {
86                         totalCount
87                     }
88                     pr_merged: pullRequests(states: MERGED) {
89                         totalCount
90                     }
91                     ref(qualifiedName: "master") {
92                         target {
93                             ... on Commit {
94                                 history(first: 0){
95                                     totalCount
96                                 }
97                             }
98                         }
99                     }
100                 }
101             }
102         """ % (owner, repo)
103 
104         # Hit the graphql endpoint and retry 3 times in case of failure
105         num_attempts = 0
106         success = False
107         while num_attempts < 3:
108             logging.info("Hitting endpoint: {} ...\n".format(url))
109             r = requests.post(url, json={'query': query}, headers=self.headers)
110             self.update_gh_rate_limit(r)
111 
112             try:
113                 data = r.json()
114             except:
115                 data = json.loads(json.dumps(r.text))
116 
117             if 'errors' in data:
118                 logging.info("Error!: {}".format(data['errors']))
119                 if data['errors'][0]['message'] == 'API rate limit exceeded':
120                     self.update_gh_rate_limit(r)
121                     continue
122 
123             if 'data' in data:
124                 success = True
125                 data = data['data']['repository']
126                 break
127             else:
128                 logging.info("Request returned a non-data dict: {}\n".format(data))
129                 if data['message'] == 'Not Found':
130                     logging.info("Github repo was not found or does not exist for endpoint: {}\n".format(url))
131                     break
132                 if data['message'] == 'You have triggered an abuse detection mechanism. Please wait a few minutes before you try again.':
133                     self.update_gh_rate_limit(r, temporarily_disable=True)
134                     continue
135                 if data['message'] == 'Bad credentials':
136                     self.update_gh_rate_limit(r, bad_credentials=True)
137                     continue
138             num_attempts += 1
139         if not success:
140             self.register_task_failure(task, repo_id, "Failed to hit endpoint: {}".format(url))
141             return
142 
143         # Get committers count info that requires seperate endpoint
144         committers_count = self.query_committers_count(owner, repo)
145         # Note that the addition of information about where a repository may be forked from, and whether a repository is archived, updates the `repo` table, not the `repo_info` table.
146         forked = self.is_forked(owner, repo)
147         archived = self.is_archived(owner, repo)
148         if archived is not False:
149             archived_date_collected = archived
150             archived = True
151 
152         # Put all data together in format of the table
153         logging.info(f'Inserting repo info for repo with id:{repo_id}, owner:{owner}, name:{repo}\n')
154         rep_inf = {
155             'repo_id': repo_id,
156             'last_updated': data['updatedAt'] if 'updatedAt' in data else None,
157             'issues_enabled': data['hasIssuesEnabled'] if 'hasIssuesEnabled' in data else None,
158             'open_issues': data['issues']['totalCount'] if data['issues'] else None,
159             'pull_requests_enabled': None,
160             'wiki_enabled': data['hasWikiEnabled'] if 'hasWikiEnabled' in data else None,
161             'pages_enabled': None,
162             'fork_count': data['forkCount'] if 'forkCount' in data else None,
163             'default_branch': data['defaultBranchRef']['name'] if data['defaultBranchRef'] else None,
164             'watchers_count': data['watchers']['totalCount'] if data['watchers'] else None,
165             'UUID': None,
166             'license': data['licenseInfo']['name'] if data['licenseInfo'] else None,
167             'stars_count': data['stargazers']['totalCount'] if data['stargazers'] else None,
168             'committers_count': committers_count,
169             'issue_contributors_count': None,
170             'changelog_file': None,
171             'contributing_file': None,
172             'license_file': data['licenseInfo']['url'] if data['licenseInfo'] else None,
173             'code_of_conduct_file': data['codeOfConduct']['url'] if data['codeOfConduct'] else None,
174             'security_issue_file': None,
175             'security_audit_file': None,
176             'status': None,
177             'keywords': None,
178             'commit_count': data['ref']['target']['history']['totalCount'] if data['ref'] else None,
179             'issues_count': data['issue_count']['totalCount'] if data['issue_count'] else None,
180             'issues_closed': data['issues_closed']['totalCount'] if data['issues_closed'] else None,
181             'pull_request_count': data['pr_count']['totalCount'] if data['pr_count'] else None,
182             'pull_requests_open': data['pr_open']['totalCount'] if data['pr_open'] else None,
183             'pull_requests_closed': data['pr_closed']['totalCount'] if data['pr_closed'] else None,
184             'pull_requests_merged': data['pr_merged']['totalCount'] if data['pr_merged'] else None,
185             'tool_source': self.tool_source,
186             'tool_version': self.tool_version,
187             'data_source': self.data_source,
188             'forked_from': forked,
189             'repo_archived': archived,
190             'repo_archived_date_collected': archived_date_collected
191         }
192 
193         result = self.db.execute(self.repo_info_table.insert().values(rep_inf))
194         logging.info(f"Primary Key inserted into repo_info table: {result.inserted_primary_key}\n")
195         self.results_counter += 1
196 
197         logging.info(f"Inserted info for {owner}/{repo}\n")
198 
199         #Register this task as completed
200         self.register_task_completion(task, repo_id, "repo_info")
201 
202     def query_committers_count(self, owner, repo):
203         logging.info('Querying committers count\n')
204         url = f'https://api.github.com/repos/{owner}/{repo}/contributors?per_page=100'
205         committers = 0
206 
207         try:
208             while True:
209                 r = requests.get(url, headers=self.headers)
210                 self.update_gh_rate_limit(r)
211                 committers += len(r.json())
212 
213                 if 'next' not in r.links:
214                     break
215                 else:
216                     url = r.links['next']['url']
217         except Exception:
218             logging.exception('An error occured while querying contributor count\n')
219 
220         return committers
221 
222     def is_forked(self, owner, repo): #/repos/:owner/:repo parent
223         logging.info('Querying parent info to verify if the repo is forked\n')
224         url = f'https://api.github.com/repos/{owner}/{repo}'
225 
226         r = requests.get(url, headers=self.headers)
227         self.update_gh_rate_limit(r)
228 
229         data = self.get_repo_data(self, url, r)
230 
231         if 'fork' in data:
232             if 'parent' in data:
233                 return data['parent']['full_name']
234             return 'Parent not available'
235 
236         return False
237 
238     def is_archived(self, owner, repo):
239         logging.info('Querying committers count\n')
240         url = f'https://api.github.com/repos/{owner}/{repo}'
241 
242         r = requests.get(url, headers=self.headers)
243         self.update_gh_rate_limit(r)
244 
245         data = self.get_repo_data(self, url, r)
246 
247         if 'archived' in data:
248             if data['archived']:
249                 if 'updated_at' in data:
250                     return data['updated_at']
251                 return 'Date not available'
252             return False
253 
254         return False
255 
256     def get_repo_data(self, url, response):
257         success = False
258         try:
259             data = response.json()
260         except:
261             data = json.loads(json.dumps(response.text))
262 
263         if 'errors' in data:
264             logging.info("Error!: {}".format(data['errors']))
265             if data['errors']['message'] == 'API rate limit exceeded':
266                 self.update_gh_rate_limit(response)
267 
268         if 'id' in data:
269             success = True
270         else:
271             logging.info("Request returned a non-data dict: {}\n".format(data))
272             if data['message'] == 'Not Found':
273                 logging.info("Github repo was not found or does not exist for endpoint: {}\n".format(url))
274             if data['message'] == 'You have triggered an abuse detection mechanism. Please wait a few minutes before you try again.':
275                 self.update_gh_rate_limit(r, temporarily_disable=True)
276             if data['message'] == 'Bad credentials':
277                 self.update_gh_rate_limit(r, bad_credentials=True)
278         if not success:
279             self.register_task_failure(task, repo_id, "Failed to hit endpoint: {}".format(url))
280 
281         return data
282
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/workers/repo_info_worker/repo_info_worker/worker.py b/workers/repo_info_worker/repo_info_worker/worker.py
--- a/workers/repo_info_worker/repo_info_worker/worker.py
+++ b/workers/repo_info_worker/repo_info_worker/worker.py
@@ -226,7 +226,7 @@
         r = requests.get(url, headers=self.headers)
         self.update_gh_rate_limit(r)
 
-        data = self.get_repo_data(self, url, r)
+        data = self.get_repo_data(url, r)
 
         if 'fork' in data:
             if 'parent' in data:
@@ -242,7 +242,7 @@
         r = requests.get(url, headers=self.headers)
         self.update_gh_rate_limit(r)
 
-        data = self.get_repo_data(self, url, r)
+        data = self.get_repo_data(url, r)
 
         if 'archived' in data:
             if data['archived']:

{"golden_diff": "diff --git a/workers/repo_info_worker/repo_info_worker/worker.py b/workers/repo_info_worker/repo_info_worker/worker.py\n--- a/workers/repo_info_worker/repo_info_worker/worker.py\n+++ b/workers/repo_info_worker/repo_info_worker/worker.py\n@@ -226,7 +226,7 @@\n         r = requests.get(url, headers=self.headers)\n         self.update_gh_rate_limit(r)\n \n-        data = self.get_repo_data(self, url, r)\n+        data = self.get_repo_data(url, r)\n \n         if 'fork' in data:\n             if 'parent' in data:\n@@ -242,7 +242,7 @@\n         r = requests.get(url, headers=self.headers)\n         self.update_gh_rate_limit(r)\n \n-        data = self.get_repo_data(self, url, r)\n+        data = self.get_repo_data(url, r)\n \n         if 'archived' in data:\n             if data['archived']:\n", "issue": "repo_info worker: dev/test branch\nPlease help us help you by filling out the following sections as thoroughly as you can.\r\n\r\n**Description:**\r\nLooks like the new Fork information collection has some kind of mismatch between the method and parameters passed: \r\n\r\n```\r\nINFO:root:Worker ran into an error for task: {'job_type': 'MAINTAIN', 'models': ['repo_info'], 'display_name': 'repo_info model for url: https://github.com/davepacheco/node-verror.git', 'given': {'github_url': 'https://github.com/davepacheco/node-verror.git'}}\r\n\r\nINFO:root:Printing traceback...\r\n\r\nINFO:root:Traceback (most recent call last):\r\n  File \"/mnt/md0/github/augur-census/workers/worker_base.py\", line 189, in collect\r\n    model_method(message, repo_id)\r\n  File \"/mnt/md0/github/augur-census/workers/repo_info_worker/repo_info_worker/worker.py\", line 149, in repo_info_model\r\n    forked = self.is_forked(owner, repo)\r\n  File \"/mnt/md0/github/augur-census/workers/repo_info_worker/repo_info_worker/worker.py\", line 232, in is_forked\r\n    data = self.get_repo_data(self, url, r)\r\nTypeError: get_repo_data() takes 3 positional arguments but 4 were given\r\n\r\nINFO:root:This task inserted 0 tuples before failure.\r\n\r\nINFO:root:Notifying broker and logging task failure in database...\r\n\r\nINFO:werkzeug:127.0.0.1 - - [31/May/2020 18:48:58] \"GET /AUGWOP/heartbeat HTTP/1.1\" 200 -\r\nINFO:root:Recorded job error in the history table for: {'job_type': 'MAINTAIN', 'models': ['repo_info'], 'display_name': 'repo_info model for url: https://github.com/davepacheco/node-verror.git', 'given': {'github_url': 'https://github.com/davepacheco/node-verror.git'}, 'worker_id': 'com.augurlabs.core.repo_info_worker.50700'}\r\n\r\nINFO:root:Updated job process for model: repo_info\r\n```\r\n\r\nIf the log does not provide enough info, let me know \n", "before_files": [{"content": "import logging, os, sys, time, requests, json\nfrom datetime import datetime\nfrom multiprocessing import Process, Queue\nimport pandas as pd\nimport sqlalchemy as s\nfrom workers.worker_base import Worker\n\n# NOTE: This worker primarily inserts rows into the REPO_INFO table, which serves the primary purposes of \n# 1. Displaying discrete metadata like \"number of forks\" and how they change over time \n# 2. Validating other workers, like those related to pull requests, issues, and commits. Our totals should be at or very near the totals in the repo_info table.\n\n# This table also updates teh REPO table in 2 cases: \n# 1. Recognizing when a repository is a forked repository by updating the \"forked_from\" field and \n# 2. Recognizing when a repository is archived, and recording the data we observed the change in status. \n\nclass RepoInfoWorker(Worker):\n    def __init__(self, config):\n        \n        # Define what this worker can be given and know how to interpret\n        given = [['github_url']]\n        models = ['repo_info']\n\n        # Define the tables needed to insert, update, or delete on\n        data_tables = ['repo_info']\n        operations_tables = ['worker_history', 'worker_job']\n\n        # Run the general worker initialization\n        super().__init__(config, given, models, data_tables, operations_tables)\n\n        # Define data collection info\n        self.tool_source = 'Repo Info Worker'\n        self.tool_version = '0.0.1'\n        self.data_source = 'GitHub API'\n\n    def repo_info_model(self, task, repo_id):\n\n        github_url = task['given']['github_url']\n\n        logging.info(\"Beginning filling the repo_info model for repo: \" + github_url + \"\\n\")\n\n        owner, repo = self.get_owner_repo(github_url)\n\n        url = 'https://api.github.com/graphql'\n\n        query = \"\"\"\n            {\n                repository(owner:\"%s\", name:\"%s\"){\n                    updatedAt\n                    hasIssuesEnabled\n                    issues(states:OPEN) {\n                        totalCount\n                    }\n                    hasWikiEnabled\n                    forkCount\n                    defaultBranchRef {\n                        name\n                    }\n                    watchers {\n                        totalCount\n                    }\n                    id\n                    licenseInfo {\n                        name\n                        url\n                    }\n                    stargazers {\n                        totalCount\n                    }\n                    codeOfConduct {\n                        name\n                        url\n                    }\n                    issue_count: issues {\n                        totalCount\n                    }\n                    issues_closed: issues(states:CLOSED) {\n                        totalCount\n                    }\n                    pr_count: pullRequests {\n                        totalCount\n                    }\n                    pr_open: pullRequests(states: OPEN) {\n                        totalCount\n                    }\n                    pr_closed: pullRequests(states: CLOSED) {\n                        totalCount\n                    }\n                    pr_merged: pullRequests(states: MERGED) {\n                        totalCount\n                    }\n                    ref(qualifiedName: \"master\") {\n                        target {\n                            ... on Commit {\n                                history(first: 0){\n                                    totalCount\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        \"\"\" % (owner, repo)\n\n        # Hit the graphql endpoint and retry 3 times in case of failure\n        num_attempts = 0\n        success = False\n        while num_attempts < 3:\n            logging.info(\"Hitting endpoint: {} ...\\n\".format(url))\n            r = requests.post(url, json={'query': query}, headers=self.headers)\n            self.update_gh_rate_limit(r)\n\n            try:\n                data = r.json()\n            except:\n                data = json.loads(json.dumps(r.text))\n\n            if 'errors' in data:\n                logging.info(\"Error!: {}\".format(data['errors']))\n                if data['errors'][0]['message'] == 'API rate limit exceeded':\n                    self.update_gh_rate_limit(r)\n                    continue\n\n            if 'data' in data:\n                success = True\n                data = data['data']['repository']\n                break\n            else:\n                logging.info(\"Request returned a non-data dict: {}\\n\".format(data))\n                if data['message'] == 'Not Found':\n                    logging.info(\"Github repo was not found or does not exist for endpoint: {}\\n\".format(url))\n                    break\n                if data['message'] == 'You have triggered an abuse detection mechanism. Please wait a few minutes before you try again.':\n                    self.update_gh_rate_limit(r, temporarily_disable=True)\n                    continue\n                if data['message'] == 'Bad credentials':\n                    self.update_gh_rate_limit(r, bad_credentials=True)\n                    continue\n            num_attempts += 1\n        if not success:\n            self.register_task_failure(task, repo_id, \"Failed to hit endpoint: {}\".format(url))\n            return\n\n        # Get committers count info that requires seperate endpoint\n        committers_count = self.query_committers_count(owner, repo)\n        # Note that the addition of information about where a repository may be forked from, and whether a repository is archived, updates the `repo` table, not the `repo_info` table.\n        forked = self.is_forked(owner, repo)\n        archived = self.is_archived(owner, repo)\n        if archived is not False:\n            archived_date_collected = archived\n            archived = True\n\n        # Put all data together in format of the table\n        logging.info(f'Inserting repo info for repo with id:{repo_id}, owner:{owner}, name:{repo}\\n')\n        rep_inf = {\n            'repo_id': repo_id,\n            'last_updated': data['updatedAt'] if 'updatedAt' in data else None,\n            'issues_enabled': data['hasIssuesEnabled'] if 'hasIssuesEnabled' in data else None,\n            'open_issues': data['issues']['totalCount'] if data['issues'] else None,\n            'pull_requests_enabled': None,\n            'wiki_enabled': data['hasWikiEnabled'] if 'hasWikiEnabled' in data else None,\n            'pages_enabled': None,\n            'fork_count': data['forkCount'] if 'forkCount' in data else None,\n            'default_branch': data['defaultBranchRef']['name'] if data['defaultBranchRef'] else None,\n            'watchers_count': data['watchers']['totalCount'] if data['watchers'] else None,\n            'UUID': None,\n            'license': data['licenseInfo']['name'] if data['licenseInfo'] else None,\n            'stars_count': data['stargazers']['totalCount'] if data['stargazers'] else None,\n            'committers_count': committers_count,\n            'issue_contributors_count': None,\n            'changelog_file': None,\n            'contributing_file': None,\n            'license_file': data['licenseInfo']['url'] if data['licenseInfo'] else None,\n            'code_of_conduct_file': data['codeOfConduct']['url'] if data['codeOfConduct'] else None,\n            'security_issue_file': None,\n            'security_audit_file': None,\n            'status': None,\n            'keywords': None,\n            'commit_count': data['ref']['target']['history']['totalCount'] if data['ref'] else None,\n            'issues_count': data['issue_count']['totalCount'] if data['issue_count'] else None,\n            'issues_closed': data['issues_closed']['totalCount'] if data['issues_closed'] else None,\n            'pull_request_count': data['pr_count']['totalCount'] if data['pr_count'] else None,\n            'pull_requests_open': data['pr_open']['totalCount'] if data['pr_open'] else None,\n            'pull_requests_closed': data['pr_closed']['totalCount'] if data['pr_closed'] else None,\n            'pull_requests_merged': data['pr_merged']['totalCount'] if data['pr_merged'] else None,\n            'tool_source': self.tool_source,\n            'tool_version': self.tool_version,\n            'data_source': self.data_source,\n            'forked_from': forked,\n            'repo_archived': archived,\n            'repo_archived_date_collected': archived_date_collected\n        }\n\n        result = self.db.execute(self.repo_info_table.insert().values(rep_inf))\n        logging.info(f\"Primary Key inserted into repo_info table: {result.inserted_primary_key}\\n\")\n        self.results_counter += 1\n\n        logging.info(f\"Inserted info for {owner}/{repo}\\n\")\n\n        #Register this task as completed\n        self.register_task_completion(task, repo_id, \"repo_info\")\n\n    def query_committers_count(self, owner, repo):\n        logging.info('Querying committers count\\n')\n        url = f'https://api.github.com/repos/{owner}/{repo}/contributors?per_page=100'\n        committers = 0\n\n        try:\n            while True:\n                r = requests.get(url, headers=self.headers)\n                self.update_gh_rate_limit(r)\n                committers += len(r.json())\n\n                if 'next' not in r.links:\n                    break\n                else:\n                    url = r.links['next']['url']\n        except Exception:\n            logging.exception('An error occured while querying contributor count\\n')\n\n        return committers\n\n    def is_forked(self, owner, repo): #/repos/:owner/:repo parent\n        logging.info('Querying parent info to verify if the repo is forked\\n')\n        url = f'https://api.github.com/repos/{owner}/{repo}'\n\n        r = requests.get(url, headers=self.headers)\n        self.update_gh_rate_limit(r)\n\n        data = self.get_repo_data(self, url, r)\n\n        if 'fork' in data:\n            if 'parent' in data:\n                return data['parent']['full_name']\n            return 'Parent not available'\n\n        return False\n\n    def is_archived(self, owner, repo):\n        logging.info('Querying committers count\\n')\n        url = f'https://api.github.com/repos/{owner}/{repo}'\n\n        r = requests.get(url, headers=self.headers)\n        self.update_gh_rate_limit(r)\n\n        data = self.get_repo_data(self, url, r)\n\n        if 'archived' in data:\n            if data['archived']:\n                if 'updated_at' in data:\n                    return data['updated_at']\n                return 'Date not available'\n            return False\n\n        return False\n\n    def get_repo_data(self, url, response):\n        success = False\n        try:\n            data = response.json()\n        except:\n            data = json.loads(json.dumps(response.text))\n\n        if 'errors' in data:\n            logging.info(\"Error!: {}\".format(data['errors']))\n            if data['errors']['message'] == 'API rate limit exceeded':\n                self.update_gh_rate_limit(response)\n\n        if 'id' in data:\n            success = True\n        else:\n            logging.info(\"Request returned a non-data dict: {}\\n\".format(data))\n            if data['message'] == 'Not Found':\n                logging.info(\"Github repo was not found or does not exist for endpoint: {}\\n\".format(url))\n            if data['message'] == 'You have triggered an abuse detection mechanism. Please wait a few minutes before you try again.':\n                self.update_gh_rate_limit(r, temporarily_disable=True)\n            if data['message'] == 'Bad credentials':\n                self.update_gh_rate_limit(r, bad_credentials=True)\n        if not success:\n            self.register_task_failure(task, repo_id, \"Failed to hit endpoint: {}\".format(url))\n\n        return data\n", "path": "workers/repo_info_worker/repo_info_worker/worker.py"}], "after_files": [{"content": "import logging, os, sys, time, requests, json\nfrom datetime import datetime\nfrom multiprocessing import Process, Queue\nimport pandas as pd\nimport sqlalchemy as s\nfrom workers.worker_base import Worker\n\n# NOTE: This worker primarily inserts rows into the REPO_INFO table, which serves the primary purposes of \n# 1. Displaying discrete metadata like \"number of forks\" and how they change over time \n# 2. Validating other workers, like those related to pull requests, issues, and commits. Our totals should be at or very near the totals in the repo_info table.\n\n# This table also updates teh REPO table in 2 cases: \n# 1. Recognizing when a repository is a forked repository by updating the \"forked_from\" field and \n# 2. Recognizing when a repository is archived, and recording the data we observed the change in status. \n\nclass RepoInfoWorker(Worker):\n    def __init__(self, config):\n        \n        # Define what this worker can be given and know how to interpret\n        given = [['github_url']]\n        models = ['repo_info']\n\n        # Define the tables needed to insert, update, or delete on\n        data_tables = ['repo_info']\n        operations_tables = ['worker_history', 'worker_job']\n\n        # Run the general worker initialization\n        super().__init__(config, given, models, data_tables, operations_tables)\n\n        # Define data collection info\n        self.tool_source = 'Repo Info Worker'\n        self.tool_version = '0.0.1'\n        self.data_source = 'GitHub API'\n\n    def repo_info_model(self, task, repo_id):\n\n        github_url = task['given']['github_url']\n\n        logging.info(\"Beginning filling the repo_info model for repo: \" + github_url + \"\\n\")\n\n        owner, repo = self.get_owner_repo(github_url)\n\n        url = 'https://api.github.com/graphql'\n\n        query = \"\"\"\n            {\n                repository(owner:\"%s\", name:\"%s\"){\n                    updatedAt\n                    hasIssuesEnabled\n                    issues(states:OPEN) {\n                        totalCount\n                    }\n                    hasWikiEnabled\n                    forkCount\n                    defaultBranchRef {\n                        name\n                    }\n                    watchers {\n                        totalCount\n                    }\n                    id\n                    licenseInfo {\n                        name\n                        url\n                    }\n                    stargazers {\n                        totalCount\n                    }\n                    codeOfConduct {\n                        name\n                        url\n                    }\n                    issue_count: issues {\n                        totalCount\n                    }\n                    issues_closed: issues(states:CLOSED) {\n                        totalCount\n                    }\n                    pr_count: pullRequests {\n                        totalCount\n                    }\n                    pr_open: pullRequests(states: OPEN) {\n                        totalCount\n                    }\n                    pr_closed: pullRequests(states: CLOSED) {\n                        totalCount\n                    }\n                    pr_merged: pullRequests(states: MERGED) {\n                        totalCount\n                    }\n                    ref(qualifiedName: \"master\") {\n                        target {\n                            ... on Commit {\n                                history(first: 0){\n                                    totalCount\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        \"\"\" % (owner, repo)\n\n        # Hit the graphql endpoint and retry 3 times in case of failure\n        num_attempts = 0\n        success = False\n        while num_attempts < 3:\n            logging.info(\"Hitting endpoint: {} ...\\n\".format(url))\n            r = requests.post(url, json={'query': query}, headers=self.headers)\n            self.update_gh_rate_limit(r)\n\n            try:\n                data = r.json()\n            except:\n                data = json.loads(json.dumps(r.text))\n\n            if 'errors' in data:\n                logging.info(\"Error!: {}\".format(data['errors']))\n                if data['errors'][0]['message'] == 'API rate limit exceeded':\n                    self.update_gh_rate_limit(r)\n                    continue\n\n            if 'data' in data:\n                success = True\n                data = data['data']['repository']\n                break\n            else:\n                logging.info(\"Request returned a non-data dict: {}\\n\".format(data))\n                if data['message'] == 'Not Found':\n                    logging.info(\"Github repo was not found or does not exist for endpoint: {}\\n\".format(url))\n                    break\n                if data['message'] == 'You have triggered an abuse detection mechanism. Please wait a few minutes before you try again.':\n                    self.update_gh_rate_limit(r, temporarily_disable=True)\n                    continue\n                if data['message'] == 'Bad credentials':\n                    self.update_gh_rate_limit(r, bad_credentials=True)\n                    continue\n            num_attempts += 1\n        if not success:\n            self.register_task_failure(task, repo_id, \"Failed to hit endpoint: {}\".format(url))\n            return\n\n        # Get committers count info that requires seperate endpoint\n        committers_count = self.query_committers_count(owner, repo)\n        # Note that the addition of information about where a repository may be forked from, and whether a repository is archived, updates the `repo` table, not the `repo_info` table.\n        forked = self.is_forked(owner, repo)\n        archived = self.is_archived(owner, repo)\n        if archived is not False:\n            archived_date_collected = archived\n            archived = True\n\n        # Put all data together in format of the table\n        logging.info(f'Inserting repo info for repo with id:{repo_id}, owner:{owner}, name:{repo}\\n')\n        rep_inf = {\n            'repo_id': repo_id,\n            'last_updated': data['updatedAt'] if 'updatedAt' in data else None,\n            'issues_enabled': data['hasIssuesEnabled'] if 'hasIssuesEnabled' in data else None,\n            'open_issues': data['issues']['totalCount'] if data['issues'] else None,\n            'pull_requests_enabled': None,\n            'wiki_enabled': data['hasWikiEnabled'] if 'hasWikiEnabled' in data else None,\n            'pages_enabled': None,\n            'fork_count': data['forkCount'] if 'forkCount' in data else None,\n            'default_branch': data['defaultBranchRef']['name'] if data['defaultBranchRef'] else None,\n            'watchers_count': data['watchers']['totalCount'] if data['watchers'] else None,\n            'UUID': None,\n            'license': data['licenseInfo']['name'] if data['licenseInfo'] else None,\n            'stars_count': data['stargazers']['totalCount'] if data['stargazers'] else None,\n            'committers_count': committers_count,\n            'issue_contributors_count': None,\n            'changelog_file': None,\n            'contributing_file': None,\n            'license_file': data['licenseInfo']['url'] if data['licenseInfo'] else None,\n            'code_of_conduct_file': data['codeOfConduct']['url'] if data['codeOfConduct'] else None,\n            'security_issue_file': None,\n            'security_audit_file': None,\n            'status': None,\n            'keywords': None,\n            'commit_count': data['ref']['target']['history']['totalCount'] if data['ref'] else None,\n            'issues_count': data['issue_count']['totalCount'] if data['issue_count'] else None,\n            'issues_closed': data['issues_closed']['totalCount'] if data['issues_closed'] else None,\n            'pull_request_count': data['pr_count']['totalCount'] if data['pr_count'] else None,\n            'pull_requests_open': data['pr_open']['totalCount'] if data['pr_open'] else None,\n            'pull_requests_closed': data['pr_closed']['totalCount'] if data['pr_closed'] else None,\n            'pull_requests_merged': data['pr_merged']['totalCount'] if data['pr_merged'] else None,\n            'tool_source': self.tool_source,\n            'tool_version': self.tool_version,\n            'data_source': self.data_source,\n            'forked_from': forked,\n            'repo_archived': archived,\n            'repo_archived_date_collected': archived_date_collected\n        }\n\n        result = self.db.execute(self.repo_info_table.insert().values(rep_inf))\n        logging.info(f\"Primary Key inserted into repo_info table: {result.inserted_primary_key}\\n\")\n        self.results_counter += 1\n\n        logging.info(f\"Inserted info for {owner}/{repo}\\n\")\n\n        #Register this task as completed\n        self.register_task_completion(task, repo_id, \"repo_info\")\n\n    def query_committers_count(self, owner, repo):\n        logging.info('Querying committers count\\n')\n        url = f'https://api.github.com/repos/{owner}/{repo}/contributors?per_page=100'\n        committers = 0\n\n        try:\n            while True:\n                r = requests.get(url, headers=self.headers)\n                self.update_gh_rate_limit(r)\n                committers += len(r.json())\n\n                if 'next' not in r.links:\n                    break\n                else:\n                    url = r.links['next']['url']\n        except Exception:\n            logging.exception('An error occured while querying contributor count\\n')\n\n        return committers\n\n    def is_forked(self, owner, repo): #/repos/:owner/:repo parent\n        logging.info('Querying parent info to verify if the repo is forked\\n')\n        url = f'https://api.github.com/repos/{owner}/{repo}'\n\n        r = requests.get(url, headers=self.headers)\n        self.update_gh_rate_limit(r)\n\n        data = self.get_repo_data(url, r)\n\n        if 'fork' in data:\n            if 'parent' in data:\n                return data['parent']['full_name']\n            return 'Parent not available'\n\n        return False\n\n    def is_archived(self, owner, repo):\n        logging.info('Querying committers count\\n')\n        url = f'https://api.github.com/repos/{owner}/{repo}'\n\n        r = requests.get(url, headers=self.headers)\n        self.update_gh_rate_limit(r)\n\n        data = self.get_repo_data(url, r)\n\n        if 'archived' in data:\n            if data['archived']:\n                if 'updated_at' in data:\n                    return data['updated_at']\n                return 'Date not available'\n            return False\n\n        return False\n\n    def get_repo_data(self, url, response):\n        success = False\n        try:\n            data = response.json()\n        except:\n            data = json.loads(json.dumps(response.text))\n\n        if 'errors' in data:\n            logging.info(\"Error!: {}\".format(data['errors']))\n            if data['errors']['message'] == 'API rate limit exceeded':\n                self.update_gh_rate_limit(response)\n\n        if 'id' in data:\n            success = True\n        else:\n            logging.info(\"Request returned a non-data dict: {}\\n\".format(data))\n            if data['message'] == 'Not Found':\n                logging.info(\"Github repo was not found or does not exist for endpoint: {}\\n\".format(url))\n            if data['message'] == 'You have triggered an abuse detection mechanism. Please wait a few minutes before you try again.':\n                self.update_gh_rate_limit(r, temporarily_disable=True)\n            if data['message'] == 'Bad credentials':\n                self.update_gh_rate_limit(r, bad_credentials=True)\n        if not success:\n            self.register_task_failure(task, repo_id, \"Failed to hit endpoint: {}\".format(url))\n\n        return data\n", "path": "workers/repo_info_worker/repo_info_worker/worker.py"}]}