{"action":"created","comment":{"url":"https://api.github.com/repos/potentialventures/cocotb/pulls/comments/240417552","pull_request_review_id":183444704,"id":240417552,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI0MDQxNzU1Mg==","diff_hunk":"@@ -117,106 +699,372 @@ def _printRecord(self, level, filename, lineno, msg, function):\n             be printed regardless\n         \"\"\"\n         if self.logger.isEnabledFor(level):\n-            record = self.logger.makeRecord(self._log_name,\n-                                            level,\n-                                            filename,\n-                                            lineno,\n-                                            msg,\n-                                            None,\n-                                            None,\n-                                            function)\n+            record = self.makeRecord(self._log_name,\n+                                     level,\n+                                     filename,\n+                                     lineno,\n+                                     msg,\n+                                     None,\n+                                     None,\n+                                     function)\n             self.logger.handle(record)\n \n-    def warn(self, msg, *args, **kwargs):\n-        self._makeRecord(logging.WARNING, msg, args, **kwargs)\n+    def __getattr__(self, attribute):\n+        \"\"\"Forward any attribute accesses on to our wrapped logger object\"\"\"\n+        return getattr(self.logger, attribute)\n \n-    def warning(self, msg, *args, **kwargs):\n-        self._makeRecord(logging.WARNING, msg, args, **kwargs)\n \n-    def debug(self, msg, *args, **kwargs):\n-        self._makeRecord(logging.DEBUG, msg, args, **kwargs)\n+class InvalidColumnFormat(Exception):\n+    \"\"\"Exception used by the ColumnFormatter\"\"\"\n+    pass\n \n-    def error(self, msg, *args, **kwargs):\n-        self._makeRecord(logging.ERROR, msg, args, **kwargs)\n+class StrFormatStyle(object):\n+    default_format = '{message}'\n+    asctime_format = '{asctime}'\n+    asctime_search = '{asctime'\n+    simtime_search = '{simtime'\n \n-    def critical(self, msg, *args, **kwargs):\n-        self._makeRecord(logging.CRITICAL, msg, args, **kwargs)\n+    def __init__(self, fmt):\n+        self._fmt = fmt or self.default_format\n \n-    def info(self, msg, *args, **kwargs):\n-        self._makeRecord(logging.INFO, msg, args, **kwargs)\n+    def usesTime(self):\n+        return self._fmt.find(self.asctime_search) >= 0\n \n-    def __getattr__(self, attribute):\n-        \"\"\"Forward any other attribute accesses on to our logger object\"\"\"\n-        return getattr(self.logger, attribute)\n+    def usesSimTime(self):\n+        return self._fmt.find(self.simtime_search) >= 0\n \n+    def format(self, record):\n+        return self._fmt.format(**record.__dict__)\n \n-class SimLogFormatter(logging.Formatter):\n-    \"\"\"Log formatter to provide consistent log message handling.\"\"\"\n+class ColumnFormatter(logging.Formatter):\n+    default_simtime_format = '{:>6.2f}ns'\n+    fmt_spec_re            = re.compile('((?P<fill>.)?(?P<align>[<>=^]))?(?P<sign>[+\\- ])?(?P<alt_form>#)?(?P<zero_fill>0)?(?P<width>\\d+)?(?P<comma>,)?(?P<precision>\\.\\d+)?(?P<type>[bcdeEfFgGnosxX%])?')\n+    fmt_simtime_re         = re.compile('(?P<spec>.*?)?(?P<resolution>fs|ps|ns|us|ms|sec)')\n+\n+    def __init__(self, fmt=None, datefmt=None, style=None, simtimefmt=None, separator=' | ', divider_char='-', divider_len=120, header_char='-', header_len=120, columns=[], show_cols=None):\n+        \"\"\"Logging formatter that formats fields in columns, ensuring the text does\n+        not exceed the column width through truncation.  Column formats must be\n+        specified in the string format style, e.g. {col:8s}\n+\n+        All columns must have a fixed width with the exception of the last column\n+        which is defined by the 'fmt' argument.\n+\n+        Multi-line messages will be properly padded to maintain the column structure\n+\n+        Kwargs:\n+                     fmt (str): Fromat for the last column\n+                 datefmt (str): Format string for creating {asctime}\n+                   style (str): IGNORED (Required for supporting fileConfig\n+              simtimefmt (str): Format string for creating {simtime}\n+               separator (str): The string separating the columns\n+           divider_char (char): Character for the divider markers\n+             divider_len (int): Length of the divider markers\n+            header_char (char): Character for the divider markers\n+              header_len (int): Length of the divider markers\n+                columns (list): List of formats for persistent columns\n+              show_cols (list): List of columns to display (None means all, Empty only shows the message)\n+\n+        Excetpions:","path":"cocotb/log.py","position":813,"original_position":813,"commit_id":"92e113e7aa0fca3b2060cc04d36fa1f55ab088cd","original_commit_id":"92e113e7aa0fca3b2060cc04d36fa1f55ab088cd","user":{"login":"cmarqu","id":360986,"node_id":"MDQ6VXNlcjM2MDk4Ng==","avatar_url":"https://avatars0.githubusercontent.com/u/360986?v=4","gravatar_id":"","url":"https://api.github.com/users/cmarqu","html_url":"https://github.com/cmarqu","followers_url":"https://api.github.com/users/cmarqu/followers","following_url":"https://api.github.com/users/cmarqu/following{/other_user}","gists_url":"https://api.github.com/users/cmarqu/gists{/gist_id}","starred_url":"https://api.github.com/users/cmarqu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cmarqu/subscriptions","organizations_url":"https://api.github.com/users/cmarqu/orgs","repos_url":"https://api.github.com/users/cmarqu/repos","events_url":"https://api.github.com/users/cmarqu/events{/privacy}","received_events_url":"https://api.github.com/users/cmarqu/received_events","type":"User","site_admin":false},"body":"Typo: \"Exceptions:\"","created_at":"2018-12-10T23:11:11Z","updated_at":"2018-12-10T23:11:11Z","html_url":"https://github.com/potentialventures/cocotb/pull/493#discussion_r240417552","pull_request_url":"https://api.github.com/repos/potentialventures/cocotb/pulls/493","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/potentialventures/cocotb/pulls/comments/240417552"},"html":{"href":"https://github.com/potentialventures/cocotb/pull/493#discussion_r240417552"},"pull_request":{"href":"https://api.github.com/repos/potentialventures/cocotb/pulls/493"}}},"pull_request":{"url":"https://api.github.com/repos/potentialventures/cocotb/pulls/493","id":90220105,"node_id":"MDExOlB1bGxSZXF1ZXN0OTAyMjAxMDU=","html_url":"https://github.com/potentialventures/cocotb/pull/493","diff_url":"https://github.com/potentialventures/cocotb/pull/493.diff","patch_url":"https://github.com/potentialventures/cocotb/pull/493.patch","issue_url":"https://api.github.com/repos/potentialventures/cocotb/issues/493","number":493,"state":"open","locked":false,"title":"Issue #10:  Logging Enhancements","user":{"login":"leftink","id":4984003,"node_id":"MDQ6VXNlcjQ5ODQwMDM=","avatar_url":"https://avatars1.githubusercontent.com/u/4984003?v=4","gravatar_id":"","url":"https://api.github.com/users/leftink","html_url":"https://github.com/leftink","followers_url":"https://api.github.com/users/leftink/followers","following_url":"https://api.github.com/users/leftink/following{/other_user}","gists_url":"https://api.github.com/users/leftink/gists{/gist_id}","starred_url":"https://api.github.com/users/leftink/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leftink/subscriptions","organizations_url":"https://api.github.com/users/leftink/orgs","repos_url":"https://api.github.com/users/leftink/repos","events_url":"https://api.github.com/users/leftink/events{/privacy}","received_events_url":"https://api.github.com/users/leftink/received_events","type":"User","site_admin":false},"body":"# Summary of Enhancements\n- User has full control of logging configuration, i.e. handlers, formatters, levels, etc.\n- Added a new level DEEP_DEBUG to allow two different levels of debug messages\n- Like the python logging facility, added module level log functions, i.e. critical(...), info(...), etc\n- Update SimLog to ensure consistent log naming and easily add keyword arguments into the format record\n- Added a ColumnFormatter with several features that is now the base class of the default log formatters.  This formatter will allow users the ability to define their own columns for the logs if they want to.\n- Added test_logging to demonstrate the features of the logging facility\n# Logging Configuration\n\nThe user can now specify a logging configuration file to be loaded at start-up by setting the environment variable **COCOTB_LOG_FMT**.\nThe user has access to the logging configuration through `cocotb.log.configure(cfg)`, where cfg is one of the formats listed below.\n## Configuration Formats\n- INI format (see python logging fileConfig format)\n  - cfg (str):  Name of file containing configuration\n  - cfg (obj): File-Like object, i.e. StringIO containing the configuration\n- DICT format (see python logging dictConfig format)\n  - cfg (dict): A dictionary containing the configuration\n  - cfg (str):  Name of file containing configuration encoded with JSON\n  - cfg (obj): File-Like object, i.e. StringIO containing configuration encoded with JSON\n  - If PyYAML available:\n    - cfg (str):  Name of file containing configuration encoded with YAML\n    - cfg (obj): File-Like object, i.e. StringIO containing configuration encoded with YAML\n\n**Note**: dictConfig() was not available until Python 2.7 so the full power of using a dictionary configuration will not work, but I did implement the \"incremental\" configuration so even older versions of python can benefit from using a DICT configuration for setting logger and handler levels.\n# Logging Levels\n\nAll existing log levels have been brought into the cocotb.log namespace so users should not need to import the python logging module at all.\n\nAdded a new Log Level **DEEP_DEBUG** and registered with the python logging module.  I have always found two levels of debugging to be extremely useful.  An example of where this could be used today would be to overhaul the debugging in the scheduler.  Currently there is another Environment variable to enable debugging in the scheduler, but that could be removed now and then current logging updated to have some basic deubug and then use the **DEEP_DEBUG** level for the information that will print a lot.  With the other changes, this will allow the users to have fine control when to enable/disable this extra logging.\n\nAdded a function `register_level_notify_cb(logger, f)` to register a callback function to be notified when the effective level of the logger changes.  An example of this use, is to notify the simulator module when the logger 'cocotb.gpi' changes levels.\n## COCOTB Group Log Level Getters/Setters\n\nI added some utility functions into the cocotb namespace to allow users to easily set/get the level for a particular group of loggers.\n\nThey take the form of:\n`<group>LogSetLevel(lvl)`, e.g. cocotbLogSetLevel(lvl)\n`<group>LogGetLevel()`, e.g. cocotbLogGetLevel()\n\nGroups:\n- cocotb:      Top Level logger, changes level for all loggers not explicitly set\n- gpi:         Controls the level for the GPI interface\n- coroutine:   Controls the level for all coroutines not explicitly set\n- function:    Controls the level for all \"functions\" not explicitly set\n- driver:      Controls the level for all drivers not explicitly set\n- handle:      Controls the level for all handlers not explicitly set\n- monitor:     Controls the level for all monitors not explicitly set\n- regression:  Controls the level for the RegressionManager\n- scheduler:   Controls the level for the Scheduler\n- scoreboard:  Controls the level for all scoreboards not explicitly set\n# Log Functions\n\nThere are module level logging functions that use the 'cocotb' logger.  I have also added a equivalent logging functions for logging deep_debug, i.e. log.deep_debug(...).\n# SimLog Enhancements\n\nLog naming no longer requires everyone to specify their logger name as 'cocotb.<name>'.  This just ensures that all logs that are created will fall under the 'cocotb' log hierarchy and therefore get the benefit of the default log level.\n\nNormally for standard logging, if you want to add addtional \"fields\" to the record that is passed to the formatter, you would have to create a dictionary and pass them through the 'extra' keyword arguments.  The updated SimLog functions will automatically take any keyword arguments that are not standard and automatically pack them into a dictionary and send to the standard \"extra\" argument.  This is useful to take advantage of several of the features in the formatter described below.\n# Column Log Formatter\n\nLogging formatter that formats fields in columns, ensuring the text does not exceed the column width through truncation.  The formatter is highly configurable.  All columns must have a fixed length with the exception of the last column.  The formatter supports multiple line messages with appropriate padding.\n\nThe user specifies a list of format strings for both the 'fixed' and the 'optional' columns.  Column formats must be specified in the string format style, e.g. {col:8s}.  The 'fixed' columns will always be formatted so the keys must be present in the record.  The 'optional' columns will try to format each column, but will not error if the key is not present in the record.  For 'optional' columns, if a key is not present in the record, the column is padded.  For 'optional' columns, if any optional column is present, then all optional columns are added to the log, using padded version if necessary, but if none of the optional column keys are present in the record, all of the optional columns will be suppressed.  We have used the optional columns to allow the user to specify an 'id' and a 'label' for each message that is not always present.\n\nThe log will have the following format:\n`<fixed_1><sep><fixed_2><sep>...<fixed_n><sep>[<optional_1><sep><optional_2><sep>...<sep><optional_n><sep>]<message>`\n## Configuration Parameters\n\n```\n                   fmt (str): Fromat for the last column\n               datefmt (str): Format string for creating {asctime}\n            simtimefmt (str): Format string for creating {simtime}\n             separator (str): The string separating the columns\n                prefix (str): A prefix that applied to the fmt string if formatting works\n               divider (int): Length of the divider/header markers\n                fixed (list): List of formats for persistent columns\n             optional (list): List of formats for optional columns\n```\n## SimTime Format\n\nThe user can specify the format and the resolution for the {simtime} field.  An example of the format string `'{>6.2f}ns'`\n## Runtime Controls\n\nThe following boolean commands can be added as keyword arguments to the logger function, i.e. logger.info(...), to have some control over formatting by setting them True/False:\n- include_optional\n- suppress\n- header\n- divider\n### include_optional\n\nThis control will force the optional columns to be shown (if True) and hidden (if False) regardless of the default formatting rules.\n### suppress\n\nIf set to True, will suppress **ALL** columns and only log the 'message' without any columns pre-pended.\n### header\n\nIf True, will put the 'message' into a header like below:\n\n```\n        -----------------------------------------------------------------------------\n        -- <message>                                                               --\n        -----------------------------------------------------------------------------\n```\n### divider\n\nIf True, will put the message into a divider string and if the message is empty, will just create a divider.\n\n```\n        ---------------------------------<message>-----------------------------------\nor\n        -----------------------------------------------------------------------------\n```\n","created_at":"2016-10-20T15:08:49Z","updated_at":"2018-12-10T23:11:11Z","closed_at":null,"merged_at":null,"merge_commit_sha":"18a1be6969e310aa16f9d390c4ea6db42d690c83","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":1153587178,"node_id":"MDU6TGFiZWwxMTUzNTg3MTc4","url":"https://api.github.com/repos/potentialventures/cocotb/labels/status:needinfo","name":"status:needinfo","color":"efe975","default":false},{"id":1153726201,"node_id":"MDU6TGFiZWwxMTUzNzI2MjAx","url":"https://api.github.com/repos/potentialventures/cocotb/labels/status:needs-rebase","name":"status:needs-rebase","color":"85c5d3","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/potentialventures/cocotb/pulls/493/commits","review_comments_url":"https://api.github.com/repos/potentialventures/cocotb/pulls/493/comments","review_comment_url":"https://api.github.com/repos/potentialventures/cocotb/pulls/comments{/number}","comments_url":"https://api.github.com/repos/potentialventures/cocotb/issues/493/comments","statuses_url":"https://api.github.com/repos/potentialventures/cocotb/statuses/92e113e7aa0fca3b2060cc04d36fa1f55ab088cd","head":{"label":"leftink:logger_update","ref":"logger_update","sha":"92e113e7aa0fca3b2060cc04d36fa1f55ab088cd","user":{"login":"leftink","id":4984003,"node_id":"MDQ6VXNlcjQ5ODQwMDM=","avatar_url":"https://avatars1.githubusercontent.com/u/4984003?v=4","gravatar_id":"","url":"https://api.github.com/users/leftink","html_url":"https://github.com/leftink","followers_url":"https://api.github.com/users/leftink/followers","following_url":"https://api.github.com/users/leftink/following{/other_user}","gists_url":"https://api.github.com/users/leftink/gists{/gist_id}","starred_url":"https://api.github.com/users/leftink/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leftink/subscriptions","organizations_url":"https://api.github.com/users/leftink/orgs","repos_url":"https://api.github.com/users/leftink/repos","events_url":"https://api.github.com/users/leftink/events{/privacy}","received_events_url":"https://api.github.com/users/leftink/received_events","type":"User","site_admin":false},"repo":{"id":39316290,"node_id":"MDEwOlJlcG9zaXRvcnkzOTMxNjI5MA==","name":"cocotb","full_name":"leftink/cocotb","private":false,"owner":{"login":"leftink","id":4984003,"node_id":"MDQ6VXNlcjQ5ODQwMDM=","avatar_url":"https://avatars1.githubusercontent.com/u/4984003?v=4","gravatar_id":"","url":"https://api.github.com/users/leftink","html_url":"https://github.com/leftink","followers_url":"https://api.github.com/users/leftink/followers","following_url":"https://api.github.com/users/leftink/following{/other_user}","gists_url":"https://api.github.com/users/leftink/gists{/gist_id}","starred_url":"https://api.github.com/users/leftink/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leftink/subscriptions","organizations_url":"https://api.github.com/users/leftink/orgs","repos_url":"https://api.github.com/users/leftink/repos","events_url":"https://api.github.com/users/leftink/events{/privacy}","received_events_url":"https://api.github.com/users/leftink/received_events","type":"User","site_admin":false},"html_url":"https://github.com/leftink/cocotb","description":"Coroutine Co-simulation Test Bench ","fork":true,"url":"https://api.github.com/repos/leftink/cocotb","forks_url":"https://api.github.com/repos/leftink/cocotb/forks","keys_url":"https://api.github.com/repos/leftink/cocotb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/leftink/cocotb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/leftink/cocotb/teams","hooks_url":"https://api.github.com/repos/leftink/cocotb/hooks","issue_events_url":"https://api.github.com/repos/leftink/cocotb/issues/events{/number}","events_url":"https://api.github.com/repos/leftink/cocotb/events","assignees_url":"https://api.github.com/repos/leftink/cocotb/assignees{/user}","branches_url":"https://api.github.com/repos/leftink/cocotb/branches{/branch}","tags_url":"https://api.github.com/repos/leftink/cocotb/tags","blobs_url":"https://api.github.com/repos/leftink/cocotb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/leftink/cocotb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/leftink/cocotb/git/refs{/sha}","trees_url":"https://api.github.com/repos/leftink/cocotb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/leftink/cocotb/statuses/{sha}","languages_url":"https://api.github.com/repos/leftink/cocotb/languages","stargazers_url":"https://api.github.com/repos/leftink/cocotb/stargazers","contributors_url":"https://api.github.com/repos/leftink/cocotb/contributors","subscribers_url":"https://api.github.com/repos/leftink/cocotb/subscribers","subscription_url":"https://api.github.com/repos/leftink/cocotb/subscription","commits_url":"https://api.github.com/repos/leftink/cocotb/commits{/sha}","git_commits_url":"https://api.github.com/repos/leftink/cocotb/git/commits{/sha}","comments_url":"https://api.github.com/repos/leftink/cocotb/comments{/number}","issue_comment_url":"https://api.github.com/repos/leftink/cocotb/issues/comments{/number}","contents_url":"https://api.github.com/repos/leftink/cocotb/contents/{+path}","compare_url":"https://api.github.com/repos/leftink/cocotb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/leftink/cocotb/merges","archive_url":"https://api.github.com/repos/leftink/cocotb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/leftink/cocotb/downloads","issues_url":"https://api.github.com/repos/leftink/cocotb/issues{/number}","pulls_url":"https://api.github.com/repos/leftink/cocotb/pulls{/number}","milestones_url":"https://api.github.com/repos/leftink/cocotb/milestones{/number}","notifications_url":"https://api.github.com/repos/leftink/cocotb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/leftink/cocotb/labels{/name}","releases_url":"https://api.github.com/repos/leftink/cocotb/releases{/id}","deployments_url":"https://api.github.com/repos/leftink/cocotb/deployments","created_at":"2015-07-18T23:44:45Z","updated_at":"2018-12-07T22:50:32Z","pushed_at":"2018-12-10T14:13:12Z","git_url":"git://github.com/leftink/cocotb.git","ssh_url":"git@github.com:leftink/cocotb.git","clone_url":"https://github.com/leftink/cocotb.git","svn_url":"https://github.com/leftink/cocotb","homepage":null,"size":3269,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"potentialventures:master","ref":"master","sha":"e86924503bbb02a78f37c41716f9af56fb5fa6a1","user":{"login":"potentialventures","id":3698838,"node_id":"MDQ6VXNlcjM2OTg4Mzg=","avatar_url":"https://avatars3.githubusercontent.com/u/3698838?v=4","gravatar_id":"","url":"https://api.github.com/users/potentialventures","html_url":"https://github.com/potentialventures","followers_url":"https://api.github.com/users/potentialventures/followers","following_url":"https://api.github.com/users/potentialventures/following{/other_user}","gists_url":"https://api.github.com/users/potentialventures/gists{/gist_id}","starred_url":"https://api.github.com/users/potentialventures/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/potentialventures/subscriptions","organizations_url":"https://api.github.com/users/potentialventures/orgs","repos_url":"https://api.github.com/users/potentialventures/repos","events_url":"https://api.github.com/users/potentialventures/events{/privacy}","received_events_url":"https://api.github.com/users/potentialventures/received_events","type":"User","site_admin":false},"repo":{"id":10651005,"node_id":"MDEwOlJlcG9zaXRvcnkxMDY1MTAwNQ==","name":"cocotb","full_name":"potentialventures/cocotb","private":false,"owner":{"login":"potentialventures","id":3698838,"node_id":"MDQ6VXNlcjM2OTg4Mzg=","avatar_url":"https://avatars3.githubusercontent.com/u/3698838?v=4","gravatar_id":"","url":"https://api.github.com/users/potentialventures","html_url":"https://github.com/potentialventures","followers_url":"https://api.github.com/users/potentialventures/followers","following_url":"https://api.github.com/users/potentialventures/following{/other_user}","gists_url":"https://api.github.com/users/potentialventures/gists{/gist_id}","starred_url":"https://api.github.com/users/potentialventures/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/potentialventures/subscriptions","organizations_url":"https://api.github.com/users/potentialventures/orgs","repos_url":"https://api.github.com/users/potentialventures/repos","events_url":"https://api.github.com/users/potentialventures/events{/privacy}","received_events_url":"https://api.github.com/users/potentialventures/received_events","type":"User","site_admin":false},"html_url":"https://github.com/potentialventures/cocotb","description":"Coroutine Co-simulation Test Bench ","fork":false,"url":"https://api.github.com/repos/potentialventures/cocotb","forks_url":"https://api.github.com/repos/potentialventures/cocotb/forks","keys_url":"https://api.github.com/repos/potentialventures/cocotb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/potentialventures/cocotb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/potentialventures/cocotb/teams","hooks_url":"https://api.github.com/repos/potentialventures/cocotb/hooks","issue_events_url":"https://api.github.com/repos/potentialventures/cocotb/issues/events{/number}","events_url":"https://api.github.com/repos/potentialventures/cocotb/events","assignees_url":"https://api.github.com/repos/potentialventures/cocotb/assignees{/user}","branches_url":"https://api.github.com/repos/potentialventures/cocotb/branches{/branch}","tags_url":"https://api.github.com/repos/potentialventures/cocotb/tags","blobs_url":"https://api.github.com/repos/potentialventures/cocotb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/potentialventures/cocotb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/potentialventures/cocotb/git/refs{/sha}","trees_url":"https://api.github.com/repos/potentialventures/cocotb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/potentialventures/cocotb/statuses/{sha}","languages_url":"https://api.github.com/repos/potentialventures/cocotb/languages","stargazers_url":"https://api.github.com/repos/potentialventures/cocotb/stargazers","contributors_url":"https://api.github.com/repos/potentialventures/cocotb/contributors","subscribers_url":"https://api.github.com/repos/potentialventures/cocotb/subscribers","subscription_url":"https://api.github.com/repos/potentialventures/cocotb/subscription","commits_url":"https://api.github.com/repos/potentialventures/cocotb/commits{/sha}","git_commits_url":"https://api.github.com/repos/potentialventures/cocotb/git/commits{/sha}","comments_url":"https://api.github.com/repos/potentialventures/cocotb/comments{/number}","issue_comment_url":"https://api.github.com/repos/potentialventures/cocotb/issues/comments{/number}","contents_url":"https://api.github.com/repos/potentialventures/cocotb/contents/{+path}","compare_url":"https://api.github.com/repos/potentialventures/cocotb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/potentialventures/cocotb/merges","archive_url":"https://api.github.com/repos/potentialventures/cocotb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/potentialventures/cocotb/downloads","issues_url":"https://api.github.com/repos/potentialventures/cocotb/issues{/number}","pulls_url":"https://api.github.com/repos/potentialventures/cocotb/pulls{/number}","milestones_url":"https://api.github.com/repos/potentialventures/cocotb/milestones{/number}","notifications_url":"https://api.github.com/repos/potentialventures/cocotb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/potentialventures/cocotb/labels{/name}","releases_url":"https://api.github.com/repos/potentialventures/cocotb/releases{/id}","deployments_url":"https://api.github.com/repos/potentialventures/cocotb/deployments","created_at":"2013-06-12T20:07:15Z","updated_at":"2018-12-10T03:00:46Z","pushed_at":"2018-12-10T16:53:27Z","git_url":"git://github.com/potentialventures/cocotb.git","ssh_url":"git@github.com:potentialventures/cocotb.git","clone_url":"https://github.com/potentialventures/cocotb.git","svn_url":"https://github.com/potentialventures/cocotb","homepage":null,"size":3276,"stargazers_count":298,"watchers_count":298,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":131,"mirror_url":null,"archived":false,"open_issues_count":174,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":131,"open_issues":174,"watchers":298,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/potentialventures/cocotb/pulls/493"},"html":{"href":"https://github.com/potentialventures/cocotb/pull/493"},"issue":{"href":"https://api.github.com/repos/potentialventures/cocotb/issues/493"},"comments":{"href":"https://api.github.com/repos/potentialventures/cocotb/issues/493/comments"},"review_comments":{"href":"https://api.github.com/repos/potentialventures/cocotb/pulls/493/comments"},"review_comment":{"href":"https://api.github.com/repos/potentialventures/cocotb/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/potentialventures/cocotb/pulls/493/commits"},"statuses":{"href":"https://api.github.com/repos/potentialventures/cocotb/statuses/92e113e7aa0fca3b2060cc04d36fa1f55ab088cd"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"cmarqu"}}