` : create a PR for this README\n "}
+
+https
+GET
+api.github.com
+None
+/repos/lmazuel/TestingRepo
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:19:26 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4837'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"725d5cec4f2c42be4592ff68c6cde59c"'), ('Last-Modified', 'Thu, 21 Apr 2016 17:29:04 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', 'repo'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.059502'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '15A5:97BA:C85441:103DFF5:5AFDF1DE')]
+{"id":56793153,"name":"TestingRepo","full_name":"lmazuel/TestingRepo","owner":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/lmazuel/TestingRepo","description":"To test to Python Github SDK. Nothing interesting here.","fork":false,"url":"https://api.github.com/repos/lmazuel/TestingRepo","forks_url":"https://api.github.com/repos/lmazuel/TestingRepo/forks","keys_url":"https://api.github.com/repos/lmazuel/TestingRepo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lmazuel/TestingRepo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lmazuel/TestingRepo/teams","hooks_url":"https://api.github.com/repos/lmazuel/TestingRepo/hooks","issue_events_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/events{/number}","events_url":"https://api.github.com/repos/lmazuel/TestingRepo/events","assignees_url":"https://api.github.com/repos/lmazuel/TestingRepo/assignees{/user}","branches_url":"https://api.github.com/repos/lmazuel/TestingRepo/branches{/branch}","tags_url":"https://api.github.com/repos/lmazuel/TestingRepo/tags","blobs_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/refs{/sha}","trees_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lmazuel/TestingRepo/statuses/{sha}","languages_url":"https://api.github.com/repos/lmazuel/TestingRepo/languages","stargazers_url":"https://api.github.com/repos/lmazuel/TestingRepo/stargazers","contributors_url":"https://api.github.com/repos/lmazuel/TestingRepo/contributors","subscribers_url":"https://api.github.com/repos/lmazuel/TestingRepo/subscribers","subscription_url":"https://api.github.com/repos/lmazuel/TestingRepo/subscription","commits_url":"https://api.github.com/repos/lmazuel/TestingRepo/commits{/sha}","git_commits_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/commits{/sha}","comments_url":"https://api.github.com/repos/lmazuel/TestingRepo/comments{/number}","issue_comment_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments{/number}","contents_url":"https://api.github.com/repos/lmazuel/TestingRepo/contents/{+path}","compare_url":"https://api.github.com/repos/lmazuel/TestingRepo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lmazuel/TestingRepo/merges","archive_url":"https://api.github.com/repos/lmazuel/TestingRepo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lmazuel/TestingRepo/downloads","issues_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues{/number}","pulls_url":"https://api.github.com/repos/lmazuel/TestingRepo/pulls{/number}","milestones_url":"https://api.github.com/repos/lmazuel/TestingRepo/milestones{/number}","notifications_url":"https://api.github.com/repos/lmazuel/TestingRepo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lmazuel/TestingRepo/labels{/name}","releases_url":"https://api.github.com/repos/lmazuel/TestingRepo/releases{/id}","deployments_url":"https://api.github.com/repos/lmazuel/TestingRepo/deployments","created_at":"2016-04-21T17:29:04Z","updated_at":"2016-04-21T17:29:04Z","pushed_at":"2018-02-14T21:55:42Z","git_url":"git://github.com/lmazuel/TestingRepo.git","ssh_url":"git@github.com:lmazuel/TestingRepo.git","clone_url":"https://github.com/lmazuel/TestingRepo.git","svn_url":"https://github.com/lmazuel/TestingRepo","homepage":null,"size":43,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":10,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":1,"open_issues":10,"watchers":0,"default_branch":"master","permissions":{"admin":true,"push":true,"pull":true},"allow_squash_merge":true,"allow_merge_commit":true,"allow_rebase_merge":true,"network_count":1,"subscribers_count":1}
+
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_clone_path.txt b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_clone_path.txt
new file mode 100644
index 000000000000..a207132972d7
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_clone_path.txt
@@ -0,0 +1,99 @@
+https
+GET
+api.github.com
+None
+/user
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Fri, 06 Jul 2018 21:50:18 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4991'), ('X-RateLimit-Reset', '1530917381'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"10b653fde1e6d20073ad0d69f59b2c3f"'), ('Last-Modified', 'Fri, 08 Jun 2018 04:11:06 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.048085'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'DFBC:85AB:4441C25:57B4B8B:5B3FE41A')]
+{"login":"lmazuel","id":1050156,"node_id":"MDQ6VXNlcjEwNTAxNTY=","avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false,"name":"Laurent Mazuel","company":"Microsoft.","blog":"","location":"Redmond, WA, USA","email":"lmazuel@microsoft.com","hireable":null,"bio":"Azure SDK for Python","public_repos":47,"public_gists":14,"followers":40,"following":11,"created_at":"2011-09-14T12:44:37Z","updated_at":"2018-06-08T04:11:06Z","private_gists":2,"total_private_repos":4,"owned_private_repos":0,"disk_usage":41453,"collaborators":0,"two_factor_authentication":true,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
+
+https
+GET
+api.github.com
+None
+/user
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Fri, 06 Jul 2018 21:50:20 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4990'), ('X-RateLimit-Reset', '1530917381'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"10b653fde1e6d20073ad0d69f59b2c3f"'), ('Last-Modified', 'Fri, 08 Jun 2018 04:11:06 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.093382'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'DFBE:85A8:208C8EA:29398CF:5B3FE41C')]
+{"login":"lmazuel","id":1050156,"node_id":"MDQ6VXNlcjEwNTAxNTY=","avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false,"name":"Laurent Mazuel","company":"Microsoft.","blog":"","location":"Redmond, WA, USA","email":"lmazuel@microsoft.com","hireable":null,"bio":"Azure SDK for Python","public_repos":47,"public_gists":14,"followers":40,"following":11,"created_at":"2011-09-14T12:44:37Z","updated_at":"2018-06-08T04:11:06Z","private_gists":2,"total_private_repos":4,"owned_private_repos":0,"disk_usage":41453,"collaborators":0,"two_factor_authentication":true,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
+
+https
+GET
+api.github.com
+None
+/user
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Fri, 06 Jul 2018 21:50:22 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4989'), ('X-RateLimit-Reset', '1530917381'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"10b653fde1e6d20073ad0d69f59b2c3f"'), ('Last-Modified', 'Fri, 08 Jun 2018 04:11:06 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.042008'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'DFC1:85A8:208C923:2939909:5B3FE41E')]
+{"login":"lmazuel","id":1050156,"node_id":"MDQ6VXNlcjEwNTAxNTY=","avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false,"name":"Laurent Mazuel","company":"Microsoft.","blog":"","location":"Redmond, WA, USA","email":"lmazuel@microsoft.com","hireable":null,"bio":"Azure SDK for Python","public_repos":47,"public_gists":14,"followers":40,"following":11,"created_at":"2011-09-14T12:44:37Z","updated_at":"2018-06-08T04:11:06Z","private_gists":2,"total_private_repos":4,"owned_private_repos":0,"disk_usage":41453,"collaborators":0,"two_factor_authentication":true,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
+
+https
+GET
+api.github.com
+None
+/user
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Fri, 06 Jul 2018 21:50:24 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4988'), ('X-RateLimit-Reset', '1530917381'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"10b653fde1e6d20073ad0d69f59b2c3f"'), ('Last-Modified', 'Fri, 08 Jun 2018 04:11:06 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.058983'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'DFC3:85A8:208C95A:2939952:5B3FE41F')]
+{"login":"lmazuel","id":1050156,"node_id":"MDQ6VXNlcjEwNTAxNTY=","avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false,"name":"Laurent Mazuel","company":"Microsoft.","blog":"","location":"Redmond, WA, USA","email":"lmazuel@microsoft.com","hireable":null,"bio":"Azure SDK for Python","public_repos":47,"public_gists":14,"followers":40,"following":11,"created_at":"2011-09-14T12:44:37Z","updated_at":"2018-06-08T04:11:06Z","private_gists":2,"total_private_repos":4,"owned_private_repos":0,"disk_usage":41453,"collaborators":0,"two_factor_authentication":true,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
+
+https
+GET
+api.github.com
+None
+/user
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Fri, 06 Jul 2018 21:50:25 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4987'), ('X-RateLimit-Reset', '1530917381'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"10b653fde1e6d20073ad0d69f59b2c3f"'), ('Last-Modified', 'Fri, 08 Jun 2018 04:11:06 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.054447'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'DFC7:85AA:3E20F9D:4F32AB0:5B3FE421')]
+{"login":"lmazuel","id":1050156,"node_id":"MDQ6VXNlcjEwNTAxNTY=","avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false,"name":"Laurent Mazuel","company":"Microsoft.","blog":"","location":"Redmond, WA, USA","email":"lmazuel@microsoft.com","hireable":null,"bio":"Azure SDK for Python","public_repos":47,"public_gists":14,"followers":40,"following":11,"created_at":"2011-09-14T12:44:37Z","updated_at":"2018-06-08T04:11:06Z","private_gists":2,"total_private_repos":4,"owned_private_repos":0,"disk_usage":41453,"collaborators":0,"two_factor_authentication":true,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
+
+https
+GET
+api.github.com
+None
+/user
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Fri, 06 Jul 2018 21:50:29 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4986'), ('X-RateLimit-Reset', '1530917381'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"10b653fde1e6d20073ad0d69f59b2c3f"'), ('Last-Modified', 'Fri, 08 Jun 2018 04:11:06 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.053094'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'DFCC:85AB:44420F3:57B51B8:5B3FE424')]
+{"login":"lmazuel","id":1050156,"node_id":"MDQ6VXNlcjEwNTAxNTY=","avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false,"name":"Laurent Mazuel","company":"Microsoft.","blog":"","location":"Redmond, WA, USA","email":"lmazuel@microsoft.com","hireable":null,"bio":"Azure SDK for Python","public_repos":47,"public_gists":14,"followers":40,"following":11,"created_at":"2011-09-14T12:44:37Z","updated_at":"2018-06-08T04:11:06Z","private_gists":2,"total_private_repos":4,"owned_private_repos":0,"disk_usage":41453,"collaborators":0,"two_factor_authentication":true,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
+
+https
+GET
+api.github.com
+None
+/repos/lmazuel/TestingRepo/pulls/2
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Fri, 06 Jul 2018 21:50:33 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4985'), ('X-RateLimit-Reset', '1530917381'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"8a6ef82b7dcdf6548b23e3a686b38341"'), ('Last-Modified', 'Thu, 05 Jul 2018 16:03:04 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.114799'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'DFD1:85AB:44422E1:57B544C:5B3FE429')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/2","id":70768598,"node_id":"MDExOlB1bGxSZXF1ZXN0NzA3Njg1OTg=","html_url":"https://github.com/lmazuel/TestingRepo/pull/2","diff_url":"https://github.com/lmazuel/TestingRepo/pull/2.diff","patch_url":"https://github.com/lmazuel/TestingRepo/pull/2.patch","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/2","number":2,"state":"open","locked":false,"title":"Update README.md","user":{"login":"AutorestCI","id":18218145,"node_id":"MDQ6VXNlcjE4MjE4MTQ1","avatar_url":"https://avatars3.githubusercontent.com/u/18218145?v=4","gravatar_id":"","url":"https://api.github.com/users/AutorestCI","html_url":"https://github.com/AutorestCI","followers_url":"https://api.github.com/users/AutorestCI/followers","following_url":"https://api.github.com/users/AutorestCI/following{/other_user}","gists_url":"https://api.github.com/users/AutorestCI/gists{/gist_id}","starred_url":"https://api.github.com/users/AutorestCI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AutorestCI/subscriptions","organizations_url":"https://api.github.com/users/AutorestCI/orgs","repos_url":"https://api.github.com/users/AutorestCI/repos","events_url":"https://api.github.com/users/AutorestCI/events{/privacy}","received_events_url":"https://api.github.com/users/AutorestCI/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-05-19T21:29:49Z","updated_at":"2018-07-05T16:03:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1d020a4d8788aa40753ca326f0818a8cd805ac93","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/2/commits","review_comments_url":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/2/comments","review_comment_url":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/comments{/number}","comments_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/2/comments","statuses_url":"https://api.github.com/repos/lmazuel/TestingRepo/statuses/40d2028637a6b5f8f6ae6e595e772d6fc33b93bb","head":{"label":"AutorestCI:AutorestCI-patch-1","ref":"AutorestCI-patch-1","sha":"40d2028637a6b5f8f6ae6e595e772d6fc33b93bb","user":{"login":"AutorestCI","id":18218145,"node_id":"MDQ6VXNlcjE4MjE4MTQ1","avatar_url":"https://avatars3.githubusercontent.com/u/18218145?v=4","gravatar_id":"","url":"https://api.github.com/users/AutorestCI","html_url":"https://github.com/AutorestCI","followers_url":"https://api.github.com/users/AutorestCI/followers","following_url":"https://api.github.com/users/AutorestCI/following{/other_user}","gists_url":"https://api.github.com/users/AutorestCI/gists{/gist_id}","starred_url":"https://api.github.com/users/AutorestCI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AutorestCI/subscriptions","organizations_url":"https://api.github.com/users/AutorestCI/orgs","repos_url":"https://api.github.com/users/AutorestCI/repos","events_url":"https://api.github.com/users/AutorestCI/events{/privacy}","received_events_url":"https://api.github.com/users/AutorestCI/received_events","type":"User","site_admin":false},"repo":{"id":59243826,"node_id":"MDEwOlJlcG9zaXRvcnk1OTI0MzgyNg==","name":"TestingRepo","full_name":"AutorestCI/TestingRepo","owner":{"login":"AutorestCI","id":18218145,"node_id":"MDQ6VXNlcjE4MjE4MTQ1","avatar_url":"https://avatars3.githubusercontent.com/u/18218145?v=4","gravatar_id":"","url":"https://api.github.com/users/AutorestCI","html_url":"https://github.com/AutorestCI","followers_url":"https://api.github.com/users/AutorestCI/followers","following_url":"https://api.github.com/users/AutorestCI/following{/other_user}","gists_url":"https://api.github.com/users/AutorestCI/gists{/gist_id}","starred_url":"https://api.github.com/users/AutorestCI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AutorestCI/subscriptions","organizations_url":"https://api.github.com/users/AutorestCI/orgs","repos_url":"https://api.github.com/users/AutorestCI/repos","events_url":"https://api.github.com/users/AutorestCI/events{/privacy}","received_events_url":"https://api.github.com/users/AutorestCI/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/AutorestCI/TestingRepo","description":"To test to Python Github SDK. Nothing interesting here.","fork":true,"url":"https://api.github.com/repos/AutorestCI/TestingRepo","forks_url":"https://api.github.com/repos/AutorestCI/TestingRepo/forks","keys_url":"https://api.github.com/repos/AutorestCI/TestingRepo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/AutorestCI/TestingRepo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/AutorestCI/TestingRepo/teams","hooks_url":"https://api.github.com/repos/AutorestCI/TestingRepo/hooks","issue_events_url":"https://api.github.com/repos/AutorestCI/TestingRepo/issues/events{/number}","events_url":"https://api.github.com/repos/AutorestCI/TestingRepo/events","assignees_url":"https://api.github.com/repos/AutorestCI/TestingRepo/assignees{/user}","branches_url":"https://api.github.com/repos/AutorestCI/TestingRepo/branches{/branch}","tags_url":"https://api.github.com/repos/AutorestCI/TestingRepo/tags","blobs_url":"https://api.github.com/repos/AutorestCI/TestingRepo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/AutorestCI/TestingRepo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/AutorestCI/TestingRepo/git/refs{/sha}","trees_url":"https://api.github.com/repos/AutorestCI/TestingRepo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/AutorestCI/TestingRepo/statuses/{sha}","languages_url":"https://api.github.com/repos/AutorestCI/TestingRepo/languages","stargazers_url":"https://api.github.com/repos/AutorestCI/TestingRepo/stargazers","contributors_url":"https://api.github.com/repos/AutorestCI/TestingRepo/contributors","subscribers_url":"https://api.github.com/repos/AutorestCI/TestingRepo/subscribers","subscription_url":"https://api.github.com/repos/AutorestCI/TestingRepo/subscription","commits_url":"https://api.github.com/repos/AutorestCI/TestingRepo/commits{/sha}","git_commits_url":"https://api.github.com/repos/AutorestCI/TestingRepo/git/commits{/sha}","comments_url":"https://api.github.com/repos/AutorestCI/TestingRepo/comments{/number}","issue_comment_url":"https://api.github.com/repos/AutorestCI/TestingRepo/issues/comments{/number}","contents_url":"https://api.github.com/repos/AutorestCI/TestingRepo/contents/{+path}","compare_url":"https://api.github.com/repos/AutorestCI/TestingRepo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/AutorestCI/TestingRepo/merges","archive_url":"https://api.github.com/repos/AutorestCI/TestingRepo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/AutorestCI/TestingRepo/downloads","issues_url":"https://api.github.com/repos/AutorestCI/TestingRepo/issues{/number}","pulls_url":"https://api.github.com/repos/AutorestCI/TestingRepo/pulls{/number}","milestones_url":"https://api.github.com/repos/AutorestCI/TestingRepo/milestones{/number}","notifications_url":"https://api.github.com/repos/AutorestCI/TestingRepo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/AutorestCI/TestingRepo/labels{/name}","releases_url":"https://api.github.com/repos/AutorestCI/TestingRepo/releases{/id}","deployments_url":"https://api.github.com/repos/AutorestCI/TestingRepo/deployments","created_at":"2016-05-19T21:26:35Z","updated_at":"2016-04-21T17:29:04Z","pushed_at":"2016-05-19T21:28:13Z","git_url":"git://github.com/AutorestCI/TestingRepo.git","ssh_url":"git@github.com:AutorestCI/TestingRepo.git","clone_url":"https://github.com/AutorestCI/TestingRepo.git","svn_url":"https://github.com/AutorestCI/TestingRepo","homepage":null,"size":1,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"lmazuel:master","ref":"master","sha":"dd82f65f1b6314b18609b8572464b6d328ea70d4","user":{"login":"lmazuel","id":1050156,"node_id":"MDQ6VXNlcjEwNTAxNTY=","avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"repo":{"id":56793153,"node_id":"MDEwOlJlcG9zaXRvcnk1Njc5MzE1Mw==","name":"TestingRepo","full_name":"lmazuel/TestingRepo","owner":{"login":"lmazuel","id":1050156,"node_id":"MDQ6VXNlcjEwNTAxNTY=","avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/lmazuel/TestingRepo","description":"To test to Python Github SDK. Nothing interesting here.","fork":false,"url":"https://api.github.com/repos/lmazuel/TestingRepo","forks_url":"https://api.github.com/repos/lmazuel/TestingRepo/forks","keys_url":"https://api.github.com/repos/lmazuel/TestingRepo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lmazuel/TestingRepo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lmazuel/TestingRepo/teams","hooks_url":"https://api.github.com/repos/lmazuel/TestingRepo/hooks","issue_events_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/events{/number}","events_url":"https://api.github.com/repos/lmazuel/TestingRepo/events","assignees_url":"https://api.github.com/repos/lmazuel/TestingRepo/assignees{/user}","branches_url":"https://api.github.com/repos/lmazuel/TestingRepo/branches{/branch}","tags_url":"https://api.github.com/repos/lmazuel/TestingRepo/tags","blobs_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/refs{/sha}","trees_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lmazuel/TestingRepo/statuses/{sha}","languages_url":"https://api.github.com/repos/lmazuel/TestingRepo/languages","stargazers_url":"https://api.github.com/repos/lmazuel/TestingRepo/stargazers","contributors_url":"https://api.github.com/repos/lmazuel/TestingRepo/contributors","subscribers_url":"https://api.github.com/repos/lmazuel/TestingRepo/subscribers","subscription_url":"https://api.github.com/repos/lmazuel/TestingRepo/subscription","commits_url":"https://api.github.com/repos/lmazuel/TestingRepo/commits{/sha}","git_commits_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/commits{/sha}","comments_url":"https://api.github.com/repos/lmazuel/TestingRepo/comments{/number}","issue_comment_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments{/number}","contents_url":"https://api.github.com/repos/lmazuel/TestingRepo/contents/{+path}","compare_url":"https://api.github.com/repos/lmazuel/TestingRepo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lmazuel/TestingRepo/merges","archive_url":"https://api.github.com/repos/lmazuel/TestingRepo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lmazuel/TestingRepo/downloads","issues_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues{/number}","pulls_url":"https://api.github.com/repos/lmazuel/TestingRepo/pulls{/number}","milestones_url":"https://api.github.com/repos/lmazuel/TestingRepo/milestones{/number}","notifications_url":"https://api.github.com/repos/lmazuel/TestingRepo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lmazuel/TestingRepo/labels{/name}","releases_url":"https://api.github.com/repos/lmazuel/TestingRepo/releases{/id}","deployments_url":"https://api.github.com/repos/lmazuel/TestingRepo/deployments","created_at":"2016-04-21T17:29:04Z","updated_at":"2016-04-21T17:29:04Z","pushed_at":"2018-02-14T21:55:42Z","git_url":"git://github.com/lmazuel/TestingRepo.git","ssh_url":"git@github.com:lmazuel/TestingRepo.git","clone_url":"https://github.com/lmazuel/TestingRepo.git","svn_url":"https://github.com/lmazuel/TestingRepo","homepage":null,"size":43,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":10,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":1,"open_issues":10,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/2"},"html":{"href":"https://github.com/lmazuel/TestingRepo/pull/2"},"issue":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/issues/2"},"comments":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/issues/2/comments"},"review_comments":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/2/comments"},"review_comment":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/2/commits"},"statuses":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/statuses/40d2028637a6b5f8f6ae6e595e772d6fc33b93bb"}},"author_association":"COLLABORATOR","merged":false,"mergeable":true,"rebaseable":false,"mergeable_state":"clean","merged_by":null,"comments":3,"review_comments":0,"maintainer_can_modify":false,"commits":1,"additions":2,"deletions":0,"changed_files":1}
+
+https
+GET
+api.github.com
+None
+/user
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Fri, 06 Jul 2018 21:50:33 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4984'), ('X-RateLimit-Reset', '1530917381'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"10b653fde1e6d20073ad0d69f59b2c3f"'), ('Last-Modified', 'Fri, 08 Jun 2018 04:11:06 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.039463'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'DFD3:85A8:208CA76:2939AE7:5B3FE429')]
+{"login":"lmazuel","id":1050156,"node_id":"MDQ6VXNlcjEwNTAxNTY=","avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false,"name":"Laurent Mazuel","company":"Microsoft.","blog":"","location":"Redmond, WA, USA","email":"lmazuel@microsoft.com","hireable":null,"bio":"Azure SDK for Python","public_repos":47,"public_gists":14,"followers":40,"following":11,"created_at":"2011-09-14T12:44:37Z","updated_at":"2018-06-08T04:11:06Z","private_gists":2,"total_private_repos":4,"owned_private_repos":0,"disk_usage":41453,"collaborators":0,"two_factor_authentication":true,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
+
+https
+GET
+api.github.com
+None
+/user
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Fri, 06 Jul 2018 21:50:36 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4983'), ('X-RateLimit-Reset', '1530917381'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"10b653fde1e6d20073ad0d69f59b2c3f"'), ('Last-Modified', 'Fri, 08 Jun 2018 04:11:06 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.042491'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'DFDB:85A5:50C84B:6722D2:5B3FE42C')]
+{"login":"lmazuel","id":1050156,"node_id":"MDQ6VXNlcjEwNTAxNTY=","avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false,"name":"Laurent Mazuel","company":"Microsoft.","blog":"","location":"Redmond, WA, USA","email":"lmazuel@microsoft.com","hireable":null,"bio":"Azure SDK for Python","public_repos":47,"public_gists":14,"followers":40,"following":11,"created_at":"2011-09-14T12:44:37Z","updated_at":"2018-06-08T04:11:06Z","private_gists":2,"total_private_repos":4,"owned_private_repos":0,"disk_usage":41453,"collaborators":0,"two_factor_authentication":true,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
+
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_configure.txt b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_configure.txt
new file mode 100644
index 000000000000..c59238163ea6
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_configure.txt
@@ -0,0 +1,11 @@
+https
+GET
+api.github.com
+None
+/user
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:30 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4801'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"77a0c498bc6360506f9e7a4dd33857df"'), ('Last-Modified', 'Tue, 08 May 2018 04:10:43 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.050830'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '16F8:97BA:C9220B:104EE7D:5AFDF3C2')]
+{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false,"name":"Laurent Mazuel","company":"Microsoft.","blog":"","location":"Redmond, WA, USA","email":"lmazuel@microsoft.com","hireable":null,"bio":"Azure SDK for Python","public_repos":46,"public_gists":14,"followers":30,"following":11,"created_at":"2011-09-14T12:44:37Z","updated_at":"2018-05-08T04:10:43Z","private_gists":1,"total_private_repos":4,"owned_private_repos":0,"disk_usage":41216,"collaborators":0,"two_factor_authentication":true,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
+
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_create_comment.txt b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_create_comment.txt
new file mode 100644
index 000000000000..d43df7590331
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_create_comment.txt
@@ -0,0 +1,66 @@
+https
+GET
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/14
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:31 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4800'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"8bb2ec36d3e6380bc0eabd5bd44e96eb"'), ('Last-Modified', 'Thu, 17 May 2018 21:15:04 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', 'repo'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.064500'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '16F9:97BA:C92251:104EED1:5AFDF3C3')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/14","repository_url":"https://api.github.com/repos/lmazuel/TestingRepo","labels_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/14/labels{/name}","comments_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/14/comments","events_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/14/events","html_url":"https://github.com/lmazuel/TestingRepo/issues/14","id":291717104,"number":14,"title":"Testing comment","user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-01-25T21:12:00Z","updated_at":"2018-05-17T21:15:04Z","closed_at":null,"author_association":"OWNER","body":"","closed_by":null}
+
+https
+POST
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/14/comments
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
+{"body": "This is a test"}
+201
+[('Date', 'Thu, 17 May 2018 21:27:31 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '1251'), ('Server', 'GitHub.com'), ('Status', '201 Created'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4799'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', '"d2dfbb8c026a93b366703c2905dd6477"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('Location', 'https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017673'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.445487'), ('X-GitHub-Request-Id', '16FA:97B8:C2461E:FB54DF:5AFDF3C3')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017673","html_url":"https://github.com/lmazuel/TestingRepo/issues/14#issuecomment-390017673","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/14","id":390017673,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-05-17T21:27:31Z","updated_at":"2018-05-17T21:27:31Z","author_association":"OWNER","body":"This is a test"}
+
+https
+DELETE
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/comments/390017673
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+204
+[('Date', 'Thu, 17 May 2018 21:27:32 GMT'), ('Content-Type', 'application/octet-stream'), ('Server', 'GitHub.com'), ('Status', '204 No Content'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4798'), ('X-RateLimit-Reset', '1526593184'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.141787'), ('Vary', 'Accept-Encoding'), ('X-GitHub-Request-Id', '16FB:97BA:C9227D:104EF10:5AFDF3C3')]
+
+
+https
+GET
+api.github.com
+None
+/repos/lmazuel/TestingRepo/pulls/2
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:32 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4797'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"e0597269209bdeaf65893e74635ff339"'), ('Last-Modified', 'Thu, 17 May 2018 21:15:05 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.132533'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '16FC:97B8:C24657:FB552C:5AFDF3C4')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/2","id":70768598,"html_url":"https://github.com/lmazuel/TestingRepo/pull/2","diff_url":"https://github.com/lmazuel/TestingRepo/pull/2.diff","patch_url":"https://github.com/lmazuel/TestingRepo/pull/2.patch","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/2","number":2,"state":"open","locked":false,"title":"Update README.md","user":{"login":"AutorestCI","id":18218145,"avatar_url":"https://avatars3.githubusercontent.com/u/18218145?v=4","gravatar_id":"","url":"https://api.github.com/users/AutorestCI","html_url":"https://github.com/AutorestCI","followers_url":"https://api.github.com/users/AutorestCI/followers","following_url":"https://api.github.com/users/AutorestCI/following{/other_user}","gists_url":"https://api.github.com/users/AutorestCI/gists{/gist_id}","starred_url":"https://api.github.com/users/AutorestCI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AutorestCI/subscriptions","organizations_url":"https://api.github.com/users/AutorestCI/orgs","repos_url":"https://api.github.com/users/AutorestCI/repos","events_url":"https://api.github.com/users/AutorestCI/events{/privacy}","received_events_url":"https://api.github.com/users/AutorestCI/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-05-19T21:29:49Z","updated_at":"2018-05-17T21:15:05Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1d020a4d8788aa40753ca326f0818a8cd805ac93","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/2/commits","review_comments_url":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/2/comments","review_comment_url":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/comments{/number}","comments_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/2/comments","statuses_url":"https://api.github.com/repos/lmazuel/TestingRepo/statuses/40d2028637a6b5f8f6ae6e595e772d6fc33b93bb","head":{"label":"AutorestCI:AutorestCI-patch-1","ref":"AutorestCI-patch-1","sha":"40d2028637a6b5f8f6ae6e595e772d6fc33b93bb","user":{"login":"AutorestCI","id":18218145,"avatar_url":"https://avatars3.githubusercontent.com/u/18218145?v=4","gravatar_id":"","url":"https://api.github.com/users/AutorestCI","html_url":"https://github.com/AutorestCI","followers_url":"https://api.github.com/users/AutorestCI/followers","following_url":"https://api.github.com/users/AutorestCI/following{/other_user}","gists_url":"https://api.github.com/users/AutorestCI/gists{/gist_id}","starred_url":"https://api.github.com/users/AutorestCI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AutorestCI/subscriptions","organizations_url":"https://api.github.com/users/AutorestCI/orgs","repos_url":"https://api.github.com/users/AutorestCI/repos","events_url":"https://api.github.com/users/AutorestCI/events{/privacy}","received_events_url":"https://api.github.com/users/AutorestCI/received_events","type":"User","site_admin":false},"repo":{"id":59243826,"name":"TestingRepo","full_name":"AutorestCI/TestingRepo","owner":{"login":"AutorestCI","id":18218145,"avatar_url":"https://avatars3.githubusercontent.com/u/18218145?v=4","gravatar_id":"","url":"https://api.github.com/users/AutorestCI","html_url":"https://github.com/AutorestCI","followers_url":"https://api.github.com/users/AutorestCI/followers","following_url":"https://api.github.com/users/AutorestCI/following{/other_user}","gists_url":"https://api.github.com/users/AutorestCI/gists{/gist_id}","starred_url":"https://api.github.com/users/AutorestCI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AutorestCI/subscriptions","organizations_url":"https://api.github.com/users/AutorestCI/orgs","repos_url":"https://api.github.com/users/AutorestCI/repos","events_url":"https://api.github.com/users/AutorestCI/events{/privacy}","received_events_url":"https://api.github.com/users/AutorestCI/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/AutorestCI/TestingRepo","description":"To test to Python Github SDK. Nothing interesting here.","fork":true,"url":"https://api.github.com/repos/AutorestCI/TestingRepo","forks_url":"https://api.github.com/repos/AutorestCI/TestingRepo/forks","keys_url":"https://api.github.com/repos/AutorestCI/TestingRepo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/AutorestCI/TestingRepo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/AutorestCI/TestingRepo/teams","hooks_url":"https://api.github.com/repos/AutorestCI/TestingRepo/hooks","issue_events_url":"https://api.github.com/repos/AutorestCI/TestingRepo/issues/events{/number}","events_url":"https://api.github.com/repos/AutorestCI/TestingRepo/events","assignees_url":"https://api.github.com/repos/AutorestCI/TestingRepo/assignees{/user}","branches_url":"https://api.github.com/repos/AutorestCI/TestingRepo/branches{/branch}","tags_url":"https://api.github.com/repos/AutorestCI/TestingRepo/tags","blobs_url":"https://api.github.com/repos/AutorestCI/TestingRepo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/AutorestCI/TestingRepo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/AutorestCI/TestingRepo/git/refs{/sha}","trees_url":"https://api.github.com/repos/AutorestCI/TestingRepo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/AutorestCI/TestingRepo/statuses/{sha}","languages_url":"https://api.github.com/repos/AutorestCI/TestingRepo/languages","stargazers_url":"https://api.github.com/repos/AutorestCI/TestingRepo/stargazers","contributors_url":"https://api.github.com/repos/AutorestCI/TestingRepo/contributors","subscribers_url":"https://api.github.com/repos/AutorestCI/TestingRepo/subscribers","subscription_url":"https://api.github.com/repos/AutorestCI/TestingRepo/subscription","commits_url":"https://api.github.com/repos/AutorestCI/TestingRepo/commits{/sha}","git_commits_url":"https://api.github.com/repos/AutorestCI/TestingRepo/git/commits{/sha}","comments_url":"https://api.github.com/repos/AutorestCI/TestingRepo/comments{/number}","issue_comment_url":"https://api.github.com/repos/AutorestCI/TestingRepo/issues/comments{/number}","contents_url":"https://api.github.com/repos/AutorestCI/TestingRepo/contents/{+path}","compare_url":"https://api.github.com/repos/AutorestCI/TestingRepo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/AutorestCI/TestingRepo/merges","archive_url":"https://api.github.com/repos/AutorestCI/TestingRepo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/AutorestCI/TestingRepo/downloads","issues_url":"https://api.github.com/repos/AutorestCI/TestingRepo/issues{/number}","pulls_url":"https://api.github.com/repos/AutorestCI/TestingRepo/pulls{/number}","milestones_url":"https://api.github.com/repos/AutorestCI/TestingRepo/milestones{/number}","notifications_url":"https://api.github.com/repos/AutorestCI/TestingRepo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/AutorestCI/TestingRepo/labels{/name}","releases_url":"https://api.github.com/repos/AutorestCI/TestingRepo/releases{/id}","deployments_url":"https://api.github.com/repos/AutorestCI/TestingRepo/deployments","created_at":"2016-05-19T21:26:35Z","updated_at":"2016-04-21T17:29:04Z","pushed_at":"2016-05-19T21:28:13Z","git_url":"git://github.com/AutorestCI/TestingRepo.git","ssh_url":"git@github.com:AutorestCI/TestingRepo.git","clone_url":"https://github.com/AutorestCI/TestingRepo.git","svn_url":"https://github.com/AutorestCI/TestingRepo","homepage":null,"size":1,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"lmazuel:master","ref":"master","sha":"dd82f65f1b6314b18609b8572464b6d328ea70d4","user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"repo":{"id":56793153,"name":"TestingRepo","full_name":"lmazuel/TestingRepo","owner":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/lmazuel/TestingRepo","description":"To test to Python Github SDK. Nothing interesting here.","fork":false,"url":"https://api.github.com/repos/lmazuel/TestingRepo","forks_url":"https://api.github.com/repos/lmazuel/TestingRepo/forks","keys_url":"https://api.github.com/repos/lmazuel/TestingRepo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lmazuel/TestingRepo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lmazuel/TestingRepo/teams","hooks_url":"https://api.github.com/repos/lmazuel/TestingRepo/hooks","issue_events_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/events{/number}","events_url":"https://api.github.com/repos/lmazuel/TestingRepo/events","assignees_url":"https://api.github.com/repos/lmazuel/TestingRepo/assignees{/user}","branches_url":"https://api.github.com/repos/lmazuel/TestingRepo/branches{/branch}","tags_url":"https://api.github.com/repos/lmazuel/TestingRepo/tags","blobs_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/refs{/sha}","trees_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lmazuel/TestingRepo/statuses/{sha}","languages_url":"https://api.github.com/repos/lmazuel/TestingRepo/languages","stargazers_url":"https://api.github.com/repos/lmazuel/TestingRepo/stargazers","contributors_url":"https://api.github.com/repos/lmazuel/TestingRepo/contributors","subscribers_url":"https://api.github.com/repos/lmazuel/TestingRepo/subscribers","subscription_url":"https://api.github.com/repos/lmazuel/TestingRepo/subscription","commits_url":"https://api.github.com/repos/lmazuel/TestingRepo/commits{/sha}","git_commits_url":"https://api.github.com/repos/lmazuel/TestingRepo/git/commits{/sha}","comments_url":"https://api.github.com/repos/lmazuel/TestingRepo/comments{/number}","issue_comment_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments{/number}","contents_url":"https://api.github.com/repos/lmazuel/TestingRepo/contents/{+path}","compare_url":"https://api.github.com/repos/lmazuel/TestingRepo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lmazuel/TestingRepo/merges","archive_url":"https://api.github.com/repos/lmazuel/TestingRepo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lmazuel/TestingRepo/downloads","issues_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues{/number}","pulls_url":"https://api.github.com/repos/lmazuel/TestingRepo/pulls{/number}","milestones_url":"https://api.github.com/repos/lmazuel/TestingRepo/milestones{/number}","notifications_url":"https://api.github.com/repos/lmazuel/TestingRepo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lmazuel/TestingRepo/labels{/name}","releases_url":"https://api.github.com/repos/lmazuel/TestingRepo/releases{/id}","deployments_url":"https://api.github.com/repos/lmazuel/TestingRepo/deployments","created_at":"2016-04-21T17:29:04Z","updated_at":"2016-04-21T17:29:04Z","pushed_at":"2018-02-14T21:55:42Z","git_url":"git://github.com/lmazuel/TestingRepo.git","ssh_url":"git@github.com:lmazuel/TestingRepo.git","clone_url":"https://github.com/lmazuel/TestingRepo.git","svn_url":"https://github.com/lmazuel/TestingRepo","homepage":null,"size":43,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":10,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":1,"open_issues":10,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/2"},"html":{"href":"https://github.com/lmazuel/TestingRepo/pull/2"},"issue":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/issues/2"},"comments":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/issues/2/comments"},"review_comments":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/2/comments"},"review_comment":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/pulls/2/commits"},"statuses":{"href":"https://api.github.com/repos/lmazuel/TestingRepo/statuses/40d2028637a6b5f8f6ae6e595e772d6fc33b93bb"}},"author_association":"COLLABORATOR","merged":false,"mergeable":true,"rebaseable":false,"mergeable_state":"clean","merged_by":null,"comments":3,"review_comments":0,"maintainer_can_modify":false,"commits":1,"additions":2,"deletions":0,"changed_files":1}
+
+https
+POST
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/2/comments
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
+{"body": "This is a test"}
+201
+[('Date', 'Thu, 17 May 2018 21:27:32 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '1247'), ('Server', 'GitHub.com'), ('Status', '201 Created'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4796'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', '"b3aba802534abbc06eb4cee35eca6eac"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('Location', 'https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017676'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.233537'), ('X-GitHub-Request-Id', '16FD:97B8:C2466C:FB5542:5AFDF3C4')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017676","html_url":"https://github.com/lmazuel/TestingRepo/pull/2#issuecomment-390017676","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/2","id":390017676,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-05-17T21:27:32Z","updated_at":"2018-05-17T21:27:32Z","author_association":"OWNER","body":"This is a test"}
+
+https
+DELETE
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/comments/390017676
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+204
+[('Date', 'Thu, 17 May 2018 21:27:33 GMT'), ('Content-Type', 'application/octet-stream'), ('Server', 'GitHub.com'), ('Status', '204 No Content'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4795'), ('X-RateLimit-Reset', '1526593184'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.189453'), ('Vary', 'Accept-Encoding'), ('X-GitHub-Request-Id', '16FE:97BA:C922C2:104EF68:5AFDF3C4')]
+
+
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_dashboard.txt b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_dashboard.txt
new file mode 100644
index 000000000000..8b62646b0d02
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_dashboard.txt
@@ -0,0 +1,110 @@
+https
+GET
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/15
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:33 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4794'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"f7880303c57eae4c85d647cee834e3f6"'), ('Last-Modified', 'Thu, 17 May 2018 21:15:07 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', 'repo'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.054964'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '16FF:97BA:C922DA:104EF8A:5AFDF3C5')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15","repository_url":"https://api.github.com/repos/lmazuel/TestingRepo","labels_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15/labels{/name}","comments_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15/comments","events_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15/events","html_url":"https://github.com/lmazuel/TestingRepo/issues/15","id":293729231,"number":15,"title":"Dashboard testing","user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-02-02T00:09:29Z","updated_at":"2018-05-17T21:15:07Z","closed_at":null,"author_association":"OWNER","body":"","closed_by":null}
+
+https
+GET
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/15/comments
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:33 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4793'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"394698f297e36caa81023c22d91e8f84"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.106485'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '1700:97BA:C922E8:104EF9A:5AFDF3C5')]
+[{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/362444226","html_url":"https://github.com/lmazuel/TestingRepo/issues/15#issuecomment-362444226","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15","id":362444226,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-02-02T00:10:56Z","updated_at":"2018-02-02T00:59:46Z","author_association":"OWNER","body":"klsfjdlkjflksd\nlskjflkdjf\n"}]
+
+https
+GET
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/15/comments
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:33 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4792'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"394698f297e36caa81023c22d91e8f84"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.066016'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '1701:97B8:C246C0:FB55B0:5AFDF3C5')]
+[{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/362444226","html_url":"https://github.com/lmazuel/TestingRepo/issues/15#issuecomment-362444226","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15","id":362444226,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-02-02T00:10:56Z","updated_at":"2018-02-02T00:59:46Z","author_association":"OWNER","body":"klsfjdlkjflksd\nlskjflkdjf\n"}]
+
+https
+POST
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/15/comments
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
+{"body": "# MYHEADER"}
+201
+[('Date', 'Thu, 17 May 2018 21:27:33 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '1247'), ('Server', 'GitHub.com'), ('Status', '201 Created'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4791'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', '"772f2729f150f5896d0a03475c5dd0c5"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('Location', 'https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017687'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.190633'), ('X-GitHub-Request-Id', '1702:97B8:C246D0:FB55C5:5AFDF3C5')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017687","html_url":"https://github.com/lmazuel/TestingRepo/issues/15#issuecomment-390017687","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15","id":390017687,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-05-17T21:27:33Z","updated_at":"2018-05-17T21:27:33Z","author_association":"OWNER","body":"# MYHEADER"}
+
+https
+PATCH
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/comments/390017687
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
+{"body": "# MYHEADER\nEncountered an unknown error: (Python bot)
\n\n```python\nsomething to do with an exception\n```\n\n
"}
+200
+[('Date', 'Thu, 17 May 2018 21:27:34 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4790'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"bd0982c93a87b03a313876721ccc76a4"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.191203'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '1703:97B8:C246F0:FB55EC:5AFDF3C5')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017687","html_url":"https://github.com/lmazuel/TestingRepo/issues/15#issuecomment-390017687","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15","id":390017687,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-05-17T21:27:33Z","updated_at":"2018-05-17T21:27:34Z","author_association":"OWNER","body":"# MYHEADER\nEncountered an unknown error: (Python bot)
\n\n```python\nsomething to do with an exception\n```\n\n
"}
+
+https
+GET
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/15/comments
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:34 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4789'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"b91f459a1d0337ede82a9105fa62ce19"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.075426'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '1704:97BA:C92330:104F002:5AFDF3C6')]
+[{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/362444226","html_url":"https://github.com/lmazuel/TestingRepo/issues/15#issuecomment-362444226","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15","id":362444226,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-02-02T00:10:56Z","updated_at":"2018-02-02T00:59:46Z","author_association":"OWNER","body":"klsfjdlkjflksd\nlskjflkdjf\n"},{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017687","html_url":"https://github.com/lmazuel/TestingRepo/issues/15#issuecomment-390017687","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15","id":390017687,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-05-17T21:27:33Z","updated_at":"2018-05-17T21:27:34Z","author_association":"OWNER","body":"# MYHEADER\nEncountered an unknown error: (Python bot)
\n\n```python\nsomething to do with an exception\n```\n\n
"}]
+
+https
+GET
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/15/comments
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:34 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4788'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"b91f459a1d0337ede82a9105fa62ce19"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.070095'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '1705:97BA:C92342:104F012:5AFDF3C6')]
+[{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/362444226","html_url":"https://github.com/lmazuel/TestingRepo/issues/15#issuecomment-362444226","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15","id":362444226,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-02-02T00:10:56Z","updated_at":"2018-02-02T00:59:46Z","author_association":"OWNER","body":"klsfjdlkjflksd\nlskjflkdjf\n"},{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017687","html_url":"https://github.com/lmazuel/TestingRepo/issues/15#issuecomment-390017687","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15","id":390017687,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-05-17T21:27:33Z","updated_at":"2018-05-17T21:27:34Z","author_association":"OWNER","body":"# MYHEADER\nEncountered an unknown error: (Python bot)
\n\n```python\nsomething to do with an exception\n```\n\n
"}]
+
+https
+PATCH
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/comments/390017687
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
+{"body": "# MYHEADER\nNew text comment"}
+200
+[('Date', 'Thu, 17 May 2018 21:27:34 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4787'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"7d8a8bf4af44d34c832747ad13a83446"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.218436'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '1706:97B8:C24728:FB5638:5AFDF3C6')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017687","html_url":"https://github.com/lmazuel/TestingRepo/issues/15#issuecomment-390017687","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15","id":390017687,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-05-17T21:27:33Z","updated_at":"2018-05-17T21:27:34Z","author_association":"OWNER","body":"# MYHEADER\nNew text comment"}
+
+https
+GET
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/15/comments
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:35 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4786'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"2765cea7edb0c5332910282095b1d4c1"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.061215'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '1707:97B8:C2473C:FB5658:5AFDF3C6')]
+[{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/362444226","html_url":"https://github.com/lmazuel/TestingRepo/issues/15#issuecomment-362444226","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15","id":362444226,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-02-02T00:10:56Z","updated_at":"2018-02-02T00:59:46Z","author_association":"OWNER","body":"klsfjdlkjflksd\nlskjflkdjf\n"},{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017687","html_url":"https://github.com/lmazuel/TestingRepo/issues/15#issuecomment-390017687","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/15","id":390017687,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-05-17T21:27:33Z","updated_at":"2018-05-17T21:27:34Z","author_association":"OWNER","body":"# MYHEADER\nNew text comment"}]
+
+https
+DELETE
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/comments/390017687
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+204
+[('Date', 'Thu, 17 May 2018 21:27:35 GMT'), ('Content-Type', 'application/octet-stream'), ('Server', 'GitHub.com'), ('Status', '204 No Content'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4785'), ('X-RateLimit-Reset', '1526593184'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.126890'), ('Vary', 'Accept-Encoding'), ('X-GitHub-Request-Id', '1708:97B4:2AC8C4:374BDD:5AFDF3C7')]
+
+
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_exception_to_github.txt b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_exception_to_github.txt
new file mode 100644
index 000000000000..935e64e2fc1f
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_exception_to_github.txt
@@ -0,0 +1,99 @@
+https
+GET
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/13
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:35 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4784'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"5d22339274e7041343287e3bfa73f758"'), ('Last-Modified', 'Thu, 17 May 2018 21:15:10 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', 'repo'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.057591'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '1709:97B6:61F179:7EE505:5AFDF3C7')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/13","repository_url":"https://api.github.com/repos/lmazuel/TestingRepo","labels_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/13/labels{/name}","comments_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/13/comments","events_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/13/events","html_url":"https://github.com/lmazuel/TestingRepo/issues/13","id":290980764,"number":13,"title":"Testing exception","user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-01-23T20:24:40Z","updated_at":"2018-05-17T21:15:10Z","closed_at":null,"author_association":"OWNER","body":"This unittest is doing something stupid, to test I'm able to log in a generic way the stacktrace in Github","closed_by":null}
+
+https
+POST
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/13/comments
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
+{"body": "Encountered an unknown error
\n\n```python\nsomething to do with an exception\n```\n\n
"}
+201
+[('Date', 'Thu, 17 May 2018 21:27:35 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '1367'), ('Server', 'GitHub.com'), ('Status', '201 Created'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4783'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', '"02c13ce01b48f85e423f4eaaa70ae776"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('Location', 'https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017694'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.207902'), ('X-GitHub-Request-Id', '170A:97BA:C923A8:104F0A2:5AFDF3C7')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017694","html_url":"https://github.com/lmazuel/TestingRepo/issues/13#issuecomment-390017694","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/13","id":390017694,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-05-17T21:27:35Z","updated_at":"2018-05-17T21:27:35Z","author_association":"OWNER","body":"Encountered an unknown error
\n\n```python\nsomething to do with an exception\n```\n\n
"}
+
+https
+DELETE
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/comments/390017694
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+204
+[('Date', 'Thu, 17 May 2018 21:27:36 GMT'), ('Content-Type', 'application/octet-stream'), ('Server', 'GitHub.com'), ('Status', '204 No Content'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4782'), ('X-RateLimit-Reset', '1526593184'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.137629'), ('Vary', 'Accept-Encoding'), ('X-GitHub-Request-Id', '170B:97B6:61F19A:7EE52A:5AFDF3C7')]
+
+
+https
+POST
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/13/comments
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
+{"body": "Encountered an unknown error: (Python bot)
\n\n```python\nsomething to do with an exception\n```\n\n
"}
+201
+[('Date', 'Thu, 17 May 2018 21:27:36 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '1381'), ('Server', 'GitHub.com'), ('Status', '201 Created'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4781'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', '"80a0e4c3cf7c8e5152378483fc9b6928"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('Location', 'https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017696'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.177832'), ('X-GitHub-Request-Id', '170C:97B4:2AC8D4:374BF5:5AFDF3C8')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017696","html_url":"https://github.com/lmazuel/TestingRepo/issues/13#issuecomment-390017696","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/13","id":390017696,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-05-17T21:27:36Z","updated_at":"2018-05-17T21:27:36Z","author_association":"OWNER","body":"Encountered an unknown error: (Python bot)
\n\n```python\nsomething to do with an exception\n```\n\n
"}
+
+https
+DELETE
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/comments/390017696
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+204
+[('Date', 'Thu, 17 May 2018 21:27:36 GMT'), ('Content-Type', 'application/octet-stream'), ('Server', 'GitHub.com'), ('Status', '204 No Content'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4780'), ('X-RateLimit-Reset', '1526593184'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.152868'), ('Vary', 'Accept-Encoding'), ('X-GitHub-Request-Id', '170D:97BA:C923DA:104F0E5:5AFDF3C8')]
+
+
+https
+POST
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/13/comments
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
+{"body": "Encountered a Subprocess error: (Python bot)
\n\nCommand: ['autorest', 'readme.md']\nFinished with return code 2\nand output:\n```shell\nError line 1\nError line 2\n```\n\n
"}
+201
+[('Date', 'Thu, 17 May 2018 21:27:36 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '1453'), ('Server', 'GitHub.com'), ('Status', '201 Created'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4779'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', '"1b1b351c9807c836fbc5facac7829561"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('Location', 'https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017699'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.193468'), ('X-GitHub-Request-Id', '170E:97B6:61F1CD:7EE566:5AFDF3C8')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017699","html_url":"https://github.com/lmazuel/TestingRepo/issues/13#issuecomment-390017699","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/13","id":390017699,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-05-17T21:27:36Z","updated_at":"2018-05-17T21:27:36Z","author_association":"OWNER","body":"Encountered a Subprocess error: (Python bot)
\n\nCommand: ['autorest', 'readme.md']\nFinished with return code 2\nand output:\n```shell\nError line 1\nError line 2\n```\n\n
"}
+
+https
+DELETE
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/comments/390017699
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+204
+[('Date', 'Thu, 17 May 2018 21:27:37 GMT'), ('Content-Type', 'application/octet-stream'), ('Server', 'GitHub.com'), ('Status', '204 No Content'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4778'), ('X-RateLimit-Reset', '1526593184'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.129749'), ('Vary', 'Accept-Encoding'), ('X-GitHub-Request-Id', '170F:97BA:C92400:104F11E:5AFDF3C8')]
+
+
+https
+POST
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/13/comments
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
+{"body": "Encountered a Subprocess error: (Python bot)
\n\nCommand: ['autorest', 'readme.md']\nFinished with return code 2\nand no output\n\n
"}
+201
+[('Date', 'Thu, 17 May 2018 21:27:37 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '1412'), ('Server', 'GitHub.com'), ('Status', '201 Created'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4777'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', '"c63186bf115722901d5391428f67a13b"'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('Location', 'https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017701'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.211042'), ('X-GitHub-Request-Id', '1710:97B8:C24810:FB5779:5AFDF3C9')]
+{"url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/comments/390017701","html_url":"https://github.com/lmazuel/TestingRepo/issues/13#issuecomment-390017701","issue_url":"https://api.github.com/repos/lmazuel/TestingRepo/issues/13","id":390017701,"user":{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false},"created_at":"2018-05-17T21:27:37Z","updated_at":"2018-05-17T21:27:37Z","author_association":"OWNER","body":"Encountered a Subprocess error: (Python bot)
\n\nCommand: ['autorest', 'readme.md']\nFinished with return code 2\nand no output\n\n
"}
+
+https
+DELETE
+api.github.com
+None
+/repos/lmazuel/TestingRepo/issues/comments/390017701
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+204
+[('Date', 'Thu, 17 May 2018 21:27:37 GMT'), ('Content-Type', 'application/octet-stream'), ('Server', 'GitHub.com'), ('Status', '204 No Content'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4776'), ('X-RateLimit-Reset', '1526593184'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.150903'), ('Vary', 'Accept-Encoding'), ('X-GitHub-Request-Id', '1711:97BA:C92421:104F154:5AFDF3C9')]
+
+
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_get_files.txt b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_get_files.txt
new file mode 100644
index 000000000000..5cc5b47e4f6a
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_get_files.txt
@@ -0,0 +1,33 @@
+https
+GET
+api.github.com
+None
+/repos/Azure/azure-sdk-for-python/pulls/1833
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:38 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4775'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"efe380b23abd3372e84ff35dbd437a3c"'), ('Last-Modified', 'Thu, 29 Mar 2018 00:23:35 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.134239'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '1712:97B8:C2483A:FB57AE:5AFDF3C9')]
+{"url":"https://api.github.com/repos/Azure/azure-sdk-for-python/pulls/1833","id":165209780,"html_url":"https://github.com/Azure/azure-sdk-for-python/pull/1833","diff_url":"https://github.com/Azure/azure-sdk-for-python/pull/1833.diff","patch_url":"https://github.com/Azure/azure-sdk-for-python/pull/1833.patch","issue_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/issues/1833","number":1833,"state":"closed","locked":false,"title":"Automatic PR of restapi_auto_bgsky_master into master","user":{"login":"AutorestCI","id":18218145,"avatar_url":"https://avatars3.githubusercontent.com/u/18218145?v=4","gravatar_id":"","url":"https://api.github.com/users/AutorestCI","html_url":"https://github.com/AutorestCI","followers_url":"https://api.github.com/users/AutorestCI/followers","following_url":"https://api.github.com/users/AutorestCI/following{/other_user}","gists_url":"https://api.github.com/users/AutorestCI/gists{/gist_id}","starred_url":"https://api.github.com/users/AutorestCI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AutorestCI/subscriptions","organizations_url":"https://api.github.com/users/AutorestCI/orgs","repos_url":"https://api.github.com/users/AutorestCI/repos","events_url":"https://api.github.com/users/AutorestCI/events{/privacy}","received_events_url":"https://api.github.com/users/AutorestCI/received_events","type":"User","site_admin":false},"body":"Created to sync https://github.com/Azure/azure-rest-api-specs/pull/2335","created_at":"2018-01-25T19:40:09Z","updated_at":"2018-02-06T18:26:44Z","closed_at":"2018-02-06T18:26:41Z","merged_at":null,"merge_commit_sha":"7a4bc4682149db0f88b1ad628b432fe90ae87786","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":803155593,"url":"https://api.github.com/repos/Azure/azure-sdk-for-python/labels/RestPRMerged","name":"RestPRMerged","color":"0e8a16","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/pulls/1833/commits","review_comments_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/pulls/1833/comments","review_comment_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/issues/1833/comments","statuses_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/statuses/3d6c419cd2ade53c240c40db96dbe34957351244","head":{"label":"Azure:restapi_auto_bgsky_master","ref":"restapi_auto_bgsky_master","sha":"3d6c419cd2ade53c240c40db96dbe34957351244","user":{"login":"Azure","id":6844498,"avatar_url":"https://avatars0.githubusercontent.com/u/6844498?v=4","gravatar_id":"","url":"https://api.github.com/users/Azure","html_url":"https://github.com/Azure","followers_url":"https://api.github.com/users/Azure/followers","following_url":"https://api.github.com/users/Azure/following{/other_user}","gists_url":"https://api.github.com/users/Azure/gists{/gist_id}","starred_url":"https://api.github.com/users/Azure/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Azure/subscriptions","organizations_url":"https://api.github.com/users/Azure/orgs","repos_url":"https://api.github.com/users/Azure/repos","events_url":"https://api.github.com/users/Azure/events{/privacy}","received_events_url":"https://api.github.com/users/Azure/received_events","type":"Organization","site_admin":false},"repo":{"id":4127088,"name":"azure-sdk-for-python","full_name":"Azure/azure-sdk-for-python","owner":{"login":"Azure","id":6844498,"avatar_url":"https://avatars0.githubusercontent.com/u/6844498?v=4","gravatar_id":"","url":"https://api.github.com/users/Azure","html_url":"https://github.com/Azure","followers_url":"https://api.github.com/users/Azure/followers","following_url":"https://api.github.com/users/Azure/following{/other_user}","gists_url":"https://api.github.com/users/Azure/gists{/gist_id}","starred_url":"https://api.github.com/users/Azure/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Azure/subscriptions","organizations_url":"https://api.github.com/users/Azure/orgs","repos_url":"https://api.github.com/users/Azure/repos","events_url":"https://api.github.com/users/Azure/events{/privacy}","received_events_url":"https://api.github.com/users/Azure/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Azure/azure-sdk-for-python","description":"Microsoft Azure SDK for Python","fork":false,"url":"https://api.github.com/repos/Azure/azure-sdk-for-python","forks_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/forks","keys_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/teams","hooks_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/hooks","issue_events_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/issues/events{/number}","events_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/events","assignees_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/assignees{/user}","branches_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/branches{/branch}","tags_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/tags","blobs_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/git/refs{/sha}","trees_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/statuses/{sha}","languages_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/languages","stargazers_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/stargazers","contributors_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contributors","subscribers_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/subscribers","subscription_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/subscription","commits_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/commits{/sha}","git_commits_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/git/commits{/sha}","comments_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/comments{/number}","issue_comment_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/issues/comments{/number}","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/{+path}","compare_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/merges","archive_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/downloads","issues_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/issues{/number}","pulls_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/pulls{/number}","milestones_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/milestones{/number}","notifications_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/labels{/name}","releases_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/releases{/id}","deployments_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/deployments","created_at":"2012-04-24T16:46:12Z","updated_at":"2018-05-16T23:44:09Z","pushed_at":"2018-05-17T20:20:22Z","git_url":"git://github.com/Azure/azure-sdk-for-python.git","ssh_url":"git@github.com:Azure/azure-sdk-for-python.git","clone_url":"https://github.com/Azure/azure-sdk-for-python.git","svn_url":"https://github.com/Azure/azure-sdk-for-python","homepage":"","size":64485,"stargazers_count":536,"watchers_count":536,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":450,"mirror_url":null,"archived":false,"open_issues_count":176,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":450,"open_issues":176,"watchers":536,"default_branch":"master"}},"base":{"label":"Azure:master","ref":"master","sha":"f4715da4f929733b2b95c03142512f85ae8728a5","user":{"login":"Azure","id":6844498,"avatar_url":"https://avatars0.githubusercontent.com/u/6844498?v=4","gravatar_id":"","url":"https://api.github.com/users/Azure","html_url":"https://github.com/Azure","followers_url":"https://api.github.com/users/Azure/followers","following_url":"https://api.github.com/users/Azure/following{/other_user}","gists_url":"https://api.github.com/users/Azure/gists{/gist_id}","starred_url":"https://api.github.com/users/Azure/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Azure/subscriptions","organizations_url":"https://api.github.com/users/Azure/orgs","repos_url":"https://api.github.com/users/Azure/repos","events_url":"https://api.github.com/users/Azure/events{/privacy}","received_events_url":"https://api.github.com/users/Azure/received_events","type":"Organization","site_admin":false},"repo":{"id":4127088,"name":"azure-sdk-for-python","full_name":"Azure/azure-sdk-for-python","owner":{"login":"Azure","id":6844498,"avatar_url":"https://avatars0.githubusercontent.com/u/6844498?v=4","gravatar_id":"","url":"https://api.github.com/users/Azure","html_url":"https://github.com/Azure","followers_url":"https://api.github.com/users/Azure/followers","following_url":"https://api.github.com/users/Azure/following{/other_user}","gists_url":"https://api.github.com/users/Azure/gists{/gist_id}","starred_url":"https://api.github.com/users/Azure/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Azure/subscriptions","organizations_url":"https://api.github.com/users/Azure/orgs","repos_url":"https://api.github.com/users/Azure/repos","events_url":"https://api.github.com/users/Azure/events{/privacy}","received_events_url":"https://api.github.com/users/Azure/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Azure/azure-sdk-for-python","description":"Microsoft Azure SDK for Python","fork":false,"url":"https://api.github.com/repos/Azure/azure-sdk-for-python","forks_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/forks","keys_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/teams","hooks_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/hooks","issue_events_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/issues/events{/number}","events_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/events","assignees_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/assignees{/user}","branches_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/branches{/branch}","tags_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/tags","blobs_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/git/refs{/sha}","trees_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/statuses/{sha}","languages_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/languages","stargazers_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/stargazers","contributors_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contributors","subscribers_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/subscribers","subscription_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/subscription","commits_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/commits{/sha}","git_commits_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/git/commits{/sha}","comments_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/comments{/number}","issue_comment_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/issues/comments{/number}","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/{+path}","compare_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/merges","archive_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/downloads","issues_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/issues{/number}","pulls_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/pulls{/number}","milestones_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/milestones{/number}","notifications_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/labels{/name}","releases_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/releases{/id}","deployments_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/deployments","created_at":"2012-04-24T16:46:12Z","updated_at":"2018-05-16T23:44:09Z","pushed_at":"2018-05-17T20:20:22Z","git_url":"git://github.com/Azure/azure-sdk-for-python.git","ssh_url":"git@github.com:Azure/azure-sdk-for-python.git","clone_url":"https://github.com/Azure/azure-sdk-for-python.git","svn_url":"https://github.com/Azure/azure-sdk-for-python","homepage":"","size":64485,"stargazers_count":536,"watchers_count":536,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":450,"mirror_url":null,"archived":false,"open_issues_count":176,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":450,"open_issues":176,"watchers":536,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Azure/azure-sdk-for-python/pulls/1833"},"html":{"href":"https://github.com/Azure/azure-sdk-for-python/pull/1833"},"issue":{"href":"https://api.github.com/repos/Azure/azure-sdk-for-python/issues/1833"},"comments":{"href":"https://api.github.com/repos/Azure/azure-sdk-for-python/issues/1833/comments"},"review_comments":{"href":"https://api.github.com/repos/Azure/azure-sdk-for-python/pulls/1833/comments"},"review_comment":{"href":"https://api.github.com/repos/Azure/azure-sdk-for-python/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Azure/azure-sdk-for-python/pulls/1833/commits"},"statuses":{"href":"https://api.github.com/repos/Azure/azure-sdk-for-python/statuses/3d6c419cd2ade53c240c40db96dbe34957351244"}},"author_association":"MEMBER","merged":false,"mergeable":null,"rebaseable":null,"mergeable_state":"unknown","merged_by":null,"comments":1,"review_comments":0,"maintainer_can_modify":false,"commits":9,"additions":1941,"deletions":43,"changed_files":23}
+
+https
+GET
+api.github.com
+None
+/repos/Azure/azure-sdk-for-python/pulls/1833/files
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:38 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4774'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"974102d71c3b4d54ea78ae6faeddeb4d"'), ('Last-Modified', 'Thu, 29 Mar 2018 00:23:35 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.104289'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '1713:97B6:61F208:7EE5BA:5AFDF3CA')]
+[{"sha":"bf24d5ec847de2a0e8e63082550a5bcfeac05048","filename":"azure-mgmt-consumption/azure/mgmt/consumption/consumption_management_client.py","status":"modified","additions":33,"deletions":4,"changes":37,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/consumption_management_client.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/consumption_management_client.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/consumption_management_client.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -14,9 +14,12 @@\n from msrestazure import AzureConfiguration\n from .version import VERSION\n from .operations.usage_details_operations import UsageDetailsOperations\n+from .operations.marketplaces_operations import MarketplacesOperations\n from .operations.reservations_summaries_operations import ReservationsSummariesOperations\n from .operations.reservations_details_operations import ReservationsDetailsOperations\n+from .operations.budgets_operations import BudgetsOperations\n from .operations.operations import Operations\n+from .operations.price_sheet_operations import PriceSheetOperations\n from . import models\n \n \n@@ -30,16 +33,24 @@ class ConsumptionManagementClientConfiguration(AzureConfiguration):\n object`\n :param subscription_id: Azure Subscription ID.\n :type subscription_id: str\n+ :param resource_group_name: Azure Resource Group Name.\n+ :type resource_group_name: str\n+ :param budget_name: Budget Name.\n+ :type budget_name: str\n :param str base_url: Service URL\n \"\"\"\n \n def __init__(\n- self, credentials, subscription_id, base_url=None):\n+ self, credentials, subscription_id, resource_group_name, budget_name, base_url=None):\n \n if credentials is None:\n raise ValueError(\"Parameter 'credentials' must not be None.\")\n if subscription_id is None:\n raise ValueError(\"Parameter 'subscription_id' must not be None.\")\n+ if resource_group_name is None:\n+ raise ValueError(\"Parameter 'resource_group_name' must not be None.\")\n+ if budget_name is None:\n+ raise ValueError(\"Parameter 'budget_name' must not be None.\")\n if not base_url:\n base_url = 'https://management.azure.com'\n \n@@ -50,6 +61,8 @@ def __init__(\n \n self.credentials = credentials\n self.subscription_id = subscription_id\n+ self.resource_group_name = resource_group_name\n+ self.budget_name = budget_name\n \n \n class ConsumptionManagementClient(object):\n@@ -60,37 +73,53 @@ class ConsumptionManagementClient(object):\n \n :ivar usage_details: UsageDetails operations\n :vartype usage_details: azure.mgmt.consumption.operations.UsageDetailsOperations\n+ :ivar marketplaces: Marketplaces operations\n+ :vartype marketplaces: azure.mgmt.consumption.operations.MarketplacesOperations\n :ivar reservations_summaries: ReservationsSummaries operations\n :vartype reservations_summaries: azure.mgmt.consumption.operations.ReservationsSummariesOperations\n :ivar reservations_details: ReservationsDetails operations\n :vartype reservations_details: azure.mgmt.consumption.operations.ReservationsDetailsOperations\n+ :ivar budgets: Budgets operations\n+ :vartype budgets: azure.mgmt.consumption.operations.BudgetsOperations\n :ivar operations: Operations operations\n :vartype operations: azure.mgmt.consumption.operations.Operations\n+ :ivar price_sheet: PriceSheet operations\n+ :vartype price_sheet: azure.mgmt.consumption.operations.PriceSheetOperations\n \n :param credentials: Credentials needed for the client to connect to Azure.\n :type credentials: :mod:`A msrestazure Credentials\n object`\n :param subscription_id: Azure Subscription ID.\n :type subscription_id: str\n+ :param resource_group_name: Azure Resource Group Name.\n+ :type resource_group_name: str\n+ :param budget_name: Budget Name.\n+ :type budget_name: str\n :param str base_url: Service URL\n \"\"\"\n \n def __init__(\n- self, credentials, subscription_id, base_url=None):\n+ self, credentials, subscription_id, resource_group_name, budget_name, base_url=None):\n \n- self.config = ConsumptionManagementClientConfiguration(credentials, subscription_id, base_url)\n+ self.config = ConsumptionManagementClientConfiguration(credentials, subscription_id, resource_group_name, budget_name, base_url)\n self._client = ServiceClient(self.config.credentials, self.config)\n \n client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}\n- self.api_version = '2017-11-30'\n+ self.api_version = '2018-01-31'\n self._serialize = Serializer(client_models)\n self._deserialize = Deserializer(client_models)\n \n self.usage_details = UsageDetailsOperations(\n self._client, self.config, self._serialize, self._deserialize)\n+ self.marketplaces = MarketplacesOperations(\n+ self._client, self.config, self._serialize, self._deserialize)\n self.reservations_summaries = ReservationsSummariesOperations(\n self._client, self.config, self._serialize, self._deserialize)\n self.reservations_details = ReservationsDetailsOperations(\n self._client, self.config, self._serialize, self._deserialize)\n+ self.budgets = BudgetsOperations(\n+ self._client, self.config, self._serialize, self._deserialize)\n self.operations = Operations(\n self._client, self.config, self._serialize, self._deserialize)\n+ self.price_sheet = PriceSheetOperations(\n+ self._client, self.config, self._serialize, self._deserialize)"},{"sha":"d071f7f2e49d6159288f76e17b5cf2c52f900933","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/__init__.py","status":"modified","additions":28,"deletions":0,"changes":28,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/__init__.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/__init__.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/__init__.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -11,34 +11,62 @@\n \n from .meter_details import MeterDetails\n from .usage_detail import UsageDetail\n+from .marketplace import Marketplace\n from .reservation_summaries import ReservationSummaries\n from .reservation_details import ReservationDetails\n+from .budget_time_period import BudgetTimePeriod\n+from .filters import Filters\n+from .current_spend import CurrentSpend\n+from .notification import Notification\n+from .budget import Budget\n from .error_details import ErrorDetails\n from .error_response import ErrorResponse, ErrorResponseException\n from .operation_display import OperationDisplay\n from .operation import Operation\n from .resource import Resource\n+from .proxy_resource import ProxyResource\n+from .price_sheet_list_result import PriceSheetListResult\n+from .price_sheet_model import PriceSheetModel\n from .usage_detail_paged import UsageDetailPaged\n+from .marketplace_paged import MarketplacePaged\n from .reservation_summaries_paged import ReservationSummariesPaged\n from .reservation_details_paged import ReservationDetailsPaged\n+from .budget_paged import BudgetPaged\n from .operation_paged import OperationPaged\n from .consumption_management_client_enums import (\n+ CategoryType,\n+ TimeGrainType,\n+ OperatorType,\n Datagrain,\n )\n \n __all__ = [\n 'MeterDetails',\n 'UsageDetail',\n+ 'Marketplace',\n 'ReservationSummaries',\n 'ReservationDetails',\n+ 'BudgetTimePeriod',\n+ 'Filters',\n+ 'CurrentSpend',\n+ 'Notification',\n+ 'Budget',\n 'ErrorDetails',\n 'ErrorResponse', 'ErrorResponseException',\n 'OperationDisplay',\n 'Operation',\n 'Resource',\n+ 'ProxyResource',\n+ 'PriceSheetListResult',\n+ 'PriceSheetModel',\n 'UsageDetailPaged',\n+ 'MarketplacePaged',\n 'ReservationSummariesPaged',\n 'ReservationDetailsPaged',\n+ 'BudgetPaged',\n 'OperationPaged',\n+ 'CategoryType',\n+ 'TimeGrainType',\n+ 'OperatorType',\n 'Datagrain',\n ]"},{"sha":"f6485d49266ddf2734c02ab55dceb9aba94bfe0a","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/budget.py","status":"added","additions":91,"deletions":0,"changes":91,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/budget.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/budget.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/budget.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,91 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from .proxy_resource import ProxyResource\n+\n+\n+class Budget(ProxyResource):\n+ \"\"\"A budget resource.\n+\n+ Variables are only populated by the server, and will be ignored when\n+ sending a request.\n+\n+ :ivar id: Resource Id.\n+ :vartype id: str\n+ :ivar name: Resource name.\n+ :vartype name: str\n+ :ivar type: Resource type.\n+ :vartype type: str\n+ :param e_tag: eTag of the resource. To handle concurrent update scenarion,\n+ this field will be used to determine whether the user is updating the\n+ latest version or not.\n+ :type e_tag: str\n+ :param category: The category of the budget, whether the budget tracks\n+ cost or usage. Possible values include: 'Cost', 'Usage'\n+ :type category: str or ~azure.mgmt.consumption.models.CategoryType\n+ :param amount: The total amount of cost to track with the budget\n+ :type amount: decimal.Decimal\n+ :param time_grain: The time covered by a budget. Tracking of the amount\n+ will be reset based on the time grain. Possible values include: 'Monthly',\n+ 'Quarterly', 'Annually'\n+ :type time_grain: str or ~azure.mgmt.consumption.models.TimeGrainType\n+ :param time_period: Has start and end date of the budget. The start date\n+ must be first of the month and should be less than the end date. Budget\n+ start date must be on or after June 1, 2017. Future start date should not\n+ be more than three months. Past start date should be selected within the\n+ timegrain preiod. There are no restrictions on the end date.\n+ :type time_period: ~azure.mgmt.consumption.models.BudgetTimePeriod\n+ :param filters: May be used to filter budgets by resource group, resource,\n+ or meter.\n+ :type filters: ~azure.mgmt.consumption.models.Filters\n+ :ivar current_spend: The current amount of cost which is being tracked for\n+ a budget.\n+ :vartype current_spend: ~azure.mgmt.consumption.models.CurrentSpend\n+ :param notifications: Dictionary of notifications associated with the\n+ budget. Budget can have up to five notifications.\n+ :type notifications: dict[str,\n+ ~azure.mgmt.consumption.models.Notification]\n+ \"\"\"\n+\n+ _validation = {\n+ 'id': {'readonly': True},\n+ 'name': {'readonly': True},\n+ 'type': {'readonly': True},\n+ 'category': {'required': True},\n+ 'amount': {'required': True},\n+ 'time_grain': {'required': True},\n+ 'time_period': {'required': True},\n+ 'current_spend': {'readonly': True},\n+ }\n+\n+ _attribute_map = {\n+ 'id': {'key': 'id', 'type': 'str'},\n+ 'name': {'key': 'name', 'type': 'str'},\n+ 'type': {'key': 'type', 'type': 'str'},\n+ 'e_tag': {'key': 'eTag', 'type': 'str'},\n+ 'category': {'key': 'properties.category', 'type': 'str'},\n+ 'amount': {'key': 'properties.amount', 'type': 'decimal'},\n+ 'time_grain': {'key': 'properties.timeGrain', 'type': 'str'},\n+ 'time_period': {'key': 'properties.timePeriod', 'type': 'BudgetTimePeriod'},\n+ 'filters': {'key': 'properties.filters', 'type': 'Filters'},\n+ 'current_spend': {'key': 'properties.currentSpend', 'type': 'CurrentSpend'},\n+ 'notifications': {'key': 'properties.notifications', 'type': '{Notification}'},\n+ }\n+\n+ def __init__(self, category, amount, time_grain, time_period, e_tag=None, filters=None, notifications=None):\n+ super(Budget, self).__init__(e_tag=e_tag)\n+ self.category = category\n+ self.amount = amount\n+ self.time_grain = time_grain\n+ self.time_period = time_period\n+ self.filters = filters\n+ self.current_spend = None\n+ self.notifications = notifications"},{"sha":"2668382253e2d7aaefb8665a466d2482193e0246","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/budget_paged.py","status":"added","additions":27,"deletions":0,"changes":27,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/budget_paged.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/budget_paged.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/budget_paged.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,27 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.paging import Paged\n+\n+\n+class BudgetPaged(Paged):\n+ \"\"\"\n+ A paging container for iterating over a list of :class:`Budget ` object\n+ \"\"\"\n+\n+ _attribute_map = {\n+ 'next_link': {'key': 'nextLink', 'type': 'str'},\n+ 'current_page': {'key': 'value', 'type': '[Budget]'}\n+ }\n+\n+ def __init__(self, *args, **kwargs):\n+\n+ super(BudgetPaged, self).__init__(*args, **kwargs)"},{"sha":"2b1c0e78418a1deb6b6147fc90ea53f1a03256d0","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/budget_time_period.py","status":"added","additions":37,"deletions":0,"changes":37,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/budget_time_period.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/budget_time_period.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/budget_time_period.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,37 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.serialization import Model\n+\n+\n+class BudgetTimePeriod(Model):\n+ \"\"\"The start and end date for a budget.\n+\n+ :param start_date: The start date for the budget.\n+ :type start_date: datetime\n+ :param end_date: The end date for the budget. If not provided, we default\n+ this to 10 years from the start date.\n+ :type end_date: datetime\n+ \"\"\"\n+\n+ _validation = {\n+ 'start_date': {'required': True},\n+ }\n+\n+ _attribute_map = {\n+ 'start_date': {'key': 'startDate', 'type': 'iso-8601'},\n+ 'end_date': {'key': 'endDate', 'type': 'iso-8601'},\n+ }\n+\n+ def __init__(self, start_date, end_date=None):\n+ super(BudgetTimePeriod, self).__init__()\n+ self.start_date = start_date\n+ self.end_date = end_date"},{"sha":"bb0db82f76b32c1d02cca1de69b0ecc49b3b548b","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/consumption_management_client_enums.py","status":"modified","additions":20,"deletions":0,"changes":20,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/consumption_management_client_enums.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/consumption_management_client_enums.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/consumption_management_client_enums.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -12,6 +12,26 @@\n from enum import Enum\n \n \n+class CategoryType(Enum):\n+\n+ cost = \"Cost\"\n+ usage = \"Usage\"\n+\n+\n+class TimeGrainType(Enum):\n+\n+ monthly = \"Monthly\"\n+ quarterly = \"Quarterly\"\n+ annually = \"Annually\"\n+\n+\n+class OperatorType(Enum):\n+\n+ equal_to = \"EqualTo\"\n+ greater_than = \"GreaterThan\"\n+ greater_than_or_equal_to = \"GreaterThanOrEqualTo\"\n+\n+\n class Datagrain(Enum):\n \n daily_grain = \"daily\""},{"sha":"839c286b104079f531a4b130f3e01082d63d08ac","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/current_spend.py","status":"added","additions":41,"deletions":0,"changes":41,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/current_spend.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/current_spend.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/current_spend.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,41 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.serialization import Model\n+\n+\n+class CurrentSpend(Model):\n+ \"\"\"The current amount of cost which is being tracked for a budget.\n+\n+ Variables are only populated by the server, and will be ignored when\n+ sending a request.\n+\n+ :ivar amount: The total amount of cost which is being tracked by the\n+ budget.\n+ :vartype amount: decimal.Decimal\n+ :ivar unit: The unit of measure for the budget amount.\n+ :vartype unit: str\n+ \"\"\"\n+\n+ _validation = {\n+ 'amount': {'readonly': True},\n+ 'unit': {'readonly': True},\n+ }\n+\n+ _attribute_map = {\n+ 'amount': {'key': 'amount', 'type': 'decimal'},\n+ 'unit': {'key': 'unit', 'type': 'str'},\n+ }\n+\n+ def __init__(self):\n+ super(CurrentSpend, self).__init__()\n+ self.amount = None\n+ self.unit = None"},{"sha":"dc010a065900621f02b77dfe1b389071e597fd73","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/filters.py","status":"added","additions":44,"deletions":0,"changes":44,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/filters.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/filters.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/filters.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,44 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.serialization import Model\n+\n+\n+class Filters(Model):\n+ \"\"\"May be used to filter budgets by resource group, resource, or meter.\n+\n+ :param resource_groups: The list of filters on resource groups, allowed at\n+ subscription level only.\n+ :type resource_groups: list[str]\n+ :param resources: The list of filters on resources.\n+ :type resources: list[str]\n+ :param meters: The list of filters on meters, mandatory for budgets of\n+ usage category.\n+ :type meters: list[str]\n+ \"\"\"\n+\n+ _validation = {\n+ 'resource_groups': {'max_items': 10, 'min_items': 0},\n+ 'resources': {'max_items': 10, 'min_items': 0},\n+ 'meters': {'max_items': 10, 'min_items': 0},\n+ }\n+\n+ _attribute_map = {\n+ 'resource_groups': {'key': 'resourceGroups', 'type': '[str]'},\n+ 'resources': {'key': 'resources', 'type': '[str]'},\n+ 'meters': {'key': 'meters', 'type': '[str]'},\n+ }\n+\n+ def __init__(self, resource_groups=None, resources=None, meters=None):\n+ super(Filters, self).__init__()\n+ self.resource_groups = resource_groups\n+ self.resources = resources\n+ self.meters = meters"},{"sha":"d401f3fdc397e6aa0d40011f987917ef0984a8bc","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/marketplace.py","status":"added","additions":174,"deletions":0,"changes":174,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/marketplace.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/marketplace.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/marketplace.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,174 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from .resource import Resource\n+\n+\n+class Marketplace(Resource):\n+ \"\"\"An marketplace resource.\n+\n+ Variables are only populated by the server, and will be ignored when\n+ sending a request.\n+\n+ :ivar id: Resource Id.\n+ :vartype id: str\n+ :ivar name: Resource name.\n+ :vartype name: str\n+ :ivar type: Resource type.\n+ :vartype type: str\n+ :ivar tags: Resource tags.\n+ :vartype tags: dict[str, str]\n+ :ivar billing_period_id: The id of the billing period resource that the\n+ usage belongs to.\n+ :vartype billing_period_id: str\n+ :ivar usage_start: The start of the date time range covered by the usage\n+ detail.\n+ :vartype usage_start: datetime\n+ :ivar usage_end: The end of the date time range covered by the usage\n+ detail.\n+ :vartype usage_end: datetime\n+ :ivar resource_rate: The marketplace resource rate.\n+ :vartype resource_rate: decimal.Decimal\n+ :ivar offer_name: The type of offer.\n+ :vartype offer_name: str\n+ :ivar resource_group: The name of resource group.\n+ :vartype resource_group: str\n+ :ivar order_number: The order number.\n+ :vartype order_number: str\n+ :ivar instance_name: The name of the resource instance that the usage is\n+ about.\n+ :vartype instance_name: str\n+ :ivar instance_id: The uri of the resource instance that the usage is\n+ about.\n+ :vartype instance_id: str\n+ :ivar currency: The ISO currency in which the meter is charged, for\n+ example, USD.\n+ :vartype currency: str\n+ :ivar consumed_quantity: The quantity of usage.\n+ :vartype consumed_quantity: decimal.Decimal\n+ :ivar unit_of_measure: The unit of measure.\n+ :vartype unit_of_measure: str\n+ :ivar pretax_cost: The amount of cost before tax.\n+ :vartype pretax_cost: decimal.Decimal\n+ :ivar is_estimated: The estimated usage is subject to change.\n+ :vartype is_estimated: bool\n+ :ivar meter_id: The meter id.\n+ :vartype meter_id: str\n+ :ivar subscription_guid: Subscription guid.\n+ :vartype subscription_guid: str\n+ :ivar subscription_name: Subscription name.\n+ :vartype subscription_name: str\n+ :ivar account_name: Account name.\n+ :vartype account_name: str\n+ :ivar department_name: Department name.\n+ :vartype department_name: str\n+ :ivar consumed_service: Consumed service name.\n+ :vartype consumed_service: str\n+ :ivar cost_center: The cost center of this department if it is a\n+ department and a costcenter exists\n+ :vartype cost_center: str\n+ :ivar additional_properties: Additional details of this usage item. By\n+ default this is not populated, unless it's specified in $expand.\n+ :vartype additional_properties: str\n+ :ivar publisher_name: The name of publisher.\n+ :vartype publisher_name: str\n+ :ivar plan_name: The name of plan.\n+ :vartype plan_name: str\n+ \"\"\"\n+\n+ _validation = {\n+ 'id': {'readonly': True},\n+ 'name': {'readonly': True},\n+ 'type': {'readonly': True},\n+ 'tags': {'readonly': True},\n+ 'billing_period_id': {'readonly': True},\n+ 'usage_start': {'readonly': True},\n+ 'usage_end': {'readonly': True},\n+ 'resource_rate': {'readonly': True},\n+ 'offer_name': {'readonly': True},\n+ 'resource_group': {'readonly': True},\n+ 'order_number': {'readonly': True},\n+ 'instance_name': {'readonly': True},\n+ 'instance_id': {'readonly': True},\n+ 'currency': {'readonly': True},\n+ 'consumed_quantity': {'readonly': True},\n+ 'unit_of_measure': {'readonly': True},\n+ 'pretax_cost': {'readonly': True},\n+ 'is_estimated': {'readonly': True},\n+ 'meter_id': {'readonly': True},\n+ 'subscription_guid': {'readonly': True},\n+ 'subscription_name': {'readonly': True},\n+ 'account_name': {'readonly': True},\n+ 'department_name': {'readonly': True},\n+ 'consumed_service': {'readonly': True},\n+ 'cost_center': {'readonly': True},\n+ 'additional_properties': {'readonly': True},\n+ 'publisher_name': {'readonly': True},\n+ 'plan_name': {'readonly': True},\n+ }\n+\n+ _attribute_map = {\n+ 'id': {'key': 'id', 'type': 'str'},\n+ 'name': {'key': 'name', 'type': 'str'},\n+ 'type': {'key': 'type', 'type': 'str'},\n+ 'tags': {'key': 'tags', 'type': '{str}'},\n+ 'billing_period_id': {'key': 'properties.billingPeriodId', 'type': 'str'},\n+ 'usage_start': {'key': 'properties.usageStart', 'type': 'iso-8601'},\n+ 'usage_end': {'key': 'properties.usageEnd', 'type': 'iso-8601'},\n+ 'resource_rate': {'key': 'properties.resourceRate', 'type': 'decimal'},\n+ 'offer_name': {'key': 'properties.offerName', 'type': 'str'},\n+ 'resource_group': {'key': 'properties.resourceGroup', 'type': 'str'},\n+ 'order_number': {'key': 'properties.orderNumber', 'type': 'str'},\n+ 'instance_name': {'key': 'properties.instanceName', 'type': 'str'},\n+ 'instance_id': {'key': 'properties.instanceId', 'type': 'str'},\n+ 'currency': {'key': 'properties.currency', 'type': 'str'},\n+ 'consumed_quantity': {'key': 'properties.consumedQuantity', 'type': 'decimal'},\n+ 'unit_of_measure': {'key': 'properties.unitOfMeasure', 'type': 'str'},\n+ 'pretax_cost': {'key': 'properties.pretaxCost', 'type': 'decimal'},\n+ 'is_estimated': {'key': 'properties.isEstimated', 'type': 'bool'},\n+ 'meter_id': {'key': 'properties.meterId', 'type': 'str'},\n+ 'subscription_guid': {'key': 'properties.subscriptionGuid', 'type': 'str'},\n+ 'subscription_name': {'key': 'properties.subscriptionName', 'type': 'str'},\n+ 'account_name': {'key': 'properties.accountName', 'type': 'str'},\n+ 'department_name': {'key': 'properties.departmentName', 'type': 'str'},\n+ 'consumed_service': {'key': 'properties.consumedService', 'type': 'str'},\n+ 'cost_center': {'key': 'properties.costCenter', 'type': 'str'},\n+ 'additional_properties': {'key': 'properties.additionalProperties', 'type': 'str'},\n+ 'publisher_name': {'key': 'properties.publisherName', 'type': 'str'},\n+ 'plan_name': {'key': 'properties.planName', 'type': 'str'},\n+ }\n+\n+ def __init__(self):\n+ super(Marketplace, self).__init__()\n+ self.billing_period_id = None\n+ self.usage_start = None\n+ self.usage_end = None\n+ self.resource_rate = None\n+ self.offer_name = None\n+ self.resource_group = None\n+ self.order_number = None\n+ self.instance_name = None\n+ self.instance_id = None\n+ self.currency = None\n+ self.consumed_quantity = None\n+ self.unit_of_measure = None\n+ self.pretax_cost = None\n+ self.is_estimated = None\n+ self.meter_id = None\n+ self.subscription_guid = None\n+ self.subscription_name = None\n+ self.account_name = None\n+ self.department_name = None\n+ self.consumed_service = None\n+ self.cost_center = None\n+ self.additional_properties = None\n+ self.publisher_name = None\n+ self.plan_name = None"},{"sha":"d360761aca550436c8a2be210180f36920169c06","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/marketplace_paged.py","status":"added","additions":27,"deletions":0,"changes":27,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/marketplace_paged.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/marketplace_paged.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/marketplace_paged.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,27 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.paging import Paged\n+\n+\n+class MarketplacePaged(Paged):\n+ \"\"\"\n+ A paging container for iterating over a list of :class:`Marketplace ` object\n+ \"\"\"\n+\n+ _attribute_map = {\n+ 'next_link': {'key': 'nextLink', 'type': 'str'},\n+ 'current_page': {'key': 'value', 'type': '[Marketplace]'}\n+ }\n+\n+ def __init__(self, *args, **kwargs):\n+\n+ super(MarketplacePaged, self).__init__(*args, **kwargs)"},{"sha":"61e1ca0ed34df63b0df71d2970b19f7fa8a866bd","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/notification.py","status":"added","additions":62,"deletions":0,"changes":62,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/notification.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/notification.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/notification.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,62 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.serialization import Model\n+\n+\n+class Notification(Model):\n+ \"\"\"The notification associated with a budget.\n+\n+ :param enabled: The notification is enabled or not.\n+ :type enabled: bool\n+ :param operator: The comparison operator. Possible values include:\n+ 'EqualTo', 'GreaterThan', 'GreaterThanOrEqualTo'\n+ :type operator: str or ~azure.mgmt.consumption.models.OperatorType\n+ :param threshold: Threshold value associated with a notification.\n+ Notification is sent when the cost exceeded the threshold. It is always\n+ percent and has to be between 0 and 1000.\n+ :type threshold: decimal.Decimal\n+ :param contact_emails: Email addresses to send the budget notification to\n+ when the threshold is exceeded.\n+ :type contact_emails: list[str]\n+ :param contact_roles: Contact roles to send the budget notification to\n+ when the threshold is exceeded.\n+ :type contact_roles: list[str]\n+ :param contact_groups: Action groups to send the budget notification to\n+ when the threshold is exceeded.\n+ :type contact_groups: list[str]\n+ \"\"\"\n+\n+ _validation = {\n+ 'enabled': {'required': True},\n+ 'operator': {'required': True},\n+ 'threshold': {'required': True},\n+ 'contact_emails': {'required': True, 'max_items': 50, 'min_items': 1},\n+ 'contact_groups': {'max_items': 50, 'min_items': 0},\n+ }\n+\n+ _attribute_map = {\n+ 'enabled': {'key': 'enabled', 'type': 'bool'},\n+ 'operator': {'key': 'operator', 'type': 'str'},\n+ 'threshold': {'key': 'threshold', 'type': 'decimal'},\n+ 'contact_emails': {'key': 'contactEmails', 'type': '[str]'},\n+ 'contact_roles': {'key': 'contactRoles', 'type': '[str]'},\n+ 'contact_groups': {'key': 'contactGroups', 'type': '[str]'},\n+ }\n+\n+ def __init__(self, enabled, operator, threshold, contact_emails, contact_roles=None, contact_groups=None):\n+ super(Notification, self).__init__()\n+ self.enabled = enabled\n+ self.operator = operator\n+ self.threshold = threshold\n+ self.contact_emails = contact_emails\n+ self.contact_roles = contact_roles\n+ self.contact_groups = contact_groups"},{"sha":"6b201161f1dd7f05fef48e2355c696e882bb029c","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet_list_result.py","status":"added","additions":41,"deletions":0,"changes":41,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet_list_result.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet_list_result.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet_list_result.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,41 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.serialization import Model\n+\n+\n+class PriceSheetListResult(Model):\n+ \"\"\"price sheet result. It contains the pricesheet associated with billing\n+ period.\n+\n+ Variables are only populated by the server, and will be ignored when\n+ sending a request.\n+\n+ :ivar value: Price sheet\n+ :vartype value: object\n+ :ivar next_link: The link (url) to the next page of results.\n+ :vartype next_link: str\n+ \"\"\"\n+\n+ _validation = {\n+ 'value': {'readonly': True},\n+ 'next_link': {'readonly': True},\n+ }\n+\n+ _attribute_map = {\n+ 'value': {'key': 'value', 'type': 'object'},\n+ 'next_link': {'key': 'nextLink', 'type': 'str'},\n+ }\n+\n+ def __init__(self):\n+ super(PriceSheetListResult, self).__init__()\n+ self.value = None\n+ self.next_link = None"},{"sha":"0f51585aa714c16764b94d5170b6f65e3f4b5ac0","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet_model.py","status":"added","additions":88,"deletions":0,"changes":88,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet_model.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet_model.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet_model.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,88 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from .resource import Resource\n+\n+\n+class PriceSheetModel(Resource):\n+ \"\"\"An pricesheet resource.\n+\n+ Variables are only populated by the server, and will be ignored when\n+ sending a request.\n+\n+ :ivar id: Resource Id.\n+ :vartype id: str\n+ :ivar name: Resource name.\n+ :vartype name: str\n+ :ivar type: Resource type.\n+ :vartype type: str\n+ :ivar tags: Resource tags.\n+ :vartype tags: dict[str, str]\n+ :ivar billing_period_id: The id of the billing period resource that the\n+ usage belongs to.\n+ :vartype billing_period_id: str\n+ :ivar meter_id: The meter id\n+ :vartype meter_id: str\n+ :ivar meter_details: The details about the meter. By default this is not\n+ populated, unless it's specified in $expand.\n+ :vartype meter_details: ~azure.mgmt.consumption.models.MeterDetails\n+ :ivar unit_of_measure: Unit of measure\n+ :vartype unit_of_measure: str\n+ :ivar included_quantity: Included quality for an offer\n+ :vartype included_quantity: decimal.Decimal\n+ :ivar part_number: Part Number\n+ :vartype part_number: str\n+ :ivar unit_price: Unit Price\n+ :vartype unit_price: decimal.Decimal\n+ :ivar currency_code: Currency Code\n+ :vartype currency_code: str\n+ \"\"\"\n+\n+ _validation = {\n+ 'id': {'readonly': True},\n+ 'name': {'readonly': True},\n+ 'type': {'readonly': True},\n+ 'tags': {'readonly': True},\n+ 'billing_period_id': {'readonly': True},\n+ 'meter_id': {'readonly': True},\n+ 'meter_details': {'readonly': True},\n+ 'unit_of_measure': {'readonly': True},\n+ 'included_quantity': {'readonly': True},\n+ 'part_number': {'readonly': True},\n+ 'unit_price': {'readonly': True},\n+ 'currency_code': {'readonly': True},\n+ }\n+\n+ _attribute_map = {\n+ 'id': {'key': 'id', 'type': 'str'},\n+ 'name': {'key': 'name', 'type': 'str'},\n+ 'type': {'key': 'type', 'type': 'str'},\n+ 'tags': {'key': 'tags', 'type': '{str}'},\n+ 'billing_period_id': {'key': 'properties.billingPeriodId', 'type': 'str'},\n+ 'meter_id': {'key': 'properties.meterId', 'type': 'str'},\n+ 'meter_details': {'key': 'properties.meterDetails', 'type': 'MeterDetails'},\n+ 'unit_of_measure': {'key': 'properties.unitOfMeasure', 'type': 'str'},\n+ 'included_quantity': {'key': 'properties.includedQuantity', 'type': 'decimal'},\n+ 'part_number': {'key': 'properties.partNumber', 'type': 'str'},\n+ 'unit_price': {'key': 'properties.unitPrice', 'type': 'decimal'},\n+ 'currency_code': {'key': 'properties.currencyCode', 'type': 'str'},\n+ }\n+\n+ def __init__(self):\n+ super(PriceSheetModel, self).__init__()\n+ self.billing_period_id = None\n+ self.meter_id = None\n+ self.meter_details = None\n+ self.unit_of_measure = None\n+ self.included_quantity = None\n+ self.part_number = None\n+ self.unit_price = None\n+ self.currency_code = None"},{"sha":"f6a9a40d22d569970958af165de44c9f84162e47","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/proxy_resource.py","status":"added","additions":51,"deletions":0,"changes":51,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/proxy_resource.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/models/proxy_resource.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/proxy_resource.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,51 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.serialization import Model\n+\n+\n+class ProxyResource(Model):\n+ \"\"\"The Resource model definition.\n+\n+ Variables are only populated by the server, and will be ignored when\n+ sending a request.\n+\n+ :ivar id: Resource Id.\n+ :vartype id: str\n+ :ivar name: Resource name.\n+ :vartype name: str\n+ :ivar type: Resource type.\n+ :vartype type: str\n+ :param e_tag: eTag of the resource. To handle concurrent update scenarion,\n+ this field will be used to determine whether the user is updating the\n+ latest version or not.\n+ :type e_tag: str\n+ \"\"\"\n+\n+ _validation = {\n+ 'id': {'readonly': True},\n+ 'name': {'readonly': True},\n+ 'type': {'readonly': True},\n+ }\n+\n+ _attribute_map = {\n+ 'id': {'key': 'id', 'type': 'str'},\n+ 'name': {'key': 'name', 'type': 'str'},\n+ 'type': {'key': 'type', 'type': 'str'},\n+ 'e_tag': {'key': 'eTag', 'type': 'str'},\n+ }\n+\n+ def __init__(self, e_tag=None):\n+ super(ProxyResource, self).__init__()\n+ self.id = None\n+ self.name = None\n+ self.type = None\n+ self.e_tag = e_tag"},{"sha":"cb1dff45a8f9ca787f34422829a20b142a1b9339","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/__init__.py","status":"modified","additions":6,"deletions":0,"changes":6,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/__init__.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/__init__.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/__init__.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -10,13 +10,19 @@\n # --------------------------------------------------------------------------\n \n from .usage_details_operations import UsageDetailsOperations\n+from .marketplaces_operations import MarketplacesOperations\n from .reservations_summaries_operations import ReservationsSummariesOperations\n from .reservations_details_operations import ReservationsDetailsOperations\n+from .budgets_operations import BudgetsOperations\n from .operations import Operations\n+from .price_sheet_operations import PriceSheetOperations\n \n __all__ = [\n 'UsageDetailsOperations',\n+ 'MarketplacesOperations',\n 'ReservationsSummariesOperations',\n 'ReservationsDetailsOperations',\n+ 'BudgetsOperations',\n 'Operations',\n+ 'PriceSheetOperations',\n ]"},{"sha":"38562f5af055bad608bd52aee7804a97040fab44","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/budgets_operations.py","status":"added","additions":514,"deletions":0,"changes":514,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/budgets_operations.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/budgets_operations.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/budgets_operations.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,514 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+import uuid\n+from msrest.pipeline import ClientRawResponse\n+\n+from .. import models\n+\n+\n+class BudgetsOperations(object):\n+ \"\"\"BudgetsOperations operations.\n+\n+ :param client: Client for service requests.\n+ :param config: Configuration of service client.\n+ :param serializer: An object model serializer.\n+ :param deserializer: An objec model deserializer.\n+ :ivar api_version: Version of the API to be used with the client request. The current version is 2018-01-31. Constant value: \"2018-01-31\".\n+ \"\"\"\n+\n+ models = models\n+\n+ def __init__(self, client, config, serializer, deserializer):\n+\n+ self._client = client\n+ self._serialize = serializer\n+ self._deserialize = deserializer\n+ self.api_version = \"2018-01-31\"\n+\n+ self.config = config\n+\n+ def list(\n+ self, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Lists all budgets for a subscription.\n+\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: An iterator like instance of Budget\n+ :rtype:\n+ ~azure.mgmt.consumption.models.BudgetPaged[~azure.mgmt.consumption.models.Budget]\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ def internal_paging(next_link=None, raw=False):\n+\n+ if not next_link:\n+ # Construct URL\n+ url = '/subscriptions/{subscriptionId}/providers/Microsoft.Consumption/budgets'\n+ path_format_arguments = {\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ else:\n+ url = next_link\n+ query_parameters = {}\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(\n+ request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ return response\n+\n+ # Deserialize response\n+ deserialized = models.BudgetPaged(internal_paging, self._deserialize.dependencies)\n+\n+ if raw:\n+ header_dict = {}\n+ client_raw_response = models.BudgetPaged(internal_paging, self._deserialize.dependencies, header_dict)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def list_by_resource_group_name(\n+ self, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Lists all budgets for a resource group under a subscription.\n+\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: An iterator like instance of Budget\n+ :rtype:\n+ ~azure.mgmt.consumption.models.BudgetPaged[~azure.mgmt.consumption.models.Budget]\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ def internal_paging(next_link=None, raw=False):\n+\n+ if not next_link:\n+ # Construct URL\n+ url = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Consumption/budgets'\n+ path_format_arguments = {\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str'),\n+ 'resourceGroupName': self._serialize.url(\"self.config.resource_group_name\", self.config.resource_group_name, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ else:\n+ url = next_link\n+ query_parameters = {}\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(\n+ request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ return response\n+\n+ # Deserialize response\n+ deserialized = models.BudgetPaged(internal_paging, self._deserialize.dependencies)\n+\n+ if raw:\n+ header_dict = {}\n+ client_raw_response = models.BudgetPaged(internal_paging, self._deserialize.dependencies, header_dict)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def get(\n+ self, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Gets the budget for a subscription by budget name.\n+\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: Budget or ClientRawResponse if raw=true\n+ :rtype: ~azure.mgmt.consumption.models.Budget or\n+ ~msrest.pipeline.ClientRawResponse\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ # Construct URL\n+ url = '/subscriptions/{subscriptionId}/providers/Microsoft.Consumption/budgets/{budgetName}'\n+ path_format_arguments = {\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str'),\n+ 'budgetName': self._serialize.url(\"self.config.budget_name\", self.config.budget_name, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ deserialized = None\n+\n+ if response.status_code == 200:\n+ deserialized = self._deserialize('Budget', response)\n+\n+ if raw:\n+ client_raw_response = ClientRawResponse(deserialized, response)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def create_or_update(\n+ self, parameters, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"The operation to create or update a budget. Update operation requires\n+ latest eTag to be set in the request mandatorily. You may obtain the\n+ latest eTag by performing a get operation. Create operation does not\n+ require eTag.\n+\n+ :param parameters: Parameters supplied to the Create Budget operation.\n+ :type parameters: ~azure.mgmt.consumption.models.Budget\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: An iterator like instance of None\n+ :rtype: ~azure.mgmt.consumption.models.Budget[None]\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ def internal_paging(next_link=None, raw=False):\n+\n+ if not next_link:\n+ # Construct URL\n+ url = '/subscriptions/{subscriptionId}/providers/Microsoft.Consumption/budgets/{budgetName}'\n+ path_format_arguments = {\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str'),\n+ 'budgetName': self._serialize.url(\"self.config.budget_name\", self.config.budget_name, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ else:\n+ url = next_link\n+ query_parameters = {}\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct body\n+ body_content = self._serialize.body(parameters, 'Budget')\n+\n+ # Construct and send request\n+ request = self._client.put(url, query_parameters)\n+ response = self._client.send(\n+ request, header_parameters, body_content, stream=False, **operation_config)\n+\n+ if response.status_code not in [200, 201]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ return response\n+\n+ # Deserialize response\n+ deserialized = models.Budget(internal_paging, self._deserialize.dependencies)\n+\n+ if raw:\n+ header_dict = {}\n+ client_raw_response = models.Budget(internal_paging, self._deserialize.dependencies, header_dict)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def delete(\n+ self, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"The operation to delete a budget.\n+\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: None or ClientRawResponse if raw=true\n+ :rtype: None or ~msrest.pipeline.ClientRawResponse\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ # Construct URL\n+ url = '/subscriptions/{subscriptionId}/providers/Microsoft.Consumption/budgets/{budgetName}'\n+ path_format_arguments = {\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str'),\n+ 'budgetName': self._serialize.url(\"self.config.budget_name\", self.config.budget_name, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.delete(url, query_parameters)\n+ response = self._client.send(request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ if raw:\n+ client_raw_response = ClientRawResponse(None, response)\n+ return client_raw_response\n+\n+ def get_by_resource_group_name(\n+ self, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Gets the budget for a resource group under a subscription by budget\n+ name.\n+\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: Budget or ClientRawResponse if raw=true\n+ :rtype: ~azure.mgmt.consumption.models.Budget or\n+ ~msrest.pipeline.ClientRawResponse\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ # Construct URL\n+ url = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Consumption/budgets/{budgetName}'\n+ path_format_arguments = {\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str'),\n+ 'resourceGroupName': self._serialize.url(\"self.config.resource_group_name\", self.config.resource_group_name, 'str'),\n+ 'budgetName': self._serialize.url(\"self.config.budget_name\", self.config.budget_name, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ deserialized = None\n+\n+ if response.status_code == 200:\n+ deserialized = self._deserialize('Budget', response)\n+\n+ if raw:\n+ client_raw_response = ClientRawResponse(deserialized, response)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def create_or_update_by_resource_group_name(\n+ self, parameters, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"The operation to create or update a budget. Update operation requires\n+ latest eTag to be set in the request mandatorily. You may obtain the\n+ latest eTag by performing a get operation. Create operation does not\n+ require eTag.\n+\n+ :param parameters: Parameters supplied to the Create Budget operation.\n+ :type parameters: ~azure.mgmt.consumption.models.Budget\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: An iterator like instance of None\n+ :rtype: ~azure.mgmt.consumption.models.Budget[None]\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ def internal_paging(next_link=None, raw=False):\n+\n+ if not next_link:\n+ # Construct URL\n+ url = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Consumption/budgets/{budgetName}'\n+ path_format_arguments = {\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str'),\n+ 'resourceGroupName': self._serialize.url(\"self.config.resource_group_name\", self.config.resource_group_name, 'str'),\n+ 'budgetName': self._serialize.url(\"self.config.budget_name\", self.config.budget_name, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ else:\n+ url = next_link\n+ query_parameters = {}\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct body\n+ body_content = self._serialize.body(parameters, 'Budget')\n+\n+ # Construct and send request\n+ request = self._client.put(url, query_parameters)\n+ response = self._client.send(\n+ request, header_parameters, body_content, stream=False, **operation_config)\n+\n+ if response.status_code not in [200, 201]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ return response\n+\n+ # Deserialize response\n+ deserialized = models.Budget(internal_paging, self._deserialize.dependencies)\n+\n+ if raw:\n+ header_dict = {}\n+ client_raw_response = models.Budget(internal_paging, self._deserialize.dependencies, header_dict)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def delete_by_resource_group_name(\n+ self, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"The operation to delete a budget.\n+\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: None or ClientRawResponse if raw=true\n+ :rtype: None or ~msrest.pipeline.ClientRawResponse\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ # Construct URL\n+ url = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Consumption/budgets/{budgetName}'\n+ path_format_arguments = {\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str'),\n+ 'resourceGroupName': self._serialize.url(\"self.config.resource_group_name\", self.config.resource_group_name, 'str'),\n+ 'budgetName': self._serialize.url(\"self.config.budget_name\", self.config.budget_name, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.delete(url, query_parameters)\n+ response = self._client.send(request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ if raw:\n+ client_raw_response = ClientRawResponse(None, response)\n+ return client_raw_response"},{"sha":"e74aa82ad6ec36fee8e4c10903efe7a5d5e9a584","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/marketplaces_operations.py","status":"added","additions":209,"deletions":0,"changes":209,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/marketplaces_operations.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/marketplaces_operations.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/marketplaces_operations.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,209 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+import uuid\n+from msrest.pipeline import ClientRawResponse\n+\n+from .. import models\n+\n+\n+class MarketplacesOperations(object):\n+ \"\"\"MarketplacesOperations operations.\n+\n+ :param client: Client for service requests.\n+ :param config: Configuration of service client.\n+ :param serializer: An object model serializer.\n+ :param deserializer: An objec model deserializer.\n+ :ivar api_version: Version of the API to be used with the client request. The current version is 2018-01-31. Constant value: \"2018-01-31\".\n+ \"\"\"\n+\n+ models = models\n+\n+ def __init__(self, client, config, serializer, deserializer):\n+\n+ self._client = client\n+ self._serialize = serializer\n+ self._deserialize = deserializer\n+ self.api_version = \"2018-01-31\"\n+\n+ self.config = config\n+\n+ def list(\n+ self, filter=None, top=None, skiptoken=None, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Lists the marketplaces for a scope by subscriptionId. Marketplaces are\n+ available via this API only for May 1, 2014 or later.\n+\n+ :param filter: May be used to filter marketplaces by\n+ properties/usageEnd (Utc time), properties/usageStart (Utc time),\n+ properties/resourceGroup, properties/instanceName or\n+ properties/instanceId. The filter supports 'eq', 'lt', 'gt', 'le',\n+ 'ge', and 'and'. It does not currently support 'ne', 'or', or 'not'.\n+ :type filter: str\n+ :param top: May be used to limit the number of results to the most\n+ recent N marketplaces.\n+ :type top: int\n+ :param skiptoken: Skiptoken is only used if a previous operation\n+ returned a partial result. If a previous response contains a nextLink\n+ element, the value of the nextLink element will include a skiptoken\n+ parameter that specifies a starting point to use for subsequent calls.\n+ :type skiptoken: str\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: An iterator like instance of Marketplace\n+ :rtype:\n+ ~azure.mgmt.consumption.models.MarketplacePaged[~azure.mgmt.consumption.models.Marketplace]\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ def internal_paging(next_link=None, raw=False):\n+\n+ if not next_link:\n+ # Construct URL\n+ url = '/subscriptions/{subscriptionId}/providers/Microsoft.Consumption/marketplaces'\n+ path_format_arguments = {\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ if filter is not None:\n+ query_parameters['$filter'] = self._serialize.query(\"filter\", filter, 'str')\n+ if top is not None:\n+ query_parameters['$top'] = self._serialize.query(\"top\", top, 'int', maximum=1000, minimum=1)\n+ if skiptoken is not None:\n+ query_parameters['$skiptoken'] = self._serialize.query(\"skiptoken\", skiptoken, 'str')\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ else:\n+ url = next_link\n+ query_parameters = {}\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(\n+ request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ return response\n+\n+ # Deserialize response\n+ deserialized = models.MarketplacePaged(internal_paging, self._deserialize.dependencies)\n+\n+ if raw:\n+ header_dict = {}\n+ client_raw_response = models.MarketplacePaged(internal_paging, self._deserialize.dependencies, header_dict)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def list_by_billing_period(\n+ self, billing_period_name, filter=None, top=None, skiptoken=None, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Lists the marketplaces for a scope by billing period and\n+ subscripotionId. Marketplaces are available via this API only for May\n+ 1, 2014 or later.\n+\n+ :param billing_period_name: Billing Period Name.\n+ :type billing_period_name: str\n+ :param filter: May be used to filter marketplaces by\n+ properties/usageEnd (Utc time), properties/usageStart (Utc time),\n+ properties/resourceGroup, properties/instanceName or\n+ properties/instanceId. The filter supports 'eq', 'lt', 'gt', 'le',\n+ 'ge', and 'and'. It does not currently support 'ne', 'or', or 'not'.\n+ :type filter: str\n+ :param top: May be used to limit the number of results to the most\n+ recent N marketplaces.\n+ :type top: int\n+ :param skiptoken: Skiptoken is only used if a previous operation\n+ returned a partial result. If a previous response contains a nextLink\n+ element, the value of the nextLink element will include a skiptoken\n+ parameter that specifies a starting point to use for subsequent calls.\n+ :type skiptoken: str\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: An iterator like instance of Marketplace\n+ :rtype:\n+ ~azure.mgmt.consumption.models.MarketplacePaged[~azure.mgmt.consumption.models.Marketplace]\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ def internal_paging(next_link=None, raw=False):\n+\n+ if not next_link:\n+ # Construct URL\n+ url = '/subscriptions/{subscriptionId}/providers/Microsoft.Billing/billingPeriods/{billingPeriodName}/providers/Microsoft.Consumption/marketplaces'\n+ path_format_arguments = {\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str'),\n+ 'billingPeriodName': self._serialize.url(\"billing_period_name\", billing_period_name, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ if filter is not None:\n+ query_parameters['$filter'] = self._serialize.query(\"filter\", filter, 'str')\n+ if top is not None:\n+ query_parameters['$top'] = self._serialize.query(\"top\", top, 'int', maximum=1000, minimum=1)\n+ if skiptoken is not None:\n+ query_parameters['$skiptoken'] = self._serialize.query(\"skiptoken\", skiptoken, 'str')\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ else:\n+ url = next_link\n+ query_parameters = {}\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(\n+ request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ return response\n+\n+ # Deserialize response\n+ deserialized = models.MarketplacePaged(internal_paging, self._deserialize.dependencies)\n+\n+ if raw:\n+ header_dict = {}\n+ client_raw_response = models.MarketplacePaged(internal_paging, self._deserialize.dependencies, header_dict)\n+ return client_raw_response\n+\n+ return deserialized"},{"sha":"f3efdae1c20868aef1cbad552979edb11f41663f","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/operations.py","status":"modified","additions":3,"deletions":3,"changes":6,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/operations.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/operations.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/operations.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -22,7 +22,7 @@ class Operations(object):\n :param config: Configuration of service client.\n :param serializer: An object model serializer.\n :param deserializer: An objec model deserializer.\n- :ivar api_version: Version of the API to be used with the client request. The current version is 2017-11-30. Constant value: \"2017-11-30\".\n+ :ivar api_version: Version of the API to be used with the client request. The current version is 2018-01-31. Constant value: \"2018-01-31\".\n \"\"\"\n \n models = models\n@@ -32,7 +32,7 @@ def __init__(self, client, config, serializer, deserializer):\n self._client = client\n self._serialize = serializer\n self._deserialize = deserializer\n- self.api_version = \"2017-11-30\"\n+ self.api_version = \"2018-01-31\"\n \n self.config = config\n \n@@ -78,7 +78,7 @@ def internal_paging(next_link=None, raw=False):\n # Construct and send request\n request = self._client.get(url, query_parameters)\n response = self._client.send(\n- request, header_parameters, **operation_config)\n+ request, header_parameters, stream=False, **operation_config)\n \n if response.status_code not in [200]:\n raise models.ErrorResponseException(self._deserialize, response)"},{"sha":"701320c573d314526b127b4b3e5f8233852ad8b1","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/price_sheet_operations.py","status":"added","additions":176,"deletions":0,"changes":176,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/price_sheet_operations.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/price_sheet_operations.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/price_sheet_operations.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -0,0 +1,176 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+import uuid\n+from msrest.pipeline import ClientRawResponse\n+\n+from .. import models\n+\n+\n+class PriceSheetOperations(object):\n+ \"\"\"PriceSheetOperations operations.\n+\n+ :param client: Client for service requests.\n+ :param config: Configuration of service client.\n+ :param serializer: An object model serializer.\n+ :param deserializer: An objec model deserializer.\n+ :ivar api_version: Version of the API to be used with the client request. The current version is 2018-01-31. Constant value: \"2018-01-31\".\n+ \"\"\"\n+\n+ models = models\n+\n+ def __init__(self, client, config, serializer, deserializer):\n+\n+ self._client = client\n+ self._serialize = serializer\n+ self._deserialize = deserializer\n+ self.api_version = \"2018-01-31\"\n+\n+ self.config = config\n+\n+ def list(\n+ self, expand=None, skiptoken=None, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Lists the price sheet for a scope by subscriptionId. Price sheets are\n+ available via this API only for May 1, 2014 or later.\n+\n+ :param expand: May be used to expand the properties/meterDetails\n+ within a price sheet. By default, these fields are not included when\n+ returning price sheet.\n+ :type expand: str\n+ :param skiptoken: Skiptoken is only used if a previous operation\n+ returned a partial result. If a previous response contains a nextLink\n+ element, the value of the nextLink element will include a skiptoken\n+ parameter that specifies a starting point to use for subsequent calls.\n+ :type skiptoken: str\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: PriceSheetListResult or ClientRawResponse if raw=true\n+ :rtype: ~azure.mgmt.consumption.models.PriceSheetListResult or\n+ ~msrest.pipeline.ClientRawResponse\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ # Construct URL\n+ url = '/subscriptions/{subscriptionId}/providers/Microsoft.Consumption/pricesheets/default'\n+ path_format_arguments = {\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ if expand is not None:\n+ query_parameters['$expand'] = self._serialize.query(\"expand\", expand, 'str')\n+ if skiptoken is not None:\n+ query_parameters['$skiptoken'] = self._serialize.query(\"skiptoken\", skiptoken, 'str')\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ deserialized = None\n+\n+ if response.status_code == 200:\n+ deserialized = self._deserialize('PriceSheetListResult', response)\n+\n+ if raw:\n+ client_raw_response = ClientRawResponse(deserialized, response)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def list_by_billing_period(\n+ self, billing_period_name, expand=None, skiptoken=None, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Lists the price sheet for a scope by subscriptionId and billing period.\n+ Price sheets are available via this API only for May 1, 2014 or later.\n+\n+ :param billing_period_name: Billing Period Name.\n+ :type billing_period_name: str\n+ :param expand: May be used to expand the properties/meterDetails\n+ within a price sheet. By default, these fields are not included when\n+ returning price sheet.\n+ :type expand: str\n+ :param skiptoken: Skiptoken is only used if a previous operation\n+ returned a partial result. If a previous response contains a nextLink\n+ element, the value of the nextLink element will include a skiptoken\n+ parameter that specifies a starting point to use for subsequent calls.\n+ :type skiptoken: str\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: PriceSheetListResult or ClientRawResponse if raw=true\n+ :rtype: ~azure.mgmt.consumption.models.PriceSheetListResult or\n+ ~msrest.pipeline.ClientRawResponse\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ # Construct URL\n+ url = '/subscriptions/{subscriptionId}/providers/Microsoft.Billing/billingPeriods/{billingPeriodName}/providers/Microsoft.Consumption/pricesheets/default'\n+ path_format_arguments = {\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str'),\n+ 'billingPeriodName': self._serialize.url(\"billing_period_name\", billing_period_name, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ if expand is not None:\n+ query_parameters['$expand'] = self._serialize.query(\"expand\", expand, 'str')\n+ if skiptoken is not None:\n+ query_parameters['$skiptoken'] = self._serialize.query(\"skiptoken\", skiptoken, 'str')\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ deserialized = None\n+\n+ if response.status_code == 200:\n+ deserialized = self._deserialize('PriceSheetListResult', response)\n+\n+ if raw:\n+ client_raw_response = ClientRawResponse(deserialized, response)\n+ return client_raw_response\n+\n+ return deserialized"},{"sha":"485bb51bf4eb5333baf96a44f51ae286faabb00c","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_details_operations.py","status":"modified","additions":82,"deletions":12,"changes":94,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_details_operations.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_details_operations.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_details_operations.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -22,7 +22,7 @@ class ReservationsDetailsOperations(object):\n :param config: Configuration of service client.\n :param serializer: An object model serializer.\n :param deserializer: An objec model deserializer.\n- :ivar api_version: Version of the API to be used with the client request. The current version is 2017-11-30. Constant value: \"2017-11-30\".\n+ :ivar api_version: Version of the API to be used with the client request. The current version is 2018-01-31. Constant value: \"2018-01-31\".\n \"\"\"\n \n models = models\n@@ -32,19 +32,16 @@ def __init__(self, client, config, serializer, deserializer):\n self._client = client\n self._serialize = serializer\n self._deserialize = deserializer\n- self.api_version = \"2017-11-30\"\n+ self.api_version = \"2018-01-31\"\n \n self.config = config\n \n- def list(\n- self, scope, filter, custom_headers=None, raw=False, **operation_config):\n+ def list_by_reservation_order(\n+ self, reservation_order_id, filter, custom_headers=None, raw=False, **operation_config):\n \"\"\"Lists the reservations details for provided date range.\n \n- :param scope: The scope of the reservation details. The scope can be\n- 'providers/Microsoft.Capacity/reservationorders/{ReservationOrderId}'\n- or\n- 'providers/Microsoft.Capacity/reservationorders/{ReservationOrderId}/reservations/{ReservationId}'\n- :type scope: str\n+ :param reservation_order_id: Order Id of the reservation\n+ :type reservation_order_id: str\n :param filter: Filter reservation details by date range. The\n properties/UsageDate for start date and end date. The filter supports\n 'le' and 'ge'\n@@ -64,9 +61,9 @@ def internal_paging(next_link=None, raw=False):\n \n if not next_link:\n # Construct URL\n- url = '/{scope}/providers/Microsoft.Consumption/reservationDetails'\n+ url = '/providers/Microsoft.Capacity/reservationorders/{reservationOrderId}/providers/Microsoft.Consumption/reservationDetails'\n path_format_arguments = {\n- 'scope': self._serialize.url(\"scope\", scope, 'str', skip_quote=True)\n+ 'reservationOrderId': self._serialize.url(\"reservation_order_id\", reservation_order_id, 'str')\n }\n url = self._client.format_url(url, **path_format_arguments)\n \n@@ -92,7 +89,80 @@ def internal_paging(next_link=None, raw=False):\n # Construct and send request\n request = self._client.get(url, query_parameters)\n response = self._client.send(\n- request, header_parameters, **operation_config)\n+ request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ return response\n+\n+ # Deserialize response\n+ deserialized = models.ReservationDetailsPaged(internal_paging, self._deserialize.dependencies)\n+\n+ if raw:\n+ header_dict = {}\n+ client_raw_response = models.ReservationDetailsPaged(internal_paging, self._deserialize.dependencies, header_dict)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def list_by_reservation_order_and_reservation(\n+ self, reservation_order_id, reservation_id, filter, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Lists the reservations details for provided date range.\n+\n+ :param reservation_order_id: Order Id of the reservation\n+ :type reservation_order_id: str\n+ :param reservation_id: Id of the reservation\n+ :type reservation_id: str\n+ :param filter: Filter reservation details by date range. The\n+ properties/UsageDate for start date and end date. The filter supports\n+ 'le' and 'ge'\n+ :type filter: str\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: An iterator like instance of ReservationDetails\n+ :rtype:\n+ ~azure.mgmt.consumption.models.ReservationDetailsPaged[~azure.mgmt.consumption.models.ReservationDetails]\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ def internal_paging(next_link=None, raw=False):\n+\n+ if not next_link:\n+ # Construct URL\n+ url = '/providers/Microsoft.Capacity/reservationorders/{reservationOrderId}/reservations/{reservationId}/providers/Microsoft.Consumption/reservationDetails'\n+ path_format_arguments = {\n+ 'reservationOrderId': self._serialize.url(\"reservation_order_id\", reservation_order_id, 'str'),\n+ 'reservationId': self._serialize.url(\"reservation_id\", reservation_id, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['$filter'] = self._serialize.query(\"filter\", filter, 'str')\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ else:\n+ url = next_link\n+ query_parameters = {}\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(\n+ request, header_parameters, stream=False, **operation_config)\n \n if response.status_code not in [200]:\n raise models.ErrorResponseException(self._deserialize, response)"},{"sha":"2c1c2b451318b518d75a578a83e49e5597c6be6d","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_summaries_operations.py","status":"modified","additions":86,"deletions":12,"changes":98,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_summaries_operations.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_summaries_operations.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_summaries_operations.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -22,7 +22,7 @@ class ReservationsSummariesOperations(object):\n :param config: Configuration of service client.\n :param serializer: An object model serializer.\n :param deserializer: An objec model deserializer.\n- :ivar api_version: Version of the API to be used with the client request. The current version is 2017-11-30. Constant value: \"2017-11-30\".\n+ :ivar api_version: Version of the API to be used with the client request. The current version is 2018-01-31. Constant value: \"2018-01-31\".\n \"\"\"\n \n models = models\n@@ -32,19 +32,16 @@ def __init__(self, client, config, serializer, deserializer):\n self._client = client\n self._serialize = serializer\n self._deserialize = deserializer\n- self.api_version = \"2017-11-30\"\n+ self.api_version = \"2018-01-31\"\n \n self.config = config\n \n- def list(\n- self, scope, grain, filter=None, custom_headers=None, raw=False, **operation_config):\n+ def list_by_reservation_order(\n+ self, reservation_order_id, grain, filter=None, custom_headers=None, raw=False, **operation_config):\n \"\"\"Lists the reservations summaries for daily or monthly grain.\n \n- :param scope: The scope of the reservation summaries. The scope can be\n- 'providers/Microsoft.Capacity/reservationorders/{ReservationOrderId}'\n- or\n- 'providers/Microsoft.Capacity/reservationorders/{ReservationOrderId}/reservations/{ReservationId}'\n- :type scope: str\n+ :param reservation_order_id: Order Id of the reservation\n+ :type reservation_order_id: str\n :param grain: Can be daily or monthly. Possible values include:\n 'DailyGrain', 'MonthlyGrain'\n :type grain: str or ~azure.mgmt.consumption.models.Datagrain\n@@ -66,9 +63,9 @@ def internal_paging(next_link=None, raw=False):\n \n if not next_link:\n # Construct URL\n- url = '/{scope}/providers/Microsoft.Consumption/reservationSummaries'\n+ url = '/providers/Microsoft.Capacity/reservationorders/{reservationOrderId}/providers/Microsoft.Consumption/reservationSummaries'\n path_format_arguments = {\n- 'scope': self._serialize.url(\"scope\", scope, 'str', skip_quote=True)\n+ 'reservationOrderId': self._serialize.url(\"reservation_order_id\", reservation_order_id, 'str')\n }\n url = self._client.format_url(url, **path_format_arguments)\n \n@@ -96,7 +93,84 @@ def internal_paging(next_link=None, raw=False):\n # Construct and send request\n request = self._client.get(url, query_parameters)\n response = self._client.send(\n- request, header_parameters, **operation_config)\n+ request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ return response\n+\n+ # Deserialize response\n+ deserialized = models.ReservationSummariesPaged(internal_paging, self._deserialize.dependencies)\n+\n+ if raw:\n+ header_dict = {}\n+ client_raw_response = models.ReservationSummariesPaged(internal_paging, self._deserialize.dependencies, header_dict)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def list_by_reservation_order_and_reservation(\n+ self, reservation_order_id, reservation_id, grain, filter=None, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Lists the reservations summaries for daily or monthly grain.\n+\n+ :param reservation_order_id: Order Id of the reservation\n+ :type reservation_order_id: str\n+ :param reservation_id: Id of the reservation\n+ :type reservation_id: str\n+ :param grain: Can be daily or monthly. Possible values include:\n+ 'DailyGrain', 'MonthlyGrain'\n+ :type grain: str or ~azure.mgmt.consumption.models.Datagrain\n+ :param filter: Required only for daily grain. The properties/UsageDate\n+ for start date and end date. The filter supports 'le' and 'ge'\n+ :type filter: str\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: An iterator like instance of ReservationSummaries\n+ :rtype:\n+ ~azure.mgmt.consumption.models.ReservationSummariesPaged[~azure.mgmt.consumption.models.ReservationSummaries]\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ def internal_paging(next_link=None, raw=False):\n+\n+ if not next_link:\n+ # Construct URL\n+ url = '/providers/Microsoft.Capacity/reservationorders/{reservationOrderId}/reservations/{reservationId}/providers/Microsoft.Consumption/reservationSummaries'\n+ path_format_arguments = {\n+ 'reservationOrderId': self._serialize.url(\"reservation_order_id\", reservation_order_id, 'str'),\n+ 'reservationId': self._serialize.url(\"reservation_id\", reservation_id, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['grain'] = self._serialize.query(\"grain\", grain, 'str')\n+ if filter is not None:\n+ query_parameters['$filter'] = self._serialize.query(\"filter\", filter, 'str')\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ else:\n+ url = next_link\n+ query_parameters = {}\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(\n+ request, header_parameters, stream=False, **operation_config)\n \n if response.status_code not in [200]:\n raise models.ErrorResponseException(self._deserialize, response)"},{"sha":"a0f6cd91bd084879c4ac7e89959d2231a4b5795e","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/usage_details_operations.py","status":"modified","additions":100,"deletions":11,"changes":111,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/usage_details_operations.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/operations/usage_details_operations.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/usage_details_operations.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -22,7 +22,7 @@ class UsageDetailsOperations(object):\n :param config: Configuration of service client.\n :param serializer: An object model serializer.\n :param deserializer: An objec model deserializer.\n- :ivar api_version: Version of the API to be used with the client request. The current version is 2017-11-30. Constant value: \"2017-11-30\".\n+ :ivar api_version: Version of the API to be used with the client request. The current version is 2018-01-31. Constant value: \"2018-01-31\".\n \"\"\"\n \n models = models\n@@ -32,20 +32,15 @@ def __init__(self, client, config, serializer, deserializer):\n self._client = client\n self._serialize = serializer\n self._deserialize = deserializer\n- self.api_version = \"2017-11-30\"\n+ self.api_version = \"2018-01-31\"\n \n self.config = config\n \n def list(\n- self, scope, expand=None, filter=None, skiptoken=None, top=None, custom_headers=None, raw=False, **operation_config):\n+ self, expand=None, filter=None, skiptoken=None, top=None, custom_headers=None, raw=False, **operation_config):\n \"\"\"Lists the usage details for a scope by billing period. Usage details\n are available via this API only for May 1, 2014 or later.\n \n- :param scope: The scope of the usage details. The scope can be\n- '/subscriptions/{subscriptionId}' for a subscription, or\n- '/subscriptions/{subscriptionId}/providers/Microsoft.Billing/billingPeriods/{billingPeriodName}'\n- for a billing perdiod.\n- :type scope: str\n :param expand: May be used to expand the\n properties/additionalProperties or properties/meterDetails within a\n list of usage details. By default, these fields are not included when\n@@ -80,9 +75,9 @@ def internal_paging(next_link=None, raw=False):\n \n if not next_link:\n # Construct URL\n- url = '/{scope}/providers/Microsoft.Consumption/usageDetails'\n+ url = '/subscriptions/{subscriptionId}/providers/Microsoft.Consumption/usageDetails'\n path_format_arguments = {\n- 'scope': self._serialize.url(\"scope\", scope, 'str', skip_quote=True)\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str')\n }\n url = self._client.format_url(url, **path_format_arguments)\n \n@@ -115,7 +110,101 @@ def internal_paging(next_link=None, raw=False):\n # Construct and send request\n request = self._client.get(url, query_parameters)\n response = self._client.send(\n- request, header_parameters, **operation_config)\n+ request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ return response\n+\n+ # Deserialize response\n+ deserialized = models.UsageDetailPaged(internal_paging, self._deserialize.dependencies)\n+\n+ if raw:\n+ header_dict = {}\n+ client_raw_response = models.UsageDetailPaged(internal_paging, self._deserialize.dependencies, header_dict)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def list_by_billing_period(\n+ self, billing_period_name, expand=None, filter=None, skiptoken=None, top=None, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Lists the usage details for a scope by billing period. Usage details\n+ are available via this API only for May 1, 2014 or later.\n+\n+ :param billing_period_name: Billing Period Name.\n+ :type billing_period_name: str\n+ :param expand: May be used to expand the\n+ properties/additionalProperties or properties/meterDetails within a\n+ list of usage details. By default, these fields are not included when\n+ listing usage details.\n+ :type expand: str\n+ :param filter: May be used to filter usageDetails by\n+ properties/usageEnd (Utc time), properties/usageStart (Utc time),\n+ properties/resourceGroup, properties/instanceName or\n+ properties/instanceId. The filter supports 'eq', 'lt', 'gt', 'le',\n+ 'ge', and 'and'. It does not currently support 'ne', 'or', or 'not'.\n+ :type filter: str\n+ :param skiptoken: Skiptoken is only used if a previous operation\n+ returned a partial result. If a previous response contains a nextLink\n+ element, the value of the nextLink element will include a skiptoken\n+ parameter that specifies a starting point to use for subsequent calls.\n+ :type skiptoken: str\n+ :param top: May be used to limit the number of results to the most\n+ recent N usageDetails.\n+ :type top: int\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: An iterator like instance of UsageDetail\n+ :rtype:\n+ ~azure.mgmt.consumption.models.UsageDetailPaged[~azure.mgmt.consumption.models.UsageDetail]\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ def internal_paging(next_link=None, raw=False):\n+\n+ if not next_link:\n+ # Construct URL\n+ url = '/subscriptions/{subscriptionId}/providers/Microsoft.Billing/billingPeriods/{billingPeriodName}/providers/Microsoft.Consumption/usageDetails'\n+ path_format_arguments = {\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str'),\n+ 'billingPeriodName': self._serialize.url(\"billing_period_name\", billing_period_name, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ if expand is not None:\n+ query_parameters['$expand'] = self._serialize.query(\"expand\", expand, 'str')\n+ if filter is not None:\n+ query_parameters['$filter'] = self._serialize.query(\"filter\", filter, 'str')\n+ if skiptoken is not None:\n+ query_parameters['$skiptoken'] = self._serialize.query(\"skiptoken\", skiptoken, 'str')\n+ if top is not None:\n+ query_parameters['$top'] = self._serialize.query(\"top\", top, 'int', maximum=1000, minimum=1)\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ else:\n+ url = next_link\n+ query_parameters = {}\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(\n+ request, header_parameters, stream=False, **operation_config)\n \n if response.status_code not in [200]:\n raise models.ErrorResponseException(self._deserialize, response)"},{"sha":"9c644827672b274106be6000914f998e7e703574","filename":"azure-mgmt-consumption/azure/mgmt/consumption/version.py","status":"modified","additions":1,"deletions":1,"changes":2,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/version.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/3d6c419cd2ade53c240c40db96dbe34957351244/azure-mgmt-consumption/azure/mgmt/consumption/version.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/version.py?ref=3d6c419cd2ade53c240c40db96dbe34957351244","patch":"@@ -9,5 +9,5 @@\n # regenerated.\n # --------------------------------------------------------------------------\n \n-VERSION = \"1.1.0\"\n+VERSION = \"1.2.0\"\n "}]
+
+https
+GET
+api.github.com
+None
+/repos/Azure/azure-sdk-for-python/commits/042b7a5840ff471776bb64e46b50950ee9f84430
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:38 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4773'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"dc862e28bdff24590d33c5d927a64947"'), ('Last-Modified', 'Thu, 25 Jan 2018 19:40:02 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.277675'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '1714:97BA:C92467:104F1B5:5AFDF3CA')]
+{"sha":"042b7a5840ff471776bb64e46b50950ee9f84430","commit":{"author":{"name":"Azure SDK for Python bot","email":"aspysdk2@microsoft.com","date":"2018-01-25T19:40:02Z"},"committer":{"name":"Azure SDK for Python bot","email":"aspysdk2@microsoft.com","date":"2018-01-25T19:40:02Z"},"message":"Generated from a59b564eca116f99d057c9758d0dd40393ce75b7\n\nIntroduce Pricesheet Arm API","tree":{"sha":"a6d63b3754e7f65c6a4fbed3d3e9c5a2d72ce778","url":"https://api.github.com/repos/Azure/azure-sdk-for-python/git/trees/a6d63b3754e7f65c6a4fbed3d3e9c5a2d72ce778"},"url":"https://api.github.com/repos/Azure/azure-sdk-for-python/git/commits/042b7a5840ff471776bb64e46b50950ee9f84430","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null}},"url":"https://api.github.com/repos/Azure/azure-sdk-for-python/commits/042b7a5840ff471776bb64e46b50950ee9f84430","html_url":"https://github.com/Azure/azure-sdk-for-python/commit/042b7a5840ff471776bb64e46b50950ee9f84430","comments_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/commits/042b7a5840ff471776bb64e46b50950ee9f84430/comments","author":{"login":"AutorestCI","id":18218145,"avatar_url":"https://avatars3.githubusercontent.com/u/18218145?v=4","gravatar_id":"","url":"https://api.github.com/users/AutorestCI","html_url":"https://github.com/AutorestCI","followers_url":"https://api.github.com/users/AutorestCI/followers","following_url":"https://api.github.com/users/AutorestCI/following{/other_user}","gists_url":"https://api.github.com/users/AutorestCI/gists{/gist_id}","starred_url":"https://api.github.com/users/AutorestCI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AutorestCI/subscriptions","organizations_url":"https://api.github.com/users/AutorestCI/orgs","repos_url":"https://api.github.com/users/AutorestCI/repos","events_url":"https://api.github.com/users/AutorestCI/events{/privacy}","received_events_url":"https://api.github.com/users/AutorestCI/received_events","type":"User","site_admin":false},"committer":{"login":"AutorestCI","id":18218145,"avatar_url":"https://avatars3.githubusercontent.com/u/18218145?v=4","gravatar_id":"","url":"https://api.github.com/users/AutorestCI","html_url":"https://github.com/AutorestCI","followers_url":"https://api.github.com/users/AutorestCI/followers","following_url":"https://api.github.com/users/AutorestCI/following{/other_user}","gists_url":"https://api.github.com/users/AutorestCI/gists{/gist_id}","starred_url":"https://api.github.com/users/AutorestCI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AutorestCI/subscriptions","organizations_url":"https://api.github.com/users/AutorestCI/orgs","repos_url":"https://api.github.com/users/AutorestCI/repos","events_url":"https://api.github.com/users/AutorestCI/events{/privacy}","received_events_url":"https://api.github.com/users/AutorestCI/received_events","type":"User","site_admin":false},"parents":[{"sha":"f4715da4f929733b2b95c03142512f85ae8728a5","url":"https://api.github.com/repos/Azure/azure-sdk-for-python/commits/f4715da4f929733b2b95c03142512f85ae8728a5","html_url":"https://github.com/Azure/azure-sdk-for-python/commit/f4715da4f929733b2b95c03142512f85ae8728a5"}],"stats":{"total":985,"additions":967,"deletions":18},"files":[{"sha":"55432c5a7edf83b2ce128aa764edf18e8bfb3149","filename":"azure-mgmt-consumption/azure/mgmt/consumption/consumption_management_client.py","status":"modified","additions":21,"deletions":4,"changes":25,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/consumption_management_client.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/consumption_management_client.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/consumption_management_client.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -16,7 +16,9 @@\n from .operations.usage_details_operations import UsageDetailsOperations\n from .operations.reservations_summaries_operations import ReservationsSummariesOperations\n from .operations.reservations_details_operations import ReservationsDetailsOperations\n+from .operations.budgets_operations import BudgetsOperations\n from .operations.operations import Operations\n+from .operations.price_sheet_operations import PriceSheetOperations\n from . import models\n \n \n@@ -30,16 +32,20 @@ class ConsumptionManagementClientConfiguration(AzureConfiguration):\n object`\n :param subscription_id: Azure Subscription ID.\n :type subscription_id: str\n+ :param name: Budget name.\n+ :type name: str\n :param str base_url: Service URL\n \"\"\"\n \n def __init__(\n- self, credentials, subscription_id, base_url=None):\n+ self, credentials, subscription_id, name, base_url=None):\n \n if credentials is None:\n raise ValueError(\"Parameter 'credentials' must not be None.\")\n if subscription_id is None:\n raise ValueError(\"Parameter 'subscription_id' must not be None.\")\n+ if name is None:\n+ raise ValueError(\"Parameter 'name' must not be None.\")\n if not base_url:\n base_url = 'https://management.azure.com'\n \n@@ -50,6 +56,7 @@ def __init__(\n \n self.credentials = credentials\n self.subscription_id = subscription_id\n+ self.name = name\n \n \n class ConsumptionManagementClient(object):\n@@ -64,25 +71,31 @@ class ConsumptionManagementClient(object):\n :vartype reservations_summaries: azure.mgmt.consumption.operations.ReservationsSummariesOperations\n :ivar reservations_details: ReservationsDetails operations\n :vartype reservations_details: azure.mgmt.consumption.operations.ReservationsDetailsOperations\n+ :ivar budgets: Budgets operations\n+ :vartype budgets: azure.mgmt.consumption.operations.BudgetsOperations\n :ivar operations: Operations operations\n :vartype operations: azure.mgmt.consumption.operations.Operations\n+ :ivar price_sheet: PriceSheet operations\n+ :vartype price_sheet: azure.mgmt.consumption.operations.PriceSheetOperations\n \n :param credentials: Credentials needed for the client to connect to Azure.\n :type credentials: :mod:`A msrestazure Credentials\n object`\n :param subscription_id: Azure Subscription ID.\n :type subscription_id: str\n+ :param name: Budget name.\n+ :type name: str\n :param str base_url: Service URL\n \"\"\"\n \n def __init__(\n- self, credentials, subscription_id, base_url=None):\n+ self, credentials, subscription_id, name, base_url=None):\n \n- self.config = ConsumptionManagementClientConfiguration(credentials, subscription_id, base_url)\n+ self.config = ConsumptionManagementClientConfiguration(credentials, subscription_id, name, base_url)\n self._client = ServiceClient(self.config.credentials, self.config)\n \n client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}\n- self.api_version = '2017-11-30'\n+ self.api_version = '2018-01-31'\n self._serialize = Serializer(client_models)\n self._deserialize = Deserializer(client_models)\n \n@@ -92,5 +105,9 @@ def __init__(\n self._client, self.config, self._serialize, self._deserialize)\n self.reservations_details = ReservationsDetailsOperations(\n self._client, self.config, self._serialize, self._deserialize)\n+ self.budgets = BudgetsOperations(\n+ self._client, self.config, self._serialize, self._deserialize)\n self.operations = Operations(\n self._client, self.config, self._serialize, self._deserialize)\n+ self.price_sheet = PriceSheetOperations(\n+ self._client, self.config, self._serialize, self._deserialize)"},{"sha":"2565b46a9d2b4dc2df7fa591699f866b2f496d1b","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/__init__.py","status":"modified","additions":24,"deletions":0,"changes":24,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/__init__.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/__init__.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/__init__.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -13,16 +13,28 @@\n from .usage_detail import UsageDetail\n from .reservation_summaries import ReservationSummaries\n from .reservation_details import ReservationDetails\n+from .budget_time_period import BudgetTimePeriod\n+from .filters import Filters\n+from .current_spend import CurrentSpend\n+from .notification import Notification\n+from .budget import Budget\n from .error_details import ErrorDetails\n from .error_response import ErrorResponse, ErrorResponseException\n from .operation_display import OperationDisplay\n from .operation import Operation\n from .resource import Resource\n+from .proxy_resource import ProxyResource\n+from .price_sheet import PriceSheet\n from .usage_detail_paged import UsageDetailPaged\n from .reservation_summaries_paged import ReservationSummariesPaged\n from .reservation_details_paged import ReservationDetailsPaged\n+from .budget_paged import BudgetPaged\n from .operation_paged import OperationPaged\n+from .price_sheet_paged import PriceSheetPaged\n from .consumption_management_client_enums import (\n+ CategoryType,\n+ TimeGrainType,\n+ OperatorType,\n Datagrain,\n )\n \n@@ -31,14 +43,26 @@\n 'UsageDetail',\n 'ReservationSummaries',\n 'ReservationDetails',\n+ 'BudgetTimePeriod',\n+ 'Filters',\n+ 'CurrentSpend',\n+ 'Notification',\n+ 'Budget',\n 'ErrorDetails',\n 'ErrorResponse', 'ErrorResponseException',\n 'OperationDisplay',\n 'Operation',\n 'Resource',\n+ 'ProxyResource',\n+ 'PriceSheet',\n 'UsageDetailPaged',\n 'ReservationSummariesPaged',\n 'ReservationDetailsPaged',\n+ 'BudgetPaged',\n 'OperationPaged',\n+ 'PriceSheetPaged',\n+ 'CategoryType',\n+ 'TimeGrainType',\n+ 'OperatorType',\n 'Datagrain',\n ]"},{"sha":"f6485d49266ddf2734c02ab55dceb9aba94bfe0a","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/budget.py","status":"added","additions":91,"deletions":0,"changes":91,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/budget.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/budget.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/budget.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -0,0 +1,91 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from .proxy_resource import ProxyResource\n+\n+\n+class Budget(ProxyResource):\n+ \"\"\"A budget resource.\n+\n+ Variables are only populated by the server, and will be ignored when\n+ sending a request.\n+\n+ :ivar id: Resource Id.\n+ :vartype id: str\n+ :ivar name: Resource name.\n+ :vartype name: str\n+ :ivar type: Resource type.\n+ :vartype type: str\n+ :param e_tag: eTag of the resource. To handle concurrent update scenarion,\n+ this field will be used to determine whether the user is updating the\n+ latest version or not.\n+ :type e_tag: str\n+ :param category: The category of the budget, whether the budget tracks\n+ cost or usage. Possible values include: 'Cost', 'Usage'\n+ :type category: str or ~azure.mgmt.consumption.models.CategoryType\n+ :param amount: The total amount of cost to track with the budget\n+ :type amount: decimal.Decimal\n+ :param time_grain: The time covered by a budget. Tracking of the amount\n+ will be reset based on the time grain. Possible values include: 'Monthly',\n+ 'Quarterly', 'Annually'\n+ :type time_grain: str or ~azure.mgmt.consumption.models.TimeGrainType\n+ :param time_period: Has start and end date of the budget. The start date\n+ must be first of the month and should be less than the end date. Budget\n+ start date must be on or after June 1, 2017. Future start date should not\n+ be more than three months. Past start date should be selected within the\n+ timegrain preiod. There are no restrictions on the end date.\n+ :type time_period: ~azure.mgmt.consumption.models.BudgetTimePeriod\n+ :param filters: May be used to filter budgets by resource group, resource,\n+ or meter.\n+ :type filters: ~azure.mgmt.consumption.models.Filters\n+ :ivar current_spend: The current amount of cost which is being tracked for\n+ a budget.\n+ :vartype current_spend: ~azure.mgmt.consumption.models.CurrentSpend\n+ :param notifications: Dictionary of notifications associated with the\n+ budget. Budget can have up to five notifications.\n+ :type notifications: dict[str,\n+ ~azure.mgmt.consumption.models.Notification]\n+ \"\"\"\n+\n+ _validation = {\n+ 'id': {'readonly': True},\n+ 'name': {'readonly': True},\n+ 'type': {'readonly': True},\n+ 'category': {'required': True},\n+ 'amount': {'required': True},\n+ 'time_grain': {'required': True},\n+ 'time_period': {'required': True},\n+ 'current_spend': {'readonly': True},\n+ }\n+\n+ _attribute_map = {\n+ 'id': {'key': 'id', 'type': 'str'},\n+ 'name': {'key': 'name', 'type': 'str'},\n+ 'type': {'key': 'type', 'type': 'str'},\n+ 'e_tag': {'key': 'eTag', 'type': 'str'},\n+ 'category': {'key': 'properties.category', 'type': 'str'},\n+ 'amount': {'key': 'properties.amount', 'type': 'decimal'},\n+ 'time_grain': {'key': 'properties.timeGrain', 'type': 'str'},\n+ 'time_period': {'key': 'properties.timePeriod', 'type': 'BudgetTimePeriod'},\n+ 'filters': {'key': 'properties.filters', 'type': 'Filters'},\n+ 'current_spend': {'key': 'properties.currentSpend', 'type': 'CurrentSpend'},\n+ 'notifications': {'key': 'properties.notifications', 'type': '{Notification}'},\n+ }\n+\n+ def __init__(self, category, amount, time_grain, time_period, e_tag=None, filters=None, notifications=None):\n+ super(Budget, self).__init__(e_tag=e_tag)\n+ self.category = category\n+ self.amount = amount\n+ self.time_grain = time_grain\n+ self.time_period = time_period\n+ self.filters = filters\n+ self.current_spend = None\n+ self.notifications = notifications"},{"sha":"2668382253e2d7aaefb8665a466d2482193e0246","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/budget_paged.py","status":"added","additions":27,"deletions":0,"changes":27,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/budget_paged.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/budget_paged.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/budget_paged.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -0,0 +1,27 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.paging import Paged\n+\n+\n+class BudgetPaged(Paged):\n+ \"\"\"\n+ A paging container for iterating over a list of :class:`Budget ` object\n+ \"\"\"\n+\n+ _attribute_map = {\n+ 'next_link': {'key': 'nextLink', 'type': 'str'},\n+ 'current_page': {'key': 'value', 'type': '[Budget]'}\n+ }\n+\n+ def __init__(self, *args, **kwargs):\n+\n+ super(BudgetPaged, self).__init__(*args, **kwargs)"},{"sha":"2b1c0e78418a1deb6b6147fc90ea53f1a03256d0","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/budget_time_period.py","status":"added","additions":37,"deletions":0,"changes":37,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/budget_time_period.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/budget_time_period.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/budget_time_period.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -0,0 +1,37 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.serialization import Model\n+\n+\n+class BudgetTimePeriod(Model):\n+ \"\"\"The start and end date for a budget.\n+\n+ :param start_date: The start date for the budget.\n+ :type start_date: datetime\n+ :param end_date: The end date for the budget. If not provided, we default\n+ this to 10 years from the start date.\n+ :type end_date: datetime\n+ \"\"\"\n+\n+ _validation = {\n+ 'start_date': {'required': True},\n+ }\n+\n+ _attribute_map = {\n+ 'start_date': {'key': 'startDate', 'type': 'iso-8601'},\n+ 'end_date': {'key': 'endDate', 'type': 'iso-8601'},\n+ }\n+\n+ def __init__(self, start_date, end_date=None):\n+ super(BudgetTimePeriod, self).__init__()\n+ self.start_date = start_date\n+ self.end_date = end_date"},{"sha":"bb0db82f76b32c1d02cca1de69b0ecc49b3b548b","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/consumption_management_client_enums.py","status":"modified","additions":20,"deletions":0,"changes":20,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/consumption_management_client_enums.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/consumption_management_client_enums.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/consumption_management_client_enums.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -12,6 +12,26 @@\n from enum import Enum\n \n \n+class CategoryType(Enum):\n+\n+ cost = \"Cost\"\n+ usage = \"Usage\"\n+\n+\n+class TimeGrainType(Enum):\n+\n+ monthly = \"Monthly\"\n+ quarterly = \"Quarterly\"\n+ annually = \"Annually\"\n+\n+\n+class OperatorType(Enum):\n+\n+ equal_to = \"EqualTo\"\n+ greater_than = \"GreaterThan\"\n+ greater_than_or_equal_to = \"GreaterThanOrEqualTo\"\n+\n+\n class Datagrain(Enum):\n \n daily_grain = \"daily\""},{"sha":"839c286b104079f531a4b130f3e01082d63d08ac","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/current_spend.py","status":"added","additions":41,"deletions":0,"changes":41,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/current_spend.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/current_spend.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/current_spend.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -0,0 +1,41 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.serialization import Model\n+\n+\n+class CurrentSpend(Model):\n+ \"\"\"The current amount of cost which is being tracked for a budget.\n+\n+ Variables are only populated by the server, and will be ignored when\n+ sending a request.\n+\n+ :ivar amount: The total amount of cost which is being tracked by the\n+ budget.\n+ :vartype amount: decimal.Decimal\n+ :ivar unit: The unit of measure for the budget amount.\n+ :vartype unit: str\n+ \"\"\"\n+\n+ _validation = {\n+ 'amount': {'readonly': True},\n+ 'unit': {'readonly': True},\n+ }\n+\n+ _attribute_map = {\n+ 'amount': {'key': 'amount', 'type': 'decimal'},\n+ 'unit': {'key': 'unit', 'type': 'str'},\n+ }\n+\n+ def __init__(self):\n+ super(CurrentSpend, self).__init__()\n+ self.amount = None\n+ self.unit = None"},{"sha":"dc010a065900621f02b77dfe1b389071e597fd73","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/filters.py","status":"added","additions":44,"deletions":0,"changes":44,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/filters.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/filters.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/filters.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -0,0 +1,44 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.serialization import Model\n+\n+\n+class Filters(Model):\n+ \"\"\"May be used to filter budgets by resource group, resource, or meter.\n+\n+ :param resource_groups: The list of filters on resource groups, allowed at\n+ subscription level only.\n+ :type resource_groups: list[str]\n+ :param resources: The list of filters on resources.\n+ :type resources: list[str]\n+ :param meters: The list of filters on meters, mandatory for budgets of\n+ usage category.\n+ :type meters: list[str]\n+ \"\"\"\n+\n+ _validation = {\n+ 'resource_groups': {'max_items': 10, 'min_items': 0},\n+ 'resources': {'max_items': 10, 'min_items': 0},\n+ 'meters': {'max_items': 10, 'min_items': 0},\n+ }\n+\n+ _attribute_map = {\n+ 'resource_groups': {'key': 'resourceGroups', 'type': '[str]'},\n+ 'resources': {'key': 'resources', 'type': '[str]'},\n+ 'meters': {'key': 'meters', 'type': '[str]'},\n+ }\n+\n+ def __init__(self, resource_groups=None, resources=None, meters=None):\n+ super(Filters, self).__init__()\n+ self.resource_groups = resource_groups\n+ self.resources = resources\n+ self.meters = meters"},{"sha":"61e1ca0ed34df63b0df71d2970b19f7fa8a866bd","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/notification.py","status":"added","additions":62,"deletions":0,"changes":62,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/notification.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/notification.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/notification.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -0,0 +1,62 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.serialization import Model\n+\n+\n+class Notification(Model):\n+ \"\"\"The notification associated with a budget.\n+\n+ :param enabled: The notification is enabled or not.\n+ :type enabled: bool\n+ :param operator: The comparison operator. Possible values include:\n+ 'EqualTo', 'GreaterThan', 'GreaterThanOrEqualTo'\n+ :type operator: str or ~azure.mgmt.consumption.models.OperatorType\n+ :param threshold: Threshold value associated with a notification.\n+ Notification is sent when the cost exceeded the threshold. It is always\n+ percent and has to be between 0 and 1000.\n+ :type threshold: decimal.Decimal\n+ :param contact_emails: Email addresses to send the budget notification to\n+ when the threshold is exceeded.\n+ :type contact_emails: list[str]\n+ :param contact_roles: Contact roles to send the budget notification to\n+ when the threshold is exceeded.\n+ :type contact_roles: list[str]\n+ :param contact_groups: Action groups to send the budget notification to\n+ when the threshold is exceeded.\n+ :type contact_groups: list[str]\n+ \"\"\"\n+\n+ _validation = {\n+ 'enabled': {'required': True},\n+ 'operator': {'required': True},\n+ 'threshold': {'required': True},\n+ 'contact_emails': {'required': True, 'max_items': 50, 'min_items': 1},\n+ 'contact_groups': {'max_items': 50, 'min_items': 0},\n+ }\n+\n+ _attribute_map = {\n+ 'enabled': {'key': 'enabled', 'type': 'bool'},\n+ 'operator': {'key': 'operator', 'type': 'str'},\n+ 'threshold': {'key': 'threshold', 'type': 'decimal'},\n+ 'contact_emails': {'key': 'contactEmails', 'type': '[str]'},\n+ 'contact_roles': {'key': 'contactRoles', 'type': '[str]'},\n+ 'contact_groups': {'key': 'contactGroups', 'type': '[str]'},\n+ }\n+\n+ def __init__(self, enabled, operator, threshold, contact_emails, contact_roles=None, contact_groups=None):\n+ super(Notification, self).__init__()\n+ self.enabled = enabled\n+ self.operator = operator\n+ self.threshold = threshold\n+ self.contact_emails = contact_emails\n+ self.contact_roles = contact_roles\n+ self.contact_groups = contact_groups"},{"sha":"bc5f89b78fbeb0a81a93d089f3a640f8e63ff3a2","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet.py","status":"added","additions":88,"deletions":0,"changes":88,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -0,0 +1,88 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from .resource import Resource\n+\n+\n+class PriceSheet(Resource):\n+ \"\"\"An pricesheet resource.\n+\n+ Variables are only populated by the server, and will be ignored when\n+ sending a request.\n+\n+ :ivar id: Resource Id.\n+ :vartype id: str\n+ :ivar name: Resource name.\n+ :vartype name: str\n+ :ivar type: Resource type.\n+ :vartype type: str\n+ :ivar tags: Resource tags.\n+ :vartype tags: dict[str, str]\n+ :ivar billing_period_id: The id of the billing period resource that the\n+ usage belongs to.\n+ :vartype billing_period_id: str\n+ :ivar meter_id: The meter id\n+ :vartype meter_id: str\n+ :ivar meter_details: The details about the meter. By default this is not\n+ populated, unless it's specified in $expand.\n+ :vartype meter_details: ~azure.mgmt.consumption.models.MeterDetails\n+ :ivar unit_of_measure: Unit of measure\n+ :vartype unit_of_measure: str\n+ :ivar included_quantity: Included quality for an offer\n+ :vartype included_quantity: decimal.Decimal\n+ :ivar part_number: Part Number\n+ :vartype part_number: str\n+ :ivar unit_price: Unit Price\n+ :vartype unit_price: decimal.Decimal\n+ :ivar currency_code: Currency Code\n+ :vartype currency_code: str\n+ \"\"\"\n+\n+ _validation = {\n+ 'id': {'readonly': True},\n+ 'name': {'readonly': True},\n+ 'type': {'readonly': True},\n+ 'tags': {'readonly': True},\n+ 'billing_period_id': {'readonly': True},\n+ 'meter_id': {'readonly': True},\n+ 'meter_details': {'readonly': True},\n+ 'unit_of_measure': {'readonly': True},\n+ 'included_quantity': {'readonly': True},\n+ 'part_number': {'readonly': True},\n+ 'unit_price': {'readonly': True},\n+ 'currency_code': {'readonly': True},\n+ }\n+\n+ _attribute_map = {\n+ 'id': {'key': 'id', 'type': 'str'},\n+ 'name': {'key': 'name', 'type': 'str'},\n+ 'type': {'key': 'type', 'type': 'str'},\n+ 'tags': {'key': 'tags', 'type': '{str}'},\n+ 'billing_period_id': {'key': 'properties.billingPeriodId', 'type': 'str'},\n+ 'meter_id': {'key': 'properties.meterId', 'type': 'str'},\n+ 'meter_details': {'key': 'properties.meterDetails', 'type': 'MeterDetails'},\n+ 'unit_of_measure': {'key': 'properties.unitOfMeasure', 'type': 'str'},\n+ 'included_quantity': {'key': 'properties.includedQuantity', 'type': 'decimal'},\n+ 'part_number': {'key': 'properties.partNumber', 'type': 'str'},\n+ 'unit_price': {'key': 'properties.unitPrice', 'type': 'decimal'},\n+ 'currency_code': {'key': 'properties.currencyCode', 'type': 'str'},\n+ }\n+\n+ def __init__(self):\n+ super(PriceSheet, self).__init__()\n+ self.billing_period_id = None\n+ self.meter_id = None\n+ self.meter_details = None\n+ self.unit_of_measure = None\n+ self.included_quantity = None\n+ self.part_number = None\n+ self.unit_price = None\n+ self.currency_code = None"},{"sha":"5dfe48207a52fc6efd11d8a2108a89bbed439301","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet_paged.py","status":"added","additions":27,"deletions":0,"changes":27,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet_paged.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet_paged.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/price_sheet_paged.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -0,0 +1,27 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.paging import Paged\n+\n+\n+class PriceSheetPaged(Paged):\n+ \"\"\"\n+ A paging container for iterating over a list of :class:`PriceSheet ` object\n+ \"\"\"\n+\n+ _attribute_map = {\n+ 'next_link': {'key': 'nextLink', 'type': 'str'},\n+ 'current_page': {'key': 'value', 'type': '[PriceSheet]'}\n+ }\n+\n+ def __init__(self, *args, **kwargs):\n+\n+ super(PriceSheetPaged, self).__init__(*args, **kwargs)"},{"sha":"f6a9a40d22d569970958af165de44c9f84162e47","filename":"azure-mgmt-consumption/azure/mgmt/consumption/models/proxy_resource.py","status":"added","additions":51,"deletions":0,"changes":51,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/proxy_resource.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/models/proxy_resource.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/models/proxy_resource.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -0,0 +1,51 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+from msrest.serialization import Model\n+\n+\n+class ProxyResource(Model):\n+ \"\"\"The Resource model definition.\n+\n+ Variables are only populated by the server, and will be ignored when\n+ sending a request.\n+\n+ :ivar id: Resource Id.\n+ :vartype id: str\n+ :ivar name: Resource name.\n+ :vartype name: str\n+ :ivar type: Resource type.\n+ :vartype type: str\n+ :param e_tag: eTag of the resource. To handle concurrent update scenarion,\n+ this field will be used to determine whether the user is updating the\n+ latest version or not.\n+ :type e_tag: str\n+ \"\"\"\n+\n+ _validation = {\n+ 'id': {'readonly': True},\n+ 'name': {'readonly': True},\n+ 'type': {'readonly': True},\n+ }\n+\n+ _attribute_map = {\n+ 'id': {'key': 'id', 'type': 'str'},\n+ 'name': {'key': 'name', 'type': 'str'},\n+ 'type': {'key': 'type', 'type': 'str'},\n+ 'e_tag': {'key': 'eTag', 'type': 'str'},\n+ }\n+\n+ def __init__(self, e_tag=None):\n+ super(ProxyResource, self).__init__()\n+ self.id = None\n+ self.name = None\n+ self.type = None\n+ self.e_tag = e_tag"},{"sha":"f791e0bc747d0bcd880175ab41f6f1a94f599bb1","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/__init__.py","status":"modified","additions":4,"deletions":0,"changes":4,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/__init__.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/__init__.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/__init__.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -12,11 +12,15 @@\n from .usage_details_operations import UsageDetailsOperations\n from .reservations_summaries_operations import ReservationsSummariesOperations\n from .reservations_details_operations import ReservationsDetailsOperations\n+from .budgets_operations import BudgetsOperations\n from .operations import Operations\n+from .price_sheet_operations import PriceSheetOperations\n \n __all__ = [\n 'UsageDetailsOperations',\n 'ReservationsSummariesOperations',\n 'ReservationsDetailsOperations',\n+ 'BudgetsOperations',\n 'Operations',\n+ 'PriceSheetOperations',\n ]"},{"sha":"1694905cc3b44bf71f17a69479734d1a90f0128a","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/budgets_operations.py","status":"added","additions":297,"deletions":0,"changes":297,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/budgets_operations.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/budgets_operations.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/budgets_operations.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -0,0 +1,297 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+import uuid\n+from msrest.pipeline import ClientRawResponse\n+\n+from .. import models\n+\n+\n+class BudgetsOperations(object):\n+ \"\"\"BudgetsOperations operations.\n+\n+ :param client: Client for service requests.\n+ :param config: Configuration of service client.\n+ :param serializer: An object model serializer.\n+ :param deserializer: An objec model deserializer.\n+ :ivar api_version: Version of the API to be used with the client request. The current version is 2018-01-31. Constant value: \"2018-01-31\".\n+ \"\"\"\n+\n+ models = models\n+\n+ def __init__(self, client, config, serializer, deserializer):\n+\n+ self._client = client\n+ self._serialize = serializer\n+ self._deserialize = deserializer\n+ self.api_version = \"2018-01-31\"\n+\n+ self.config = config\n+\n+ def list(\n+ self, scope, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Lists all budgets for a scope.\n+\n+ :param scope: The scope of the budgets. The scope can be\n+ 'subscriptions/{subscriptionId}' for a subscription, or\n+ 'subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}' for a\n+ resource group under a subscription.\n+ :type scope: str\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: An iterator like instance of Budget\n+ :rtype:\n+ ~azure.mgmt.consumption.models.BudgetPaged[~azure.mgmt.consumption.models.Budget]\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ def internal_paging(next_link=None, raw=False):\n+\n+ if not next_link:\n+ # Construct URL\n+ url = '/{scope}/providers/Microsoft.Consumption/budgets'\n+ path_format_arguments = {\n+ 'scope': self._serialize.url(\"scope\", scope, 'str', skip_quote=True),\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ else:\n+ url = next_link\n+ query_parameters = {}\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(\n+ request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ return response\n+\n+ # Deserialize response\n+ deserialized = models.BudgetPaged(internal_paging, self._deserialize.dependencies)\n+\n+ if raw:\n+ header_dict = {}\n+ client_raw_response = models.BudgetPaged(internal_paging, self._deserialize.dependencies, header_dict)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def get(\n+ self, scope, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Gets the budget for a scope by budget name.\n+\n+ :param scope: The scope of the budgets. The scope can be\n+ 'subscriptions/{subscriptionId}' for a subscription, or\n+ 'subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}' for a\n+ resource group under a subscription.\n+ :type scope: str\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: Budget or ClientRawResponse if raw=true\n+ :rtype: ~azure.mgmt.consumption.models.Budget or\n+ ~msrest.pipeline.ClientRawResponse\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ # Construct URL\n+ url = '/{scope}/providers/Microsoft.Consumption/budgets/{name}'\n+ path_format_arguments = {\n+ 'scope': self._serialize.url(\"scope\", scope, 'str', skip_quote=True),\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str'),\n+ 'name': self._serialize.url(\"self.config.name\", self.config.name, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ deserialized = None\n+\n+ if response.status_code == 200:\n+ deserialized = self._deserialize('Budget', response)\n+\n+ if raw:\n+ client_raw_response = ClientRawResponse(deserialized, response)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def create_or_update(\n+ self, scope, parameters, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"The operation to create or update a budget. Update operation requires\n+ latest eTag to be set in the request mandatorily. You may obtain the\n+ latest eTag by performing a get operation. Create operation does not\n+ require eTag.\n+\n+ :param scope: The scope of the budgets. The scope can be\n+ 'subscriptions/{subscriptionId}' for a subscription, or\n+ 'subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}' for a\n+ resource group under a subscription.\n+ :type scope: str\n+ :param parameters: Parameters supplied to the Create Budget operation.\n+ :type parameters: ~azure.mgmt.consumption.models.Budget\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: An iterator like instance of None\n+ :rtype: ~azure.mgmt.consumption.models.Budget[None]\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ def internal_paging(next_link=None, raw=False):\n+\n+ if not next_link:\n+ # Construct URL\n+ url = '/{scope}/providers/Microsoft.Consumption/budgets/{name}'\n+ path_format_arguments = {\n+ 'scope': self._serialize.url(\"scope\", scope, 'str', skip_quote=True),\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str'),\n+ 'name': self._serialize.url(\"self.config.name\", self.config.name, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ else:\n+ url = next_link\n+ query_parameters = {}\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct body\n+ body_content = self._serialize.body(parameters, 'Budget')\n+\n+ # Construct and send request\n+ request = self._client.put(url, query_parameters)\n+ response = self._client.send(\n+ request, header_parameters, body_content, stream=False, **operation_config)\n+\n+ if response.status_code not in [200, 201]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ return response\n+\n+ # Deserialize response\n+ deserialized = models.Budget(internal_paging, self._deserialize.dependencies)\n+\n+ if raw:\n+ header_dict = {}\n+ client_raw_response = models.Budget(internal_paging, self._deserialize.dependencies, header_dict)\n+ return client_raw_response\n+\n+ return deserialized\n+\n+ def delete(\n+ self, scope, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"The operation to delete a budget.\n+\n+ :param scope: The scope of the budgets. The scope can be\n+ 'subscriptions/{subscriptionId}' for a subscription, or\n+ 'subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}' for a\n+ resource group under a subscription.\n+ :type scope: str\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: None or ClientRawResponse if raw=true\n+ :rtype: None or ~msrest.pipeline.ClientRawResponse\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ # Construct URL\n+ url = '/{scope}/providers/Microsoft.Consumption/budgets/{name}'\n+ path_format_arguments = {\n+ 'scope': self._serialize.url(\"scope\", scope, 'str', skip_quote=True),\n+ 'subscriptionId': self._serialize.url(\"self.config.subscription_id\", self.config.subscription_id, 'str'),\n+ 'name': self._serialize.url(\"self.config.name\", self.config.name, 'str')\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.delete(url, query_parameters)\n+ response = self._client.send(request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ if raw:\n+ client_raw_response = ClientRawResponse(None, response)\n+ return client_raw_response"},{"sha":"f3efdae1c20868aef1cbad552979edb11f41663f","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/operations.py","status":"modified","additions":3,"deletions":3,"changes":6,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/operations.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/operations.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/operations.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -22,7 +22,7 @@ class Operations(object):\n :param config: Configuration of service client.\n :param serializer: An object model serializer.\n :param deserializer: An objec model deserializer.\n- :ivar api_version: Version of the API to be used with the client request. The current version is 2017-11-30. Constant value: \"2017-11-30\".\n+ :ivar api_version: Version of the API to be used with the client request. The current version is 2018-01-31. Constant value: \"2018-01-31\".\n \"\"\"\n \n models = models\n@@ -32,7 +32,7 @@ def __init__(self, client, config, serializer, deserializer):\n self._client = client\n self._serialize = serializer\n self._deserialize = deserializer\n- self.api_version = \"2017-11-30\"\n+ self.api_version = \"2018-01-31\"\n \n self.config = config\n \n@@ -78,7 +78,7 @@ def internal_paging(next_link=None, raw=False):\n # Construct and send request\n request = self._client.get(url, query_parameters)\n response = self._client.send(\n- request, header_parameters, **operation_config)\n+ request, header_parameters, stream=False, **operation_config)\n \n if response.status_code not in [200]:\n raise models.ErrorResponseException(self._deserialize, response)"},{"sha":"d5663fb7895a1f04d509f50a5821dbe9b94704dc","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/price_sheet_operations.py","status":"added","additions":119,"deletions":0,"changes":119,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/price_sheet_operations.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/price_sheet_operations.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/price_sheet_operations.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -0,0 +1,119 @@\n+# coding=utf-8\n+# --------------------------------------------------------------------------\n+# Copyright (c) Microsoft Corporation. All rights reserved.\n+# Licensed under the MIT License. See License.txt in the project root for\n+# license information.\n+#\n+# Code generated by Microsoft (R) AutoRest Code Generator.\n+# Changes may cause incorrect behavior and will be lost if the code is\n+# regenerated.\n+# --------------------------------------------------------------------------\n+\n+import uuid\n+from msrest.pipeline import ClientRawResponse\n+\n+from .. import models\n+\n+\n+class PriceSheetOperations(object):\n+ \"\"\"PriceSheetOperations operations.\n+\n+ :param client: Client for service requests.\n+ :param config: Configuration of service client.\n+ :param serializer: An object model serializer.\n+ :param deserializer: An objec model deserializer.\n+ :ivar api_version: Version of the API to be used with the client request. The current version is 2018-01-31. Constant value: \"2018-01-31\".\n+ \"\"\"\n+\n+ models = models\n+\n+ def __init__(self, client, config, serializer, deserializer):\n+\n+ self._client = client\n+ self._serialize = serializer\n+ self._deserialize = deserializer\n+ self.api_version = \"2018-01-31\"\n+\n+ self.config = config\n+\n+ def list(\n+ self, scope, expand=None, skiptoken=None, custom_headers=None, raw=False, **operation_config):\n+ \"\"\"Returns the price sheet associated with subscription guid, for a scope\n+ by billing period.\n+\n+ :param scope: The scope of the price sheet. The scope can be\n+ '/subscriptions/{subscriptionId}' for a subscription, or\n+ '/subscriptions/{subscriptionId}/providers/Microsoft.Billing/billingPeriods/{billingPeriodId}'\n+ for a billing period.\n+ :type scope: str\n+ :param expand: May be used to expand the properties/meterDetails\n+ within a price sheet. By default, these fields are not included when\n+ returning price sheet.\n+ :type expand: str\n+ :param skiptoken: Skiptoken is only used if a previous operation\n+ returned a partial result. If a previous response contains a nextLink\n+ element, the value of the nextLink element will include a skiptoken\n+ parameter that specifies a starting point to use for subsequent calls.\n+ :type skiptoken: str\n+ :param dict custom_headers: headers that will be added to the request\n+ :param bool raw: returns the direct response alongside the\n+ deserialized response\n+ :param operation_config: :ref:`Operation configuration\n+ overrides`.\n+ :return: An iterator like instance of PriceSheet\n+ :rtype:\n+ ~azure.mgmt.consumption.models.PriceSheetPaged[~azure.mgmt.consumption.models.PriceSheet]\n+ :raises:\n+ :class:`ErrorResponseException`\n+ \"\"\"\n+ def internal_paging(next_link=None, raw=False):\n+\n+ if not next_link:\n+ # Construct URL\n+ url = '/{scope}/providers/Microsoft.Consumption/pricesheets/default'\n+ path_format_arguments = {\n+ 'scope': self._serialize.url(\"scope\", scope, 'str', skip_quote=True)\n+ }\n+ url = self._client.format_url(url, **path_format_arguments)\n+\n+ # Construct parameters\n+ query_parameters = {}\n+ if expand is not None:\n+ query_parameters['$expand'] = self._serialize.query(\"expand\", expand, 'str')\n+ if skiptoken is not None:\n+ query_parameters['$skiptoken'] = self._serialize.query(\"skiptoken\", skiptoken, 'str')\n+ query_parameters['api-version'] = self._serialize.query(\"self.api_version\", self.api_version, 'str')\n+\n+ else:\n+ url = next_link\n+ query_parameters = {}\n+\n+ # Construct headers\n+ header_parameters = {}\n+ header_parameters['Content-Type'] = 'application/json; charset=utf-8'\n+ if self.config.generate_client_request_id:\n+ header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())\n+ if custom_headers:\n+ header_parameters.update(custom_headers)\n+ if self.config.accept_language is not None:\n+ header_parameters['accept-language'] = self._serialize.header(\"self.config.accept_language\", self.config.accept_language, 'str')\n+\n+ # Construct and send request\n+ request = self._client.get(url, query_parameters)\n+ response = self._client.send(\n+ request, header_parameters, stream=False, **operation_config)\n+\n+ if response.status_code not in [200]:\n+ raise models.ErrorResponseException(self._deserialize, response)\n+\n+ return response\n+\n+ # Deserialize response\n+ deserialized = models.PriceSheetPaged(internal_paging, self._deserialize.dependencies)\n+\n+ if raw:\n+ header_dict = {}\n+ client_raw_response = models.PriceSheetPaged(internal_paging, self._deserialize.dependencies, header_dict)\n+ return client_raw_response\n+\n+ return deserialized"},{"sha":"300e09f55c73071474db4e279693c0d4eef7d4db","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_details_operations.py","status":"modified","additions":3,"deletions":3,"changes":6,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_details_operations.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_details_operations.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_details_operations.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -22,7 +22,7 @@ class ReservationsDetailsOperations(object):\n :param config: Configuration of service client.\n :param serializer: An object model serializer.\n :param deserializer: An objec model deserializer.\n- :ivar api_version: Version of the API to be used with the client request. The current version is 2017-11-30. Constant value: \"2017-11-30\".\n+ :ivar api_version: Version of the API to be used with the client request. The current version is 2018-01-31. Constant value: \"2018-01-31\".\n \"\"\"\n \n models = models\n@@ -32,7 +32,7 @@ def __init__(self, client, config, serializer, deserializer):\n self._client = client\n self._serialize = serializer\n self._deserialize = deserializer\n- self.api_version = \"2017-11-30\"\n+ self.api_version = \"2018-01-31\"\n \n self.config = config\n \n@@ -92,7 +92,7 @@ def internal_paging(next_link=None, raw=False):\n # Construct and send request\n request = self._client.get(url, query_parameters)\n response = self._client.send(\n- request, header_parameters, **operation_config)\n+ request, header_parameters, stream=False, **operation_config)\n \n if response.status_code not in [200]:\n raise models.ErrorResponseException(self._deserialize, response)"},{"sha":"2c5124d9e9e4263cb4b1279bd8347fb627d199c5","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_summaries_operations.py","status":"modified","additions":3,"deletions":3,"changes":6,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_summaries_operations.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_summaries_operations.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/reservations_summaries_operations.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -22,7 +22,7 @@ class ReservationsSummariesOperations(object):\n :param config: Configuration of service client.\n :param serializer: An object model serializer.\n :param deserializer: An objec model deserializer.\n- :ivar api_version: Version of the API to be used with the client request. The current version is 2017-11-30. Constant value: \"2017-11-30\".\n+ :ivar api_version: Version of the API to be used with the client request. The current version is 2018-01-31. Constant value: \"2018-01-31\".\n \"\"\"\n \n models = models\n@@ -32,7 +32,7 @@ def __init__(self, client, config, serializer, deserializer):\n self._client = client\n self._serialize = serializer\n self._deserialize = deserializer\n- self.api_version = \"2017-11-30\"\n+ self.api_version = \"2018-01-31\"\n \n self.config = config\n \n@@ -96,7 +96,7 @@ def internal_paging(next_link=None, raw=False):\n # Construct and send request\n request = self._client.get(url, query_parameters)\n response = self._client.send(\n- request, header_parameters, **operation_config)\n+ request, header_parameters, stream=False, **operation_config)\n \n if response.status_code not in [200]:\n raise models.ErrorResponseException(self._deserialize, response)"},{"sha":"69abfd9386466b0d517e293a16264e8082e42147","filename":"azure-mgmt-consumption/azure/mgmt/consumption/operations/usage_details_operations.py","status":"modified","additions":4,"deletions":4,"changes":8,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/usage_details_operations.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/operations/usage_details_operations.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/operations/usage_details_operations.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -22,7 +22,7 @@ class UsageDetailsOperations(object):\n :param config: Configuration of service client.\n :param serializer: An object model serializer.\n :param deserializer: An objec model deserializer.\n- :ivar api_version: Version of the API to be used with the client request. The current version is 2017-11-30. Constant value: \"2017-11-30\".\n+ :ivar api_version: Version of the API to be used with the client request. The current version is 2018-01-31. Constant value: \"2018-01-31\".\n \"\"\"\n \n models = models\n@@ -32,7 +32,7 @@ def __init__(self, client, config, serializer, deserializer):\n self._client = client\n self._serialize = serializer\n self._deserialize = deserializer\n- self.api_version = \"2017-11-30\"\n+ self.api_version = \"2018-01-31\"\n \n self.config = config\n \n@@ -44,7 +44,7 @@ def list(\n :param scope: The scope of the usage details. The scope can be\n '/subscriptions/{subscriptionId}' for a subscription, or\n '/subscriptions/{subscriptionId}/providers/Microsoft.Billing/billingPeriods/{billingPeriodName}'\n- for a billing perdiod.\n+ for a billing period.\n :type scope: str\n :param expand: May be used to expand the\n properties/additionalProperties or properties/meterDetails within a\n@@ -115,7 +115,7 @@ def internal_paging(next_link=None, raw=False):\n # Construct and send request\n request = self._client.get(url, query_parameters)\n response = self._client.send(\n- request, header_parameters, **operation_config)\n+ request, header_parameters, stream=False, **operation_config)\n \n if response.status_code not in [200]:\n raise models.ErrorResponseException(self._deserialize, response)"},{"sha":"7bae806554140ef811329cd7f7e3a8e337d580fe","filename":"azure-mgmt-consumption/azure/mgmt/consumption/version.py","status":"modified","additions":1,"deletions":1,"changes":2,"blob_url":"https://github.com/Azure/azure-sdk-for-python/blob/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/version.py","raw_url":"https://github.com/Azure/azure-sdk-for-python/raw/042b7a5840ff471776bb64e46b50950ee9f84430/azure-mgmt-consumption/azure/mgmt/consumption/version.py","contents_url":"https://api.github.com/repos/Azure/azure-sdk-for-python/contents/azure-mgmt-consumption/azure/mgmt/consumption/version.py?ref=042b7a5840ff471776bb64e46b50950ee9f84430","patch":"@@ -9,5 +9,5 @@\n # regenerated.\n # --------------------------------------------------------------------------\n \n-VERSION = \"1.1.0\"\n+VERSION = \"2018-01-31\"\n "}]}
+
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_get_or_create_pull.txt b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_get_or_create_pull.txt
new file mode 100644
index 000000000000..70d25dd0519d
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_get_or_create_pull.txt
@@ -0,0 +1,22 @@
+https
+POST
+api.github.com
+None
+/repos/lmazuel/TestingRepo/pulls
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
+{"title": "Title", "body": "Body", "base": "b2", "head": "b1"}
+422
+[('Date', 'Thu, 17 May 2018 21:27:38 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '209'), ('Server', 'GitHub.com'), ('Status', '422 Unprocessable Entity'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4772'), ('X-RateLimit-Reset', '1526593184'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.087848'), ('X-GitHub-Request-Id', '1715:97B6:61F22E:7EE5EA:5AFDF3CA')]
+{"message":"Validation Failed","errors":[{"resource":"PullRequest","code":"custom","message":"No commits between b2 and b1"}],"documentation_url":"https://developer.github.com/v3/pulls/#create-a-pull-request"}
+
+https
+POST
+api.github.com
+None
+/repos/lmazuel/TestingRepo/pulls
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
+{"title": "Title", "body": "Body", "base": "b2", "head": "b1"}
+422
+[('Date', 'Thu, 17 May 2018 21:27:39 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '209'), ('Server', 'GitHub.com'), ('Status', '422 Unprocessable Entity'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4771'), ('X-RateLimit-Reset', '1526593184'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.118070'), ('X-GitHub-Request-Id', '1716:97B8:C24888:FB581B:5AFDF3CA')]
+{"message":"Validation Failed","errors":[{"resource":"PullRequest","code":"custom","message":"No commits between b2 and b1"}],"documentation_url":"https://developer.github.com/v3/pulls/#create-a-pull-request"}
+
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_get_user.txt b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_get_user.txt
new file mode 100644
index 000000000000..059d39112e47
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_get_user.txt
@@ -0,0 +1,11 @@
+https
+GET
+api.github.com
+None
+/user
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:39 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4770'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"77a0c498bc6360506f9e7a4dd33857df"'), ('Last-Modified', 'Tue, 08 May 2018 04:10:43 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.048690'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '1717:97B6:61F247:7EE60C:5AFDF3CB')]
+{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false,"name":"Laurent Mazuel","company":"Microsoft.","blog":"","location":"Redmond, WA, USA","email":"lmazuel@microsoft.com","hireable":null,"bio":"Azure SDK for Python","public_repos":46,"public_gists":14,"followers":30,"following":11,"created_at":"2011-09-14T12:44:37Z","updated_at":"2018-05-08T04:10:43Z","private_gists":1,"total_private_repos":4,"owned_private_repos":0,"disk_usage":41216,"collaborators":0,"two_factor_authentication":true,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
+
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_manage_git_folder.txt b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_manage_git_folder.txt
new file mode 100644
index 000000000000..e994d3de5241
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/ReplayData/GithubTools.test_manage_git_folder.txt
@@ -0,0 +1,33 @@
+https
+GET
+api.github.com
+None
+/user
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:39 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4769'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"77a0c498bc6360506f9e7a4dd33857df"'), ('Last-Modified', 'Tue, 08 May 2018 04:10:43 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.070117'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '1719:97B6:61F253:7EE61B:5AFDF3CB')]
+{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false,"name":"Laurent Mazuel","company":"Microsoft.","blog":"","location":"Redmond, WA, USA","email":"lmazuel@microsoft.com","hireable":null,"bio":"Azure SDK for Python","public_repos":46,"public_gists":14,"followers":30,"following":11,"created_at":"2011-09-14T12:44:37Z","updated_at":"2018-05-08T04:10:43Z","private_gists":1,"total_private_repos":4,"owned_private_repos":0,"disk_usage":41216,"collaborators":0,"two_factor_authentication":true,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
+
+https
+GET
+api.github.com
+None
+/user
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:42 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4768'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"77a0c498bc6360506f9e7a4dd33857df"'), ('Last-Modified', 'Tue, 08 May 2018 04:10:43 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.054549'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '171C:97B6:61F309:7EE6FD:5AFDF3CE')]
+{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false,"name":"Laurent Mazuel","company":"Microsoft.","blog":"","location":"Redmond, WA, USA","email":"lmazuel@microsoft.com","hireable":null,"bio":"Azure SDK for Python","public_repos":46,"public_gists":14,"followers":30,"following":11,"created_at":"2011-09-14T12:44:37Z","updated_at":"2018-05-08T04:10:43Z","private_gists":1,"total_private_repos":4,"owned_private_repos":0,"disk_usage":41216,"collaborators":0,"two_factor_authentication":true,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
+
+https
+GET
+api.github.com
+None
+/user
+{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Thu, 17 May 2018 21:27:46 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4767'), ('X-RateLimit-Reset', '1526593184'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"77a0c498bc6360506f9e7a4dd33857df"'), ('Last-Modified', 'Tue, 08 May 2018 04:10:43 GMT'), ('X-OAuth-Scopes', 'repo, user'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-Runtime-rack', '0.063164'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '171F:97B8:C24AB5:FB5AD5:5AFDF3D2')]
+{"login":"lmazuel","id":1050156,"avatar_url":"https://avatars3.githubusercontent.com/u/1050156?v=4","gravatar_id":"","url":"https://api.github.com/users/lmazuel","html_url":"https://github.com/lmazuel","followers_url":"https://api.github.com/users/lmazuel/followers","following_url":"https://api.github.com/users/lmazuel/following{/other_user}","gists_url":"https://api.github.com/users/lmazuel/gists{/gist_id}","starred_url":"https://api.github.com/users/lmazuel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lmazuel/subscriptions","organizations_url":"https://api.github.com/users/lmazuel/orgs","repos_url":"https://api.github.com/users/lmazuel/repos","events_url":"https://api.github.com/users/lmazuel/events{/privacy}","received_events_url":"https://api.github.com/users/lmazuel/received_events","type":"User","site_admin":false,"name":"Laurent Mazuel","company":"Microsoft.","blog":"","location":"Redmond, WA, USA","email":"lmazuel@microsoft.com","hireable":null,"bio":"Azure SDK for Python","public_repos":46,"public_gists":14,"followers":30,"following":11,"created_at":"2011-09-14T12:44:37Z","updated_at":"2018-05-08T04:10:43Z","private_gists":1,"total_private_repos":4,"owned_private_repos":0,"disk_usage":41216,"collaborators":0,"two_factor_authentication":true,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
+
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/__init__.py b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/conftest.py b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/conftest.py
new file mode 100644
index 000000000000..869626a022c2
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/conftest.py
@@ -0,0 +1,44 @@
+"""Configuration of fixtures for pytest"""
+import logging
+import os
+import sys
+import types
+
+from github import Github
+
+import pytest
+
+_LOGGER = logging.getLogger(__name__)
+
+collect_ignore = []
+if sys.version_info < (3, 6):
+ # Might do something more generic later
+ collect_ignore.append("test_bot_framework.py")
+ collect_ignore.append("test_git_tools.py")
+ collect_ignore.append("test_github_tools.py")
+
+_context = {
+ 'login': "login",
+ 'password': "password",
+ 'oauth_token': os.environ.get('GH_TOKEN', 'oauth_token')
+}
+_test_context_module = types.ModuleType(
+ 'GithubCredentials',
+ 'Module created to provide a context for tests'
+)
+_test_context_module.__dict__.update(_context)
+sys.modules['GithubCredentials'] = _test_context_module
+
+
+@pytest.fixture
+def github_token():
+ """Return the Github token to use for real tests."""
+ if not 'GH_TOKEN' in os.environ:
+ _LOGGER.warning('GH_TOKEN must be defined for this test')
+ return "faketoken"
+ return os.environ['GH_TOKEN']
+
+@pytest.fixture
+def github_client(github_token):
+ """Return a Github client with configured token."""
+ return Github(github_token)
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/test_bot_framework.py b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/test_bot_framework.py
new file mode 100644
index 000000000000..d7d407bc970e
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/test_bot_framework.py
@@ -0,0 +1,215 @@
+import os.path
+from unittest import mock
+
+import pytest
+from github.tests import Framework
+
+from azure_devtools.ci_tools.bot_framework import BotHandler, order, build_from_issue_comment, build_from_issues
+
+class BotFrameworkTest(Framework.TestCase):
+
+ def setUp(self):
+ self.maxDiff = None # Big diff to come
+ self.recordMode = False # turn to True to record
+ self.tokenAuthMode = True
+ self.replayDataFolder = os.path.join(os.path.dirname(__file__), "ReplayData")
+ super(BotFrameworkTest, self).setUp()
+
+ def test_webhook_data(self):
+ github_token = self.oauth_token
+ repo = self.g.get_repo("lmazuel/TestingRepo")
+
+ fake_webhook = {
+ 'action': 'opened', # What is the comment state?
+ 'repository': {
+ 'full_name': repo.full_name # On what repo is this command?
+ },
+ 'issue': {
+ 'number': 16, # On what issue is this comment?
+ 'body': "@AutorestCI help" # Message?
+ },
+ 'sender': {
+ 'login': "lmazuel" # Who wrote the command?
+ },
+ }
+ webhook_data = build_from_issues(github_token, fake_webhook)
+ assert webhook_data.text == "@AutorestCI help"
+ assert webhook_data.issue.number == 16
+ assert webhook_data.repo.full_name == repo.full_name
+
+ fake_webhook = {
+ 'action': 'created', # What is the comment state?
+ 'repository': {
+ 'full_name': repo.full_name # On what repo is this command?
+ },
+ 'issue': {
+ 'number': 16 # On what issue is this comment?
+ },
+ 'sender': {
+ 'login': "lmazuel" # Who wrote the command?
+ },
+ 'comment': {
+ 'id': 365120206,
+ 'body': "@AutorestCI help" # Message?
+ }
+ }
+ webhook_data = build_from_issue_comment(github_token, fake_webhook)
+ assert webhook_data.text == "@AutorestCI help"
+ assert webhook_data.issue.number == 16
+ assert webhook_data.repo.full_name == repo.full_name
+
+ def test_bot_help(self):
+ github_token = self.oauth_token
+ repo = self.g.get_repo("lmazuel/TestingRepo")
+ issue = repo.get_issue(16)
+
+ class BotHelp:
+ @order
+ def command1(self, issue):
+ pass
+ @order
+ def command2(self, issue):
+ pass
+ def notacommand(self):
+ pass
+
+ bot = BotHandler(BotHelp(), "AutorestCI", github_token)
+
+ fake_webhook = {
+ 'action': 'opened', # What is the comment state?
+ 'repository': {
+ 'full_name': issue.repository.full_name # On what repo is this command?
+ },
+ 'issue': {
+ 'number': issue.number, # On what issue is this comment?
+ 'body': "@AutorestCI help" # Message?
+ },
+ 'sender': {
+ 'login': "lmazuel" # Who wrote the command?
+ },
+ }
+
+ response = bot.issues(fake_webhook)
+ assert "this help message" in response["message"]
+ assert "command1" in response["message"]
+ assert "notacommand" not in response["message"]
+
+ help_comment = list(issue.get_comments())[-1]
+ assert "this help message" in help_comment.body
+ assert "command1" in help_comment.body
+ assert "notacommand" not in help_comment.body
+
+ # Clean
+ help_comment.delete()
+
+ def test_bot_basic_command(self):
+ github_token = self.oauth_token
+ repo = self.g.get_repo("lmazuel/TestingRepo")
+ issue = repo.get_issue(17)
+
+ class BotCommand:
+ @order
+ def command1(self, issue, param1):
+ assert issue.number == 17
+ return "I did something with "+param1
+
+ bot = BotHandler(BotCommand(), "AutorestCI", github_token)
+
+ fake_webhook = {
+ 'action': 'opened', # What is the comment state?
+ 'repository': {
+ 'full_name': issue.repository.full_name # On what repo is this command?
+ },
+ 'issue': {
+ 'number': issue.number, # On what issue is this comment?
+ 'body': "@AutorestCI command1 myparameter" # Message?
+ },
+ 'sender': {
+ 'login': "lmazuel" # Who wrote the command?
+ },
+ }
+
+ response = bot.issues(fake_webhook)
+ assert response["message"] == "I did something with myparameter"
+
+ help_comment = list(issue.get_comments())[-1]
+ assert "I did something with myparameter" in help_comment.body
+
+ # Clean
+ help_comment.delete()
+
+ @mock.patch('traceback.format_exc')
+ def test_bot_basic_failure(self, format_exc):
+ format_exc.return_value = 'something to do with an exception'
+
+ github_token = self.oauth_token
+ repo = self.g.get_repo("lmazuel/TestingRepo")
+ issue = repo.get_issue(18)
+
+ class BotCommand:
+ @order
+ def command1(self, issue, param1):
+ assert issue.number == 18
+ raise ValueError("Not happy")
+
+ bot = BotHandler(BotCommand(), "AutorestCI", github_token)
+
+ fake_webhook = {
+ 'action': 'opened', # What is the comment state?
+ 'repository': {
+ 'full_name': issue.repository.full_name # On what repo is this command?
+ },
+ 'issue': {
+ 'number': issue.number, # On what issue is this comment?
+ 'body': "@AutorestCI command1 myparameter" # Message?
+ },
+ 'sender': {
+ 'login': "lmazuel" # Who wrote the command?
+ },
+ }
+
+ response = bot.issues(fake_webhook)
+ assert response['message'] == 'Nothing for me or exception'
+
+ help_comment = list(issue.get_comments())[-1]
+ assert "something to do with an exception" in help_comment.body
+ assert "```python" in help_comment.body
+
+ # Clean
+ help_comment.delete()
+
+
+ def test_bot_unknown_command(self):
+ github_token = self.oauth_token
+ repo = self.g.get_repo("lmazuel/TestingRepo")
+ issue = repo.get_issue(19)
+
+ class BotCommand:
+ pass
+
+ bot = BotHandler(BotCommand(), "AutorestCI", github_token)
+
+ fake_webhook = {
+ 'action': 'opened', # What is the comment state?
+ 'repository': {
+ 'full_name': issue.repository.full_name # On what repo is this command?
+ },
+ 'issue': {
+ 'number': issue.number, # On what issue is this comment?
+ 'body': "@AutorestCI command1 myparameter" # Message?
+ },
+ 'sender': {
+ 'login': "lmazuel" # Who wrote the command?
+ },
+ }
+
+ response = bot.issues(fake_webhook)
+ assert "I didn't understand your command" in response['message']
+ assert "command1 myparameter" in response['message']
+
+ help_comment = list(issue.get_comments())[-1]
+ assert "I didn't understand your command" in help_comment.body
+ assert "command1 myparameter" in help_comment.body
+
+ # Clean
+ help_comment.delete()
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/test_git_tools.py b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/test_git_tools.py
new file mode 100644
index 000000000000..432824f611b1
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/test_git_tools.py
@@ -0,0 +1,72 @@
+from pathlib import Path
+import tempfile
+
+from git import Repo
+
+from azure_devtools.ci_tools.git_tools import (
+ do_commit,
+ get_files_in_commit
+)
+
+def test_do_commit():
+ finished = False # Authorize PermissionError on cleanup
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ Repo.clone_from('https://github.com/lmazuel/TestingRepo.git', temp_dir)
+ repo = Repo(temp_dir)
+
+ result = do_commit(repo, 'Test {hexsha}', 'testing', 'fakehexsha')
+ assert not result
+ assert 'fakehexsha' not in repo.head.commit.message
+ assert repo.active_branch.name == 'master'
+
+ file_path = Path(temp_dir, 'file.txt')
+ file_path.write_text('Something')
+
+ result = do_commit(repo, 'Test {hexsha}', 'testing', 'fakehexsha')
+ assert result
+ assert repo.head.commit.message == 'Test fakehexsha'
+ assert repo.active_branch.name == 'testing'
+ assert 'file.txt' in repo.head.commit.stats.files
+
+ file_path.write_text('New content')
+
+ result = do_commit(repo, 'Now it is {hexsha}', 'newbranch', 'new-fakehexsha')
+ assert result
+ assert repo.head.commit.message == 'Now it is new-fakehexsha'
+ assert repo.active_branch.name == 'newbranch'
+ assert 'file.txt' in repo.head.commit.stats.files
+
+ file_path.unlink()
+ file_path.write_text('New content')
+
+ result = do_commit(repo, 'Now it is {hexsha}', 'fakebranch', 'hexsha_not_used')
+ assert not result
+ assert repo.head.commit.message == 'Now it is new-fakehexsha'
+ assert repo.active_branch.name == 'newbranch'
+
+ finished = True
+ except PermissionError:
+ if finished:
+ return
+ raise
+
+def test_get_files_in_commit():
+ finished = False # Authorize PermissionError on cleanup
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ Repo.clone_from('https://github.com/lmazuel/swagger-to-sdk.git', temp_dir)
+
+ files = get_files_in_commit(temp_dir, "b40451e55b26e3db61ea17bd751181cbf91f60c5")
+
+ assert files == [
+ 'swaggertosdk/generate_package.py',
+ 'swaggertosdk/python_sdk_tools.py',
+ 'swaggertosdk/restapi/sdkbot.py'
+ ]
+
+ finished = True
+ except PermissionError:
+ if finished:
+ return
+ raise
diff --git a/tools/azure-devtools/src/azure_devtools/ci_tools/tests/test_github_tools.py b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/test_github_tools.py
new file mode 100644
index 000000000000..a6829810be80
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/ci_tools/tests/test_github_tools.py
@@ -0,0 +1,382 @@
+import os.path
+from pathlib import Path
+from subprocess import CalledProcessError
+import tempfile
+from unittest import mock
+
+import pytest
+
+from git import Repo, GitCommandError
+from github import GithubException
+from github.tests import Framework
+
+from azure_devtools.ci_tools.github_tools import (
+ exception_to_github,
+ user_from_token,
+ configure_user,
+ clone_to_path,
+ manage_git_folder,
+ do_pr,
+ get_files,
+ create_comment,
+ GithubLink,
+ DashboardCommentableObject,
+ DashboardComment,
+ get_or_create_pull
+)
+
+class GithubTools(Framework.TestCase):
+
+ def setUp(self):
+ self.maxDiff = None # Big diff to come
+ self.recordMode = False # turn to True to record
+ self.tokenAuthMode = True
+ self.replayDataFolder = os.path.join(os.path.dirname(__file__), "ReplayData")
+ super(GithubTools, self).setUp()
+
+ @mock.patch('traceback.format_exc')
+ def test_exception_to_github(self, format_exc):
+ format_exc.return_value = 'something to do with an exception'
+
+ # Prepare
+ repo = self.g.get_repo("lmazuel/TestingRepo")
+ issue = repo.get_issue(13)
+
+ # Act
+ with exception_to_github(issue) as error:
+ pass
+
+ assert error.comment is None
+
+ # Act
+ with exception_to_github(issue) as error:
+ "Test".fakemethod(12) # pylint: disable=no-member
+
+ # Test
+ assert error.comment is not None
+ assert "Encountered an unknown error" in error.comment.body
+
+ # Clean my mess
+ error.comment.delete()
+
+ # Act
+ with exception_to_github(issue, "Python bot") as error:
+ "Test".fakemethod(12) # pylint: disable=no-member
+
+ # Test
+ assert error.comment is not None
+ assert "Encountered an unknown error: (Python bot)" in error.comment.body
+
+ # Clean my mess
+ error.comment.delete()
+
+ # Act
+ with exception_to_github(issue, "Python bot") as error:
+ raise CalledProcessError(
+ 2,
+ ["autorest", "readme.md"],
+ "Error line 1\nError line 2"
+ )
+
+ # Test
+ assert error.comment is not None
+ assert "Encountered a Subprocess error: (Python bot)" in error.comment.body
+ assert "Error line 1" in error.comment.body
+
+ # Clean my mess
+ error.comment.delete()
+
+ # Act
+ with exception_to_github(issue, "Python bot") as error:
+ raise CalledProcessError(
+ 2,
+ ["autorest", "readme.md"],
+ )
+
+ # Test
+ assert error.comment is not None
+ assert "Encountered a Subprocess error: (Python bot)" in error.comment.body
+ assert "no output" in error.comment.body
+
+ # Clean my mess
+ error.comment.delete()
+
+ def test_get_or_create_pull(self):
+ repo = self.g.get_repo("lmazuel/TestingRepo")
+
+ # b1 and b2 should exist and be the same
+ with pytest.raises(GithubException):
+ get_or_create_pull(repo, "Title", "Body", "b1", "b2")
+
+ prresult = get_or_create_pull(repo, "Title", "Body", "b1", "b2", none_if_no_commit=True)
+ assert prresult is None
+
+ @mock.patch('traceback.format_exc')
+ def test_dashboard(self, format_exc):
+ format_exc.return_value = 'something to do with an exception'
+
+ # Prepare
+ repo = self.g.get_repo("lmazuel/TestingRepo")
+ issue = repo.get_issue(15)
+ initial_size = len(list(issue.get_comments()))
+ header = "# MYHEADER"
+
+ dashboard = DashboardCommentableObject(issue, header)
+
+ with exception_to_github(dashboard, "Python bot") as error:
+ "Test".fakemethod(12) # pylint: disable=no-member
+
+ after_size = len(list(issue.get_comments()))
+ assert after_size == initial_size + 1
+
+ assert error.comment is not None
+ assert "Encountered an unknown error" in error.comment.body
+
+ dashboard.create_comment("New text comment")
+ after_size_2 = len(list(issue.get_comments()))
+ assert after_size == after_size_2
+
+ # Clean my mess
+ error.comment.delete()
+
+ def test_get_user(self):
+ github_token = self.oauth_token
+ user = user_from_token(github_token)
+ assert user.login == 'lmazuel'
+
+ def test_get_files(self):
+ repo = self.g.get_repo("Azure/azure-sdk-for-python")
+ pr = repo.get_pull(1833)
+ files = get_files(pr)
+ assert "azure-mgmt-consumption/azure/mgmt/consumption/consumption_management_client.py" in [f.filename for f in files]
+
+ commit = repo.get_commit("042b7a5840ff471776bb64e46b50950ee9f84430")
+ files = get_files(commit)
+ assert "azure-mgmt-consumption/azure/mgmt/consumption/consumption_management_client.py" in [f.filename for f in files]
+
+ def test_create_comment(self):
+ repo = self.g.get_repo("lmazuel/TestingRepo")
+ issue = repo.get_issue(14)
+ comment = create_comment(issue, "This is a test")
+ comment.delete()
+
+ pull = repo.get_pull(2)
+ comment = create_comment(pull, "This is a test")
+ comment.delete()
+
+ def test_configure(self):
+ github_token = self.oauth_token
+ finished = False
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ try:
+ Repo.clone_from('https://github.com/lmazuel/TestingRepo.git', temp_dir)
+ repo = Repo(temp_dir)
+
+ # If it's not throwing, I'm happy enough
+ configure_user(github_token, repo)
+
+ assert repo.git.config('--get', 'user.name') == 'Laurent Mazuel'
+ except Exception as err:
+ print(err)
+ pytest.fail(err)
+ else:
+ finished = True
+ except PermissionError:
+ if finished:
+ return
+ raise
+
+ def test_clone_path(self):
+ github_token = self.oauth_token
+ finished = False # Authorize PermissionError on cleanup
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ clone_to_path(github_token, temp_dir, "lmazuel/TestingRepo")
+ assert (Path(temp_dir) / Path("README.md")).exists()
+
+ finished = True
+ except PermissionError:
+ if not finished:
+ raise
+
+ finished = False # Authorize PermissionError on cleanup
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ clone_to_path(github_token, temp_dir, "https://github.com/lmazuel/TestingRepo")
+ assert (Path(temp_dir) / Path("README.md")).exists()
+
+ finished = True
+ except PermissionError:
+ if not finished:
+ raise
+
+ finished = False # Authorize PermissionError on cleanup
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ clone_to_path(github_token, temp_dir, "lmazuel/TestingRepo", "lmazuel-patch-1")
+ assert (Path(temp_dir) / Path("README.md")).exists()
+
+ finished = True
+ except PermissionError:
+ if not finished:
+ raise
+
+ finished = False # Authorize PermissionError on cleanup
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ with pytest.raises(GitCommandError):
+ clone_to_path(github_token, temp_dir, "lmazuel/TestingRepo", "fakebranch")
+
+ finished = True
+ except (PermissionError, FileNotFoundError):
+ if not finished:
+ raise
+
+ finished = False # Authorize PermissionError on cleanup
+ # PR 2 must be open, or the test means nothing
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ clone_to_path(github_token, temp_dir, "lmazuel/TestingRepo", pr_number=2)
+ assert (Path(temp_dir) / Path("README.md")).exists()
+
+ finished = True
+ except (PermissionError, FileNotFoundError):
+ if not finished:
+ raise
+
+ finished = False # Authorize PermissionError on cleanup
+ # PR 1 must be MERGED, or the test means nothing
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ clone_to_path(github_token, temp_dir, "lmazuel/TestingRepo", pr_number=1)
+ assert (Path(temp_dir) / Path("README.md")).exists()
+
+ finished = True
+ except (PermissionError, FileNotFoundError):
+ if not finished:
+ raise
+
+ finished = False # Authorize PermissionError on cleanup
+ # PR 2 must be opened, or the test means nothing
+ repo = self.g.get_repo("lmazuel/TestingRepo")
+ pr = repo.get_pull(2)
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ clone_to_path(github_token, temp_dir, "lmazuel/TestingRepo", branch_or_commit=pr.merge_commit_sha, pr_number=2)
+ assert (Path(temp_dir) / Path("README.md")).stat().st_size >= 107 # File in the PR
+
+ finished = True
+ except (PermissionError, FileNotFoundError):
+ if not finished:
+ raise
+
+ finished = False # Authorize PermissionError on cleanup
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ with pytest.raises(GitCommandError):
+ clone_to_path(github_token, temp_dir, "lmazuel/TestingRepo", pr_number=123456789)
+
+ finished = True
+ except (PermissionError, FileNotFoundError):
+ if not finished:
+ raise
+
+ def test_manage_git_folder(self):
+ github_token = self.oauth_token
+ finished = False # Authorize PermissionError on cleanup
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir, \
+ manage_git_folder(github_token, temp_dir, "lmazuel/TestingRepo") as rest_repo:
+
+ assert (Path(rest_repo) / Path("README.md")).exists()
+
+ finished = True
+ except (PermissionError, FileNotFoundError):
+ if not finished:
+ raise
+
+ finished = False # Authorize PermissionError on cleanup
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir, \
+ manage_git_folder(github_token, temp_dir, "lmazuel/TestingRepo@lmazuel-patch-1") as rest_repo:
+
+ assert (Path(rest_repo) / Path("README.md")).exists()
+ assert "lmazuel-patch-1" in str(Repo(rest_repo).active_branch)
+
+ finished = True
+ except (PermissionError, FileNotFoundError):
+ if not finished:
+ raise
+
+ finished = False # Authorize PermissionError on cleanup
+ try:
+ with tempfile.TemporaryDirectory() as temp_dir, \
+ manage_git_folder(github_token, temp_dir, "lmazuel/TestingRepo", pr_number=1) as rest_repo:
+
+ assert (Path(rest_repo) / Path("README.md")).exists()
+ with pytest.raises(TypeError) as err:
+ Repo(rest_repo).active_branch
+ assert "HEAD is a detached symbolic reference" in str(err)
+
+ finished = True
+ except (PermissionError, FileNotFoundError):
+ if not finished:
+ raise
+
+ def test_do_pr(self):
+ github_token = self.oauth_token
+ # Should do nothing
+ do_pr(None, 'bad', 'bad', 'bad', 'bad')
+
+ # Should do nothing
+ do_pr(github_token, 'bad', None, 'bad', 'bad')
+
+ # FIXME - more tests
+
+
+def test_github_link():
+ inputstr = "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/billing/resource-manager/readme.md"
+ link = GithubLink.from_string(inputstr)
+ assert link.gitid == "Azure/azure-rest-api-specs"
+ assert link.branch_or_commit == "master"
+ assert link.link_type == "raw"
+ assert link.path == "specification/billing/resource-manager/readme.md"
+ assert str(link) == inputstr
+ raw_link = link.as_raw_link()
+ assert isinstance(raw_link, GithubLink)
+ assert str(raw_link) == str(link)
+
+ inputstr = "https://github.com/Azure/azure-rest-api-specs/blob/master/specification/billing/resource-manager/readme.md"
+ link = GithubLink.from_string(inputstr)
+ assert link.gitid == "Azure/azure-rest-api-specs"
+ assert link.branch_or_commit == "master"
+ assert link.link_type == "blob"
+ assert link.path == "specification/billing/resource-manager/readme.md"
+ assert str(link) == inputstr
+ raw_link = link.as_raw_link()
+ assert isinstance(raw_link, GithubLink)
+ assert str(raw_link) == "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/billing/resource-manager/readme.md"
+
+ inputstr = "https://github.com/Azure/azure-rest-api-specs/tree/master/specification/billing/resource-manager"
+ link = GithubLink.from_string(inputstr)
+ assert link.gitid == "Azure/azure-rest-api-specs"
+ assert link.branch_or_commit == "master"
+ assert link.link_type == "tree"
+ assert link.path == "specification/billing/resource-manager"
+ assert str(link) == inputstr
+ with pytest.raises(ValueError):
+ link.as_raw_link()
+
+ inputstr = "https://token@github.com/Azure/azure-rest-api-specs/blob/master/specification/billing/resource-manager/readme.md"
+ link = GithubLink.from_string(inputstr)
+ assert link.token == "token"
+ assert link.gitid == "Azure/azure-rest-api-specs"
+ assert link.branch_or_commit == "master"
+ assert link.link_type == "blob"
+ assert link.path == "specification/billing/resource-manager/readme.md"
+ assert str(link) == inputstr
+ raw_link = link.as_raw_link()
+ assert isinstance(raw_link, GithubLink)
+ # Raw link with token does not use token in URL, since it has to be provided as Authorization: token
+ assert str(raw_link) == "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/billing/resource-manager/readme.md"
diff --git a/tools/azure-devtools/src/azure_devtools/scenario_tests/__init__.py b/tools/azure-devtools/src/azure_devtools/scenario_tests/__init__.py
new file mode 100644
index 000000000000..b90b5aaa96b8
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/scenario_tests/__init__.py
@@ -0,0 +1,28 @@
+# --------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# --------------------------------------------------------------------------------------------
+
+from .base import IntegrationTestBase, ReplayableTest, LiveTest
+from .exceptions import AzureTestError
+from .decorators import live_only, record_only, AllowLargeResponse
+from .patches import mock_in_unit_test, patch_time_sleep_api, patch_long_run_operation_delay
+from .preparers import AbstractPreparer, SingleValueReplacer
+from .recording_processors import (
+ RecordingProcessor, SubscriptionRecordingProcessor,
+ LargeRequestBodyProcessor, LargeResponseBodyProcessor, LargeResponseBodyReplacer,
+ OAuthRequestResponsesFilter, DeploymentNameReplacer, GeneralNameReplacer, AccessTokenReplacer, RequestUrlNormalizer,
+)
+from .utilities import create_random_name, get_sha1_hash
+
+__all__ = ['IntegrationTestBase', 'ReplayableTest', 'LiveTest',
+ 'AzureTestError',
+ 'mock_in_unit_test', 'patch_time_sleep_api', 'patch_long_run_operation_delay',
+ 'AbstractPreparer', 'SingleValueReplacer', 'AllowLargeResponse',
+ 'RecordingProcessor', 'SubscriptionRecordingProcessor',
+ 'LargeRequestBodyProcessor', 'LargeResponseBodyProcessor', 'LargeResponseBodyReplacer',
+ 'OAuthRequestResponsesFilter', 'DeploymentNameReplacer', 'GeneralNameReplacer',
+ 'AccessTokenReplacer', 'RequestUrlNormalizer',
+ 'live_only', 'record_only',
+ 'create_random_name', 'get_sha1_hash']
+__version__ = '0.5.2'
diff --git a/tools/azure-devtools/src/azure_devtools/scenario_tests/base.py b/tools/azure-devtools/src/azure_devtools/scenario_tests/base.py
new file mode 100644
index 000000000000..81d90f96a46c
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/scenario_tests/base.py
@@ -0,0 +1,214 @@
+# --------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# --------------------------------------------------------------------------------------------
+
+from __future__ import print_function
+import unittest
+import os
+import inspect
+import tempfile
+import shutil
+import logging
+import threading
+import six
+import vcr
+
+from .config import TestConfig
+from .const import ENV_TEST_DIAGNOSE
+from .utilities import create_random_name
+from .decorators import live_only
+
+
+class IntegrationTestBase(unittest.TestCase):
+ def __init__(self, method_name):
+ super(IntegrationTestBase, self).__init__(method_name)
+ self.diagnose = os.environ.get(ENV_TEST_DIAGNOSE, None) == 'True'
+ self.logger = logging.getLogger('azure_devtools.scenario_tests')
+
+ def create_random_name(self, prefix, length): # pylint: disable=no-self-use
+ return create_random_name(prefix=prefix, length=length)
+
+ def create_temp_file(self, size_kb, full_random=False):
+ """ Create a temporary file for testing. The test harness will delete the file during tearing down. """
+ fd, path = tempfile.mkstemp()
+ os.close(fd)
+ self.addCleanup(lambda: os.remove(path))
+
+ with open(path, mode='r+b') as f:
+ if full_random:
+ chunk = os.urandom(1024)
+ else:
+ chunk = bytearray([0] * 1024)
+ for _ in range(size_kb):
+ f.write(chunk)
+
+ return path
+
+ def create_temp_dir(self):
+ """
+ Create a temporary directory for testing. The test harness will delete the directory during tearing down.
+ """
+ temp_dir = tempfile.mkdtemp()
+ self.addCleanup(lambda: shutil.rmtree(temp_dir, ignore_errors=True))
+
+ return temp_dir
+
+ @classmethod
+ def set_env(cls, key, val):
+ os.environ[key] = val
+
+ @classmethod
+ def pop_env(cls, key):
+ return os.environ.pop(key, None)
+
+
+@live_only()
+class LiveTest(IntegrationTestBase):
+ pass
+
+
+class ReplayableTest(IntegrationTestBase): # pylint: disable=too-many-instance-attributes
+ FILTER_HEADERS = [
+ 'authorization',
+ 'client-request-id',
+ 'retry-after',
+ 'x-ms-client-request-id',
+ 'x-ms-correlation-request-id',
+ 'x-ms-ratelimit-remaining-subscription-reads',
+ 'x-ms-request-id',
+ 'x-ms-routing-request-id',
+ 'x-ms-gateway-service-instanceid',
+ 'x-ms-ratelimit-remaining-tenant-reads',
+ 'x-ms-served-by',
+ 'x-ms-authorization-auxiliary'
+ ]
+
+ def __init__(self, # pylint: disable=too-many-arguments
+ method_name, config_file=None, recording_dir=None, recording_name=None, recording_processors=None,
+ replay_processors=None, recording_patches=None, replay_patches=None):
+ super(ReplayableTest, self).__init__(method_name)
+
+ self.recording_processors = recording_processors or []
+ self.replay_processors = replay_processors or []
+
+ self.recording_patches = recording_patches or []
+ self.replay_patches = replay_patches or []
+
+ self.config = TestConfig(config_file=config_file)
+
+ self.disable_recording = False
+
+ test_file_path = inspect.getfile(self.__class__)
+ recording_dir = recording_dir or os.path.join(os.path.dirname(test_file_path), 'recordings')
+ self.is_live = self.config.record_mode
+
+ self.vcr = vcr.VCR(
+ cassette_library_dir=recording_dir,
+ before_record_request=self._process_request_recording,
+ before_record_response=self._process_response_recording,
+ decode_compressed_response=True,
+ record_mode='once' if not self.is_live else 'all',
+ filter_headers=self.FILTER_HEADERS
+ )
+ self.vcr.register_matcher('query', self._custom_request_query_matcher)
+
+ self.recording_file = os.path.join(
+ recording_dir,
+ '{}.yaml'.format(recording_name or method_name)
+ )
+ if self.is_live and os.path.exists(self.recording_file):
+ os.remove(self.recording_file)
+
+ self.in_recording = self.is_live or not os.path.exists(self.recording_file)
+ self.test_resources_count = 0
+ self.original_env = os.environ.copy()
+
+ def setUp(self):
+ super(ReplayableTest, self).setUp()
+
+ # set up cassette
+ cm = self.vcr.use_cassette(self.recording_file)
+ self.cassette = cm.__enter__()
+ self.addCleanup(cm.__exit__)
+
+ # set up mock patches
+ if self.in_recording:
+ for patch in self.recording_patches:
+ patch(self)
+ else:
+ for patch in self.replay_patches:
+ patch(self)
+
+ def tearDown(self):
+ os.environ = self.original_env
+ # Autorest.Python 2.x
+ assert not [t for t in threading.enumerate() if t.name.startswith("AzureOperationPoller")], \
+ "You need to call 'result' or 'wait' on all AzureOperationPoller you have created"
+ # Autorest.Python 3.x
+ assert not [t for t in threading.enumerate() if t.name.startswith("LROPoller")], \
+ "You need to call 'result' or 'wait' on all LROPoller you have created"
+
+ def _process_request_recording(self, request):
+ if self.disable_recording:
+ return None
+
+ if self.in_recording:
+ for processor in self.recording_processors:
+ request = processor.process_request(request)
+ if not request:
+ break
+ else:
+ for processor in self.replay_processors:
+ request = processor.process_request(request)
+ if not request:
+ break
+
+ return request
+
+ def _process_response_recording(self, response):
+ from .utilities import is_text_payload
+ if self.in_recording:
+ # make header name lower case and filter unwanted headers
+ headers = {}
+ for key in response['headers']:
+ if key.lower() not in self.FILTER_HEADERS:
+ headers[key.lower()] = response['headers'][key]
+ response['headers'] = headers
+
+ body = response['body']['string']
+ if is_text_payload(response) and body and not isinstance(body, six.string_types):
+ response['body']['string'] = body.decode('utf-8')
+
+ for processor in self.recording_processors:
+ response = processor.process_response(response)
+ if not response:
+ break
+ else:
+ for processor in self.replay_processors:
+ response = processor.process_response(response)
+ if not response:
+ break
+
+ return response
+
+ @classmethod
+ def _custom_request_query_matcher(cls, r1, r2):
+ """ Ensure method, path, and query parameters match. """
+ from six.moves.urllib_parse import urlparse, parse_qs # pylint: disable=import-error,relative-import
+
+ url1 = urlparse(r1.uri)
+ url2 = urlparse(r2.uri)
+
+ q1 = parse_qs(url1.query)
+ q2 = parse_qs(url2.query)
+ shared_keys = set(q1.keys()).intersection(set(q2.keys()))
+
+ if len(shared_keys) != len(q1) or len(shared_keys) != len(q2):
+ return False
+
+ for key in shared_keys:
+ if q1[key][0].lower() != q2[key][0].lower():
+ return False
+
+ return True
diff --git a/tools/azure-devtools/src/azure_devtools/scenario_tests/config.py b/tools/azure-devtools/src/azure_devtools/scenario_tests/config.py
new file mode 100644
index 000000000000..ac6ac6f91c0a
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/scenario_tests/config.py
@@ -0,0 +1,28 @@
+# --------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# --------------------------------------------------------------------------------------------
+
+import configargparse
+
+from .const import ENV_LIVE_TEST
+
+
+class TestConfig(object): # pylint: disable=too-few-public-methods
+ def __init__(self, parent_parsers=None, config_file=None):
+ parent_parsers = parent_parsers or []
+ self.parser = configargparse.ArgumentParser(parents=parent_parsers)
+ self.parser.add_argument(
+ '-c', '--config', is_config_file=True, default=config_file,
+ help='Path to a configuration file in YAML format.'
+ )
+ self.parser.add_argument(
+ '-l', '--live-mode', action='store_true', dest='live_mode',
+ env_var=ENV_LIVE_TEST,
+ help='Activate "live" recording mode for tests.'
+ )
+ self.args = self.parser.parse_args([])
+
+ @property
+ def record_mode(self):
+ return self.args.live_mode
diff --git a/tools/azure-devtools/src/azure_devtools/scenario_tests/const.py b/tools/azure-devtools/src/azure_devtools/scenario_tests/const.py
new file mode 100644
index 000000000000..e27e7289a021
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/scenario_tests/const.py
@@ -0,0 +1,14 @@
+# --------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# --------------------------------------------------------------------------------------------
+
+# Replaced mock values
+MOCKED_SUBSCRIPTION_ID = '00000000-0000-0000-0000-000000000000'
+MOCKED_TENANT_ID = '00000000-0000-0000-0000-000000000000'
+
+# Configuration environment variable
+ENV_COMMAND_COVERAGE = 'AZURE_TEST_COMMAND_COVERAGE'
+ENV_LIVE_TEST = 'AZURE_TEST_RUN_LIVE'
+ENV_SKIP_ASSERT = 'AZURE_TEST_SKIP_ASSERT'
+ENV_TEST_DIAGNOSE = 'AZURE_TEST_DIAGNOSE'
diff --git a/tools/azure-devtools/src/azure_devtools/scenario_tests/decorators.py b/tools/azure-devtools/src/azure_devtools/scenario_tests/decorators.py
new file mode 100644
index 000000000000..b31d8ee29dae
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/scenario_tests/decorators.py
@@ -0,0 +1,44 @@
+# --------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# --------------------------------------------------------------------------------------------
+
+import os
+import functools
+import unittest
+from .const import ENV_LIVE_TEST
+from .utilities import trim_kwargs_from_test_function
+
+
+def live_only():
+ return unittest.skipUnless(
+ os.environ.get(ENV_LIVE_TEST, False),
+ 'This is a live only test. A live test will bypass all vcrpy components.')
+
+
+def record_only():
+ return unittest.skipUnless(
+ not os.environ.get(ENV_LIVE_TEST, False),
+ 'This test is excluded from being run live. To force a recording, please remove the recording file.')
+
+
+class AllowLargeResponse(object): # pylint: disable=too-few-public-methods
+
+ def __init__(self, size_kb=1024):
+ self.size_kb = size_kb
+
+ def __call__(self, fn):
+ def _preparer_wrapper(test_class_instance, **kwargs):
+ from azure_devtools.scenario_tests import LargeResponseBodyProcessor
+ large_resp_body = next((r for r in test_class_instance.recording_processors
+ if isinstance(r, LargeResponseBodyProcessor)), None)
+ if large_resp_body:
+ large_resp_body._max_response_body = self.size_kb # pylint: disable=protected-access
+
+ trim_kwargs_from_test_function(fn, kwargs)
+
+ fn(test_class_instance, **kwargs)
+
+ setattr(_preparer_wrapper, '__is_preparer', True)
+ functools.update_wrapper(_preparer_wrapper, fn)
+ return _preparer_wrapper
diff --git a/tools/azure-devtools/src/azure_devtools/scenario_tests/exceptions.py b/tools/azure-devtools/src/azure_devtools/scenario_tests/exceptions.py
new file mode 100644
index 000000000000..bdebae0b44e8
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/scenario_tests/exceptions.py
@@ -0,0 +1,10 @@
+# --------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# --------------------------------------------------------------------------------------------
+
+
+class AzureTestError(Exception):
+ def __init__(self, error_message):
+ message = 'An error caused by the Azure test harness failed the test: {}'
+ super(AzureTestError, self).__init__(message.format(error_message))
diff --git a/tools/azure-devtools/src/azure_devtools/scenario_tests/patches.py b/tools/azure-devtools/src/azure_devtools/scenario_tests/patches.py
new file mode 100644
index 000000000000..74c27927c29c
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/scenario_tests/patches.py
@@ -0,0 +1,37 @@
+# --------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# --------------------------------------------------------------------------------------------
+
+from .exceptions import AzureTestError
+
+
+def patch_time_sleep_api(unit_test):
+ def _time_sleep_skip(*_):
+ return
+
+ mock_in_unit_test(unit_test, 'time.sleep', _time_sleep_skip)
+
+
+def patch_long_run_operation_delay(unit_test):
+ def _shortcut_long_run_operation(*args, **kwargs): # pylint: disable=unused-argument
+ return
+
+ mock_in_unit_test(unit_test,
+ 'msrestazure.azure_operation.AzureOperationPoller._delay',
+ _shortcut_long_run_operation)
+
+
+def mock_in_unit_test(unit_test, target, replacement):
+ try:
+ import unittest.mock as mock
+ except ImportError:
+ import mock
+ import unittest
+
+ if not isinstance(unit_test, unittest.TestCase):
+ raise AzureTestError('Patches can be only called from a unit test')
+
+ mp = mock.patch(target, replacement)
+ mp.__enter__()
+ unit_test.addCleanup(mp.__exit__)
diff --git a/tools/azure-devtools/src/azure_devtools/scenario_tests/preparers.py b/tools/azure-devtools/src/azure_devtools/scenario_tests/preparers.py
new file mode 100644
index 000000000000..b10d8c949b68
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/scenario_tests/preparers.py
@@ -0,0 +1,122 @@
+# --------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# --------------------------------------------------------------------------------------------
+
+import contextlib
+import functools
+
+from .base import ReplayableTest
+from .utilities import create_random_name, is_text_payload, trim_kwargs_from_test_function
+from .recording_processors import RecordingProcessor
+
+
+# Core Utility
+
+class AbstractPreparer(object):
+ def __init__(self, name_prefix, name_len, disable_recording=False):
+ self.name_prefix = name_prefix
+ self.name_len = name_len
+ self.resource_moniker = None
+ self.resource_random_name = None
+ self.test_class_instance = None
+ self.live_test = False
+ self.disable_recording = disable_recording
+
+ def __call__(self, fn):
+ def _preparer_wrapper(test_class_instance, **kwargs):
+ self.live_test = not isinstance(test_class_instance, ReplayableTest)
+ self.test_class_instance = test_class_instance
+
+ if self.live_test or test_class_instance.in_recording:
+ resource_name = self.random_name
+ if not self.live_test and isinstance(self, RecordingProcessor):
+ test_class_instance.recording_processors.append(self)
+ else:
+ resource_name = self.moniker
+
+ with self.override_disable_recording():
+ parameter_update = self.create_resource(
+ resource_name,
+ **kwargs
+ )
+
+ if parameter_update:
+ kwargs.update(parameter_update)
+
+ trim_kwargs_from_test_function(fn, kwargs)
+
+ try:
+ fn(test_class_instance, **kwargs)
+ finally:
+ # Russian Doll - the last declared resource to be deleted first.
+ self.remove_resource_with_record_override(resource_name, **kwargs)
+
+ setattr(_preparer_wrapper, '__is_preparer', True)
+ functools.update_wrapper(_preparer_wrapper, fn)
+ return _preparer_wrapper
+
+ @contextlib.contextmanager
+ def override_disable_recording(self):
+ if hasattr(self.test_class_instance, 'disable_recording'):
+ orig_enabled = self.test_class_instance.disable_recording
+ self.test_class_instance.disable_recording = self.disable_recording
+ yield
+ self.test_class_instance.disable_recording = orig_enabled
+ else:
+ yield
+
+ @property
+ def moniker(self):
+ if not self.resource_moniker:
+ self.test_class_instance.test_resources_count += 1
+ self.resource_moniker = '{}{:06}'.format(self.name_prefix,
+ self.test_class_instance.test_resources_count)
+ return self.resource_moniker
+
+ def create_random_name(self):
+ return create_random_name(self.name_prefix, self.name_len)
+
+ @property
+ def random_name(self):
+ if not self.resource_random_name:
+ self.resource_random_name = self.create_random_name()
+ return self.resource_random_name
+
+ def create_resource(self, name, **kwargs): # pylint: disable=unused-argument,no-self-use
+ return {}
+
+ def remove_resource(self, name, **kwargs): # pylint: disable=unused-argument
+ pass
+
+ def remove_resource_with_record_override(self, name, **kwargs):
+ with self.override_disable_recording():
+ self.remove_resource(name, **kwargs)
+
+
+class SingleValueReplacer(RecordingProcessor):
+ # pylint: disable=no-member
+ def process_request(self, request):
+ from six.moves.urllib_parse import quote_plus # pylint: disable=import-error,relative-import
+ if self.random_name in request.uri:
+ request.uri = request.uri.replace(self.random_name, self.moniker)
+ elif quote_plus(self.random_name) in request.uri:
+ request.uri = request.uri.replace(quote_plus(self.random_name),
+ quote_plus(self.moniker))
+
+ if is_text_payload(request) and request.body:
+ body = str(request.body, 'utf-8') if isinstance(request.body, bytes) else str(request.body)
+ if self.random_name in body:
+ request.body = body.replace(self.random_name, self.moniker)
+
+ return request
+
+ def process_response(self, response):
+ if is_text_payload(response) and response['body']['string']:
+ response['body']['string'] = response['body']['string'].replace(self.random_name,
+ self.moniker)
+
+ self.replace_header(response, 'location', self.random_name, self.moniker)
+ self.replace_header(response, 'azure-asyncoperation', self.random_name, self.moniker)
+
+ return response
diff --git a/tools/azure-devtools/src/azure_devtools/scenario_tests/recording_processors.py b/tools/azure-devtools/src/azure_devtools/scenario_tests/recording_processors.py
new file mode 100644
index 000000000000..cfbc6b3cfd96
--- /dev/null
+++ b/tools/azure-devtools/src/azure_devtools/scenario_tests/recording_processors.py
@@ -0,0 +1,200 @@
+# --------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# --------------------------------------------------------------------------------------------
+
+from .utilities import is_text_payload, is_json_payload
+
+
+class RecordingProcessor(object):
+ def process_request(self, request): # pylint: disable=no-self-use
+ return request
+
+ def process_response(self, response): # pylint: disable=no-self-use
+ return response
+
+ @classmethod
+ def replace_header(cls, entity, header, old, new):
+ cls.replace_header_fn(entity, header, lambda v: v.replace(old, new))
+
+ @classmethod
+ def replace_header_fn(cls, entity, header, replace_fn):
+ # Loop over the headers to find the one we want case insensitively,
+ # but we don't want to modify the case of original header key.
+ for key, values in entity['headers'].items():
+ if key.lower() == header.lower():
+ entity['headers'][key] = [replace_fn(v) for v in values]
+
+
+class SubscriptionRecordingProcessor(RecordingProcessor):
+ def __init__(self, replacement):
+ self._replacement = replacement
+
+ def process_request(self, request):
+ request.uri = self._replace_subscription_id(request.uri)
+
+ if is_text_payload(request) and request.body:
+ request.body = self._replace_subscription_id(request.body.decode()).encode()
+
+ return request
+
+ def process_response(self, response):
+ if is_text_payload(response) and response['body']['string']:
+ response['body']['string'] = self._replace_subscription_id(response['body']['string'])
+
+ self.replace_header_fn(response, 'location', self._replace_subscription_id)
+ self.replace_header_fn(response, 'azure-asyncoperation', self._replace_subscription_id)
+
+ return response
+
+ def _replace_subscription_id(self, val):
+ import re
+ # subscription presents in all api call
+ retval = re.sub('/(subscriptions)/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}',
+ r'/\1/{}'.format(self._replacement),
+ val,
+ flags=re.IGNORECASE)
+
+ # subscription is also used in graph call
+ retval = re.sub('https://(graph.windows.net)/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}',
+ r'https://\1/{}'.format(self._replacement),
+ retval,
+ flags=re.IGNORECASE)
+ return retval
+
+
+class LargeRequestBodyProcessor(RecordingProcessor):
+ def __init__(self, max_request_body=128):
+ self._max_request_body = max_request_body
+
+ def process_request(self, request):
+ if is_text_payload(request) and request.body and len(request.body) > self._max_request_body * 1024:
+ request.body = '!!! The request body has been omitted from the recording because its ' \
+ 'size {} is larger than {}KB. !!!'.format(len(request.body),
+ self._max_request_body)
+
+ return request
+
+
+class LargeResponseBodyProcessor(RecordingProcessor):
+ control_flag = ''
+
+ def __init__(self, max_response_body=128):
+ self._max_response_body = max_response_body
+
+ def process_response(self, response):
+ if is_text_payload(response):
+ length = len(response['body']['string'] or '')
+ if length > self._max_response_body * 1024:
+
+ if is_json_payload(response):
+ from .decorators import AllowLargeResponse # pylint: disable=cyclic-import
+ raise ValueError("The json response body exceeds the default limit of {}kb. Use '@{}' "
+ "on your test method to increase the limit or update test logics to avoid "
+ "big payloads".format(self._max_response_body, AllowLargeResponse.__name__))
+
+ response['body']['string'] = \
+ "!!! The response body has been omitted from the recording because it is larger " \
+ "than {} KB. It will be replaced with blank content of {} bytes while replay. " \
+ "{}{}".format(self._max_response_body, length, self.control_flag, length)
+ return response
+
+
+class LargeResponseBodyReplacer(RecordingProcessor):
+ def process_response(self, response):
+ if is_text_payload(response) and not is_json_payload(response):
+ import six
+ body = response['body']['string']
+
+ # backward compatibility. under 2.7 response body is unicode, under 3.5 response body is
+ # bytes. when set the value back, the same type must be used.
+ body_is_string = isinstance(body, six.string_types)
+
+ content_in_string = (response['body']['string'] or b'').decode('utf-8')
+ index = content_in_string.find(LargeResponseBodyProcessor.control_flag)
+
+ if index > -1:
+ length = int(content_in_string[index + len(LargeResponseBodyProcessor.control_flag):])
+ if body_is_string:
+ response['body']['string'] = '0' * length
+ else:
+ response['body']['string'] = bytes([0] * length)
+
+ return response
+
+
+class OAuthRequestResponsesFilter(RecordingProcessor):
+ """Remove oauth authentication requests and responses from recording."""
+
+ def process_request(self, request):
+ # filter request like:
+ # GET https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/oauth2/token
+ # POST https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/oauth2/v2.0/token
+ import re
+ if not re.match('https://login.microsoftonline.com/([^/]+)/oauth2(?:/v2.0)?/token', request.uri):
+ return request
+ return None
+
+
+class DeploymentNameReplacer(RecordingProcessor):
+ """Replace the random deployment name with a fixed mock name."""
+
+ def process_request(self, request):
+ import re
+ request.uri = re.sub('/deployments/([^/?]+)', '/deployments/mock-deployment', request.uri)
+ return request
+
+
+class AccessTokenReplacer(RecordingProcessor):
+ """Replace the access token for service principal authentication in a response body."""
+
+ def __init__(self, replacement='fake_token'):
+ self._replacement = replacement
+
+ def process_response(self, response):
+ import json
+ try:
+ body = json.loads(response['body']['string'])
+ body['access_token'] = self._replacement
+ except (KeyError, ValueError):
+ return response
+ response['body']['string'] = json.dumps(body)
+ return response
+
+
+class GeneralNameReplacer(RecordingProcessor):
+ def __init__(self):
+ self.names_name = []
+
+ def register_name_pair(self, old, new):
+ self.names_name.append((old, new))
+
+ def process_request(self, request):
+ for old, new in self.names_name:
+ request.uri = request.uri.replace(old, new)
+
+ if is_text_payload(request) and request.body:
+ body = str(request.body)
+ if old in body:
+ request.body = body.replace(old, new)
+
+ return request
+
+ def process_response(self, response):
+ for old, new in self.names_name:
+ if is_text_payload(response) and response['body']['string']:
+ response['body']['string'] = response['body']['string'].replace(old, new)
+
+ self.replace_header(response, 'location', old, new)
+ self.replace_header(response, 'azure-asyncoperation', old, new)
+
+ return response
+
+
+class RequestUrlNormalizer(RecordingProcessor):
+ """URL parsing fix to account for '//' vs '/' in different versions of python"""
+
+ def process_request(self, request):
+ import re
+ request.uri = re.sub('(? length:
+ raise ValueError('The length of the prefix must not be longer than random name length')
+
+ padding_size = length - len(prefix)
+ if padding_size < 4:
+ raise ValueError('The randomized part of the name is shorter than 4, which may not be able to offer enough '
+ 'randomness')
+
+ random_bytes = os.urandom(int(math.ceil(float(padding_size) / 8) * 5))
+ random_padding = base64.b32encode(random_bytes)[:padding_size]
+
+ return str(prefix + random_padding.decode().lower())
+
+
+def get_sha1_hash(file_path):
+ sha1 = hashlib.sha256()
+ with open(file_path, 'rb') as f:
+ while True:
+ data = f.read(65536)
+ if not data:
+ break
+ sha1.update(data)
+
+ return sha1.hexdigest()
+
+
+def _get_content_type(entity):
+ # 'headers' is a field of 'request', but it is a dict-key in 'response'
+ headers = getattr(entity, 'headers', None)
+ if headers is None:
+ headers = entity.get('headers')
+
+ content_type = None
+ if headers:
+ content_type = headers.get('content-type', None)
+ if content_type:
+ # content-type could an array from response, let us extract it out
+ content_type = content_type[0] if isinstance(content_type, list) else content_type
+ content_type = content_type.split(";")[0].lower()
+ return content_type
+
+
+def is_text_payload(entity):
+ text_content_list = ['application/json', 'application/xml', 'text/', 'application/test-content']
+
+ content_type = _get_content_type(entity)
+ if content_type:
+ return any(content_type.startswith(x) for x in text_content_list)
+ return True
+
+
+def is_json_payload(entity):
+ return _get_content_type(entity) == 'application/json'
+
+
+def trim_kwargs_from_test_function(fn, kwargs):
+ # the next function is the actual test function. the kwargs need to be trimmed so
+ # that parameters which are not required will not be passed to it.
+ if not is_preparer_func(fn):
+ args, _, kw, _ = inspect.getargspec(fn) # pylint: disable=deprecated-method
+ if kw is None:
+ args = set(args)
+ for key in [k for k in kwargs if k not in args]:
+ del kwargs[key]
+
+
+def is_preparer_func(fn):
+ return getattr(fn, '__is_preparer', False)
diff --git a/tools/azure-sdk-tools/dev_requirements.txt b/tools/azure-sdk-tools/dev_requirements.txt
new file mode 100644
index 000000000000..252afe5ae37a
--- /dev/null
+++ b/tools/azure-sdk-tools/dev_requirements.txt
@@ -0,0 +1 @@
+-e ../azure-devtools
\ No newline at end of file