{"action":"created","comment":{"url":"https://api.github.com/repos/caterinaurban/Lyra/pulls/comments/107864415","pull_request_review_id":28861442,"id":107864415,"diff_hunk":"@@ -0,0 +1,360 @@\n+\"\"\"Inferrer for python expressions.\n+\n+Infers the types for the following expressions:\n+     - BinOp(expr left, operator op, expr right)\n+     - UnaryOp(unaryop op, expr operand)\n+     - Dict(expr* keys, expr* values)\n+     - Set(expr* elts)\n+     - Num(object n)\n+     - Str(string s)\n+     - NameConstant(singleton value)\n+     - List(expr* elts, expr_context ctx)\n+     - Tuple(expr* elts, expr_context ctx)\n+     - Bytes(bytes s)\n+     - IfExp(expr test, expr body, expr orelse)\n+\t - Subscript(expr value, slice slice, expr_context ctx)\n+\t - Await(expr value) --> Python 3.5+\n+\t - Yield(expr? value)\n+     - Compare(expr left, cmpop* ops, expr* comparators)\n+     - Name(identifier id, expr_context ctx)\n+     - FormattedValue(expr value, int? conversion, expr? format_spec) --> Python 3.6+\n+     - JoinedStr(expr* values) --> Python 3.6+\n+     - ListComp(expr elt, comprehension* generators)\n+     - SetComp(expr elt, comprehension* generators)\n+     - DictComp(expr key, expr value, comprehension* generators)\n+\n+     TODO:\n+     - Lambda(arguments args, expr body)\n+     - GeneratorExp(expr elt, comprehension* generators)\n+     - YieldFrom(expr value)\n+     - Call(expr func, expr* args, keyword* keywords)\n+     - Attribute(expr value, identifier attr, expr_co0ontext ctx)\n+     - Starred(expr value, expr_context ctx)\n+\n+     TODO:\n+     - Infer (or narrow) types based on context. For example, in the following expression:\n+        (x + 2) * 3\n+        if the type of x is still not inferred (or inferred to be a union type), we can infer (narrow) that x\n+        is a numeric value (TBool, TInt or TFloat)\n+        Affected inference functions:\n+            - infer_binary_operation\n+            - infer_unary_operation\n+            - infer_subscript\n+            - infer_compare\n+\"\"\"\n+\n+import ast, sys\n+from i_types import *\n+from context import Context\n+from abc import ABCMeta, abstractmethod\n+from exceptions import HomogeneousTypesConflict\n+\n+def infer_numeric(node):\n+    \"\"\"Infer the type of a numeric node\"\"\"\n+    if type(node.n) == int:\n+        return TInt()\n+    if type(node.n) == float:\n+        return TFloat()\n+\n+def __get_supertype(elts, context):\n+    if len(elts) == 0:\n+        return TNone()\n+    supertype = infer(elts[0], context)\n+    for i in range(1, len(elts)):\n+        cur_type = infer(elts[i], context)\n+        if supertype.is_subtype(cur_type): # get the most generic type\n+            supertype = cur_type\n+        elif not cur_type.is_subtype(supertype): # make sure the list is homogeneous\n+            raise HomogeneousTypesConflict(supertype.get_name(), cur_type.get_name())\n+    return supertype\n+\n+def infer_list(node, context):\n+    \"\"\"Infer the type of a homogeneous list\n+\n+    Returns: TList(Type t), where t is the type of the list elements\n+    \"\"\"\n+    return TList(__get_supertype(node.elts, context))\n+\n+def infer_dict(node, context):\n+    \"\"\"Infer the type of a dictionary with homogeneous key set and value set\n+\n+    Returns: TDictionary(Type k_t, Type v_t), where:\n+            k_t is the type of dictionary keys\n+            v_t is the type of dictionary values\n+    \"\"\"\n+    keys_type = __get_supertype(node.keys, context)\n+    values_type = __get_supertype(node.values, context)\n+    return TDictionary(keys_type, values_type)\n+\n+def infer_tuple(node, context):\n+    \"\"\"Infer the type of a tuple\n+\n+    Returns: TTuple(Type[] t), where t is a list of the tuple's elements types\n+    \"\"\"\n+    tuple_types = []\n+    for elem in node.elts:\n+        elem_type = infer(elem, context)\n+        tuple_types.append(elem_type)\n+\n+    return TTuple(tuple_types)\n+\n+def infer_name_constant(node):\n+    \"\"\"Infer the type of name constants like: True, False, None\"\"\"\n+    if node.value == True or node.value == False:\n+        return TBool()\n+    elif node.value is None:\n+        return TNone()\n+    raise NotImplementedError(\"The inference for {} is not supported.\".format(node.value))\n+\n+def infer_set(node, context):\n+    \"\"\"Infer the type of a homogeneous set\n+\n+    Returns: TSet(Type t), where t is the type of the set elements\n+    \"\"\"\n+    return TSet(__get_supertype(node.elts, context))\n+\n+def is_numeric(t):\n+\treturn t.is_subtype(TFloat())\n+\n+def binary_operation_type(left_type, op, right_type):\n+    if isinstance(op, ast.Mult):\n+        # Handle sequence multiplication. Ex.:\n+        # [1,2,3] * 2 --> [1,2,3,1,2,3]\n+        # 2 * \"abc\" -- > \"abcabc\"\n+        if left_type.is_subtype(TInt()) and is_sequence(right_type):\n+            return right_type\n+        elif right_type.is_subtype(TInt()) and is_sequence(left_type):\n+            return left_type\n+\n+    if isinstance(op, ast.Add): # Check if it is a concatenation operation between sequences\n+        if isinstance(left_type, TTuple) and isinstance(right_type, TTuple):\n+            # Handle tuples concatenation:\n+            # (1, 2.0, \"string\") + (True, X()) --> (1, 2.0, \"string\", True, X())\n+            # The result type is the concatenation of both tuples' types\n+            new_tuple_types = left_type.types + right_type.types\n+            return TTuple(new_tuple_types)\n+\n+        if is_sequence(left_type) and is_sequence(right_type):\n+            if left_type.is_subtype(right_type):\n+                return right_type\n+            elif right_type.is_subtype(left_type):\n+                return left_type\n+\n+    if isinstance(op, ast.Div): # Check if it is a float division operation\n+        if left_type.is_subtype(TFloat()) and right_type.is_subtype(TFloat()):\n+            return TFloat()","path":"frontend/expr_inferrer.py","position":145,"original_position":145,"commit_id":"a5a5e9ac93311031fd4d27f80d027d95b5101732","original_commit_id":"a5a5e9ac93311031fd4d27f80d027d95b5101732","user":{"login":"mostafa-abdullah","id":12327683,"avatar_url":"https://avatars2.githubusercontent.com/u/12327683?v=3","gravatar_id":"","url":"https://api.github.com/users/mostafa-abdullah","html_url":"https://github.com/mostafa-abdullah","followers_url":"https://api.github.com/users/mostafa-abdullah/followers","following_url":"https://api.github.com/users/mostafa-abdullah/following{/other_user}","gists_url":"https://api.github.com/users/mostafa-abdullah/gists{/gist_id}","starred_url":"https://api.github.com/users/mostafa-abdullah/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mostafa-abdullah/subscriptions","organizations_url":"https://api.github.com/users/mostafa-abdullah/orgs","repos_url":"https://api.github.com/users/mostafa-abdullah/repos","events_url":"https://api.github.com/users/mostafa-abdullah/events{/privacy}","received_events_url":"https://api.github.com/users/mostafa-abdullah/received_events","type":"User","site_admin":false},"body":"int is a subtype of float, in case of `5 / 4` it will return a float type too.","created_at":"2017-03-24T09:38:28Z","updated_at":"2017-03-24T09:38:28Z","html_url":"https://github.com/caterinaurban/Lyra/pull/1#discussion_r107864415","pull_request_url":"https://api.github.com/repos/caterinaurban/Lyra/pulls/1","_links":{"self":{"href":"https://api.github.com/repos/caterinaurban/Lyra/pulls/comments/107864415"},"html":{"href":"https://github.com/caterinaurban/Lyra/pull/1#discussion_r107864415"},"pull_request":{"href":"https://api.github.com/repos/caterinaurban/Lyra/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/caterinaurban/Lyra/pulls/1","id":111518650,"html_url":"https://github.com/caterinaurban/Lyra/pull/1","diff_url":"https://github.com/caterinaurban/Lyra/pull/1.diff","patch_url":"https://github.com/caterinaurban/Lyra/pull/1.patch","issue_url":"https://api.github.com/repos/caterinaurban/Lyra/issues/1","number":1,"state":"open","locked":false,"title":"Implemented Expressions Inference","user":{"login":"mostafa-abdullah","id":12327683,"avatar_url":"https://avatars2.githubusercontent.com/u/12327683?v=3","gravatar_id":"","url":"https://api.github.com/users/mostafa-abdullah","html_url":"https://github.com/mostafa-abdullah","followers_url":"https://api.github.com/users/mostafa-abdullah/followers","following_url":"https://api.github.com/users/mostafa-abdullah/following{/other_user}","gists_url":"https://api.github.com/users/mostafa-abdullah/gists{/gist_id}","starred_url":"https://api.github.com/users/mostafa-abdullah/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mostafa-abdullah/subscriptions","organizations_url":"https://api.github.com/users/mostafa-abdullah/orgs","repos_url":"https://api.github.com/users/mostafa-abdullah/repos","events_url":"https://api.github.com/users/mostafa-abdullah/events{/privacy}","received_events_url":"https://api.github.com/users/mostafa-abdullah/received_events","type":"User","site_admin":false},"body":"Implemented the inference for all program expressions except those involving functions, classes and generators (To be implemented after sprint 2 and 3).\r\n\r\nThe changes include four files:\r\n\r\n- `i_types.py`: containing the classes for the inferred types.\r\n- `context.py`: containing the class for the context/scope mapping the program variables to their type.\r\n- `exceptions.py`: containing user defined exceptions.\r\n- `expr_inference.py`: The main module for inferring expressions.\r\n\r\nThe main inference function, depending on the type of the node passed as its argument, calls a specific inference function which handle the inference for specific nodes.\r\n\r\nI'm thinking instead of using nested `if/elif` conditions in `infer` function which violates the open-closed principle in some way, we can have a separate file that maps the types of the AST node to the corresponding inference function. I haven't figured out the best way to do it yet, but I'm thinking of a couple of approaches that I may try implementing, and of course any suggestions with this would be appreciated.","created_at":"2017-03-20T10:04:11Z","updated_at":"2017-03-24T09:38:28Z","closed_at":null,"merged_at":null,"merge_commit_sha":"247adb75f359bb24393f72779959e2ec769f15ea","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/caterinaurban/Lyra/pulls/1/commits","review_comments_url":"https://api.github.com/repos/caterinaurban/Lyra/pulls/1/comments","review_comment_url":"https://api.github.com/repos/caterinaurban/Lyra/pulls/comments{/number}","comments_url":"https://api.github.com/repos/caterinaurban/Lyra/issues/1/comments","statuses_url":"https://api.github.com/repos/caterinaurban/Lyra/statuses/a5a5e9ac93311031fd4d27f80d027d95b5101732","head":{"label":"mostafa-abdullah:master","ref":"master","sha":"a5a5e9ac93311031fd4d27f80d027d95b5101732","user":{"login":"mostafa-abdullah","id":12327683,"avatar_url":"https://avatars2.githubusercontent.com/u/12327683?v=3","gravatar_id":"","url":"https://api.github.com/users/mostafa-abdullah","html_url":"https://github.com/mostafa-abdullah","followers_url":"https://api.github.com/users/mostafa-abdullah/followers","following_url":"https://api.github.com/users/mostafa-abdullah/following{/other_user}","gists_url":"https://api.github.com/users/mostafa-abdullah/gists{/gist_id}","starred_url":"https://api.github.com/users/mostafa-abdullah/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mostafa-abdullah/subscriptions","organizations_url":"https://api.github.com/users/mostafa-abdullah/orgs","repos_url":"https://api.github.com/users/mostafa-abdullah/repos","events_url":"https://api.github.com/users/mostafa-abdullah/events{/privacy}","received_events_url":"https://api.github.com/users/mostafa-abdullah/received_events","type":"User","site_admin":false},"repo":{"id":84197840,"name":"Lyra","full_name":"mostafa-abdullah/Lyra","owner":{"login":"mostafa-abdullah","id":12327683,"avatar_url":"https://avatars2.githubusercontent.com/u/12327683?v=3","gravatar_id":"","url":"https://api.github.com/users/mostafa-abdullah","html_url":"https://github.com/mostafa-abdullah","followers_url":"https://api.github.com/users/mostafa-abdullah/followers","following_url":"https://api.github.com/users/mostafa-abdullah/following{/other_user}","gists_url":"https://api.github.com/users/mostafa-abdullah/gists{/gist_id}","starred_url":"https://api.github.com/users/mostafa-abdullah/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mostafa-abdullah/subscriptions","organizations_url":"https://api.github.com/users/mostafa-abdullah/orgs","repos_url":"https://api.github.com/users/mostafa-abdullah/repos","events_url":"https://api.github.com/users/mostafa-abdullah/events{/privacy}","received_events_url":"https://api.github.com/users/mostafa-abdullah/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mostafa-abdullah/Lyra","description":null,"fork":true,"url":"https://api.github.com/repos/mostafa-abdullah/Lyra","forks_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/forks","keys_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/teams","hooks_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/hooks","issue_events_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/issues/events{/number}","events_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/events","assignees_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/assignees{/user}","branches_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/branches{/branch}","tags_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/tags","blobs_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/git/refs{/sha}","trees_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/statuses/{sha}","languages_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/languages","stargazers_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/stargazers","contributors_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/contributors","subscribers_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/subscribers","subscription_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/subscription","commits_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/commits{/sha}","git_commits_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/git/commits{/sha}","comments_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/comments{/number}","issue_comment_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/issues/comments{/number}","contents_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/contents/{+path}","compare_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/merges","archive_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/downloads","issues_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/issues{/number}","pulls_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/pulls{/number}","milestones_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/milestones{/number}","notifications_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/labels{/name}","releases_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/releases{/id}","deployments_url":"https://api.github.com/repos/mostafa-abdullah/Lyra/deployments","created_at":"2017-03-07T12:43:04Z","updated_at":"2017-03-07T12:43:06Z","pushed_at":"2017-03-23T16:39:45Z","git_url":"git://github.com/mostafa-abdullah/Lyra.git","ssh_url":"git@github.com:mostafa-abdullah/Lyra.git","clone_url":"https://github.com/mostafa-abdullah/Lyra.git","svn_url":"https://github.com/mostafa-abdullah/Lyra","homepage":null,"size":109,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"caterinaurban:master","ref":"master","sha":"955f5816893eac9bbda5361e6218130db55f1d5d","user":{"login":"caterinaurban","id":7695758,"avatar_url":"https://avatars3.githubusercontent.com/u/7695758?v=3","gravatar_id":"","url":"https://api.github.com/users/caterinaurban","html_url":"https://github.com/caterinaurban","followers_url":"https://api.github.com/users/caterinaurban/followers","following_url":"https://api.github.com/users/caterinaurban/following{/other_user}","gists_url":"https://api.github.com/users/caterinaurban/gists{/gist_id}","starred_url":"https://api.github.com/users/caterinaurban/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caterinaurban/subscriptions","organizations_url":"https://api.github.com/users/caterinaurban/orgs","repos_url":"https://api.github.com/users/caterinaurban/repos","events_url":"https://api.github.com/users/caterinaurban/events{/privacy}","received_events_url":"https://api.github.com/users/caterinaurban/received_events","type":"User","site_admin":false},"repo":{"id":82156905,"name":"Lyra","full_name":"caterinaurban/Lyra","owner":{"login":"caterinaurban","id":7695758,"avatar_url":"https://avatars3.githubusercontent.com/u/7695758?v=3","gravatar_id":"","url":"https://api.github.com/users/caterinaurban","html_url":"https://github.com/caterinaurban","followers_url":"https://api.github.com/users/caterinaurban/followers","following_url":"https://api.github.com/users/caterinaurban/following{/other_user}","gists_url":"https://api.github.com/users/caterinaurban/gists{/gist_id}","starred_url":"https://api.github.com/users/caterinaurban/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caterinaurban/subscriptions","organizations_url":"https://api.github.com/users/caterinaurban/orgs","repos_url":"https://api.github.com/users/caterinaurban/repos","events_url":"https://api.github.com/users/caterinaurban/events{/privacy}","received_events_url":"https://api.github.com/users/caterinaurban/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/caterinaurban/Lyra","description":null,"fork":false,"url":"https://api.github.com/repos/caterinaurban/Lyra","forks_url":"https://api.github.com/repos/caterinaurban/Lyra/forks","keys_url":"https://api.github.com/repos/caterinaurban/Lyra/keys{/key_id}","collaborators_url":"https://api.github.com/repos/caterinaurban/Lyra/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/caterinaurban/Lyra/teams","hooks_url":"https://api.github.com/repos/caterinaurban/Lyra/hooks","issue_events_url":"https://api.github.com/repos/caterinaurban/Lyra/issues/events{/number}","events_url":"https://api.github.com/repos/caterinaurban/Lyra/events","assignees_url":"https://api.github.com/repos/caterinaurban/Lyra/assignees{/user}","branches_url":"https://api.github.com/repos/caterinaurban/Lyra/branches{/branch}","tags_url":"https://api.github.com/repos/caterinaurban/Lyra/tags","blobs_url":"https://api.github.com/repos/caterinaurban/Lyra/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/caterinaurban/Lyra/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/caterinaurban/Lyra/git/refs{/sha}","trees_url":"https://api.github.com/repos/caterinaurban/Lyra/git/trees{/sha}","statuses_url":"https://api.github.com/repos/caterinaurban/Lyra/statuses/{sha}","languages_url":"https://api.github.com/repos/caterinaurban/Lyra/languages","stargazers_url":"https://api.github.com/repos/caterinaurban/Lyra/stargazers","contributors_url":"https://api.github.com/repos/caterinaurban/Lyra/contributors","subscribers_url":"https://api.github.com/repos/caterinaurban/Lyra/subscribers","subscription_url":"https://api.github.com/repos/caterinaurban/Lyra/subscription","commits_url":"https://api.github.com/repos/caterinaurban/Lyra/commits{/sha}","git_commits_url":"https://api.github.com/repos/caterinaurban/Lyra/git/commits{/sha}","comments_url":"https://api.github.com/repos/caterinaurban/Lyra/comments{/number}","issue_comment_url":"https://api.github.com/repos/caterinaurban/Lyra/issues/comments{/number}","contents_url":"https://api.github.com/repos/caterinaurban/Lyra/contents/{+path}","compare_url":"https://api.github.com/repos/caterinaurban/Lyra/compare/{base}...{head}","merges_url":"https://api.github.com/repos/caterinaurban/Lyra/merges","archive_url":"https://api.github.com/repos/caterinaurban/Lyra/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/caterinaurban/Lyra/downloads","issues_url":"https://api.github.com/repos/caterinaurban/Lyra/issues{/number}","pulls_url":"https://api.github.com/repos/caterinaurban/Lyra/pulls{/number}","milestones_url":"https://api.github.com/repos/caterinaurban/Lyra/milestones{/number}","notifications_url":"https://api.github.com/repos/caterinaurban/Lyra/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/caterinaurban/Lyra/labels{/name}","releases_url":"https://api.github.com/repos/caterinaurban/Lyra/releases{/id}","deployments_url":"https://api.github.com/repos/caterinaurban/Lyra/deployments","created_at":"2017-02-16T08:21:18Z","updated_at":"2017-02-16T08:26:27Z","pushed_at":"2017-03-22T14:11:06Z","git_url":"git://github.com/caterinaurban/Lyra.git","ssh_url":"git@github.com:caterinaurban/Lyra.git","clone_url":"https://github.com/caterinaurban/Lyra.git","svn_url":"https://github.com/caterinaurban/Lyra","homepage":null,"size":45,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":1,"forks":1,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/caterinaurban/Lyra/pulls/1"},"html":{"href":"https://github.com/caterinaurban/Lyra/pull/1"},"issue":{"href":"https://api.github.com/repos/caterinaurban/Lyra/issues/1"},"comments":{"href":"https://api.github.com/repos/caterinaurban/Lyra/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/caterinaurban/Lyra/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/caterinaurban/Lyra/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/caterinaurban/Lyra/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/caterinaurban/Lyra/statuses/a5a5e9ac93311031fd4d27f80d027d95b5101732"}}}}
{"actor":{"display_login":"mostafa-abdullah"}}