├── README.md ├── 0x01-python_async_function ├── README.md ├── __pycache__ │ ├── 3-tasks.cpython-39.pyc │ ├── 4-tasks.cpython-39.pyc │ ├── 2-measure_runtime.cpython-39.pyc │ ├── 0-basic_async_syntax.cpython-39.pyc │ └── 1-concurrent_coroutines.cpython-39.pyc ├── 2-main.py ├── 4-main.py ├── 0-main.py ├── 3-main.py ├── 1-main.py ├── 3-tasks.py ├── 2-measure_runtime.py ├── 0-basic_async_syntax.py ├── 4-tasks.py └── 1-concurrent_coroutines.py ├── 0x00-python_variable_annotations ├── README.md ├── 4-define_variables.py ├── 1-concat.py ├── 3-to_str.py ├── 2-floor.py ├── 0-add.py ├── 6-sum_mixed_list.py ├── 9-element_length.py ├── 5-sum_list.py ├── 7-to_kv.py ├── 100-safe_first_element.py ├── 102-type_checking.py ├── 101-safely_get_value.py └── 8-make_multiplier.py ├── 0x02-python_async_comprehension ├── README.md ├── __pycache__ │ ├── 0-async_generator.cpython-39.pyc │ ├── 2-measure_runtime.cpython-39.pyc │ └── 1-async_comprehension.cpython-39.pyc ├── 1-main.py ├── 2-main.py ├── 0-main.py ├── 0-async_generator.py ├── 1-async_comprehension.py └── 2-measure_runtime.py └── 0x03-Unittests_and_integration_tests ├── README.md ├── client.py ├── utils.py ├── test_utils.py ├── test_client.py └── fixtures.py /README.md: -------------------------------------------------------------------------------- 1 | # ALX Backend Python -------------------------------------------------------------------------------- /0x01-python_async_function/README.md: -------------------------------------------------------------------------------- 1 | # 0x01-python_async_function -------------------------------------------------------------------------------- /0x00-python_variable_annotations/README.md: -------------------------------------------------------------------------------- 1 | # 0x00-python_variable_annotations -------------------------------------------------------------------------------- /0x02-python_async_comprehension/README.md: -------------------------------------------------------------------------------- 1 | # 0x02-python_async_comprehension -------------------------------------------------------------------------------- /0x03-Unittests_and_integration_tests/README.md: -------------------------------------------------------------------------------- 1 | # 0x03-Unittests_and_integration_tests -------------------------------------------------------------------------------- /0x01-python_async_function/__pycache__/3-tasks.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdallah-sameh-ragab/alx-backend-python/main/0x01-python_async_function/__pycache__/3-tasks.cpython-39.pyc -------------------------------------------------------------------------------- /0x01-python_async_function/__pycache__/4-tasks.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdallah-sameh-ragab/alx-backend-python/main/0x01-python_async_function/__pycache__/4-tasks.cpython-39.pyc -------------------------------------------------------------------------------- /0x01-python_async_function/2-main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | measure_time = __import__('2-measure_runtime').measure_time 4 | 5 | n = 5 6 | max_delay = 9 7 | 8 | print(measure_time(n, max_delay)) 9 | -------------------------------------------------------------------------------- /0x01-python_async_function/__pycache__/2-measure_runtime.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdallah-sameh-ragab/alx-backend-python/main/0x01-python_async_function/__pycache__/2-measure_runtime.cpython-39.pyc -------------------------------------------------------------------------------- /0x00-python_variable_annotations/4-define_variables.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ Define variables """ 3 | 4 | a: int = 1 5 | pi: float = 3.14 6 | i_understand_annotations: bool = True 7 | school: str = "Holberton" 8 | -------------------------------------------------------------------------------- /0x01-python_async_function/__pycache__/0-basic_async_syntax.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdallah-sameh-ragab/alx-backend-python/main/0x01-python_async_function/__pycache__/0-basic_async_syntax.cpython-39.pyc -------------------------------------------------------------------------------- /0x02-python_async_comprehension/__pycache__/0-async_generator.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdallah-sameh-ragab/alx-backend-python/main/0x02-python_async_comprehension/__pycache__/0-async_generator.cpython-39.pyc -------------------------------------------------------------------------------- /0x02-python_async_comprehension/__pycache__/2-measure_runtime.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdallah-sameh-ragab/alx-backend-python/main/0x02-python_async_comprehension/__pycache__/2-measure_runtime.cpython-39.pyc -------------------------------------------------------------------------------- /0x01-python_async_function/__pycache__/1-concurrent_coroutines.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdallah-sameh-ragab/alx-backend-python/main/0x01-python_async_function/__pycache__/1-concurrent_coroutines.cpython-39.pyc -------------------------------------------------------------------------------- /0x00-python_variable_annotations/1-concat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ Basic annotations concat """ 4 | 5 | 6 | def concat(str1: str, str2: str) -> str: 7 | """ Returns sum of two strings """ 8 | return str1 + str2 9 | -------------------------------------------------------------------------------- /0x01-python_async_function/4-main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import asyncio 4 | 5 | task_wait_n = __import__('4-tasks').task_wait_n 6 | 7 | n = 5 8 | max_delay = 6 9 | print(asyncio.run(task_wait_n(n, max_delay))) 10 | -------------------------------------------------------------------------------- /0x02-python_async_comprehension/__pycache__/1-async_comprehension.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdallah-sameh-ragab/alx-backend-python/main/0x02-python_async_comprehension/__pycache__/1-async_comprehension.cpython-39.pyc -------------------------------------------------------------------------------- /0x00-python_variable_annotations/3-to_str.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ Basic annotations - to string """ 3 | 4 | 5 | def to_str(n: float) -> str: 6 | """ Returns the string representation of the float. """ 7 | return str(n) 8 | -------------------------------------------------------------------------------- /0x00-python_variable_annotations/2-floor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ Basic annotations concat """ 3 | 4 | import math 5 | 6 | 7 | def floor(n: float) -> int: 8 | """ Returns the floor of the float """ 9 | return math.floor(n) 10 | -------------------------------------------------------------------------------- /0x00-python_variable_annotations/0-add.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' 4 | Basic annotations for variables. 5 | ''' 6 | 7 | 8 | def add(a: float, b: float) -> float: 9 | ''' 10 | Returns sum of two floats. 11 | ''' 12 | return a + b 13 | -------------------------------------------------------------------------------- /0x01-python_async_function/0-main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import asyncio 4 | 5 | wait_random = __import__('0-basic_async_syntax').wait_random 6 | 7 | print(asyncio.run(wait_random())) 8 | print(asyncio.run(wait_random(5))) 9 | print(asyncio.run(wait_random(15))) 10 | -------------------------------------------------------------------------------- /0x02-python_async_comprehension/1-main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import asyncio 4 | 5 | async_comprehension = __import__('1-async_comprehension').async_comprehension 6 | 7 | 8 | async def main(): 9 | print(await async_comprehension()) 10 | 11 | asyncio.run(main()) 12 | -------------------------------------------------------------------------------- /0x00-python_variable_annotations/6-sum_mixed_list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ mixed list """ 4 | from typing import Union, List 5 | 6 | 7 | def sum_mixed_list(mxd_lst: List[Union[int, float]]) -> float: 8 | """ returns sum as a float. """ 9 | return float(sum(mxd_lst)) 10 | -------------------------------------------------------------------------------- /0x02-python_async_comprehension/2-main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import asyncio 4 | 5 | 6 | measure_runtime = __import__('2-measure_runtime').measure_runtime 7 | 8 | 9 | async def main(): 10 | return await(measure_runtime()) 11 | 12 | print( 13 | asyncio.run(main()) 14 | ) 15 | -------------------------------------------------------------------------------- /0x01-python_async_function/3-main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import asyncio 4 | 5 | task_wait_random = __import__('3-tasks').task_wait_random 6 | 7 | 8 | async def test(max_delay: int) -> float: 9 | task = task_wait_random(max_delay) 10 | await task 11 | print(task.__class__) 12 | 13 | asyncio.run(test(5)) 14 | -------------------------------------------------------------------------------- /0x01-python_async_function/1-main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | Test file for printing the correct output of the wait_n coroutine 4 | ''' 5 | import asyncio 6 | 7 | wait_n = __import__('1-concurrent_coroutines').wait_n 8 | 9 | print(asyncio.run(wait_n(5, 5))) 10 | print(asyncio.run(wait_n(10, 7))) 11 | print(asyncio.run(wait_n(10, 0))) 12 | -------------------------------------------------------------------------------- /0x00-python_variable_annotations/9-element_length.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ Let's duck type an iterable object""" 3 | from typing import Mapping, MutableMapping, Sequence, Iterable, List, Tuple 4 | 5 | 6 | def element_length(lst: Iterable[Sequence]) -> List[Tuple[Sequence, int]]: 7 | """ Element length """ 8 | return [(i, len(i)) for i in lst] 9 | -------------------------------------------------------------------------------- /0x01-python_async_function/3-tasks.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ Async basics """ 3 | 4 | from asyncio import Task, create_task 5 | 6 | wait_random = __import__('0-basic_async_syntax').wait_random 7 | 8 | 9 | def task_wait_random(max_delay: int) -> Task: 10 | """ Tasks """ 11 | task = create_task(wait_random(max_delay)) 12 | return task 13 | -------------------------------------------------------------------------------- /0x02-python_async_comprehension/0-main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import asyncio 4 | 5 | async_generator = __import__('0-async_generator').async_generator 6 | 7 | async def print_yielded_values(): 8 | result = [] 9 | async for i in async_generator(): 10 | result.append(i) 11 | print(result) 12 | 13 | asyncio.run(print_yielded_values()) 14 | -------------------------------------------------------------------------------- /0x00-python_variable_annotations/5-sum_list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ Complex types - list of floats """ 3 | from typing import Callable, Iterator, Union, Optional, List 4 | 5 | 6 | def sum_list(input_list: List[float]) -> float: 7 | """ 8 | Takes a list input_list of floats as argument 9 | returns their sum as a float. 10 | """ 11 | 12 | return sum(input_list) 13 | -------------------------------------------------------------------------------- /0x00-python_variable_annotations/7-to_kv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ Complex types - string and int/float to tuple""" 3 | from typing import Callable, Iterator, Union, Optional, List, Tuple 4 | 5 | 6 | def to_kv(k: str, v: Union[int, float]) -> Tuple[str, float]: 7 | """ 8 | takes a string k and an int OR float v as arguments 9 | returns a tuple. 10 | """ 11 | 12 | return (k, v**2) 13 | -------------------------------------------------------------------------------- /0x02-python_async_comprehension/0-async_generator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ Async Comprehensions """ 4 | 5 | from asyncio import sleep 6 | from random import uniform 7 | from typing import Generator 8 | 9 | 10 | async def async_generator() -> Generator[float, None, None]: 11 | """ Async Generator """ 12 | for _ in range(10): 13 | await sleep(1) 14 | yield uniform(0, 10) 15 | -------------------------------------------------------------------------------- /0x00-python_variable_annotations/100-safe_first_element.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ Duck typing - first element of a sequence """ 3 | from typing import Any, Union, Sequence, Iterable, List, Tuple 4 | 5 | 6 | # The types of the elements of the input are not know 7 | def safe_first_element(lst: Sequence[Any]) -> Union[Any, None]: 8 | """ Safe first element """ 9 | if lst: 10 | return lst[0] 11 | else: 12 | return None 13 | -------------------------------------------------------------------------------- /0x02-python_async_comprehension/1-async_comprehension.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ Async Comprehensions """ 4 | 5 | from asyncio import sleep 6 | from random import uniform 7 | from typing import List 8 | 9 | async_generator = __import__('0-async_generator').async_generator 10 | 11 | 12 | async def async_comprehension() -> List[float]: 13 | """ Async Comprehensions """ 14 | a = [i async for i in async_generator()] 15 | return a 16 | -------------------------------------------------------------------------------- /0x01-python_async_function/2-measure_runtime.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ The basics of async """ 3 | 4 | from asyncio import run 5 | from time import time 6 | 7 | wait_n = __import__('1-concurrent_coroutines').wait_n 8 | 9 | 10 | def measure_time(n: int, max_delay: int) -> float: 11 | """ Measure the runtime """ 12 | start = time() 13 | 14 | run(wait_n(n, max_delay)) 15 | 16 | end = time() 17 | 18 | return (end - start) / n 19 | -------------------------------------------------------------------------------- /0x00-python_variable_annotations/102-type_checking.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ Type Checking """ 3 | from typing import Tuple, List 4 | 5 | 6 | def zoom_array(lst: Tuple, factor: int = 2) -> List: 7 | """ Zoom Array """ 8 | zoomed_in: List = [ 9 | item for item in lst 10 | for i in range(factor) 11 | ] 12 | return zoomed_in 13 | 14 | 15 | array = (12, 72, 91) 16 | 17 | zoom_2x = zoom_array(array) 18 | 19 | zoom_3x = zoom_array(array, 3) 20 | -------------------------------------------------------------------------------- /0x01-python_async_function/0-basic_async_syntax.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | The basics of async. 4 | ''' 5 | 6 | import asyncio 7 | import random 8 | 9 | 10 | async def wait_random(max_delay: int = 10) -> float: 11 | """ 12 | waits for a random delay between 0 and max_delay (included and float value) 13 | seconds and eventually returns it. 14 | """ 15 | delay = random.uniform(0, max_delay) 16 | await asyncio.sleep(delay) 17 | return delay 18 | -------------------------------------------------------------------------------- /0x00-python_variable_annotations/101-safely_get_value.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ More involved type annotations """ 3 | from typing import Mapping, Any, Sequence, Union, TypeVar 4 | 5 | 6 | T = TypeVar('T') 7 | 8 | 9 | def safely_get_value(dct: Mapping, key: Any, 10 | default: Union[T, None] = None 11 | ) -> Union[Any, T]: 12 | """ Safely get value """ 13 | if key in dct: 14 | return dct[key] 15 | else: 16 | return default 17 | -------------------------------------------------------------------------------- /0x01-python_async_function/4-tasks.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ The basics of async """ 3 | 4 | import asyncio 5 | from typing import List 6 | 7 | task_wait_random = __import__('3-tasks').task_wait_random 8 | 9 | 10 | async def task_wait_n(n: int, max_delay: int) -> List[float]: 11 | """ 12 | spawn task_wait_random n times with the specified max_delay. 13 | """ 14 | tasks = [task_wait_random(max_delay) for _ in range(n)] 15 | return [await task for task in asyncio.as_completed(tasks)] 16 | -------------------------------------------------------------------------------- /0x01-python_async_function/1-concurrent_coroutines.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ The basics of async """ 3 | 4 | import asyncio 5 | from typing import List 6 | 7 | wait_random = __import__('0-basic_async_syntax').wait_random 8 | 9 | 10 | async def wait_n(n: int, max_delay: int) -> List[float]: 11 | """ 12 | spawn wait_random n times with the specified max_delay. 13 | """ 14 | tasks = [asyncio.create_task(wait_random(max_delay)) for _ in range(n)] 15 | return [await task for task in asyncio.as_completed(tasks)] 16 | -------------------------------------------------------------------------------- /0x02-python_async_comprehension/2-measure_runtime.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ Async Comprehensions """ 4 | 5 | from asyncio import gather 6 | from time import time 7 | 8 | async_comprehension = __import__('1-async_comprehension').async_comprehension 9 | 10 | 11 | async def measure_runtime() -> float: 12 | """ Run time for four parallel comprehensions """ 13 | start = time() 14 | tasks = [async_comprehension() for i in range(4)] 15 | await gather(*tasks) 16 | end = time() 17 | return (end - start) 18 | -------------------------------------------------------------------------------- /0x00-python_variable_annotations/8-make_multiplier.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ Complex types - functions""" 3 | from typing import Callable, Iterator, Union, Optional, List, Tuple 4 | 5 | 6 | def make_multiplier(multiplier: float) -> Callable[[float], float]: 7 | """ 8 | takes a float multiplier as argument, 9 | returns a function that multiplies a float by multiplier. 10 | """ 11 | def f(n: float) -> float: 12 | """ multiplies a float by multiplier """ 13 | return float(n * multiplier) 14 | 15 | return f 16 | -------------------------------------------------------------------------------- /0x03-Unittests_and_integration_tests/client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """A github org client 3 | """ 4 | from typing import ( 5 | List, 6 | Dict, 7 | ) 8 | 9 | from utils import ( 10 | get_json, 11 | access_nested_map, 12 | memoize, 13 | ) 14 | 15 | 16 | class GithubOrgClient: 17 | """A Githib org client 18 | """ 19 | ORG_URL = "https://api.github.com/orgs/{org}" 20 | 21 | def __init__(self, org_name: str) -> None: 22 | """Init method of GithubOrgClient""" 23 | self._org_name = org_name 24 | 25 | @memoize 26 | def org(self) -> Dict: 27 | """Memoize org""" 28 | return get_json(self.ORG_URL.format(org=self._org_name)) 29 | 30 | @property 31 | def _public_repos_url(self) -> str: 32 | """Public repos URL""" 33 | return self.org["repos_url"] 34 | 35 | @memoize 36 | def repos_payload(self) -> Dict: 37 | """Memoize repos payload""" 38 | return get_json(self._public_repos_url) 39 | 40 | def public_repos(self, license: str = None) -> List[str]: 41 | """Public repos""" 42 | json_payload = self.repos_payload 43 | public_repos = [ 44 | repo["name"] for repo in json_payload 45 | if license is None or self.has_license(repo, license) 46 | ] 47 | 48 | return public_repos 49 | 50 | @staticmethod 51 | def has_license(repo: Dict[str, Dict], license_key: str) -> bool: 52 | """Static: has_license""" 53 | assert license_key is not None, "license_key cannot be None" 54 | try: 55 | has_license = access_nested_map(repo, ("license", "key")) == license_key 56 | except KeyError: 57 | return False 58 | return has_license 59 | -------------------------------------------------------------------------------- /0x03-Unittests_and_integration_tests/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Generic utilities for github org client. 3 | """ 4 | import requests 5 | from functools import wraps 6 | from typing import ( 7 | Mapping, 8 | Sequence, 9 | Any, 10 | Dict, 11 | Callable, 12 | ) 13 | 14 | __all__ = [ 15 | "access_nested_map", 16 | "get_json", 17 | "memoize", 18 | ] 19 | 20 | 21 | def access_nested_map(nested_map: Mapping, path: Sequence) -> Any: 22 | """Access nested map with key path. 23 | Parameters 24 | ---------- 25 | nested_map: Mapping 26 | A nested map 27 | path: Sequence 28 | a sequence of key representing a path to the value 29 | Example 30 | ------- 31 | >>> nested_map = {"a": {"b": {"c": 1}}} 32 | >>> access_nested_map(nested_map, ["a", "b", "c"]) 33 | 1 34 | """ 35 | for key in path: 36 | if not isinstance(nested_map, Mapping): 37 | raise KeyError(key) 38 | nested_map = nested_map[key] 39 | 40 | return nested_map 41 | 42 | 43 | def get_json(url: str) -> Dict: 44 | """Get JSON from remote URL. 45 | """ 46 | response = requests.get(url) 47 | return response.json() 48 | 49 | 50 | def memoize(fn: Callable) -> Callable: 51 | """Decorator to memoize a method. 52 | Example 53 | ------- 54 | class MyClass: 55 | @memoize 56 | def a_method(self): 57 | print("a_method called") 58 | return 42 59 | >>> my_object = MyClass() 60 | >>> my_object.a_method 61 | a_method called 62 | 42 63 | >>> my_object.a_method 64 | 42 65 | """ 66 | attr_name = "_{}".format(fn.__name__) 67 | 68 | @wraps(fn) 69 | def memoized(self): 70 | """"memoized wraps""" 71 | if not hasattr(self, attr_name): 72 | setattr(self, attr_name, fn(self)) 73 | return getattr(self, attr_name) 74 | 75 | return property(memoized) 76 | -------------------------------------------------------------------------------- /0x03-Unittests_and_integration_tests/test_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ Module for testing utils """ 3 | 4 | from parameterized import parameterized 5 | import unittest 6 | from unittest.mock import patch 7 | from utils import (access_nested_map, get_json, memoize) 8 | import requests 9 | 10 | 11 | class TestAccessNestedMap(unittest.TestCase): 12 | """ Class for Testing Access Nested Map """ 13 | 14 | @parameterized.expand([ 15 | ({"a": 1}, ("a",), 1), 16 | ({"a": {"b": 2}}, ("a",), {'b': 2}), 17 | ({"a": {"b": 2}}, ("a", "b"), 2) 18 | ]) 19 | def test_access_nested_map(self, nested_map, path, expected): 20 | """ Test that the method returns what it is supposed to """ 21 | self.assertEqual(access_nested_map(nested_map, path), expected) 22 | 23 | @parameterized.expand([ 24 | ({}, ("a",), 'a'), 25 | ({"a": 1}, ("a", "b"), 'b') 26 | ]) 27 | def test_access_nested_map_exception(self, nested_map, path, expected): 28 | """ Test that a KeyError is raised for the respective inputs """ 29 | with self.assertRaises(KeyError) as e: 30 | access_nested_map(nested_map, path) 31 | self.assertEqual(f"KeyError('{expected}')", repr(e.exception)) 32 | 33 | 34 | class TestGetJson(unittest.TestCase): 35 | """ Class for Testing Get Json """ 36 | 37 | @parameterized.expand([ 38 | ("http://example.com", {"payload": True}), 39 | ("http://holberton.io", {"payload": False}) 40 | ]) 41 | def test_get_json(self, test_url, test_payload): 42 | """ Test that utils.get_json returns the expected result.""" 43 | config = {'return_value.json.return_value': test_payload} 44 | patcher = patch('requests.get', **config) 45 | mock = patcher.start() 46 | self.assertEqual(get_json(test_url), test_payload) 47 | mock.assert_called_once() 48 | patcher.stop() 49 | 50 | 51 | class TestMemoize(unittest.TestCase): 52 | """ Class for Testing Memoize """ 53 | 54 | def test_memoize(self): 55 | """ Test that when calling a_property twice, the correct result 56 | is returned but a_method is only called once using 57 | assert_called_once 58 | """ 59 | 60 | class TestClass: 61 | """ Test Class for wrapping with memoize """ 62 | 63 | def a_method(self): 64 | return 42 65 | 66 | @memoize 67 | def a_property(self): 68 | return self.a_method() 69 | 70 | with patch.object(TestClass, 'a_method') as mock: 71 | test_class = TestClass() 72 | test_class.a_property() 73 | test_class.a_property() 74 | mock.assert_called_once() 75 | -------------------------------------------------------------------------------- /0x03-Unittests_and_integration_tests/test_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ Module for testing client """ 3 | 4 | from client import GithubOrgClient 5 | from fixtures import TEST_PAYLOAD 6 | from parameterized import parameterized, parameterized_class 7 | import json 8 | import unittest 9 | from unittest.mock import patch, PropertyMock, Mock 10 | 11 | 12 | class TestGithubOrgClient(unittest.TestCase): 13 | """ Class for Testing Github Org Client """ 14 | 15 | @parameterized.expand([ 16 | ('google'), 17 | ('abc') 18 | ]) 19 | @patch('client.get_json') 20 | def test_org(self, input, mock): 21 | """Test that GithubOrgClient.org returns the correct value""" 22 | test_class = GithubOrgClient(input) 23 | test_class.org() 24 | mock.assert_called_once_with(f'https://api.github.com/orgs/{input}') 25 | 26 | def test_public_repos_url(self): 27 | """ Test that the result of _public_repos_url is the expected one 28 | based on the mocked payload 29 | """ 30 | with patch('client.GithubOrgClient.org', 31 | new_callable=PropertyMock) as mock: 32 | payload = {"repos_url": "World"} 33 | mock.return_value = payload 34 | test_class = GithubOrgClient('test') 35 | result = test_class._public_repos_url 36 | self.assertEqual(result, payload["repos_url"]) 37 | 38 | @patch('client.get_json') 39 | def test_public_repos(self, mock_json): 40 | """ 41 | Test that the list of repos is what you expect from the chosen payload. 42 | Test that the mocked property and the mocked get_json was called once. 43 | """ 44 | json_payload = [{"name": "Google"}, {"name": "Twitter"}] 45 | mock_json.return_value = json_payload 46 | 47 | with patch('client.GithubOrgClient._public_repos_url', 48 | new_callable=PropertyMock) as mock_public: 49 | 50 | mock_public.return_value = "hello/world" 51 | test_class = GithubOrgClient('test') 52 | result = test_class.public_repos() 53 | 54 | check = [i["name"] for i in json_payload] 55 | self.assertEqual(result, check) 56 | 57 | mock_public.assert_called_once() 58 | mock_json.assert_called_once() 59 | 60 | @parameterized.expand([ 61 | ({"license": {"key": "my_license"}}, "my_license", True), 62 | ({"license": {"key": "other_license"}}, "my_license", False) 63 | ]) 64 | def test_has_license(self, repo, license_key, expected): 65 | """ unit-test for GithubOrgClient.has_license """ 66 | result = GithubOrgClient.has_license(repo, license_key) 67 | self.assertEqual(result, expected) 68 | 69 | 70 | @parameterized_class( 71 | ("org_payload", "repos_payload", "expected_repos", "apache2_repos"), 72 | TEST_PAYLOAD 73 | ) 74 | class TestIntegrationGithubOrgClient(unittest.TestCase): 75 | """ Class for Integration test of fixtures """ 76 | 77 | @classmethod 78 | def setUpClass(cls): 79 | """A class method called before tests in an individual class are run""" 80 | # def my_side_effect(url): 81 | # """ Side Effect function for test """ 82 | # test_url = "https://api.github.com/orgs/google" 83 | # if url == test_url: 84 | # return cls.org_payload 85 | # return cls.repos_payload 86 | 87 | config = {'return_value.json.side_effect': 88 | [ 89 | cls.org_payload, cls.repos_payload, 90 | cls.org_payload, cls.repos_payload 91 | ] 92 | } 93 | cls.get_patcher = patch('requests.get', **config) 94 | 95 | cls.mock = cls.get_patcher.start() 96 | 97 | def test_public_repos(self): 98 | """ Integration test: public repos""" 99 | test_class = GithubOrgClient("google") 100 | 101 | self.assertEqual(test_class.org, self.org_payload) 102 | self.assertEqual(test_class.repos_payload, self.repos_payload) 103 | self.assertEqual(test_class.public_repos(), self.expected_repos) 104 | self.assertEqual(test_class.public_repos("XLICENSE"), []) 105 | self.mock.assert_called() 106 | 107 | def test_public_repos_with_license(self): 108 | """ Integration test for public repos with License """ 109 | test_class = GithubOrgClient("google") 110 | 111 | self.assertEqual(test_class.public_repos(), self.expected_repos) 112 | self.assertEqual(test_class.public_repos("XLICENSE"), []) 113 | self.assertEqual(test_class.public_repos( 114 | "apache-2.0"), self.apache2_repos) 115 | self.mock.assert_called() 116 | 117 | @classmethod 118 | def tearDownClass(cls): 119 | """A class method called after tests in an individual class have run""" 120 | cls.get_patcher.stop() 121 | -------------------------------------------------------------------------------- /0x03-Unittests_and_integration_tests/fixtures.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | TEST_PAYLOAD = [ 4 | ( 5 | {"repos_url": "https://api.github.com/orgs/google/repos"}, 6 | [ 7 | { 8 | "id": 7697149, 9 | "node_id": "MDEwOlJlcG9zaXRvcnk3Njk3MTQ5", 10 | "name": "episodes.dart", 11 | "full_name": "google/episodes.dart", 12 | "private": False, 13 | "owner": { 14 | "login": "google", 15 | "id": 1342004, 16 | "node_id": "MDEyOk9yZ2FuaXphdGlvbjEzNDIwMDQ=", 17 | "avatar_url": "https://avatars1.githubusercontent.com/u/1342004?v=4", 18 | "gravatar_id": "", 19 | "url": "https://api.github.com/users/google", 20 | "html_url": "https://github.com/google", 21 | "followers_url": "https://api.github.com/users/google/followers", 22 | "following_url": "https://api.github.com/users/google/following{/other_user}", 23 | "gists_url": "https://api.github.com/users/google/gists{/gist_id}", 24 | "starred_url": "https://api.github.com/users/google/starred{/owner}{/repo}", 25 | "subscriptions_url": "https://api.github.com/users/google/subscriptions", 26 | "organizations_url": "https://api.github.com/users/google/orgs", 27 | "repos_url": "https://api.github.com/users/google/repos", 28 | "events_url": "https://api.github.com/users/google/events{/privacy}", 29 | "received_events_url": "https://api.github.com/users/google/received_events", 30 | "type": "Organization", 31 | "site_admin": False 32 | }, 33 | "html_url": "https://github.com/google/episodes.dart", 34 | "description": "A framework for timing performance of web apps.", 35 | "fork": False, 36 | "url": "https://api.github.com/repos/google/episodes.dart", 37 | "forks_url": "https://api.github.com/repos/google/episodes.dart/forks", 38 | "keys_url": "https://api.github.com/repos/google/episodes.dart/keys{/key_id}", 39 | "collaborators_url": "https://api.github.com/repos/google/episodes.dart/collaborators{/collaborator}", 40 | "teams_url": "https://api.github.com/repos/google/episodes.dart/teams", 41 | "hooks_url": "https://api.github.com/repos/google/episodes.dart/hooks", 42 | "issue_events_url": "https://api.github.com/repos/google/episodes.dart/issues/events{/number}", 43 | "events_url": "https://api.github.com/repos/google/episodes.dart/events", 44 | "assignees_url": "https://api.github.com/repos/google/episodes.dart/assignees{/user}", 45 | "branches_url": "https://api.github.com/repos/google/episodes.dart/branches{/branch}", 46 | "tags_url": "https://api.github.com/repos/google/episodes.dart/tags", 47 | "blobs_url": "https://api.github.com/repos/google/episodes.dart/git/blobs{/sha}", 48 | "git_tags_url": "https://api.github.com/repos/google/episodes.dart/git/tags{/sha}", 49 | "git_refs_url": "https://api.github.com/repos/google/episodes.dart/git/refs{/sha}", 50 | "trees_url": "https://api.github.com/repos/google/episodes.dart/git/trees{/sha}", 51 | "statuses_url": "https://api.github.com/repos/google/episodes.dart/statuses/{sha}", 52 | "languages_url": "https://api.github.com/repos/google/episodes.dart/languages", 53 | "stargazers_url": "https://api.github.com/repos/google/episodes.dart/stargazers", 54 | "contributors_url": "https://api.github.com/repos/google/episodes.dart/contributors", 55 | "subscribers_url": "https://api.github.com/repos/google/episodes.dart/subscribers", 56 | "subscription_url": "https://api.github.com/repos/google/episodes.dart/subscription", 57 | "commits_url": "https://api.github.com/repos/google/episodes.dart/commits{/sha}", 58 | "git_commits_url": "https://api.github.com/repos/google/episodes.dart/git/commits{/sha}", 59 | "comments_url": "https://api.github.com/repos/google/episodes.dart/comments{/number}", 60 | "issue_comment_url": "https://api.github.com/repos/google/episodes.dart/issues/comments{/number}", 61 | "contents_url": "https://api.github.com/repos/google/episodes.dart/contents/{+path}", 62 | "compare_url": "https://api.github.com/repos/google/episodes.dart/compare/{base}...{head}", 63 | "merges_url": "https://api.github.com/repos/google/episodes.dart/merges", 64 | "archive_url": "https://api.github.com/repos/google/episodes.dart/{archive_format}{/ref}", 65 | "downloads_url": "https://api.github.com/repos/google/episodes.dart/downloads", 66 | "issues_url": "https://api.github.com/repos/google/episodes.dart/issues{/number}", 67 | "pulls_url": "https://api.github.com/repos/google/episodes.dart/pulls{/number}", 68 | "milestones_url": "https://api.github.com/repos/google/episodes.dart/milestones{/number}", 69 | "notifications_url": "https://api.github.com/repos/google/episodes.dart/notifications{?since,all,participating}", 70 | "labels_url": "https://api.github.com/repos/google/episodes.dart/labels{/name}", 71 | "releases_url": "https://api.github.com/repos/google/episodes.dart/releases{/id}", 72 | "deployments_url": "https://api.github.com/repos/google/episodes.dart/deployments", 73 | "created_at": "2013-01-19T00:31:37Z", 74 | "updated_at": "2019-09-23T11:53:58Z", 75 | "pushed_at": "2014-10-09T21:39:33Z", 76 | "git_url": "git://github.com/google/episodes.dart.git", 77 | "ssh_url": "git@github.com:google/episodes.dart.git", 78 | "clone_url": "https://github.com/google/episodes.dart.git", 79 | "svn_url": "https://github.com/google/episodes.dart", 80 | "homepage": None, 81 | "size": 191, 82 | "stargazers_count": 12, 83 | "watchers_count": 12, 84 | "language": "Dart", 85 | "has_issues": True, 86 | "has_projects": True, 87 | "has_downloads": True, 88 | "has_wiki": True, 89 | "has_pages": False, 90 | "forks_count": 22, 91 | "mirror_url": None, 92 | "archived": False, 93 | "disabled": False, 94 | "open_issues_count": 0, 95 | "license": { 96 | "key": "bsd-3-clause", 97 | "name": "BSD 3-Clause \"New\" or \"Revised\" License", 98 | "spdx_id": "BSD-3-Clause", 99 | "url": "https://api.github.com/licenses/bsd-3-clause", 100 | "node_id": "MDc6TGljZW5zZTU=" 101 | }, 102 | "forks": 22, 103 | "open_issues": 0, 104 | "watchers": 12, 105 | "default_branch": "master", 106 | "permissions": { 107 | "admin": False, 108 | "push": False, 109 | "pull": True 110 | } 111 | }, 112 | { 113 | "id": 7776515, 114 | "node_id": "MDEwOlJlcG9zaXRvcnk3Nzc2NTE1", 115 | "name": "cpp-netlib", 116 | "full_name": "google/cpp-netlib", 117 | "private": False, 118 | "owner": { 119 | "login": "google", 120 | "id": 1342004, 121 | "node_id": "MDEyOk9yZ2FuaXphdGlvbjEzNDIwMDQ=", 122 | "avatar_url": "https://avatars1.githubusercontent.com/u/1342004?v=4", 123 | "gravatar_id": "", 124 | "url": "https://api.github.com/users/google", 125 | "html_url": "https://github.com/google", 126 | "followers_url": "https://api.github.com/users/google/followers", 127 | "following_url": "https://api.github.com/users/google/following{/other_user}", 128 | "gists_url": "https://api.github.com/users/google/gists{/gist_id}", 129 | "starred_url": "https://api.github.com/users/google/starred{/owner}{/repo}", 130 | "subscriptions_url": "https://api.github.com/users/google/subscriptions", 131 | "organizations_url": "https://api.github.com/users/google/orgs", 132 | "repos_url": "https://api.github.com/users/google/repos", 133 | "events_url": "https://api.github.com/users/google/events{/privacy}", 134 | "received_events_url": "https://api.github.com/users/google/received_events", 135 | "type": "Organization", 136 | "site_admin": False 137 | }, 138 | "html_url": "https://github.com/google/cpp-netlib", 139 | "description": "The C++ Network Library Project -- header-only, cross-platform, standards compliant networking library.", 140 | "fork": True, 141 | "url": "https://api.github.com/repos/google/cpp-netlib", 142 | "forks_url": "https://api.github.com/repos/google/cpp-netlib/forks", 143 | "keys_url": "https://api.github.com/repos/google/cpp-netlib/keys{/key_id}", 144 | "collaborators_url": "https://api.github.com/repos/google/cpp-netlib/collaborators{/collaborator}", 145 | "teams_url": "https://api.github.com/repos/google/cpp-netlib/teams", 146 | "hooks_url": "https://api.github.com/repos/google/cpp-netlib/hooks", 147 | "issue_events_url": "https://api.github.com/repos/google/cpp-netlib/issues/events{/number}", 148 | "events_url": "https://api.github.com/repos/google/cpp-netlib/events", 149 | "assignees_url": "https://api.github.com/repos/google/cpp-netlib/assignees{/user}", 150 | "branches_url": "https://api.github.com/repos/google/cpp-netlib/branches{/branch}", 151 | "tags_url": "https://api.github.com/repos/google/cpp-netlib/tags", 152 | "blobs_url": "https://api.github.com/repos/google/cpp-netlib/git/blobs{/sha}", 153 | "git_tags_url": "https://api.github.com/repos/google/cpp-netlib/git/tags{/sha}", 154 | "git_refs_url": "https://api.github.com/repos/google/cpp-netlib/git/refs{/sha}", 155 | "trees_url": "https://api.github.com/repos/google/cpp-netlib/git/trees{/sha}", 156 | "statuses_url": "https://api.github.com/repos/google/cpp-netlib/statuses/{sha}", 157 | "languages_url": "https://api.github.com/repos/google/cpp-netlib/languages", 158 | "stargazers_url": "https://api.github.com/repos/google/cpp-netlib/stargazers", 159 | "contributors_url": "https://api.github.com/repos/google/cpp-netlib/contributors", 160 | "subscribers_url": "https://api.github.com/repos/google/cpp-netlib/subscribers", 161 | "subscription_url": "https://api.github.com/repos/google/cpp-netlib/subscription", 162 | "commits_url": "https://api.github.com/repos/google/cpp-netlib/commits{/sha}", 163 | "git_commits_url": "https://api.github.com/repos/google/cpp-netlib/git/commits{/sha}", 164 | "comments_url": "https://api.github.com/repos/google/cpp-netlib/comments{/number}", 165 | "issue_comment_url": "https://api.github.com/repos/google/cpp-netlib/issues/comments{/number}", 166 | "contents_url": "https://api.github.com/repos/google/cpp-netlib/contents/{+path}", 167 | "compare_url": "https://api.github.com/repos/google/cpp-netlib/compare/{base}...{head}", 168 | "merges_url": "https://api.github.com/repos/google/cpp-netlib/merges", 169 | "archive_url": "https://api.github.com/repos/google/cpp-netlib/{archive_format}{/ref}", 170 | "downloads_url": "https://api.github.com/repos/google/cpp-netlib/downloads", 171 | "issues_url": "https://api.github.com/repos/google/cpp-netlib/issues{/number}", 172 | "pulls_url": "https://api.github.com/repos/google/cpp-netlib/pulls{/number}", 173 | "milestones_url": "https://api.github.com/repos/google/cpp-netlib/milestones{/number}", 174 | "notifications_url": "https://api.github.com/repos/google/cpp-netlib/notifications{?since,all,participating}", 175 | "labels_url": "https://api.github.com/repos/google/cpp-netlib/labels{/name}", 176 | "releases_url": "https://api.github.com/repos/google/cpp-netlib/releases{/id}", 177 | "deployments_url": "https://api.github.com/repos/google/cpp-netlib/deployments", 178 | "created_at": "2013-01-23T14:45:32Z", 179 | "updated_at": "2019-11-15T02:26:31Z", 180 | "pushed_at": "2018-12-05T17:42:29Z", 181 | "git_url": "git://github.com/google/cpp-netlib.git", 182 | "ssh_url": "git@github.com:google/cpp-netlib.git", 183 | "clone_url": "https://github.com/google/cpp-netlib.git", 184 | "svn_url": "https://github.com/google/cpp-netlib", 185 | "homepage": "http://cpp-netlib.github.com/", 186 | "size": 8937, 187 | "stargazers_count": 292, 188 | "watchers_count": 292, 189 | "language": "C++", 190 | "has_issues": False, 191 | "has_projects": True, 192 | "has_downloads": True, 193 | "has_wiki": True, 194 | "has_pages": False, 195 | "forks_count": 59, 196 | "mirror_url": None, 197 | "archived": False, 198 | "disabled": False, 199 | "open_issues_count": 0, 200 | "license": { 201 | "key": "bsl-1.0", 202 | "name": "Boost Software License 1.0", 203 | "spdx_id": "BSL-1.0", 204 | "url": "https://api.github.com/licenses/bsl-1.0", 205 | "node_id": "MDc6TGljZW5zZTI4" 206 | }, 207 | "forks": 59, 208 | "open_issues": 0, 209 | "watchers": 292, 210 | "default_branch": "master", 211 | "permissions": { 212 | "admin": False, 213 | "push": False, 214 | "pull": True 215 | } 216 | }, 217 | { 218 | "id": 7968417, 219 | "node_id": "MDEwOlJlcG9zaXRvcnk3OTY4NDE3", 220 | "name": "dagger", 221 | "full_name": "google/dagger", 222 | "private": False, 223 | "owner": { 224 | "login": "google", 225 | "id": 1342004, 226 | "node_id": "MDEyOk9yZ2FuaXphdGlvbjEzNDIwMDQ=", 227 | "avatar_url": "https://avatars1.githubusercontent.com/u/1342004?v=4", 228 | "gravatar_id": "", 229 | "url": "https://api.github.com/users/google", 230 | "html_url": "https://github.com/google", 231 | "followers_url": "https://api.github.com/users/google/followers", 232 | "following_url": "https://api.github.com/users/google/following{/other_user}", 233 | "gists_url": "https://api.github.com/users/google/gists{/gist_id}", 234 | "starred_url": "https://api.github.com/users/google/starred{/owner}{/repo}", 235 | "subscriptions_url": "https://api.github.com/users/google/subscriptions", 236 | "organizations_url": "https://api.github.com/users/google/orgs", 237 | "repos_url": "https://api.github.com/users/google/repos", 238 | "events_url": "https://api.github.com/users/google/events{/privacy}", 239 | "received_events_url": "https://api.github.com/users/google/received_events", 240 | "type": "Organization", 241 | "site_admin": False 242 | }, 243 | "html_url": "https://github.com/google/dagger", 244 | "description": "A fast dependency injector for Android and Java.", 245 | "fork": True, 246 | "url": "https://api.github.com/repos/google/dagger", 247 | "forks_url": "https://api.github.com/repos/google/dagger/forks", 248 | "keys_url": "https://api.github.com/repos/google/dagger/keys{/key_id}", 249 | "collaborators_url": "https://api.github.com/repos/google/dagger/collaborators{/collaborator}", 250 | "teams_url": "https://api.github.com/repos/google/dagger/teams", 251 | "hooks_url": "https://api.github.com/repos/google/dagger/hooks", 252 | "issue_events_url": "https://api.github.com/repos/google/dagger/issues/events{/number}", 253 | "events_url": "https://api.github.com/repos/google/dagger/events", 254 | "assignees_url": "https://api.github.com/repos/google/dagger/assignees{/user}", 255 | "branches_url": "https://api.github.com/repos/google/dagger/branches{/branch}", 256 | "tags_url": "https://api.github.com/repos/google/dagger/tags", 257 | "blobs_url": "https://api.github.com/repos/google/dagger/git/blobs{/sha}", 258 | "git_tags_url": "https://api.github.com/repos/google/dagger/git/tags{/sha}", 259 | "git_refs_url": "https://api.github.com/repos/google/dagger/git/refs{/sha}", 260 | "trees_url": "https://api.github.com/repos/google/dagger/git/trees{/sha}", 261 | "statuses_url": "https://api.github.com/repos/google/dagger/statuses/{sha}", 262 | "languages_url": "https://api.github.com/repos/google/dagger/languages", 263 | "stargazers_url": "https://api.github.com/repos/google/dagger/stargazers", 264 | "contributors_url": "https://api.github.com/repos/google/dagger/contributors", 265 | "subscribers_url": "https://api.github.com/repos/google/dagger/subscribers", 266 | "subscription_url": "https://api.github.com/repos/google/dagger/subscription", 267 | "commits_url": "https://api.github.com/repos/google/dagger/commits{/sha}", 268 | "git_commits_url": "https://api.github.com/repos/google/dagger/git/commits{/sha}", 269 | "comments_url": "https://api.github.com/repos/google/dagger/comments{/number}", 270 | "issue_comment_url": "https://api.github.com/repos/google/dagger/issues/comments{/number}", 271 | "contents_url": "https://api.github.com/repos/google/dagger/contents/{+path}", 272 | "compare_url": "https://api.github.com/repos/google/dagger/compare/{base}...{head}", 273 | "merges_url": "https://api.github.com/repos/google/dagger/merges", 274 | "archive_url": "https://api.github.com/repos/google/dagger/{archive_format}{/ref}", 275 | "downloads_url": "https://api.github.com/repos/google/dagger/downloads", 276 | "issues_url": "https://api.github.com/repos/google/dagger/issues{/number}", 277 | "pulls_url": "https://api.github.com/repos/google/dagger/pulls{/number}", 278 | "milestones_url": "https://api.github.com/repos/google/dagger/milestones{/number}", 279 | "notifications_url": "https://api.github.com/repos/google/dagger/notifications{?since,all,participating}", 280 | "labels_url": "https://api.github.com/repos/google/dagger/labels{/name}", 281 | "releases_url": "https://api.github.com/repos/google/dagger/releases{/id}", 282 | "deployments_url": "https://api.github.com/repos/google/dagger/deployments", 283 | "created_at": "2013-02-01T23:14:14Z", 284 | "updated_at": "2019-12-03T12:39:55Z", 285 | "pushed_at": "2019-11-27T21:20:38Z", 286 | "git_url": "git://github.com/google/dagger.git", 287 | "ssh_url": "git@github.com:google/dagger.git", 288 | "clone_url": "https://github.com/google/dagger.git", 289 | "svn_url": "https://github.com/google/dagger", 290 | "homepage": "https://dagger.dev", 291 | "size": 59129, 292 | "stargazers_count": 14492, 293 | "watchers_count": 14492, 294 | "language": "Java", 295 | "has_issues": True, 296 | "has_projects": True, 297 | "has_downloads": True, 298 | "has_wiki": True, 299 | "has_pages": True, 300 | "forks_count": 1741, 301 | "mirror_url": None, 302 | "archived": False, 303 | "disabled": False, 304 | "open_issues_count": 148, 305 | "license": { 306 | "key": "apache-2.0", 307 | "name": "Apache License 2.0", 308 | "spdx_id": "Apache-2.0", 309 | "url": "https://api.github.com/licenses/apache-2.0", 310 | "node_id": "MDc6TGljZW5zZTI=" 311 | }, 312 | "forks": 1741, 313 | "open_issues": 148, 314 | "watchers": 14492, 315 | "default_branch": "master", 316 | "permissions": { 317 | "admin": False, 318 | "push": False, 319 | "pull": True 320 | } 321 | }, 322 | { 323 | "id": 8165161, 324 | "node_id": "MDEwOlJlcG9zaXRvcnk4MTY1MTYx", 325 | "name": "ios-webkit-debug-proxy", 326 | "full_name": "google/ios-webkit-debug-proxy", 327 | "private": False, 328 | "owner": { 329 | "login": "google", 330 | "id": 1342004, 331 | "node_id": "MDEyOk9yZ2FuaXphdGlvbjEzNDIwMDQ=", 332 | "avatar_url": "https://avatars1.githubusercontent.com/u/1342004?v=4", 333 | "gravatar_id": "", 334 | "url": "https://api.github.com/users/google", 335 | "html_url": "https://github.com/google", 336 | "followers_url": "https://api.github.com/users/google/followers", 337 | "following_url": "https://api.github.com/users/google/following{/other_user}", 338 | "gists_url": "https://api.github.com/users/google/gists{/gist_id}", 339 | "starred_url": "https://api.github.com/users/google/starred{/owner}{/repo}", 340 | "subscriptions_url": "https://api.github.com/users/google/subscriptions", 341 | "organizations_url": "https://api.github.com/users/google/orgs", 342 | "repos_url": "https://api.github.com/users/google/repos", 343 | "events_url": "https://api.github.com/users/google/events{/privacy}", 344 | "received_events_url": "https://api.github.com/users/google/received_events", 345 | "type": "Organization", 346 | "site_admin": False 347 | }, 348 | "html_url": "https://github.com/google/ios-webkit-debug-proxy", 349 | "description": "A DevTools proxy (Chrome Remote Debugging Protocol) for iOS devices (Safari Remote Web Inspector).", 350 | "fork": False, 351 | "url": "https://api.github.com/repos/google/ios-webkit-debug-proxy", 352 | "forks_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/forks", 353 | "keys_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/keys{/key_id}", 354 | "collaborators_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/collaborators{/collaborator}", 355 | "teams_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/teams", 356 | "hooks_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/hooks", 357 | "issue_events_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/issues/events{/number}", 358 | "events_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/events", 359 | "assignees_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/assignees{/user}", 360 | "branches_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/branches{/branch}", 361 | "tags_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/tags", 362 | "blobs_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/git/blobs{/sha}", 363 | "git_tags_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/git/tags{/sha}", 364 | "git_refs_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/git/refs{/sha}", 365 | "trees_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/git/trees{/sha}", 366 | "statuses_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/statuses/{sha}", 367 | "languages_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/languages", 368 | "stargazers_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/stargazers", 369 | "contributors_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/contributors", 370 | "subscribers_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/subscribers", 371 | "subscription_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/subscription", 372 | "commits_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/commits{/sha}", 373 | "git_commits_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/git/commits{/sha}", 374 | "comments_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/comments{/number}", 375 | "issue_comment_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/issues/comments{/number}", 376 | "contents_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/contents/{+path}", 377 | "compare_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/compare/{base}...{head}", 378 | "merges_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/merges", 379 | "archive_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/{archive_format}{/ref}", 380 | "downloads_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/downloads", 381 | "issues_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/issues{/number}", 382 | "pulls_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/pulls{/number}", 383 | "milestones_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/milestones{/number}", 384 | "notifications_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/notifications{?since,all,participating}", 385 | "labels_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/labels{/name}", 386 | "releases_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/releases{/id}", 387 | "deployments_url": "https://api.github.com/repos/google/ios-webkit-debug-proxy/deployments", 388 | "created_at": "2013-02-12T19:08:19Z", 389 | "updated_at": "2019-12-04T02:06:43Z", 390 | "pushed_at": "2019-11-24T07:02:13Z", 391 | "git_url": "git://github.com/google/ios-webkit-debug-proxy.git", 392 | "ssh_url": "git@github.com:google/ios-webkit-debug-proxy.git", 393 | "clone_url": "https://github.com/google/ios-webkit-debug-proxy.git", 394 | "svn_url": "https://github.com/google/ios-webkit-debug-proxy", 395 | "homepage": "", 396 | "size": 680, 397 | "stargazers_count": 4630, 398 | "watchers_count": 4630, 399 | "language": "C", 400 | "has_issues": True, 401 | "has_projects": True, 402 | "has_downloads": True, 403 | "has_wiki": False, 404 | "has_pages": False, 405 | "forks_count": 395, 406 | "mirror_url": None, 407 | "archived": False, 408 | "disabled": False, 409 | "open_issues_count": 24, 410 | "license": { 411 | "key": "other", 412 | "name": "Other", 413 | "spdx_id": "NOASSERTION", 414 | "url": None, 415 | "node_id": "MDc6TGljZW5zZTA=" 416 | }, 417 | "forks": 395, 418 | "open_issues": 24, 419 | "watchers": 4630, 420 | "default_branch": "master", 421 | "permissions": { 422 | "admin": False, 423 | "push": False, 424 | "pull": True 425 | } 426 | }, 427 | { 428 | "id": 8459994, 429 | "node_id": "MDEwOlJlcG9zaXRvcnk4NDU5OTk0", 430 | "name": "google.github.io", 431 | "full_name": "google/google.github.io", 432 | "private": False, 433 | "owner": { 434 | "login": "google", 435 | "id": 1342004, 436 | "node_id": "MDEyOk9yZ2FuaXphdGlvbjEzNDIwMDQ=", 437 | "avatar_url": "https://avatars1.githubusercontent.com/u/1342004?v=4", 438 | "gravatar_id": "", 439 | "url": "https://api.github.com/users/google", 440 | "html_url": "https://github.com/google", 441 | "followers_url": "https://api.github.com/users/google/followers", 442 | "following_url": "https://api.github.com/users/google/following{/other_user}", 443 | "gists_url": "https://api.github.com/users/google/gists{/gist_id}", 444 | "starred_url": "https://api.github.com/users/google/starred{/owner}{/repo}", 445 | "subscriptions_url": "https://api.github.com/users/google/subscriptions", 446 | "organizations_url": "https://api.github.com/users/google/orgs", 447 | "repos_url": "https://api.github.com/users/google/repos", 448 | "events_url": "https://api.github.com/users/google/events{/privacy}", 449 | "received_events_url": "https://api.github.com/users/google/received_events", 450 | "type": "Organization", 451 | "site_admin": False 452 | }, 453 | "html_url": "https://github.com/google/google.github.io", 454 | "description": None, 455 | "fork": False, 456 | "url": "https://api.github.com/repos/google/google.github.io", 457 | "forks_url": "https://api.github.com/repos/google/google.github.io/forks", 458 | "keys_url": "https://api.github.com/repos/google/google.github.io/keys{/key_id}", 459 | "collaborators_url": "https://api.github.com/repos/google/google.github.io/collaborators{/collaborator}", 460 | "teams_url": "https://api.github.com/repos/google/google.github.io/teams", 461 | "hooks_url": "https://api.github.com/repos/google/google.github.io/hooks", 462 | "issue_events_url": "https://api.github.com/repos/google/google.github.io/issues/events{/number}", 463 | "events_url": "https://api.github.com/repos/google/google.github.io/events", 464 | "assignees_url": "https://api.github.com/repos/google/google.github.io/assignees{/user}", 465 | "branches_url": "https://api.github.com/repos/google/google.github.io/branches{/branch}", 466 | "tags_url": "https://api.github.com/repos/google/google.github.io/tags", 467 | "blobs_url": "https://api.github.com/repos/google/google.github.io/git/blobs{/sha}", 468 | "git_tags_url": "https://api.github.com/repos/google/google.github.io/git/tags{/sha}", 469 | "git_refs_url": "https://api.github.com/repos/google/google.github.io/git/refs{/sha}", 470 | "trees_url": "https://api.github.com/repos/google/google.github.io/git/trees{/sha}", 471 | "statuses_url": "https://api.github.com/repos/google/google.github.io/statuses/{sha}", 472 | "languages_url": "https://api.github.com/repos/google/google.github.io/languages", 473 | "stargazers_url": "https://api.github.com/repos/google/google.github.io/stargazers", 474 | "contributors_url": "https://api.github.com/repos/google/google.github.io/contributors", 475 | "subscribers_url": "https://api.github.com/repos/google/google.github.io/subscribers", 476 | "subscription_url": "https://api.github.com/repos/google/google.github.io/subscription", 477 | "commits_url": "https://api.github.com/repos/google/google.github.io/commits{/sha}", 478 | "git_commits_url": "https://api.github.com/repos/google/google.github.io/git/commits{/sha}", 479 | "comments_url": "https://api.github.com/repos/google/google.github.io/comments{/number}", 480 | "issue_comment_url": "https://api.github.com/repos/google/google.github.io/issues/comments{/number}", 481 | "contents_url": "https://api.github.com/repos/google/google.github.io/contents/{+path}", 482 | "compare_url": "https://api.github.com/repos/google/google.github.io/compare/{base}...{head}", 483 | "merges_url": "https://api.github.com/repos/google/google.github.io/merges", 484 | "archive_url": "https://api.github.com/repos/google/google.github.io/{archive_format}{/ref}", 485 | "downloads_url": "https://api.github.com/repos/google/google.github.io/downloads", 486 | "issues_url": "https://api.github.com/repos/google/google.github.io/issues{/number}", 487 | "pulls_url": "https://api.github.com/repos/google/google.github.io/pulls{/number}", 488 | "milestones_url": "https://api.github.com/repos/google/google.github.io/milestones{/number}", 489 | "notifications_url": "https://api.github.com/repos/google/google.github.io/notifications{?since,all,participating}", 490 | "labels_url": "https://api.github.com/repos/google/google.github.io/labels{/name}", 491 | "releases_url": "https://api.github.com/repos/google/google.github.io/releases{/id}", 492 | "deployments_url": "https://api.github.com/repos/google/google.github.io/deployments", 493 | "created_at": "2013-02-27T16:21:19Z", 494 | "updated_at": "2019-12-03T01:38:02Z", 495 | "pushed_at": "2019-12-03T01:37:58Z", 496 | "git_url": "git://github.com/google/google.github.io.git", 497 | "ssh_url": "git@github.com:google/google.github.io.git", 498 | "clone_url": "https://github.com/google/google.github.io.git", 499 | "svn_url": "https://github.com/google/google.github.io", 500 | "homepage": None, 501 | "size": 8, 502 | "stargazers_count": 38, 503 | "watchers_count": 38, 504 | "language": "HTML", 505 | "has_issues": False, 506 | "has_projects": True, 507 | "has_downloads": True, 508 | "has_wiki": False, 509 | "has_pages": True, 510 | "forks_count": 44, 511 | "mirror_url": None, 512 | "archived": False, 513 | "disabled": False, 514 | "open_issues_count": 0, 515 | "license": None, 516 | "forks": 44, 517 | "open_issues": 0, 518 | "watchers": 38, 519 | "default_branch": "master", 520 | "permissions": { 521 | "admin": False, 522 | "push": False, 523 | "pull": True 524 | } 525 | }, 526 | { 527 | "id": 8566972, 528 | "node_id": "MDEwOlJlcG9zaXRvcnk4NTY2OTcy", 529 | "name": "kratu", 530 | "full_name": "google/kratu", 531 | "private": False, 532 | "owner": { 533 | "login": "google", 534 | "id": 1342004, 535 | "node_id": "MDEyOk9yZ2FuaXphdGlvbjEzNDIwMDQ=", 536 | "avatar_url": "https://avatars1.githubusercontent.com/u/1342004?v=4", 537 | "gravatar_id": "", 538 | "url": "https://api.github.com/users/google", 539 | "html_url": "https://github.com/google", 540 | "followers_url": "https://api.github.com/users/google/followers", 541 | "following_url": "https://api.github.com/users/google/following{/other_user}", 542 | "gists_url": "https://api.github.com/users/google/gists{/gist_id}", 543 | "starred_url": "https://api.github.com/users/google/starred{/owner}{/repo}", 544 | "subscriptions_url": "https://api.github.com/users/google/subscriptions", 545 | "organizations_url": "https://api.github.com/users/google/orgs", 546 | "repos_url": "https://api.github.com/users/google/repos", 547 | "events_url": "https://api.github.com/users/google/events{/privacy}", 548 | "received_events_url": "https://api.github.com/users/google/received_events", 549 | "type": "Organization", 550 | "site_admin": False 551 | }, 552 | "html_url": "https://github.com/google/kratu", 553 | "description": None, 554 | "fork": False, 555 | "url": "https://api.github.com/repos/google/kratu", 556 | "forks_url": "https://api.github.com/repos/google/kratu/forks", 557 | "keys_url": "https://api.github.com/repos/google/kratu/keys{/key_id}", 558 | "collaborators_url": "https://api.github.com/repos/google/kratu/collaborators{/collaborator}", 559 | "teams_url": "https://api.github.com/repos/google/kratu/teams", 560 | "hooks_url": "https://api.github.com/repos/google/kratu/hooks", 561 | "issue_events_url": "https://api.github.com/repos/google/kratu/issues/events{/number}", 562 | "events_url": "https://api.github.com/repos/google/kratu/events", 563 | "assignees_url": "https://api.github.com/repos/google/kratu/assignees{/user}", 564 | "branches_url": "https://api.github.com/repos/google/kratu/branches{/branch}", 565 | "tags_url": "https://api.github.com/repos/google/kratu/tags", 566 | "blobs_url": "https://api.github.com/repos/google/kratu/git/blobs{/sha}", 567 | "git_tags_url": "https://api.github.com/repos/google/kratu/git/tags{/sha}", 568 | "git_refs_url": "https://api.github.com/repos/google/kratu/git/refs{/sha}", 569 | "trees_url": "https://api.github.com/repos/google/kratu/git/trees{/sha}", 570 | "statuses_url": "https://api.github.com/repos/google/kratu/statuses/{sha}", 571 | "languages_url": "https://api.github.com/repos/google/kratu/languages", 572 | "stargazers_url": "https://api.github.com/repos/google/kratu/stargazers", 573 | "contributors_url": "https://api.github.com/repos/google/kratu/contributors", 574 | "subscribers_url": "https://api.github.com/repos/google/kratu/subscribers", 575 | "subscription_url": "https://api.github.com/repos/google/kratu/subscription", 576 | "commits_url": "https://api.github.com/repos/google/kratu/commits{/sha}", 577 | "git_commits_url": "https://api.github.com/repos/google/kratu/git/commits{/sha}", 578 | "comments_url": "https://api.github.com/repos/google/kratu/comments{/number}", 579 | "issue_comment_url": "https://api.github.com/repos/google/kratu/issues/comments{/number}", 580 | "contents_url": "https://api.github.com/repos/google/kratu/contents/{+path}", 581 | "compare_url": "https://api.github.com/repos/google/kratu/compare/{base}...{head}", 582 | "merges_url": "https://api.github.com/repos/google/kratu/merges", 583 | "archive_url": "https://api.github.com/repos/google/kratu/{archive_format}{/ref}", 584 | "downloads_url": "https://api.github.com/repos/google/kratu/downloads", 585 | "issues_url": "https://api.github.com/repos/google/kratu/issues{/number}", 586 | "pulls_url": "https://api.github.com/repos/google/kratu/pulls{/number}", 587 | "milestones_url": "https://api.github.com/repos/google/kratu/milestones{/number}", 588 | "notifications_url": "https://api.github.com/repos/google/kratu/notifications{?since,all,participating}", 589 | "labels_url": "https://api.github.com/repos/google/kratu/labels{/name}", 590 | "releases_url": "https://api.github.com/repos/google/kratu/releases{/id}", 591 | "deployments_url": "https://api.github.com/repos/google/kratu/deployments", 592 | "created_at": "2013-03-04T22:52:33Z", 593 | "updated_at": "2019-11-15T22:22:16Z", 594 | "pushed_at": "2017-08-06T05:44:34Z", 595 | "git_url": "git://github.com/google/kratu.git", 596 | "ssh_url": "git@github.com:google/kratu.git", 597 | "clone_url": "https://github.com/google/kratu.git", 598 | "svn_url": "https://github.com/google/kratu", 599 | "homepage": None, 600 | "size": 1777, 601 | "stargazers_count": 280, 602 | "watchers_count": 280, 603 | "language": "JavaScript", 604 | "has_issues": True, 605 | "has_projects": True, 606 | "has_downloads": True, 607 | "has_wiki": True, 608 | "has_pages": True, 609 | "forks_count": 32, 610 | "mirror_url": None, 611 | "archived": False, 612 | "disabled": False, 613 | "open_issues_count": 0, 614 | "license": { 615 | "key": "apache-2.0", 616 | "name": "Apache License 2.0", 617 | "spdx_id": "Apache-2.0", 618 | "url": "https://api.github.com/licenses/apache-2.0", 619 | "node_id": "MDc6TGljZW5zZTI=" 620 | }, 621 | "forks": 32, 622 | "open_issues": 0, 623 | "watchers": 280, 624 | "default_branch": "master", 625 | "permissions": { 626 | "admin": False, 627 | "push": False, 628 | "pull": True 629 | } 630 | }, 631 | { 632 | "id": 8858648, 633 | "node_id": "MDEwOlJlcG9zaXRvcnk4ODU4NjQ4", 634 | "name": "build-debian-cloud", 635 | "full_name": "google/build-debian-cloud", 636 | "private": False, 637 | "owner": { 638 | "login": "google", 639 | "id": 1342004, 640 | "node_id": "MDEyOk9yZ2FuaXphdGlvbjEzNDIwMDQ=", 641 | "avatar_url": "https://avatars1.githubusercontent.com/u/1342004?v=4", 642 | "gravatar_id": "", 643 | "url": "https://api.github.com/users/google", 644 | "html_url": "https://github.com/google", 645 | "followers_url": "https://api.github.com/users/google/followers", 646 | "following_url": "https://api.github.com/users/google/following{/other_user}", 647 | "gists_url": "https://api.github.com/users/google/gists{/gist_id}", 648 | "starred_url": "https://api.github.com/users/google/starred{/owner}{/repo}", 649 | "subscriptions_url": "https://api.github.com/users/google/subscriptions", 650 | "organizations_url": "https://api.github.com/users/google/orgs", 651 | "repos_url": "https://api.github.com/users/google/repos", 652 | "events_url": "https://api.github.com/users/google/events{/privacy}", 653 | "received_events_url": "https://api.github.com/users/google/received_events", 654 | "type": "Organization", 655 | "site_admin": False 656 | }, 657 | "html_url": "https://github.com/google/build-debian-cloud", 658 | "description": "Script to create Debian Squeeze & Wheezy Amazon Machine Images (AMIs) and Google Compute Engine images", 659 | "fork": True, 660 | "url": "https://api.github.com/repos/google/build-debian-cloud", 661 | "forks_url": "https://api.github.com/repos/google/build-debian-cloud/forks", 662 | "keys_url": "https://api.github.com/repos/google/build-debian-cloud/keys{/key_id}", 663 | "collaborators_url": "https://api.github.com/repos/google/build-debian-cloud/collaborators{/collaborator}", 664 | "teams_url": "https://api.github.com/repos/google/build-debian-cloud/teams", 665 | "hooks_url": "https://api.github.com/repos/google/build-debian-cloud/hooks", 666 | "issue_events_url": "https://api.github.com/repos/google/build-debian-cloud/issues/events{/number}", 667 | "events_url": "https://api.github.com/repos/google/build-debian-cloud/events", 668 | "assignees_url": "https://api.github.com/repos/google/build-debian-cloud/assignees{/user}", 669 | "branches_url": "https://api.github.com/repos/google/build-debian-cloud/branches{/branch}", 670 | "tags_url": "https://api.github.com/repos/google/build-debian-cloud/tags", 671 | "blobs_url": "https://api.github.com/repos/google/build-debian-cloud/git/blobs{/sha}", 672 | "git_tags_url": "https://api.github.com/repos/google/build-debian-cloud/git/tags{/sha}", 673 | "git_refs_url": "https://api.github.com/repos/google/build-debian-cloud/git/refs{/sha}", 674 | "trees_url": "https://api.github.com/repos/google/build-debian-cloud/git/trees{/sha}", 675 | "statuses_url": "https://api.github.com/repos/google/build-debian-cloud/statuses/{sha}", 676 | "languages_url": "https://api.github.com/repos/google/build-debian-cloud/languages", 677 | "stargazers_url": "https://api.github.com/repos/google/build-debian-cloud/stargazers", 678 | "contributors_url": "https://api.github.com/repos/google/build-debian-cloud/contributors", 679 | "subscribers_url": "https://api.github.com/repos/google/build-debian-cloud/subscribers", 680 | "subscription_url": "https://api.github.com/repos/google/build-debian-cloud/subscription", 681 | "commits_url": "https://api.github.com/repos/google/build-debian-cloud/commits{/sha}", 682 | "git_commits_url": "https://api.github.com/repos/google/build-debian-cloud/git/commits{/sha}", 683 | "comments_url": "https://api.github.com/repos/google/build-debian-cloud/comments{/number}", 684 | "issue_comment_url": "https://api.github.com/repos/google/build-debian-cloud/issues/comments{/number}", 685 | "contents_url": "https://api.github.com/repos/google/build-debian-cloud/contents/{+path}", 686 | "compare_url": "https://api.github.com/repos/google/build-debian-cloud/compare/{base}...{head}", 687 | "merges_url": "https://api.github.com/repos/google/build-debian-cloud/merges", 688 | "archive_url": "https://api.github.com/repos/google/build-debian-cloud/{archive_format}{/ref}", 689 | "downloads_url": "https://api.github.com/repos/google/build-debian-cloud/downloads", 690 | "issues_url": "https://api.github.com/repos/google/build-debian-cloud/issues{/number}", 691 | "pulls_url": "https://api.github.com/repos/google/build-debian-cloud/pulls{/number}", 692 | "milestones_url": "https://api.github.com/repos/google/build-debian-cloud/milestones{/number}", 693 | "notifications_url": "https://api.github.com/repos/google/build-debian-cloud/notifications{?since,all,participating}", 694 | "labels_url": "https://api.github.com/repos/google/build-debian-cloud/labels{/name}", 695 | "releases_url": "https://api.github.com/repos/google/build-debian-cloud/releases{/id}", 696 | "deployments_url": "https://api.github.com/repos/google/build-debian-cloud/deployments", 697 | "created_at": "2013-03-18T16:32:00Z", 698 | "updated_at": "2019-09-23T11:54:00Z", 699 | "pushed_at": "2014-06-17T18:52:10Z", 700 | "git_url": "git://github.com/google/build-debian-cloud.git", 701 | "ssh_url": "git@github.com:google/build-debian-cloud.git", 702 | "clone_url": "https://github.com/google/build-debian-cloud.git", 703 | "svn_url": "https://github.com/google/build-debian-cloud", 704 | "homepage": "", 705 | "size": 986, 706 | "stargazers_count": 32, 707 | "watchers_count": 32, 708 | "language": "Shell", 709 | "has_issues": False, 710 | "has_projects": True, 711 | "has_downloads": True, 712 | "has_wiki": False, 713 | "has_pages": False, 714 | "forks_count": 22, 715 | "mirror_url": None, 716 | "archived": False, 717 | "disabled": False, 718 | "open_issues_count": 5, 719 | "license": { 720 | "key": "other", 721 | "name": "Other", 722 | "spdx_id": "NOASSERTION", 723 | "url": None, 724 | "node_id": "MDc6TGljZW5zZTA=" 725 | }, 726 | "forks": 22, 727 | "open_issues": 5, 728 | "watchers": 32, 729 | "default_branch": "master", 730 | "permissions": { 731 | "admin": False, 732 | "push": False, 733 | "pull": True 734 | } 735 | }, 736 | { 737 | "id": 9060347, 738 | "node_id": "MDEwOlJlcG9zaXRvcnk5MDYwMzQ3", 739 | "name": "traceur-compiler", 740 | "full_name": "google/traceur-compiler", 741 | "private": False, 742 | "owner": { 743 | "login": "google", 744 | "id": 1342004, 745 | "node_id": "MDEyOk9yZ2FuaXphdGlvbjEzNDIwMDQ=", 746 | "avatar_url": "https://avatars1.githubusercontent.com/u/1342004?v=4", 747 | "gravatar_id": "", 748 | "url": "https://api.github.com/users/google", 749 | "html_url": "https://github.com/google", 750 | "followers_url": "https://api.github.com/users/google/followers", 751 | "following_url": "https://api.github.com/users/google/following{/other_user}", 752 | "gists_url": "https://api.github.com/users/google/gists{/gist_id}", 753 | "starred_url": "https://api.github.com/users/google/starred{/owner}{/repo}", 754 | "subscriptions_url": "https://api.github.com/users/google/subscriptions", 755 | "organizations_url": "https://api.github.com/users/google/orgs", 756 | "repos_url": "https://api.github.com/users/google/repos", 757 | "events_url": "https://api.github.com/users/google/events{/privacy}", 758 | "received_events_url": "https://api.github.com/users/google/received_events", 759 | "type": "Organization", 760 | "site_admin": False 761 | }, 762 | "html_url": "https://github.com/google/traceur-compiler", 763 | "description": "Traceur is a JavaScript.next-to-JavaScript-of-today compiler", 764 | "fork": False, 765 | "url": "https://api.github.com/repos/google/traceur-compiler", 766 | "forks_url": "https://api.github.com/repos/google/traceur-compiler/forks", 767 | "keys_url": "https://api.github.com/repos/google/traceur-compiler/keys{/key_id}", 768 | "collaborators_url": "https://api.github.com/repos/google/traceur-compiler/collaborators{/collaborator}", 769 | "teams_url": "https://api.github.com/repos/google/traceur-compiler/teams", 770 | "hooks_url": "https://api.github.com/repos/google/traceur-compiler/hooks", 771 | "issue_events_url": "https://api.github.com/repos/google/traceur-compiler/issues/events{/number}", 772 | "events_url": "https://api.github.com/repos/google/traceur-compiler/events", 773 | "assignees_url": "https://api.github.com/repos/google/traceur-compiler/assignees{/user}", 774 | "branches_url": "https://api.github.com/repos/google/traceur-compiler/branches{/branch}", 775 | "tags_url": "https://api.github.com/repos/google/traceur-compiler/tags", 776 | "blobs_url": "https://api.github.com/repos/google/traceur-compiler/git/blobs{/sha}", 777 | "git_tags_url": "https://api.github.com/repos/google/traceur-compiler/git/tags{/sha}", 778 | "git_refs_url": "https://api.github.com/repos/google/traceur-compiler/git/refs{/sha}", 779 | "trees_url": "https://api.github.com/repos/google/traceur-compiler/git/trees{/sha}", 780 | "statuses_url": "https://api.github.com/repos/google/traceur-compiler/statuses/{sha}", 781 | "languages_url": "https://api.github.com/repos/google/traceur-compiler/languages", 782 | "stargazers_url": "https://api.github.com/repos/google/traceur-compiler/stargazers", 783 | "contributors_url": "https://api.github.com/repos/google/traceur-compiler/contributors", 784 | "subscribers_url": "https://api.github.com/repos/google/traceur-compiler/subscribers", 785 | "subscription_url": "https://api.github.com/repos/google/traceur-compiler/subscription", 786 | "commits_url": "https://api.github.com/repos/google/traceur-compiler/commits{/sha}", 787 | "git_commits_url": "https://api.github.com/repos/google/traceur-compiler/git/commits{/sha}", 788 | "comments_url": "https://api.github.com/repos/google/traceur-compiler/comments{/number}", 789 | "issue_comment_url": "https://api.github.com/repos/google/traceur-compiler/issues/comments{/number}", 790 | "contents_url": "https://api.github.com/repos/google/traceur-compiler/contents/{+path}", 791 | "compare_url": "https://api.github.com/repos/google/traceur-compiler/compare/{base}...{head}", 792 | "merges_url": "https://api.github.com/repos/google/traceur-compiler/merges", 793 | "archive_url": "https://api.github.com/repos/google/traceur-compiler/{archive_format}{/ref}", 794 | "downloads_url": "https://api.github.com/repos/google/traceur-compiler/downloads", 795 | "issues_url": "https://api.github.com/repos/google/traceur-compiler/issues{/number}", 796 | "pulls_url": "https://api.github.com/repos/google/traceur-compiler/pulls{/number}", 797 | "milestones_url": "https://api.github.com/repos/google/traceur-compiler/milestones{/number}", 798 | "notifications_url": "https://api.github.com/repos/google/traceur-compiler/notifications{?since,all,participating}", 799 | "labels_url": "https://api.github.com/repos/google/traceur-compiler/labels{/name}", 800 | "releases_url": "https://api.github.com/repos/google/traceur-compiler/releases{/id}", 801 | "deployments_url": "https://api.github.com/repos/google/traceur-compiler/deployments", 802 | "created_at": "2013-03-27T18:05:40Z", 803 | "updated_at": "2019-12-02T16:45:54Z", 804 | "pushed_at": "2018-05-28T04:37:54Z", 805 | "git_url": "git://github.com/google/traceur-compiler.git", 806 | "ssh_url": "git@github.com:google/traceur-compiler.git", 807 | "clone_url": "https://github.com/google/traceur-compiler.git", 808 | "svn_url": "https://github.com/google/traceur-compiler", 809 | "homepage": "", 810 | "size": 27487, 811 | "stargazers_count": 8033, 812 | "watchers_count": 8033, 813 | "language": "JavaScript", 814 | "has_issues": True, 815 | "has_projects": True, 816 | "has_downloads": True, 817 | "has_wiki": True, 818 | "has_pages": True, 819 | "forks_count": 604, 820 | "mirror_url": None, 821 | "archived": False, 822 | "disabled": False, 823 | "open_issues_count": 296, 824 | "license": { 825 | "key": "apache-2.0", 826 | "name": "Apache License 2.0", 827 | "spdx_id": "Apache-2.0", 828 | "url": "https://api.github.com/licenses/apache-2.0", 829 | "node_id": "MDc6TGljZW5zZTI=" 830 | }, 831 | "forks": 604, 832 | "open_issues": 296, 833 | "watchers": 8033, 834 | "default_branch": "master", 835 | "permissions": { 836 | "admin": False, 837 | "push": False, 838 | "pull": True 839 | } 840 | }, 841 | { 842 | "id": 9065917, 843 | "node_id": "MDEwOlJlcG9zaXRvcnk5MDY1OTE3", 844 | "name": "firmata.py", 845 | "full_name": "google/firmata.py", 846 | "private": False, 847 | "owner": { 848 | "login": "google", 849 | "id": 1342004, 850 | "node_id": "MDEyOk9yZ2FuaXphdGlvbjEzNDIwMDQ=", 851 | "avatar_url": "https://avatars1.githubusercontent.com/u/1342004?v=4", 852 | "gravatar_id": "", 853 | "url": "https://api.github.com/users/google", 854 | "html_url": "https://github.com/google", 855 | "followers_url": "https://api.github.com/users/google/followers", 856 | "following_url": "https://api.github.com/users/google/following{/other_user}", 857 | "gists_url": "https://api.github.com/users/google/gists{/gist_id}", 858 | "starred_url": "https://api.github.com/users/google/starred{/owner}{/repo}", 859 | "subscriptions_url": "https://api.github.com/users/google/subscriptions", 860 | "organizations_url": "https://api.github.com/users/google/orgs", 861 | "repos_url": "https://api.github.com/users/google/repos", 862 | "events_url": "https://api.github.com/users/google/events{/privacy}", 863 | "received_events_url": "https://api.github.com/users/google/received_events", 864 | "type": "Organization", 865 | "site_admin": False 866 | }, 867 | "html_url": "https://github.com/google/firmata.py", 868 | "description": None, 869 | "fork": False, 870 | "url": "https://api.github.com/repos/google/firmata.py", 871 | "forks_url": "https://api.github.com/repos/google/firmata.py/forks", 872 | "keys_url": "https://api.github.com/repos/google/firmata.py/keys{/key_id}", 873 | "collaborators_url": "https://api.github.com/repos/google/firmata.py/collaborators{/collaborator}", 874 | "teams_url": "https://api.github.com/repos/google/firmata.py/teams", 875 | "hooks_url": "https://api.github.com/repos/google/firmata.py/hooks", 876 | "issue_events_url": "https://api.github.com/repos/google/firmata.py/issues/events{/number}", 877 | "events_url": "https://api.github.com/repos/google/firmata.py/events", 878 | "assignees_url": "https://api.github.com/repos/google/firmata.py/assignees{/user}", 879 | "branches_url": "https://api.github.com/repos/google/firmata.py/branches{/branch}", 880 | "tags_url": "https://api.github.com/repos/google/firmata.py/tags", 881 | "blobs_url": "https://api.github.com/repos/google/firmata.py/git/blobs{/sha}", 882 | "git_tags_url": "https://api.github.com/repos/google/firmata.py/git/tags{/sha}", 883 | "git_refs_url": "https://api.github.com/repos/google/firmata.py/git/refs{/sha}", 884 | "trees_url": "https://api.github.com/repos/google/firmata.py/git/trees{/sha}", 885 | "statuses_url": "https://api.github.com/repos/google/firmata.py/statuses/{sha}", 886 | "languages_url": "https://api.github.com/repos/google/firmata.py/languages", 887 | "stargazers_url": "https://api.github.com/repos/google/firmata.py/stargazers", 888 | "contributors_url": "https://api.github.com/repos/google/firmata.py/contributors", 889 | "subscribers_url": "https://api.github.com/repos/google/firmata.py/subscribers", 890 | "subscription_url": "https://api.github.com/repos/google/firmata.py/subscription", 891 | "commits_url": "https://api.github.com/repos/google/firmata.py/commits{/sha}", 892 | "git_commits_url": "https://api.github.com/repos/google/firmata.py/git/commits{/sha}", 893 | "comments_url": "https://api.github.com/repos/google/firmata.py/comments{/number}", 894 | "issue_comment_url": "https://api.github.com/repos/google/firmata.py/issues/comments{/number}", 895 | "contents_url": "https://api.github.com/repos/google/firmata.py/contents/{+path}", 896 | "compare_url": "https://api.github.com/repos/google/firmata.py/compare/{base}...{head}", 897 | "merges_url": "https://api.github.com/repos/google/firmata.py/merges", 898 | "archive_url": "https://api.github.com/repos/google/firmata.py/{archive_format}{/ref}", 899 | "downloads_url": "https://api.github.com/repos/google/firmata.py/downloads", 900 | "issues_url": "https://api.github.com/repos/google/firmata.py/issues{/number}", 901 | "pulls_url": "https://api.github.com/repos/google/firmata.py/pulls{/number}", 902 | "milestones_url": "https://api.github.com/repos/google/firmata.py/milestones{/number}", 903 | "notifications_url": "https://api.github.com/repos/google/firmata.py/notifications{?since,all,participating}", 904 | "labels_url": "https://api.github.com/repos/google/firmata.py/labels{/name}", 905 | "releases_url": "https://api.github.com/repos/google/firmata.py/releases{/id}", 906 | "deployments_url": "https://api.github.com/repos/google/firmata.py/deployments", 907 | "created_at": "2013-03-27T23:20:35Z", 908 | "updated_at": "2019-09-23T11:54:02Z", 909 | "pushed_at": "2013-03-27T23:34:35Z", 910 | "git_url": "git://github.com/google/firmata.py.git", 911 | "ssh_url": "git@github.com:google/firmata.py.git", 912 | "clone_url": "https://github.com/google/firmata.py.git", 913 | "svn_url": "https://github.com/google/firmata.py", 914 | "homepage": None, 915 | "size": 160, 916 | "stargazers_count": 15, 917 | "watchers_count": 15, 918 | "language": "Python", 919 | "has_issues": True, 920 | "has_projects": True, 921 | "has_downloads": True, 922 | "has_wiki": True, 923 | "has_pages": False, 924 | "forks_count": 15, 925 | "mirror_url": None, 926 | "archived": False, 927 | "disabled": False, 928 | "open_issues_count": 0, 929 | "license": { 930 | "key": "apache-2.0", 931 | "name": "Apache License 2.0", 932 | "spdx_id": "Apache-2.0", 933 | "url": "https://api.github.com/licenses/apache-2.0", 934 | "node_id": "MDc6TGljZW5zZTI=" 935 | }, 936 | "forks": 15, 937 | "open_issues": 0, 938 | "watchers": 15, 939 | "default_branch": "master", 940 | "permissions": { 941 | "admin": False, 942 | "push": False, 943 | "pull": True 944 | } 945 | } 946 | ], 947 | ['episodes.dart', 'cpp-netlib', 'dagger', 'ios-webkit-debug-proxy', 'google.github.io', 'kratu', 'build-debian-cloud', 'traceur-compiler', 'firmata.py'], 948 | ['dagger', 'kratu', 'traceur-compiler', 'firmata.py'], 949 | ) 950 | ] 951 | --------------------------------------------------------------------------------