diff --git a/github3/repos/contents.py b/github3/repos/contents.py index c8f7e75b8..e143d3475 100644 --- a/github3/repos/contents.py +++ b/github3/repos/contents.py @@ -156,10 +156,10 @@ def update(self, message, content, branch=None, committer=None, 'author': validate_commmitter(author)} self._remove_none(data) json = self._json(self._put(self._api, data=dumps(data)), 200) - if 'content' in json: + if json and 'content' in json: self._update_attributes(json['content']) json['content'] = self - if 'commit' in json: + if json and 'commit' in json: json['commit'] = Commit(json['commit'], self) return json diff --git a/tests/cassettes/Contents_update.json b/tests/cassettes/Contents_update.json new file mode 100644 index 000000000..d5b22a684 --- /dev/null +++ b/tests/cassettes/Contents_update.json @@ -0,0 +1 @@ +{"http_interactions": [{"request": {"body": {"string": "", "encoding": "utf-8"}, "headers": {"Accept-Encoding": "gzip, deflate", "Accept": "application/vnd.github.v3.full+json", "User-Agent": "github3.py/1.0.0a2", "Accept-Charset": "utf-8", "Connection": "keep-alive", "Content-Type": "application/json", "Authorization": "token "}, "method": "GET", "uri": "https://api.github.com/repos/github3py/delete_contents"}, "response": {"body": {"string": "", "base64_string": "H4sIAAAAAAAAA+2Y326jOhDGXyXi9mTjJN1Nu0hHe95gb3q1N5EBB6wajGyTKkV99/PZ5l+yVUnqXlaqKgKenz/GHjMzbcSzKP6x/v6w296tl1FFSxbFUcYEM2yfysqwyuhoGR0aIfbd05yboknu6hP5e5x8rpiK4jYSMucVUMNgQOxcm/uH7ebHbhnRIzVU7RslMKowptYxIf6mXnmrRjPVaVilsiQN6ax/Hf+9Ay9XHcSCI9y4gNW8A3lr0DSZ6ilMKS4E+Mdu/HTkQQohn2F/qffdKchgZj3oELzKP4KAWUukKRgchtd4tS/PtblRjjNp8WLa7HlmIRpLoFh2m6TOCILsYr+2RLFaOlqT6FTx2nBZ3SjtzBQoqXJa8Rf6ARRM7Y61om4U4Uxgyo5219/mFG/TklrxI01P1h2KpYwf4d2P8C6MgTOn2sbm74lnrM85ApVmpQ22AxWavS4jp8FgsLuxRHRdtc/fCOeMDQuKqR8Lrhf4M6yspaKKi9MC2zFbJKdFFy2r+rQ4SLXgODkQnnb5MFwbbGCIxZOnQdW7weqWYgzBN6RZ1swazUAQnkBA1hM7BZIsoSX438VVimCnCXxk5NyZMSfyDNWS6U+7yQyjZaB4hwCqkDLUow4BFNe6YVft+7nXdyRN+vCqmjLx5981QTUH9wzopVrzvGIs0JMDpiX9MZ0oWqVFKLintMRfuZWneaBcSwAoETIJJCH6icO0RBfUf57MPlyh5VrKGVaxwyfItZQBa1Tw2jupFjNA8Z002AaBWnsKaTvPClrlDc1DuQMGO8B+0XP6MpvfzMXTyAHUZm6KJ81nHIEjyar1aQbOgVDXjqAR67KX97/9s26Y5EHOEWXJ5/KJOWYHOQuETwHbfXsJt7/nU6BrJFtKS8ZT238YOn6Yl7svQ691OktfuIRN0FNI+09NTWFPNUxWU8VCuQ5C2oQiXVutVm3BqEvHS6aC49ozAKMqLZB+hmltewpypZIal+wfrNQMyb+QNAsMwQEDpF/QML2eMd0LNSrXQJEOMWWWXCCnlVXoGTxypvRKGn7g6TW1z1wInqHaX5pXKVtSIZbYgIanHPsambldT6SrLNRPnoFXQRfBF0CCYYsHel+hGWEpLfE1a8ZqIU+fcD5NQDa0FUPNlO2pQaWzXW9239abb9v7x/Uu3uzi77s/GNPU2eyYutHFX5iHx/V9vP0Z3zkMjtxul+MKXQ9fO503HS4rHtvJgKnWxWj632gY+8s3mjKdYSqwXS9i65Z5j5ffxGuMIbiQJauRrURxhSiy9eoLrtFqmuQcqWwqeB03n6lBsozv+nirz1N6QEH13kd5FBvV2PIWd8ZzZHLzmT/x6SCrQw/1py8gx4lKrpTsGlJeq6xZ1c01EeSrRqt28vxMvfuRsQNthNn7hB17qqTaoDeG8pypEm+ANANi2qgr3v272N3TS7bHjr9GTT9tiHz117r+41d/beycvt+J/OqvnXd/kcacNecQltf31ypmntE6mpwJ05KkO1E2r/8DMfbCQV0XAAA=", "encoding": "utf-8"}, "headers": {"vary": "Accept, Authorization, Cookie, X-GitHub-OTP", "x-github-media-type": "github.v3; param=full; format=json", "x-oauth-scopes": "admin:public_key, gist, repo, user", "x-xss-protection": "1; mode=block", "x-content-type-options": "nosniff", "x-accepted-oauth-scopes": "repo", "etag": "W/\"2b7352621b54ddc5cc69e260ad86b555\"", "cache-control": "private, max-age=60, s-maxage=60", "status": "200 OK", "x-ratelimit-remaining": "4978", "x-served-by": "cee4c0729c8e9147e7abcb45b9d69689", "access-control-expose-headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", "transfer-encoding": "chunked", "x-github-request-id": "97E45D32:14F48:218827:56A9C3BB", "access-control-allow-credentials": "true", "last-modified": "Wed, 27 Jan 2016 06:16:46 GMT", "date": "Thu, 28 Jan 2016 07:31:07 GMT", "access-control-allow-origin": "*", "content-security-policy": "default-src 'none'", "content-encoding": "gzip", "strict-transport-security": "max-age=31536000; includeSubdomains; preload", "server": "GitHub.com", "x-ratelimit-limit": "5000", "x-frame-options": "deny", "content-type": "application/json; charset=utf-8", "x-ratelimit-reset": "1453967471"}, "status": {"message": "OK", "code": 200}, "url": "https://api.github.com/repos/github3py/delete_contents"}, "recorded_at": "2016-01-28T07:31:07"}, {"request": {"body": {"string": "", "encoding": "utf-8"}, "headers": {"Accept-Encoding": "gzip, deflate", "Accept": "application/vnd.github.v3.full+json", "User-Agent": "github3.py/1.0.0a2", "Accept-Charset": "utf-8", "Connection": "keep-alive", "Content-Type": "application/json", "Authorization": "token "}, "method": "GET", "uri": "https://api.github.com/repos/github3py/delete_contents/readme"}, "response": {"body": {"string": "", "base64_string": "H4sIAAAAAAAAA7WSX2vCMBTFv0ufxVRr1Qoy5uZqHb44UBRB0uT2z0zS0KS4TvzuS6eIk/mgYw8h4UB+99xz784SmIPVs6bDx+fJsM6pVbMk1smFpBJslHbHc0O306LYBohc14mcVtdzutBxIkwj2rYbtNUJXcNQ6afBdps1q8iZ+ZpoLVUPISzTepzqpAjrJOMoB5kpdBAcWSIKDDSsSSY0CK3Q6XHy95BD1OdYachNmURztv5Z4Yx+nRuyLEQHCjpv3fy4wN1o2ABQBVfohrBothUsw/SidI63x6wKBfkxiu/Yrjf2S0+6lNWEo5SBSeyIMUJQDjbL+Qej/ixaNL3C3AUdTV5nfiJJOaiOvZw3tqEzTghnCt4GDdKcbQJ/7K5E4FNJ/aSxeJ8UZLSJl9wrA59VFEH4i43nXhGMpow4UxlyUjzF/f5KGAMgSEZTERsHIVbQbhltzVKxUVZvZylg0f+ti8ntfvhdo60W9KzkH5Zzv/8C4g372q0DAAA=", "encoding": "utf-8"}, "headers": {"vary": "Accept, Authorization, Cookie, X-GitHub-OTP", "x-github-media-type": "github.v3; param=full; format=json", "x-oauth-scopes": "admin:public_key, gist, repo, user", "x-xss-protection": "1; mode=block", "x-content-type-options": "nosniff", "x-accepted-oauth-scopes": "", "etag": "W/\"f96980266c26e5e87d6ff79c2b424621\"", "cache-control": "private, max-age=60, s-maxage=60", "status": "200 OK", "x-ratelimit-remaining": "4977", "x-served-by": "5aeb3f30c9e3ef6ef7bcbcddfd9a68f7", "access-control-expose-headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", "transfer-encoding": "chunked", "x-github-request-id": "97E45D32:14F48:21884A:56A9C3BB", "access-control-allow-credentials": "true", "last-modified": "Thu, 28 Jan 2016 07:29:36 GMT", "date": "Thu, 28 Jan 2016 07:31:07 GMT", "access-control-allow-origin": "*", "content-security-policy": "default-src 'none'", "content-encoding": "gzip", "strict-transport-security": "max-age=31536000; includeSubdomains; preload", "server": "GitHub.com", "x-ratelimit-limit": "5000", "x-frame-options": "deny", "content-type": "application/json; charset=utf-8", "x-ratelimit-reset": "1453967471"}, "status": {"message": "OK", "code": 200}, "url": "https://api.github.com/repos/github3py/delete_contents/readme"}, "recorded_at": "2016-01-28T07:31:07"}, {"request": {"body": {"string": "{\"content\": \"SEVMTE8=\", \"sha\": \"6795b574da0eef553f348938e73fadfd601d47b5\", \"message\": \"Updating README.md\"}", "encoding": "utf-8"}, "headers": {"Content-Length": "107", "Accept-Encoding": "gzip, deflate", "Accept": "application/vnd.github.v3.full+json", "User-Agent": "github3.py/1.0.0a2", "Accept-Charset": "utf-8", "Connection": "keep-alive", "Content-Type": "application/json", "Authorization": "token "}, "method": "PUT", "uri": "https://api.github.com/repos/github3py/delete_contents/contents/README.md"}, "response": {"body": {"string": "", "base64_string": "H4sIAAAAAAAAA7VUy27bMBD8lUBnx6ReJCWgSIo2x1yK9tKiMPhYWkL1gkghSAP9e5ex4zpGA8SPAjoQK2lmZ3a4T5HuOw+dj8qnqJMtRGX05e7j5/u7ZWuiRTRIXx2UXCWxYgpGc60kF0IBHsHqLGaQUKMgjxMuRWJSSmPEcPVvhM0X0TQ2+Gfl/eBKQuRQL9e1rya11H1LRhh6RzaFdHgkBhrwsNq258jusGvvZgT7oZXOw4gslW+b1WuGPfS3cVXTK7JBIfvK8Y8DuCMbRgASwB05wivTP3RNL80B9Sgftl5NDsatFc+2vS3sH5r84xAGbOsG0LFVU3e/XBi8g8b+v8lgi6eDn+RiyMIe5Rk5mOcF3pC2DRLQp+foc5MnOqHUCHyY5dQqI1MoQNlMUEYF47awLEeLz0p8kL7hduQIzlMvwobqGCY5+aof9zbHvfT+6lM1dWvUDq2swxRq71o8e6/Di9t1KIfo4idG+pDHhMbsmsbXifhKeZnGJeXfo53x4Xr/XU4XpvAjYAcvk2VaZSZVuZGgZSYsB81xt3GqtYit4YVWOdeUX2KygdmRdzOiHS04J9fBsG8DOld366vXq3rEPY73+ceLHGGBCp4zlhTAbZ6ntkAFomC4mQ3PbMZZDEJcNKhHcJ4Z1HczzT/n+Q+GPTUB6AYAAA==", "encoding": "utf-8"}, "headers": {"vary": "Accept, Authorization, Cookie, X-GitHub-OTP", "x-github-media-type": "github.v3; param=full; format=json", "x-oauth-scopes": "admin:public_key, gist, repo, user", "x-xss-protection": "1; mode=block", "x-content-type-options": "nosniff", "x-accepted-oauth-scopes": "", "etag": "W/\"b7558c14fd20e3506470ac71d1d932c0\"", "cache-control": "private, max-age=60, s-maxage=60", "status": "200 OK", "x-ratelimit-remaining": "4976", "x-served-by": "8a5c38021a5cd7cef7b8f49a296fee40", "access-control-expose-headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", "transfer-encoding": "chunked", "x-github-request-id": "97E45D32:14F48:21885B:56A9C3BB", "access-control-allow-credentials": "true", "date": "Thu, 28 Jan 2016 07:31:07 GMT", "access-control-allow-origin": "*", "content-security-policy": "default-src 'none'", "content-encoding": "gzip", "strict-transport-security": "max-age=31536000; includeSubdomains; preload", "server": "GitHub.com", "x-ratelimit-limit": "5000", "x-frame-options": "deny", "content-type": "application/json; charset=utf-8", "x-ratelimit-reset": "1453967471"}, "status": {"message": "OK", "code": 200}, "url": "https://api.github.com/repos/github3py/delete_contents/contents/README.md"}, "recorded_at": "2016-01-28T07:31:08"}], "recorded_with": "betamax/0.5.0"} \ No newline at end of file diff --git a/tests/cassettes/Hook_delete.json b/tests/cassettes/Hook_delete.json new file mode 100644 index 000000000..f7ca049ce --- /dev/null +++ b/tests/cassettes/Hook_delete.json @@ -0,0 +1 @@ +{"http_interactions": [{"request": {"body": {"string": "", "encoding": "utf-8"}, "headers": {"Accept-Encoding": "gzip, deflate", "Accept": "application/vnd.github.v3.full+json", "User-Agent": "github3.py/1.0.0a2", "Accept-Charset": "utf-8", "Connection": "keep-alive", "Content-Type": "application/json", "Authorization": "token "}, "method": "GET", "uri": "https://api.github.com/repos/github3py/delete_contents"}, "response": {"body": {"string": "", "base64_string": "H4sIAAAAAAAAA+2Y326rOBDGXyXidnPipD0nrZBWZ99gb3q1N5EDDlgFjGyTKkV99/3G5l9yqpLUvaxUVQQ8P3+MPWZm2kimUfxr/fNxe3e/XkYVL0UUR6kohBW7RFVWVNZEy+jQFMWue5pJmzf7+/rE/hynXiqho7iNCpXJCqhhMCA01+bh8W7za7uM+JFbrneNLjAqt7Y2MWP+pll5q8YI3WlYJapkDeusfx//vgcv0x2EwBFuXMBq2YG8NWiGTfXktiwuBPjHbvx05EEVhXqB/aXeD6dggxl50CFklX0GAbOWKZsLOAyv8UYvL429UY4zafFixu5kShCDJdAivU1SZwRBtNhvLdOiVo7W7E2iZW2lqm6UdmYKlNIZr+Qr/wQKprRjSdSNIpwJTMWRdv1tTvE2Lau1PPLkRO7QIhHyCO9+hndhDJw91RSb/048Qz6XCFSelhRsB14Y8baMnAaLwe7GEtF11T5/J5xTMSwopn7KpVngz4qyVpprWZwW2I7pYn9adNGyqk+Lg9ILiZMD4UnLh+HGYgNDLJ48D6o+DFa3FGMIviONWDNrNANBeAIBWc/iFEgiQsvwv4urBMHO9/CRVXNnxpzIM1TLpj9pk1nBy0DxDgFUrlSoRx0CKGlMI67a93Ov70iG9eFVNeXen3/XBNUc3DOglxsjs0qIQE8OmJb1x/Re8yrJQ8E9pWX+yq08zwLlEgGgfaH2gSREP3OYlpmc+8+T3YUrJC5RzrBaHL5ALlEGrNXBa++kEmaA4jtpsQ0CtfYU1naeLXiVNTwL5Q4Y7AD6omf8dTa/mYunkQMoZW5a7puvOAJHEqn1aQbOgVDXjqAR67KXj7/9s26Y5EHOEWUp5/KJOWYHOQuELwHTvr2E0+/5FOgayURp2Xhq+w9Dxw/zcvdl6LVOZ+kLl7AJegpr/6q5zelUw2Q11yKU6yCs3XOka6vVqs0Fd+l4KXRwXHsGYFwnOdLPMK1tT0GuVHLrkv0DSU2R/BeKp4EhOGCA9AsaptczpnuhRuUaKNIhpsxSFshpVRV6Bo+cKb1SVh5kck3tMxeCZ6j2t5FVIpa8KJbYgFYmEvsamTmtJ9JVEeonz8CroIvgC6BCYIsHel+jGUGUlvmaNRV1oU5fcD5NQBTaWqBmSnfcotK5W2+2P9abH3cPT+ttvNnGP7f/YUxTp7Nj6sbkf2Aen9YP8f0mXj8SBkdut8txha6Hr53Omw6XFQ91MmBqTD6a/jMaxv7ynaZMZ5gU2K4XsXXLvMfLb+I1xhCcq1LUyFaiuEIUUb36iuvNWc6RqKaC19F/euEWyTK+6+OtPk/pATk3Ox/lUWx1Q+Ut7oznyOTmi3yW00Gkwwz1py8gx4lKqbXqGlJeq6pF1c01EeSrRlI7eX6m3v1IxYE3hd35hB17quTGojeG8lzoEm+ANANi2qgr3v270O7pJdOx469R008bIt/9ta7/+N1fGzunH3civ/tr591fpDFnzTmE5fX9tUrYF7SOJmfCtCTpTpTN2/9Zr+3bXRcAAA==", "encoding": "utf-8"}, "headers": {"vary": "Accept, Authorization, Cookie, X-GitHub-OTP", "x-github-media-type": "github.v3; param=full; format=json", "x-oauth-scopes": "admin:public_key, gist, repo, user", "x-xss-protection": "1; mode=block", "x-content-type-options": "nosniff", "x-accepted-oauth-scopes": "repo", "etag": "W/\"f5392cd70006da08fc695a5a5ec0ae66\"", "cache-control": "private, max-age=60, s-maxage=60", "status": "200 OK", "x-ratelimit-remaining": "4998", "x-served-by": "2c18a09f3ac5e4dd1e004af7c5a94769", "access-control-expose-headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", "transfer-encoding": "chunked", "x-github-request-id": "97E45D32:14F48:25F4A2:56A9CB17", "access-control-allow-credentials": "true", "last-modified": "Wed, 27 Jan 2016 06:16:46 GMT", "date": "Thu, 28 Jan 2016 08:02:31 GMT", "access-control-allow-origin": "*", "content-security-policy": "default-src 'none'", "content-encoding": "gzip", "strict-transport-security": "max-age=31536000; includeSubdomains; preload", "server": "GitHub.com", "x-ratelimit-limit": "5000", "x-frame-options": "deny", "content-type": "application/json; charset=utf-8", "x-ratelimit-reset": "1453971690"}, "status": {"message": "OK", "code": 200}, "url": "https://api.github.com/repos/github3py/delete_contents"}, "recorded_at": "2016-01-28T08:02:31"}, {"request": {"body": {"string": "", "encoding": "utf-8"}, "headers": {"Accept-Encoding": "gzip, deflate", "Accept": "application/vnd.github.v3.full+json", "User-Agent": "github3.py/1.0.0a2", "Accept-Charset": "utf-8", "Connection": "keep-alive", "Content-Type": "application/json", "Authorization": "token "}, "method": "GET", "uri": "https://api.github.com/repos/github3py/delete_contents/hooks/7096472"}, "response": {"body": {"string": "", "base64_string": "H4sIAAAAAAAAA62QwU7DMAyG38VH1C1ZGRvNK3DgwgmEqqw1bbYuCbEzNk17dxwxJG5cJkWK/Mf5/Ps/Q04TGBiZIxmlbHTzwfGYN/Mu7FXCGEj9CPfxpHqckLHtgmf0TGoMYUdqrZvVcl1DBYzE7e2IqvAEG50fboktPBKu68FczVfg7R4liS/cyIvt2B2k5JSxAjyUbcG8wR28VyDrf7gBzPlPeJJdws8sfjdz59Wx2TbL1bER1DWslk+x8LcUfBntCbucsCUq+WuRREjIUsClgslKkgkpBmkso7rQy11rLY1sOYudX5cV7JHIDgX//FR+59hbxr61BVfrxWqmF7P68UWvzYOc+rX4SvhPz+Ub1JtoIx4CAAA=", "encoding": "utf-8"}, "headers": {"vary": "Accept, Authorization, Cookie, X-GitHub-OTP", "x-github-media-type": "github.v3; param=full; format=json", "x-oauth-scopes": "admin:public_key, gist, repo, user", "x-xss-protection": "1; mode=block", "x-content-type-options": "nosniff", "x-accepted-oauth-scopes": "admin:repo_hook, public_repo, read:repo_hook, repo, write:repo_hook", "etag": "W/\"2ddddf92bbbb624c8f4087732e25da04\"", "cache-control": "private, max-age=60, s-maxage=60", "status": "200 OK", "x-ratelimit-remaining": "4997", "x-served-by": "cee4c0729c8e9147e7abcb45b9d69689", "access-control-expose-headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", "transfer-encoding": "chunked", "x-github-request-id": "97E45D32:14F48:25F4CC:56A9CB17", "access-control-allow-credentials": "true", "last-modified": "Thu, 28 Jan 2016 07:57:52 GMT", "date": "Thu, 28 Jan 2016 08:02:31 GMT", "access-control-allow-origin": "*", "content-security-policy": "default-src 'none'", "content-encoding": "gzip", "strict-transport-security": "max-age=31536000; includeSubdomains; preload", "server": "GitHub.com", "x-ratelimit-limit": "5000", "x-frame-options": "deny", "content-type": "application/json; charset=utf-8", "x-ratelimit-reset": "1453971690"}, "status": {"message": "OK", "code": 200}, "url": "https://api.github.com/repos/github3py/delete_contents/hooks/7096472"}, "recorded_at": "2016-01-28T08:02:31"}, {"request": {"body": {"string": "", "encoding": "utf-8"}, "headers": {"Content-Length": "0", "Accept-Encoding": "gzip, deflate", "Accept": "application/vnd.github.v3.full+json", "User-Agent": "github3.py/1.0.0a2", "Accept-Charset": "utf-8", "Connection": "keep-alive", "Content-Type": "application/json", "Authorization": "token "}, "method": "DELETE", "uri": "https://api.github.com/repos/github3py/delete_contents/hooks/7096472"}, "response": {"body": {"string": "", "encoding": null}, "headers": {"status": "204 No Content", "x-ratelimit-remaining": "4996", "x-github-media-type": "github.v3; param=full; format=json", "x-content-type-options": "nosniff", "content-security-policy": "default-src 'none'", "access-control-expose-headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", "x-github-request-id": "97E45D32:14F48:25F4ED:56A9CB17", "strict-transport-security": "max-age=31536000; includeSubdomains; preload", "vary": "Accept-Encoding", "server": "GitHub.com", "x-ratelimit-limit": "5000", "x-oauth-scopes": "admin:public_key, gist, repo, user", "x-served-by": "318e55760cf7cdb40e61175a4d36cd32", "access-control-allow-credentials": "true", "date": "Thu, 28 Jan 2016 08:02:31 GMT", "x-frame-options": "deny", "access-control-allow-origin": "*", "x-accepted-oauth-scopes": "admin:repo_hook, public_repo, repo", "x-xss-protection": "1; mode=block", "x-ratelimit-reset": "1453971690"}, "status": {"message": "No Content", "code": 204}, "url": "https://api.github.com/repos/github3py/delete_contents/hooks/7096472"}, "recorded_at": "2016-01-28T08:02:31"}], "recorded_with": "betamax/0.5.0"} \ No newline at end of file diff --git a/tests/integration/test_repos_repo.py b/tests/integration/test_repos_repo.py index 9c423d594..1dcd6f2da 100644 --- a/tests/integration/test_repos_repo.py +++ b/tests/integration/test_repos_repo.py @@ -1066,3 +1066,32 @@ def test_delete(self): deleted = content.delete('Deleting readme from repository') assert deleted + + def test_update(self): + """Test the ability to update a file's content from a repository.""" + self.token_login() + cassette_name = self.cassette_name('update') + with self.recorder.use_cassette(cassette_name): + repository = self.gh.repository('github3py', 'delete_contents') + content = repository.readme() + update = content.update(message='Updating README.md', + content=b'HELLO') + + assert isinstance(update, dict) + assert isinstance(update['content'], github3.repos.contents.Contents) + assert isinstance(update['commit'], github3.git.Commit) + + +class TestHook(helper.IntegrationHelper): + + """Integration tests for Hook object.""" + + def test_delete(self): + self.token_login() + cassette_name = self.cassette_name('delete') + with self.recorder.use_cassette(cassette_name): + repository = self.gh.repository('github3py', 'delete_contents') + hook = repository.hook(7096472) + deleted = hook.delete() + + assert deleted is True diff --git a/tests/test_repos.py b/tests/test_repos.py index 9d6aef2ff..b0f8de480 100644 --- a/tests/test_repos.py +++ b/tests/test_repos.py @@ -4,46 +4,6 @@ from github3 import repos from tests.utils import (BaseCase, load, mock) -class TestContents(BaseCase): - def __init__(self, methodName='runTest'): - super(TestContents, self).__init__(methodName) - self.contents = repos.contents.Contents(load('readme')) - self.api = self.contents._api - - def setUp(self): - super(TestContents, self).setUp() - self.contents = repos.contents.Contents(self.contents.as_dict(), - self.g) - - def test_equality(self): - contents = repos.contents.Contents(load('readme')) - assert self.contents == contents - contents.sha = 'fakesha' - assert self.contents != contents - - @pytest.mark.xfail - def test_update(self): - self.response('create_content', 200) - self.put(self.api) - self.conf = { - 'data': { - 'message': 'foo', - 'content': 'Zm9vIGJhciBib2d1cw==', - 'sha': self.contents.sha, - } - } - - self.assertRaises(github3.GitHubError, self.contents.update, - None, None) - - self.not_called() - self.login() - - ret = self.contents.update('foo', b'foo bar bogus') - assert isinstance(ret, github3.git.Commit) - self.mock_assertions() - - class TestHook(BaseCase): def __init__(self, methodName='runTest'): super(TestHook, self).__init__(methodName) @@ -55,26 +15,6 @@ def setUp(self): super(TestHook, self).setUp() self.hook = repos.hook.Hook(self.hook.as_dict(), self.g) - def test_equality(self): - h = repos.hook.Hook(load('hook')) - assert self.hook == h - h._uniq = 1 - assert self.hook != h - - def test_repr(self): - assert repr(self.hook) == '' - - def test_delete(self): - self.response('', 204) - self.delete(self.api) - - self.assertRaises(github3.GitHubError, self.hook.delete) - self.not_called() - - self.login() - assert self.hook.delete() - self.mock_assertions() - def test_edit(self): self.response('hook', 200) self.patch(self.api) diff --git a/tests/unit/json/hook_example b/tests/unit/json/hook_example new file mode 100644 index 000000000..cf4bdbf80 --- /dev/null +++ b/tests/unit/json/hook_example @@ -0,0 +1,18 @@ +{ + "id": 1, + "url": "https://api.github.com/repos/octocat/Hello-World/hooks/1", + "test_url": "https://api.github.com/repos/octocat/Hello-World/hooks/1/test", + "ping_url": "https://api.github.com/repos/octocat/Hello-World/hooks/1/pings", + "name": "web", + "events": [ + "push", + "pull_request" + ], + "active": true, + "config": { + "url": "http://example.com/webhook", + "content_type": "json" + }, + "updated_at": "2011-09-06T20:39:23Z", + "created_at": "2011-09-06T17:26:27Z" +} diff --git a/tests/unit/test_repos_repo.py b/tests/unit/test_repos_repo.py index c16d17720..957675c8a 100644 --- a/tests/unit/test_repos_repo.py +++ b/tests/unit/test_repos_repo.py @@ -6,7 +6,7 @@ from base64 import b64encode from github3 import GitHubError from github3.null import NullObject -from github3.repos.repo import Repository, Contents +from github3.repos.repo import Repository, Contents, Hook from github3.models import GitHubCore from . import helper @@ -14,6 +14,9 @@ contents_url_for = helper.create_url_helper( 'https://api.github.com/repos/github3py/github3.py/contents/README.rst' ) +hook_url_for = helper.create_url_helper( + 'https://api.github.com/repos/octocat/Hello-World/hooks/1' +) url_for = helper.create_url_helper( 'https://api.github.com/repos/octocat/Hello-World' ) @@ -24,11 +27,15 @@ get_content_example_data = helper.create_example_data_helper( 'content_example' ) +get_hook_example_data = helper.create_example_data_helper( + 'hook_example' +) create_file_contents_example_data = helper.create_example_data_helper( 'create_file_contents_example' ) content_example_data = get_content_example_data() create_file_contents_example_data = create_file_contents_example_data() +hook_example_data = get_hook_example_data() repo_example_data = get_repo_example_data() @@ -1569,6 +1576,37 @@ def test_str(self): self.instance.path ) + def test_update(self): + """ + Verify the request for updating a file's contents on a repository. + """ + data = { + 'message': 'Updating content files.', + 'content': b'Updated content here.' + } + + self.instance.update(**data) + data.update({ + 'content': b64encode(data['content']).decode('utf-8'), + 'sha': self.instance.sha + }) + + self.put_called_with( + contents_url_for(), + data=data + ) + + def test_update_required_content(self): + """ + Verify the request for updating a file's contents on a repository. + """ + data = { + 'message': 'Updating content files.', + 'content': 1, + } + with pytest.raises(ValueError): + self.instance.update(**data) + class TestContentsRequiresAuth(helper.UnitRequiresAuthenticationHelper): @@ -1582,3 +1620,42 @@ def test_delete(self): Show that deleting content from a repository requires authentication. """ self.assert_requires_auth(self.instance.delete) + + def test_update(self): + """ + Show that updating a file's content on a repository requires + authentication. + """ + self.assert_requires_auth(self.instance.update) + + +class TestHook(helper.UnitHelper): + + """Test methods on Hook class.""" + + described_class = Hook + example_data = hook_example_data + + def test_str(self): + """Show that instance string is formatted correctly.""" + assert str(self.instance) == ''.format(self.instance.name) + + def test_edit(self): + """Verify the request for editing a hook.""" + self.instance.delete() + + self.session.delete.assert_called_once_with( + hook_url_for() + ) + + +class TestHookRequiresAuth(helper.UnitRequiresAuthenticationHelper): + + """Test methods on Hook object that require authentication.""" + + def delete(self): + """ + Show that a user must be authenticated to delete a hook on a + repository. + """ + self.assert_requires_auth(self.instance.delete)