Repository: PyGithub/PyGithub

Issue:
ProjectCard should have the move action?

How can one move a project card with PyGithub.  It seems like the moves action is not implemented.  Or am I missing something?  I need to be able to move a card from one column to another.


Discussion:
https://developer.github.com/v3/projects/cards/#move-a-project-card

Resolving patch:
diff --git a/github/ProjectCard.py b/github/ProjectCard.py
--- a/github/ProjectCard.py
+++ b/github/ProjectCard.py
@@ -24,6 +24,8 @@
 
 import github.GithubObject
 
+from . import Consts
+
 # NOTE: There is currently no way to get cards "in triage" for a project.
 # https://platform.github.community/t/moving-github-project-cards-that-are-in-triage/3784
 #
@@ -135,6 +137,31 @@ def get_content(self, content_type=github.GithubObject.NotSet):
         headers, data = self._requester.requestJsonAndCheck("GET", url)
         return retclass(self._requester, headers, data, completed=True)
 
+    def move(self, position, column):
+        """
+        :calls: `POST /projects/columns/cards/:card_id/moves <https://developer.github.com/v3/projects/cards>`_
+        :param position: string
+        :param column: :class:`github.ProjectColumn.ProjectColumn` or int
+        :rtype: bool
+        """
+        assert isinstance(position, str), position
+        assert isinstance(column, github.ProjectColumn.ProjectColumn) or isinstance(
+            column, int
+        ), column
+        post_parameters = {
+            "position": position,
+            "column": column.id
+            if isinstance(column, github.ProjectColumn.ProjectColumn)
+            else column,
+        }
+        status, _, _ = self._requester.requestJson(
+            "POST",
+            self.url + "/moves",
+            input=post_parameters,
+            headers={"Accept": Consts.mediaTypeProjectsPreview},
+        )
+        return status == 201
+
     def _initAttributes(self):
         self._archived = github.GithubObject.NotSet
         self._column_url = github.GithubObject.NotSet


Test patch:
diff --git a/tests/Project.py b/tests/Project.py
--- a/tests/Project.py
+++ b/tests/Project.py
@@ -138,6 +138,13 @@ def testGetProjectCardContent(self):
         note_content = note_card.get_content()
         self.assertEqual(note_content, None)
 
+    def testProjectCardMove(self):
+        proj = self.g.get_project(1682941)
+        cols = proj.get_columns()
+        card = cols[1].get_cards()[0]
+        self.assertTrue(card.move("top", cols[2].id))
+        self.assertTrue(card.move("bottom", cols[1]))
+
     def testGetAllProjectCards(self):
         expectedProjects = ["TestProject"]
         expectedCards = 5
