Пример работы с GitHub API с помощью requests
На лекции был пример получения информации через GitHub API с помощью requests. В основном он использовался как пример получения данных в формате JSON, но как базовый пример использования requests он тоже подойдет.
Базовый пример
Для начала работы с requests, его надо установить:
pip install requests
Затем импортировать модуль:
In [1]: import requests
И указать логин и пароль вашего пользователя на GitHub:
In [2]: from getpass import getpass
In [3]: username = 'natenka'
In [4]: password = getpass.getpass()
getpass запросит пароль, как функция input, но вводимые символы не будут отображаться.
Этот запрос позволяет получить информацию о пользователе:
In [5]: r = requests.get('https://api.github.com/user', auth=(username, password))
Все ссылки, которые используются для работы с GitHub API описаны в документации
После выполнения запроса, можно просмотреть результат в формате JSON:
In [6]: r.text
Out[6]: '{"login":"natenka","id":15850513,"avatar_url":"https://avatars0.githubusercontent.com/u/15850513?v=4","gravatar_id":"","url":"https://api.github.com/users/natenka","html_url":"https://github.com/natenka","followers_url":"https://api.github.com/users/natenka/followers","following_url":"https://api.github.com/users/natenka/following{/other_user}","gists_url":"https://api.github.com/users/natenka/gists{/gist_id}","starred_url":"https://api.github.com/users/natenka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/natenka/subscriptions","organizations_url":"https://api.github.com/users/natenka/orgs","repos_url":"https://api.github.com/users/natenka/repos","events_url":"https://api.github.com/users/natenka/events{/privacy}","received_events_url":"https://api.github.com/users/natenka/received_events","type":"User","site_admin":false,"name":"Наташа Самойленко","company":null,"blog":"https://natenka.github.io/","location":null,"email":"natasha.samoylenko@gmail.com","hireable":null,"bio":null,"public_repos":11,"public_gists":2,"followers":49,"following":27,"created_at":"2015-11-14T20:32:44Z","updated_at":"2017-09-27T17:27:19Z","private_gists":0,"total_private_repos":0,"owned_private_repos":0,"disk_usage":53691,"collaborators":0,"two_factor_authentication":false,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}'
Метод json конвертирует строку в формате JSON в объекты Python:
In [7]: r.json()
Out[7]:
{'avatar_url': 'https://avatars0.githubusercontent.com/u/15850513?v=4',
'bio': None,
'blog': 'https://natenka.github.io/',
'collaborators': 0,
'company': None,
'created_at': '2015-11-14T20:32:44Z',
'disk_usage': 53691,
'email': 'natasha.samoylenko@gmail.com',
'events_url': 'https://api.github.com/users/natenka/events{/privacy}',
'followers': 49,
'followers_url': 'https://api.github.com/users/natenka/followers',
'following': 27,
'following_url': 'https://api.github.com/users/natenka/following{/other_user}',
'gists_url': 'https://api.github.com/users/natenka/gists{/gist_id}',
'gravatar_id': '',
'hireable': None,
'html_url': 'https://github.com/natenka',
'id': 15850513,
'location': None,
'login': 'natenka',
'name': 'Наташа Самойленко',
'organizations_url': 'https://api.github.com/users/natenka/orgs',
'owned_private_repos': 0,
'plan': {'collaborators': 0,
'name': 'free',
'private_repos': 0,
'space': 976562499},
'private_gists': 0,
'public_gists': 2,
'public_repos': 11,
'received_events_url': 'https://api.github.com/users/natenka/received_events',
'repos_url': 'https://api.github.com/users/natenka/repos',
'site_admin': False,
'starred_url': 'https://api.github.com/users/natenka/starred{/owner}{/repo}',
'subscriptions_url': 'https://api.github.com/users/natenka/subscriptions',
'total_private_repos': 0,
'type': 'User',
'updated_at': '2017-09-27T17:27:19Z',
'url': 'https://api.github.com/users/natenka'}
Получить все репозитории пользователя
Для получения всех ваших репозиториев, используется ссылка https://api.github.com/user/repos
In [8]: repos = requests.get('https://api.github.com/user/repos', auth=(username, password))
Пример информации о репозитории (сокращенный):
In [10]: repos.json()[1]
Out[10]:
{'archive_url': 'https://api.github.com/repos/natenka/Ansible-for-network-engineers/{archive_format}{/ref}',
'created_at': '2017-01-10T09:36:16Z',
'default_branch': 'master',
'deployments_url': 'https://api.github.com/repos/natenka/Ansible-for-network-engineers/deployments',
'description': 'Репозиторий курса "Ansible для сетевых инженеров". Курс находится на GitBook: https://www.gitbook.com/book/natenka/ansible-dlya-setevih-inzhenerov',
'downloads_url': 'https://api.github.com/repos/natenka/Ansible-for-network-engineers/downloads',
'events_url': 'https://api.github.com/repos/natenka/Ansible-for-network-engineers/events',
'fork': False,
'forks': 4,
'forks_count': 4,
'forks_url': 'https://api.github.com/repos/natenka/Ansible-for-network-engineers/forks',
'full_name': 'natenka/Ansible-for-network-engineers',
'hooks_url': 'https://api.github.com/repos/natenka/Ansible-for-network-engineers/hooks',
'html_url': 'https://github.com/natenka/Ansible-for-network-engineers',
'id': 78518623,
'name': 'Ansible-for-network-engineers',
'notifications_url': 'https://api.github.com/repos/natenka/Ansible-for-network-engineers/notifications{?since,all,participating}',
'open_issues': 0,
'open_issues_count': 0,
'owner': {'avatar_url': 'https://avatars0.githubusercontent.com/u/15850513?v=4',
'events_url': 'https://api.github.com/users/natenka/events{/privacy}',
'followers_url': 'https://api.github.com/users/natenka/followers',
'following_url': 'https://api.github.com/users/natenka/following{/other_user}',
'gists_url': 'https://api.github.com/users/natenka/gists{/gist_id}',
'gravatar_id': '',
'html_url': 'https://github.com/natenka',
'id': 15850513,
'login': 'natenka',
'organizations_url': 'https://api.github.com/users/natenka/orgs',
'received_events_url': 'https://api.github.com/users/natenka/received_events',
'repos_url': 'https://api.github.com/users/natenka/repos',
'site_admin': False,
'starred_url': 'https://api.github.com/users/natenka/starred{/owner}{/repo}',
'subscriptions_url': 'https://api.github.com/users/natenka/subscriptions',
'type': 'User',
'url': 'https://api.github.com/users/natenka'},
'permissions': {'admin': True, 'pull': True, 'push': True},
'private': False,
'ssh_url': 'git@github.com:natenka/Ansible-for-network-engineers.git',
'stargazers_count': 9,
'updated_at': '2017-10-10T06:50:33Z',
'url': 'https://api.github.com/repos/natenka/Ansible-for-network-engineers',
'watchers': 9,
'watchers_count': 9}
Таким образом можно вывести ссылку всех public репозиториев:
In [12]: for repo in repos.json():
...: if not repo['private']:
...: print(repo['html_url'])
...:
https://github.com/linkmeup/CCIE
https://github.com/natenka/Ansible-for-network-engineers
https://github.com/natenka/grade-system
https://github.com/natenka/Its_Clojure_Time
https://github.com/natenka/My_Coding_Challenges
https://github.com/natenka/My_Scripts
https://github.com/natenka/natenka.github.io
https://github.com/natenka/NetDay
https://github.com/natenka/PyNEng
https://github.com/natenka/pyneng-examples-exercises
https://github.com/natenka/pyneng-slides
https://github.com/natenka/python-ansible-experiments
https://github.com/pyneng/pyneng-online-jun-jul-2017
https://github.com/pyneng/pyneng.github.io
Получение файла
Аналогичным образом через GitHub API можно получить файл:
In [13]: file_path = 'exercises/10_serialization/task_10_2c.py'
In [14]: github_api_file_url = 'https://api.github.com/repos/natenka/pyneng-examples-exercises/contents/'
In [15]: file_response = requests.get(github_api_file_url+file_path, auth=(username, password))
Результат:
In [16]: file_response.json()
Out[16]:
{'_links': {'git': 'https://api.github.com/repos/natenka/pyneng-examples-exercises/git/blobs/815db87494071a883cc16d257a99cf024bdb1d0b',
'html': 'https://github.com/natenka/pyneng-examples-exercises/blob/master/exercises/10_serialization/task_10_2c.py',
'self': 'https://api.github.com/repos/natenka/pyneng-examples-exercises/contents/exercises/10_serialization/task_10_2c.py?ref=master'},
'content': 'IyAtKi0gY29kaW5nOiB1dGYtOCAtKi0KCicnJwrQl9Cw0LTQsNC90LjQtSAx\nMC4yYwoK0KEg0L/QvtC80L7RidGM0Y4g0YTRg9C90LrRhtC40LggZHJhd190\nb3BvbG9neSDQuNC3INGE0LDQudC70LAgZHJhd19uZXR3b3JrX2dyYXBoLnB5\nCtGB0LPQtdC90LXRgNC40YDQvtCy0LDRgtGMINGC0L7Qv9C+0LvQvtCz0LjR\njiwg0LrQvtGC0L7RgNCw0Y8g0YHQvtC+0YLQstC10YLRgdGC0LLRg9C10YIg\n0L7Qv9C40YHQsNC90LjRjiDQsiDRhNCw0LnQu9C1IHRvcG9sb2d5LnlhbWwK\nCtCe0LHRgNCw0YLQuNGC0LUg0LLQvdC40LzQsNC90LjQtSDQvdCwINGC0L4s\nINC60LDQutC+0Lkg0YTQvtGA0LzQsNGCINC00LDQvdC90YvRhSDQvtC20LjQ\ntNCw0LXRgiDRhNGD0L3QutGG0LjRjyBkcmF3X3RvcG9sb2d5LgrQntC/0LjR\ngdCw0L3QuNC1INGC0L7Qv9C+0LvQvtCz0LjQuCDQuNC3INGE0LDQudC70LAg\ndG9wb2xvZ3kueWFtbCDQvdGD0LbQvdC+INC/0YDQtdC+0LHRgNCw0LfQvtCy\n0LDRgtGMINGB0L7QvtGC0LLQtdGC0YHRgtCy0YPRjtGJ0LjQvCDQvtCx0YDQ\nsNC30L7QvCwK0YfRgtC+0LHRiyDQuNGB0L/QvtC70YzQt9C+0LLQsNGC0Ywg\n0YTRg9C90LrRhtC40Y4gZHJhd190b3BvbG9neS4KCtCU0LvRjyDRgNC10YjQ\ntdC90LjRjyDQt9Cw0LTQsNC90LjRjyDQvNC+0LbQvdC+INGB0L7Qt9C00LDR\ngtGMINC70Y7QsdGL0LUg0LLRgdC/0L7QvNC+0LPQsNGC0LXQu9GM0L3Ri9C1\nINGE0YPQvdC60YbQuNC4LgoK0J3QtSDQutC+0L/QuNGA0L7QstCw0YLRjCDQ\nutC+0LQg0YTRg9C90LrRhtC40LggZHJhd190b3BvbG9neS4KCtCSINC40YLQ\nvtCz0LUsINC00L7Qu9C20L3QviDQsdGL0YLRjCDRgdCz0LXQvdC10YDQuNGA\n0L7QstCw0L3QviDQuNC30L7QsdGA0LDQttC10L3QuNC1INGC0L7Qv9C+0LvQ\nvtCz0LjQuC4K0KDQtdC30YPQu9GM0YLQsNGCINC00L7Qu9C20LXQvSDQstGL\n0LPQu9GP0LTQtdGC0Ywg0YLQsNC6INC20LUsINC60LDQuiDRgdGF0LXQvNCw\nINCyINGE0LDQudC70LUgdGFza18xMF8yY190b3BvbG9neS5zdmcKCtCf0YDQ\nuCDRjdGC0L7QvDoKKiDQmNC90YLQtdGA0YTQtdC50YHRiyDQvNC+0LPRg9GC\nINCx0YvRgtGMINC30LDQv9C40YHQsNC90Ysg0YEg0L/RgNC+0LHQtdC70L7Q\nvCBGYSAwLzAg0LjQu9C4INCx0LXQtyBGYTAvMC4KKiDQoNCw0YHQv9C+0LvQ\nvtC20LXQvdC40LUg0YPRgdGC0YDQvtC50YHRgtCyINC90LAg0YHRhdC10LzQ\ntSDQvNC+0LbQtdGCINCx0YvRgtGMINC00YDRg9Cz0LjQvAoqINCh0L7QtdC0\n0LjQvdC10L3QuNGPINC00L7Qu9C20L3RiyDRgdC+0L7RgtCy0LXRgtGB0YLQ\nstC+0LLQsNGC0Ywg0YHRhdC10LzQtQoKCj4g0JTQu9GPINCy0YvQv9C+0LvQ\nvdC10L3QuNGPINGN0YLQvtCz0L4g0LfQsNC00LDQvdC40Y8sINC00L7Qu9C2\n0LXQvSDQsdGL0YLRjCDRg9GB0YLQsNC90L7QstC70LXQvSBncmFwaHZpejoK\nPiBhcHQtZ2V0IGluc3RhbGwgZ3JhcGh2aXoKCj4g0Jgg0LzQvtC00YPQu9GM\nIHB5dGhvbiDQtNC70Y8g0YDQsNCx0L7RgtGLINGBIGdyYXBodml6Ogo+IHBp\ncCBpbnN0YWxsIGdyYXBodml6CgonJycK\n',
'download_url': 'https://raw.githubusercontent.com/natenka/pyneng-examples-exercises/master/exercises/10_serialization/task_10_2c.py',
'encoding': 'base64',
'git_url': 'https://api.github.com/repos/natenka/pyneng-examples-exercises/git/blobs/815db87494071a883cc16d257a99cf024bdb1d0b',
'html_url': 'https://github.com/natenka/pyneng-examples-exercises/blob/master/exercises/10_serialization/task_10_2c.py',
'name': 'task_10_2c.py',
'path': 'exercises/10_serialization/task_10_2c.py',
'sha': '815db87494071a883cc16d257a99cf024bdb1d0b',
'size': 1554,
'type': 'file',
'url': 'https://api.github.com/repos/natenka/pyneng-examples-exercises/contents/exercises/10_serialization/task_10_2c.py?ref=master'}
Обратите внимание на поле encoding:
In [17]: file_response.json()['encoding']
Out[17]: 'base64'
Чтобы получить содержимое файла, нужно использовать модуль base64:
In [18]: import base64
Модуль позволяет декодировать строку и возвращает байты:
In [19]: file_bytes = base64.b64decode(file_response.json()['content'])
In [20]: file_bytes
Out[88]: b"# -*- coding: utf-8 -*-\n\n'''\n\xd0\x97\xd0\xb0\xd0\xb4\xd0\xb0\xd0\xbd\xd0\xb8\xd0\xb5 10.2c\n\n\xd0\xa1 \xd0\xbf\xd0\xbe\xd0\xbc\xd0\xbe\xd1\x89\xd1\x8c\xd1\x8e \xd1\x84\xd1\x83\xd0\xbd\xd0\xba\xd1\x86\xd0\xb8\xd0\xb8 draw_topology \xd0\xb8\xd0\xb7 \xd1\x84\xd0\xb0\xd0\xb9\xd0\xbb\xd0\xb0 draw_network_graph.py\n\xd1\x81\xd0\xb3\xd0\xb5\xd0\xbd\xd0\xb5\xd1\x80\xd0\xb8\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb0\xd1\x82\xd1\x8c \xd1\x82\xd0\xbe\xd0\xbf\xd0\xbe\xd0\xbb\xd0\xbe\xd0\xb3\xd0\xb8\xd1\x8e, \xd0\xba\xd0\xbe\xd1\x82\xd0\xbe\xd1\x80\xd0\xb0\xd1\x8f \xd1\x81\xd0\xbe\xd0\xbe\xd1\x82\xd0\xb2\xd0\xb5\xd1\x82\xd1\x81\xd1\x82\xd0\xb2\xd1\x83\xd0\xb5\xd1\x82 \xd0\xbe\xd0\xbf\xd0\xb8\xd1\x81\xd0\xb0\xd0\xbd\xd0\xb8\xd1\x8e \xd0\xb2 \xd1\x84\xd0\xb0\xd0\xb9\xd0\xbb\xd0\xb5 topology.yaml\n\n\xd0\x9e\xd0\xb1\xd1\x80\xd0\xb0\xd1\x82\xd0\xb8\xd1\x82\xd0\xb5 \xd0\xb2\xd0\xbd\xd0\xb8\xd0\xbc\xd0\xb0\xd0\xbd\xd0\xb8\xd0\xb5 \xd0\xbd\xd0\xb0 \xd1\x82\xd0\xbe, \xd0\xba\xd0\xb0\xd0\xba\xd0\xbe\xd0\xb9 \xd1\x84\xd0\xbe\xd1\x80\xd0\xbc\xd0\xb0\xd1\x82 \xd0\xb4\xd0\xb0\xd0\xbd\xd0\xbd\xd1\x8b\xd1\x85 \xd0\xbe\xd0\xb6\xd0\xb8\xd0\xb4\xd0\xb0\xd0\xb5\xd1\x82 \xd1\x84\xd1\x83\xd0\xbd\xd0\xba\xd1\x86\xd0\xb8\xd1\x8f draw_topology.\n\xd0\x9e\xd0\xbf\xd0\xb8\xd1\x81\xd0\xb0\xd0\xbd\xd0\xb8\xd0\xb5 \xd1\x82\xd0\xbe\xd0\xbf\xd0\xbe\xd0\xbb\xd0\xbe\xd0\xb3\xd0\xb8\xd0\xb8 \xd0\xb8\xd0\xb7 \xd1\x84\xd0\xb0\xd0\xb9\xd0\xbb\xd0\xb0 topology.yaml \xd0\xbd\xd1\x83\xd0\xb6\xd0\xbd\xd0\xbe \xd0\xbf\xd1\x80\xd0\xb5\xd0\xbe\xd0\xb1\xd1\x80\xd0\xb0\xd0\xb7\xd0\xbe\xd0\xb2\xd0\xb0\xd1\x82\xd1\x8c \xd1\x81\xd0\xbe\xd0\xbe\xd1\x82\xd0\xb2\xd0\xb5\xd1\x82\xd1\x81\xd1\x82\xd0\xb2\xd1\x83\xd1\x8e\xd1\x89\xd0\xb8\xd0\xbc \xd0\xbe\xd0\xb1\xd1\x80\xd0\xb0\xd0\xb7\xd0\xbe\xd0\xbc,\n\xd1\x87\xd1\x82\xd0\xbe\xd0\xb1\xd1\x8b \xd0\xb8\xd1\x81\xd0\xbf\xd0\xbe\xd0\xbb\xd1\x8c\xd0\xb7\xd0\xbe\xd0\xb2\xd0\xb0\xd1\x82\xd1\x8c \xd1\x84\xd1\x83\xd0\xbd\xd0\xba\xd1\x86\xd0\xb8\xd1\x8e draw_topology.\n\n\xd0\x94\xd0\xbb\xd1\x8f \xd1\x80\xd0\xb5\xd1\x88\xd0\xb5\xd0\xbd\xd0\xb8\xd1\x8f \xd0\xb7\xd0\xb0\xd0\xb4\xd0\xb0\xd0\xbd\xd0\xb8\xd1\x8f \xd0\xbc\xd0\xbe\xd0\xb6\xd0\xbd\xd0\xbe \xd1\x81\xd0\xbe\xd0\xb7\xd0\xb4\xd0\xb0\xd1\x82\xd1\x8c \xd0\xbb\xd1\x8e\xd0\xb1\xd1\x8b\xd0\xb5 \xd0\xb2\xd1\x81\xd0\xbf\xd0\xbe\xd0\xbc\xd0\xbe\xd0\xb3\xd0\xb0\xd1\x82\xd0\xb5\xd0\xbb\xd1\x8c\xd0\xbd\xd1\x8b\xd0\xb5 \xd1\x84\xd1\x83\xd0\xbd\xd0\xba\xd1\x86\xd0\xb8\xd0\xb8.\n\n\xd0\x9d\xd0\xb5 \xd0\xba\xd0\xbe\xd0\xbf\xd0\xb8\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb0\xd1\x82\xd1\x8c \xd0\xba\xd0\xbe\xd0\xb4 \xd1\x84\xd1\x83\xd0\xbd\xd0\xba\xd1\x86\xd0\xb8\xd0\xb8 draw_topology.\n\n\xd0\x92 \xd0\xb8\xd1\x82\xd0\xbe\xd0\xb3\xd0\xb5, \xd0\xb4\xd0\xbe\xd0\xbb\xd0\xb6\xd0\xbd\xd0\xbe \xd0\xb1\xd1\x8b\xd1\x82\xd1\x8c \xd1\x81\xd0\xb3\xd0\xb5\xd0\xbd\xd0\xb5\xd1\x80\xd0\xb8\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb0\xd0\xbd\xd0\xbe \xd0\xb8\xd0\xb7\xd0\xbe\xd0\xb1\xd1\x80\xd0\xb0\xd0\xb6\xd0\xb5\xd0\xbd\xd0\xb8\xd0\xb5 \xd1\x82\xd0\xbe\xd0\xbf\xd0\xbe\xd0\xbb\xd0\xbe\xd0\xb3\xd0\xb8\xd0\xb8.\n\xd0\xa0\xd0\xb5\xd0\xb7\xd1\x83\xd0\xbb\xd1\x8c\xd1\x82\xd0\xb0\xd1\x82 \xd0\xb4\xd0\xbe\xd0\xbb\xd0\xb6\xd0\xb5\xd0\xbd \xd0\xb2\xd1\x8b\xd0\xb3\xd0\xbb\xd1\x8f\xd0\xb4\xd0\xb5\xd1\x82\xd1\x8c \xd1\x82\xd0\xb0\xd0\xba \xd0\xb6\xd0\xb5, \xd0\xba\xd0\xb0\xd0\xba \xd1\x81\xd1\x85\xd0\xb5\xd0\xbc\xd0\xb0 \xd0\xb2 \xd1\x84\xd0\xb0\xd0\xb9\xd0\xbb\xd0\xb5 task_10_2c_topology.svg\n\n\xd0\x9f\xd1\x80\xd0\xb8 \xd1\x8d\xd1\x82\xd0\xbe\xd0\xbc:\n* \xd0\x98\xd0\xbd\xd1\x82\xd0\xb5\xd1\x80\xd1\x84\xd0\xb5\xd0\xb9\xd1\x81\xd1\x8b \xd0\xbc\xd0\xbe\xd0\xb3\xd1\x83\xd1\x82 \xd0\xb1\xd1\x8b\xd1\x82\xd1\x8c \xd0\xb7\xd0\xb0\xd0\xbf\xd0\xb8\xd1\x81\xd0\xb0\xd0\xbd\xd1\x8b \xd1\x81 \xd0\xbf\xd1\x80\xd0\xbe\xd0\xb1\xd0\xb5\xd0\xbb\xd0\xbe\xd0\xbc Fa 0/0 \xd0\xb8\xd0\xbb\xd0\xb8 \xd0\xb1\xd0\xb5\xd0\xb7 Fa0/0.\n* \xd0\xa0\xd0\xb0\xd1\x81\xd0\xbf\xd0\xbe\xd0\xbb\xd0\xbe\xd0\xb6\xd0\xb5\xd0\xbd\xd0\xb8\xd0\xb5 \xd1\x83\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xb9\xd1\x81\xd1\x82\xd0\xb2 \xd0\xbd\xd0\xb0 \xd1\x81\xd1\x85\xd0\xb5\xd0\xbc\xd0\xb5 \xd0\xbc\xd0\xbe\xd0\xb6\xd0\xb5\xd1\x82 \xd0\xb1\xd1\x8b\xd1\x82\xd1\x8c \xd0\xb4\xd1\x80\xd1\x83\xd0\xb3\xd0\xb8\xd0\xbc\n* \xd0\xa1\xd0\xbe\xd0\xb5\xd0\xb4\xd0\xb8\xd0\xbd\xd0\xb5\xd0\xbd\xd0\xb8\xd1\x8f \xd0\xb4\xd0\xbe\xd0\xbb\xd0\xb6\xd0\xbd\xd1\x8b \xd1\x81\xd0\xbe\xd0\xbe\xd1\x82\xd0\xb2\xd0\xb5\xd1\x82\xd1\x81\xd1\x82\xd0\xb2\xd0\xbe\xd0\xb2\xd0\xb0\xd1\x82\xd1\x8c \xd1\x81\xd1\x85\xd0\xb5\xd0\xbc\xd0\xb5\n\n\n> \xd0\x94\xd0\xbb\xd1\x8f \xd0\xb2\xd1\x8b\xd0\xbf\xd0\xbe\xd0\xbb\xd0\xbd\xd0\xb5\xd0\xbd\xd0\xb8\xd1\x8f \xd1\x8d\xd1\x82\xd0\xbe\xd0\xb3\xd0\xbe \xd0\xb7\xd0\xb0\xd0\xb4\xd0\xb0\xd0\xbd\xd0\xb8\xd1\x8f, \xd0\xb4\xd0\xbe\xd0\xbb\xd0\xb6\xd0\xb5\xd0\xbd \xd0\xb1\xd1\x8b\xd1\x82\xd1\x8c \xd1\x83\xd1\x81\xd1\x82\xd0\xb0\xd0\xbd\xd0\xbe\xd0\xb2\xd0\xbb\xd0\xb5\xd0\xbd graphviz:\n> apt-get install graphviz\n\n> \xd0\x98 \xd0\xbc\xd0\xbe\xd0\xb4\xd1\x83\xd0\xbb\xd1\x8c python \xd0\xb4\xd0\xbb\xd1\x8f \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd1\x8b \xd1\x81 graphviz:\n> pip install graphviz\n\n'''\n"
Чтобы получить строку Python, используется decode:
In [21]: file_str = file_bytes.decode('utf-8')
In [22]: print(file_str)
# -*- coding: utf-8 -*-
'''
Задание 10.2c
С помощью функции draw_topology из файла draw_network_graph.py
сгенерировать топологию, которая соответствует описанию в файле topology.yaml
Обратите внимание на то, какой формат данных ожидает функция draw_topology.
Описание топологии из файла topology.yaml нужно преобразовать соответствующим образом,
чтобы использовать функцию draw_topology.
Для решения задания можно создать любые вспомогательные функции.
Не копировать код функции draw_topology.
В итоге, должно быть сгенерировано изображение топологии.
Результат должен выглядеть так же, как схема в файле task_10_2c_topology.svg
При этом:
* Интерфейсы могут быть записаны с пробелом Fa 0/0 или без Fa0/0.
* Расположение устройств на схеме может быть другим
* Соединения должны соответствовать схеме
> Для выполнения этого задания, должен быть установлен graphviz:
> apt-get install graphviz
> И модуль python для работы с graphviz:
> pip install graphviz
'''
Создание файла
Для создания файла надо передать его содержимое в кодировке Base64. При этом, сама кодировка ожидает байты и возвращает байты, а формату JSON надо передать строку, а не байты.
Поэтому надо сделать несколько конвертаций, чтобы в итоге получить нужный формат:
In [25]: content = 'Проверка GitHub API'
In [26]: b_content = content.encode('utf-8')
In [27]: b_content
Out[27]: b'\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80\xd0\xba\xd0\xb0 GitHub API'
In [28]: base64_content = base64.b64encode(b_content)
In [29]: base64_content
Out[29]: b'0J/RgNC+0LLQtdGA0LrQsCBHaXRIdWIgQVBJ'
In [30]: base64_content_str = base64_content.decode('utf-8')
In [31]: base64_content_str
Out[31]: '0J/RgNC+0LLQtdGA0LrQsCBHaXRIdWIgQVBJ'
Теперь можно составить словарь с параметрами файла:
In [32]: f = {'path':'',
...: 'message': 'Create new file via GitHub API',
...: 'content': base64_content_str}
...:
И передать его как строку в параметр data:
In [33]: f_resp = requests.put('https://api.github.com/repos/natenka/My_Scripts/contents/try_gh_api.md',
...: auth=(username, password),
...: headers={ "Content-Type": "application/json" },
...: data=json.dumps(f))
...:
Ответ в формате JSON:
In [35]: f_resp.json()
Out[35]:
{'commit': {'author': {'date': '2017-10-14T15:19:35Z',
'email': 'nataliya.samoylenko@gmail.com',
'name': 'Наташа Самойленко'},
'committer': {'date': '2017-10-14T15:19:35Z',
'email': 'nataliya.samoylenko@gmail.com',
'name': 'Наташа Самойленко'},
'html_url': 'https://github.com/natenka/My_Scripts/commit/5d70c0320e344b431e09ef1a64e8e9c043000bb1',
'message': 'Create new file via GitHub API',
'parents': [{'html_url': 'https://github.com/natenka/My_Scripts/commit/9896e5cc60881045046bc34e4abd656b97ad2266',
'sha': '9896e5cc60881045046bc34e4abd656b97ad2266',
'url': 'https://api.github.com/repos/natenka/My_Scripts/git/commits/9896e5cc60881045046bc34e4abd656b97ad2266'}],
'sha': '5d70c0320e344b431e09ef1a64e8e9c043000bb1',
'tree': {'sha': '3dde275cf96dd1ca59f171a282df7e4fe871158f',
'url': 'https://api.github.com/repos/natenka/My_Scripts/git/trees/3dde275cf96dd1ca59f171a282df7e4fe871158f'},
'url': 'https://api.github.com/repos/natenka/My_Scripts/git/commits/5d70c0320e344b431e09ef1a64e8e9c043000bb1',
'verification': {'payload': None,
'reason': 'unsigned',
'signature': None,
'verified': False}},
'content': {'_links': {'git': 'https://api.github.com/repos/natenka/My_Scripts/git/blobs/16c126f1181e013c8f72846f7b92dcff7a207ed9',
'html': 'https://github.com/natenka/My_Scripts/blob/master/try_gh_api.md',
'self': 'https://api.github.com/repos/natenka/My_Scripts/contents/try_gh_api.md?ref=master'},
'download_url': 'https://raw.githubusercontent.com/natenka/My_Scripts/master/try_gh_api.md',
'git_url': 'https://api.github.com/repos/natenka/My_Scripts/git/blobs/16c126f1181e013c8f72846f7b92dcff7a207ed9',
'html_url': 'https://github.com/natenka/My_Scripts/blob/master/try_gh_api.md',
'name': 'try_gh_api.md',
'path': 'try_gh_api.md',
'sha': '16c126f1181e013c8f72846f7b92dcff7a207ed9',
'size': 27,
'type': 'file',
'url': 'https://api.github.com/repos/natenka/My_Scripts/contents/try_gh_api.md?ref=master'}}
Leave a Comment