diff --git a/tests/ReplayData/Project.testProjectCardMove.txt b/tests/ReplayData/Project.testProjectCardMove.txt
new file mode 100644
--- /dev/null
+++ b/tests/ReplayData/Project.testProjectCardMove.txt
@@ -0,0 +1,55 @@
+https
+GET
+api.github.com
+None
+/projects/1682941
+{'Accept': 'application/vnd.github.inertia-preview+json', 'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Mon, 13 Aug 2018 20:46: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', '4990'), ('X-RateLimit-Reset', '1534195928'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"d41667487e81d823d4dfd11da0547f36"'), ('X-OAuth-Scopes', 'read:org, read:user, repo, user:email'), ('X-Accepted-OAuth-Scopes', 'public_repo, repo'), ('X-GitHub-Media-Type', 'github.inertia-preview; 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.074803'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'ED5E:528C:C8567:104287:5B71EE27')]
+{"owner_url":"https://api.github.com/repos/bbi-yggy/PyGithub","url":"https://api.github.com/projects/1682941","html_url":"https://github.com/bbi-yggy/PyGithub/projects/1","columns_url":"https://api.github.com/projects/1682941/columns","id":1682941,"node_id":"MDc6UHJvamVjdDE2ODI5NDE=","name":"TestProject","body":"To be used for testing project access API for PyGithub.","number":1,"state":"open","creator":{"login":"bbi-yggy","id":6392037,"node_id":"MDQ6VXNlcjYzOTIwMzc=","avatar_url":"https://avatars3.githubusercontent.com/u/6392037?v=4","gravatar_id":"","url":"https://api.github.com/users/bbi-yggy","html_url":"https://github.com/bbi-yggy","followers_url":"https://api.github.com/users/bbi-yggy/followers","following_url":"https://api.github.com/users/bbi-yggy/following{/other_user}","gists_url":"https://api.github.com/users/bbi-yggy/gists{/gist_id}","starred_url":"https://api.github.com/users/bbi-yggy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bbi-yggy/subscriptions","organizations_url":"https://api.github.com/users/bbi-yggy/orgs","repos_url":"https://api.github.com/users/bbi-yggy/repos","events_url":"https://api.github.com/users/bbi-yggy/events{/privacy}","received_events_url":"https://api.github.com/users/bbi-yggy/received_events","type":"User","site_admin":false},"created_at":"2018-08-01T04:06:57Z","updated_at":"2018-08-13T05:36:20Z"}
+
+https
+GET
+api.github.com
+None
+/projects/1682941/columns
+{'Accept': 'application/vnd.github.inertia-preview+json', 'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Mon, 13 Aug 2018 20:46: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', '4989'), ('X-RateLimit-Reset', '1534195928'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"2651dd36184e34861070c99961911f72"'), ('X-OAuth-Scopes', 'read:org, read:user, repo, user:email'), ('X-Accepted-OAuth-Scopes', 'public_repo, repo'), ('X-GitHub-Media-Type', 'github.inertia-preview; 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.068263'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'EDAB:528C:C8574:104296:5B71EE27')]
+[{"url":"https://api.github.com/projects/columns/3138830","project_url":"https://api.github.com/projects/1682941","cards_url":"https://api.github.com/projects/columns/3138830/cards","id":3138830,"node_id":"MDEzOlByb2plY3RDb2x1bW4zMTM4ODMw","name":"To Do","created_at":"2018-08-01T04:07:35Z","updated_at":"2018-08-01T04:07:35Z"},{"url":"https://api.github.com/projects/columns/3138831","project_url":"https://api.github.com/projects/1682941","cards_url":"https://api.github.com/projects/columns/3138831/cards","id":3138831,"node_id":"MDEzOlByb2plY3RDb2x1bW4zMTM4ODMx","name":"In Progress","created_at":"2018-08-01T04:07:43Z","updated_at":"2018-08-13T05:36:20Z"},{"url":"https://api.github.com/projects/columns/3138832","project_url":"https://api.github.com/projects/1682941","cards_url":"https://api.github.com/projects/columns/3138832/cards","id":3138832,"node_id":"MDEzOlByb2plY3RDb2x1bW4zMTM4ODMy","name":"Done","created_at":"2018-08-01T04:07:47Z","updated_at":"2018-08-03T00:31:17Z"}]
+
+https
+GET
+api.github.com
+None
+/projects/columns/3138831/cards
+{'Accept': 'application/vnd.github.inertia-preview+json', 'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Mon, 13 Aug 2018 20:46: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', '4988'), ('X-RateLimit-Reset', '1534195928'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('ETag', 'W/"b34981c73fa8d0ac5117df1816b3548f"'), ('X-OAuth-Scopes', 'read:org, read:user, repo, user:email'), ('X-Accepted-OAuth-Scopes', 'public_repo, repo'), ('X-GitHub-Media-Type', 'github.inertia-preview; 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.133604'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'EDCD:528D:FD1E6:146E30:5B71EE27')]
+[{"url":"https://api.github.com/projects/columns/cards/11780055","id":11780055,"node_id":"MDExOlByb2plY3RDYXJkMTE3ODAwNTU=","note":null,"archived":false,"creator":{"login":"bbi-yggy","id":6392037,"node_id":"MDQ6VXNlcjYzOTIwMzc=","avatar_url":"https://avatars3.githubusercontent.com/u/6392037?v=4","gravatar_id":"","url":"https://api.github.com/users/bbi-yggy","html_url":"https://github.com/bbi-yggy","followers_url":"https://api.github.com/users/bbi-yggy/followers","following_url":"https://api.github.com/users/bbi-yggy/following{/other_user}","gists_url":"https://api.github.com/users/bbi-yggy/gists{/gist_id}","starred_url":"https://api.github.com/users/bbi-yggy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bbi-yggy/subscriptions","organizations_url":"https://api.github.com/users/bbi-yggy/orgs","repos_url":"https://api.github.com/users/bbi-yggy/repos","events_url":"https://api.github.com/users/bbi-yggy/events{/privacy}","received_events_url":"https://api.github.com/users/bbi-yggy/received_events","type":"User","site_admin":false},"created_at":"2018-08-01T04:53:59Z","updated_at":"2018-08-01T04:54:16Z","column_url":"https://api.github.com/projects/columns/3138831","content_url":"https://api.github.com/repos/bbi-yggy/PyGithub/issues/1"},{"url":"https://api.github.com/projects/columns/cards/12078706","id":12078706,"node_id":"MDExOlByb2plY3RDYXJkMTIwNzg3MDY=","note":null,"archived":false,"creator":{"login":"bbi-yggy","id":6392037,"node_id":"MDQ6VXNlcjYzOTIwMzc=","avatar_url":"https://avatars3.githubusercontent.com/u/6392037?v=4","gravatar_id":"","url":"https://api.github.com/users/bbi-yggy","html_url":"https://github.com/bbi-yggy","followers_url":"https://api.github.com/users/bbi-yggy/followers","following_url":"https://api.github.com/users/bbi-yggy/following{/other_user}","gists_url":"https://api.github.com/users/bbi-yggy/gists{/gist_id}","starred_url":"https://api.github.com/users/bbi-yggy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bbi-yggy/subscriptions","organizations_url":"https://api.github.com/users/bbi-yggy/orgs","repos_url":"https://api.github.com/users/bbi-yggy/repos","events_url":"https://api.github.com/users/bbi-yggy/events{/privacy}","received_events_url":"https://api.github.com/users/bbi-yggy/received_events","type":"User","site_admin":false},"created_at":"2018-08-13T04:46:29Z","updated_at":"2018-08-13T04:46:44Z","column_url":"https://api.github.com/projects/columns/3138831","content_url":"https://api.github.com/repos/bbi-yggy/PyGithub/issues/2"},{"url":"https://api.github.com/projects/columns/cards/12079385","id":12079385,"node_id":"MDExOlByb2plY3RDYXJkMTIwNzkzODU=","note":"Test note","archived":false,"creator":{"login":"bbi-yggy","id":6392037,"node_id":"MDQ6VXNlcjYzOTIwMzc=","avatar_url":"https://avatars3.githubusercontent.com/u/6392037?v=4","gravatar_id":"","url":"https://api.github.com/users/bbi-yggy","html_url":"https://github.com/bbi-yggy","followers_url":"https://api.github.com/users/bbi-yggy/followers","following_url":"https://api.github.com/users/bbi-yggy/following{/other_user}","gists_url":"https://api.github.com/users/bbi-yggy/gists{/gist_id}","starred_url":"https://api.github.com/users/bbi-yggy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bbi-yggy/subscriptions","organizations_url":"https://api.github.com/users/bbi-yggy/orgs","repos_url":"https://api.github.com/users/bbi-yggy/repos","events_url":"https://api.github.com/users/bbi-yggy/events{/privacy}","received_events_url":"https://api.github.com/users/bbi-yggy/received_events","type":"User","site_admin":false},"created_at":"2018-08-13T05:36:13Z","updated_at":"2018-08-13T05:36:20Z","column_url":"https://api.github.com/projects/columns/3138831"}]
+
+https
+POST
+api.github.com
+None
+/projects/columns/cards/11780055/moves
+{'Accept': 'application/vnd.github.inertia-preview+json', 'Authorization': 'Basic login_and_password_removed', 'Content-Type': 'application/json', 'User-Agent': 'PyGithub/Python'}
+{"column": 3138832, "position": "top"}
+201
+[('status', '201 Created'), ('x-ratelimit-remaining', '4982'), ('content-length', '2'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"f79a53550c9b90814f0be2b54ab2cc8e"'), ('date', 'Fri, 17 Jan 2020 02:03:18 GMT'), ('content-type', 'application/json; charset=utf-8')]
+{}
+
+https
+POST
+api.github.com
+None
+/projects/columns/cards/11780055/moves
+{'Accept': 'application/vnd.github.inertia-preview+json', 'Authorization': 'Basic login_and_password_removed', 'Content-Type': 'application/json', 'User-Agent': 'PyGithub/Python'}
+{"column": 3138831, "position": "bottom"}
+201
+[('status', '201 Created'), ('x-ratelimit-remaining', '4982'), ('content-length', '2'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"e87658ab0c9b90814f0be2b54ab2cc8e"'), ('date', 'Fri, 17 Jan 2020 02:03:24 GMT'), ('content-type', 'application/json; charset=utf-8')]
+{}
+