{"action":"created","comment":{"url":"https://api.github.com/repos/opalmer/pywincffi/pulls/comments/59101173","id":59101173,"diff_hunk":"@@ -120,3 +122,95 @@ def test_process_dies_before_timeout(self):\n         self.assertEqual(\n             WaitForSingleObject(hProcess, library.INFINITE),\n             library.WAIT_OBJECT_0)\n+\n+\n+class TestGetHandleInformation(TestCase):\n+    \"\"\"\n+    Tests for :func:`pywincffi.kernel32.GetHandleInformation`\n+    \"\"\"\n+    def _expected_inheritance(self):\n+        # Python >= 3.4 creates non-inheritable handles (PEP 0446)\n+        if sys.hexversion >= 0x30400f0:\n+            return 0\n+        else:\n+            return 1\n+\n+    def test_get_handle_info_stdin(self):\n+        _, library = dist.load()\n+        handle_stdin = GetStdHandle(library.STD_INPUT_HANDLE)\n+        inherit = GetHandleInformation(handle_stdin) & 1\n+        expected = self._expected_inheritance()\n+        self.assertEqual(inherit, expected)\n+\n+    def test_get_handle_info_file(self):\n+        # can't use mkstemp: not inheritable on Python < 3.4\n+        dirname = tempfile.mkdtemp()\n+        filename = os.path.join(dirname, \"test_file\")\n+        test_file = open(filename, \"w\")\n+        test_file.write(\"data\")\n+        file_handle = handle_from_file(test_file)\n+        inherit = GetHandleInformation(file_handle) & 1\n+\n+        expected = self._expected_inheritance()\n+        self.assertEqual(inherit, expected)\n+        test_file.close()\n+        os.unlink(filename)\n+        os.rmdir(dirname)\n+\n+    def test_get_handle_info_socket(self):\n+        ffi, _ = dist.load()\n+        s = socket.socket()\n+        socket_handle = ffi.cast('void *', s.fileno())\n+\n+        inherit = GetHandleInformation(socket_handle) & 1\n+        expected = self._expected_inheritance()\n+        self.assertEqual(inherit, expected)\n+        s.close()\n+\n+\n+class TestSetHandleInformation(TestCase):\n+    \"\"\"\n+    Tests for :func:`pywincffi.kernel32.SetHandleInformation`\n+    \"\"\"\n+    def test_set_handle_info_file_inherit(self):\n+        dirname = tempfile.mkdtemp()\n+        filename = os.path.join(dirname, \"test_file\")\n+        test_file = open(filename, \"w\")\n+        test_file.write(\"data\")\n+        file_handle = handle_from_file(test_file)\n+\n+        SetHandleInformation(file_handle, 1, 1)\n+\n+        test_file.close()\n+        os.unlink(filename)\n+        os.rmdir(dirname)\n+\n+    def test_set_handle_info_file_noinherit(self):\n+        dirname = tempfile.mkdtemp()\n+        filename = os.path.join(dirname, \"test_file\")\n+        test_file = open(filename, \"w\")\n+        test_file.write(\"data\")\n+        file_handle = handle_from_file(test_file)\n+\n+        SetHandleInformation(file_handle, 1, 0)","path":"tests/test_kernel32/test_handle.py","position":91,"original_position":91,"commit_id":"d741b388e213c0d824dfa0f99d2674ceaf0d6a6a","original_commit_id":"d741b388e213c0d824dfa0f99d2674ceaf0d6a6a","user":{"login":"opalmer","id":255117,"avatar_url":"https://avatars.githubusercontent.com/u/255117?v=3","gravatar_id":"","url":"https://api.github.com/users/opalmer","html_url":"https://github.com/opalmer","followers_url":"https://api.github.com/users/opalmer/followers","following_url":"https://api.github.com/users/opalmer/following{/other_user}","gists_url":"https://api.github.com/users/opalmer/gists{/gist_id}","starred_url":"https://api.github.com/users/opalmer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opalmer/subscriptions","organizations_url":"https://api.github.com/users/opalmer/orgs","repos_url":"https://api.github.com/users/opalmer/repos","events_url":"https://api.github.com/users/opalmer/events{/privacy}","received_events_url":"https://api.github.com/users/opalmer/received_events","type":"User","site_admin":false},"body":"We should use a constant rather than hard coding integers for constants.  Since the msdn documentation for `SetHandleInformation` references two constants I suggest you add those to constants.h and then use `HANDLE_FLAG_INHERIT` here.","created_at":"2016-04-08T23:10:54Z","updated_at":"2016-04-08T23:10:54Z","html_url":"https://github.com/opalmer/pywincffi/pull/66#discussion_r59101173","pull_request_url":"https://api.github.com/repos/opalmer/pywincffi/pulls/66","_links":{"self":{"href":"https://api.github.com/repos/opalmer/pywincffi/pulls/comments/59101173"},"html":{"href":"https://github.com/opalmer/pywincffi/pull/66#discussion_r59101173"},"pull_request":{"href":"https://api.github.com/repos/opalmer/pywincffi/pulls/66"}}},"pull_request":{"url":"https://api.github.com/repos/opalmer/pywincffi/pulls/66","id":65777922,"html_url":"https://github.com/opalmer/pywincffi/pull/66","diff_url":"https://github.com/opalmer/pywincffi/pull/66.diff","patch_url":"https://github.com/opalmer/pywincffi/pull/66.patch","issue_url":"https://api.github.com/repos/opalmer/pywincffi/issues/66","number":66,"state":"open","locked":false,"title":"Adding GetHandleInformation and SetHandleInformation","user":{"login":"exvito","id":7661068,"avatar_url":"https://avatars.githubusercontent.com/u/7661068?v=3","gravatar_id":"","url":"https://api.github.com/users/exvito","html_url":"https://github.com/exvito","followers_url":"https://api.github.com/users/exvito/followers","following_url":"https://api.github.com/users/exvito/following{/other_user}","gists_url":"https://api.github.com/users/exvito/gists{/gist_id}","starred_url":"https://api.github.com/users/exvito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/exvito/subscriptions","organizations_url":"https://api.github.com/users/exvito/orgs","repos_url":"https://api.github.com/users/exvito/repos","events_url":"https://api.github.com/users/exvito/events{/privacy}","received_events_url":"https://api.github.com/users/exvito/received_events","type":"User","site_admin":false},"body":"Following #65 here is my first take at adding these APIs.\r\n\r\nPreliminary work:\r\n* I did read the README.rst file and setup my environment as documented.\r\n* In master, commit c29bf1b5dc8966d1b0c84533ea6e78e44accbff6, some tests are failing:  `FAILED (SKIP=8, errors=4)` - looks related to the fact that I don't have Visual Studio, they all `raise DistutilsPlatformError(\"Unable to find vcvarsall.bat\")`\r\n  * tests.test_core.test_dist.TestLoad\r\n  * tests.test_core.test_dist.TestImportPath\r\n  * tests.test_core.test_dist.TestCompile\r\n  * tests.test_core.test_dist.TestCompile\r\n* Other than that, the 9 tests in tests/test_kernel32/test_handle.py are passing (even though one of those is outputting `close failed in file object destructor: IOError: [Errno 9] Bad file descriptor`.\r\n\r\nRegarding my code:\r\n* I tried to follow existing code layout and conventions.\r\n* Handle test count now 16 and passing: I'd appreciate your review and improvement recommendations.\r\n* I'm not sure how to add / use / make the associated constants available: I see several constants declared in pywincffi/core/cdefs/headers/constants.h, but don't understand:\r\n   * Why their respective values are missing and `...` is used instead.\r\n   * How to use them within pywincffi code (not needed currently).\r\n   * How to expose them to pywincffi users.\r\n\r\nAdditionally, I created a one-off test program which makes effective use of the APIs. It binds a socket, forks a child, closes the socket, rebinds the socket to the same address and stops the child. Without the SetHandleInformation call to clear the socket handle's information the rebinding should fail on Python < 3.4 (which is my case).\r\n\r\nHere it is, for reference:\r\n```python\r\n# -------------------------------------------------------------------\r\n\r\nfrom __future__ import print_function\r\n\r\nimport sys\r\nimport subprocess\r\nimport socket\r\n\r\nfrom pywincffi import kernel32\r\n\r\n\r\n# -------------------------------------------------------------------\r\n\r\nclass Handle(object):\r\n\r\n    import cffi as _cffi\r\n    _ffi = _cffi.FFI()\r\n\r\n    def __init__(self, integer):\r\n        self._handle = Handle._ffi.cast('HANDLE', integer)\r\n        self._addr = Handle._ffi.cast('unsigned long', self._handle)\r\n\r\n    def __repr__(self):\r\n        return '<Handle 0x%x>' % self._addr\r\n\r\n    @property\r\n    def value(self):\r\n        return self._handle\r\n\r\n\r\n# -------------------------------------------------------------------\r\n\r\nif __name__ == '__main__':\r\n\r\n    bind_addr = ('127.0.0.1', 10001)\r\n\r\n    s = socket.socket()\r\n    s_handle = Handle(s.fileno()) # fileno() is socket handle on Win\r\n    s.bind(bind_addr)\r\n    s_addr = s.getsockname()\r\n    print('bound socket %s to %r' % (s_handle, s_addr))\r\n\r\n    inherit = kernel32.GetHandleInformation(s_handle.value)\r\n    print('socket handle inheritance flag: %s' % inherit)\r\n\r\n    kernel32.SetHandleInformation(s_handle.value, 1, 0)\r\n    print('cleared socket handle inheritance flag')\r\n\r\n    inherit = kernel32.GetHandleInformation(s_handle.value)\r\n    print('socket handle inheritance flag: %s' % inherit)\r\n\r\n    p = subprocess.Popen(\r\n        args=[sys.executable],\r\n        stdin=subprocess.PIPE,\r\n        stdout=subprocess.PIPE,\r\n        stderr=subprocess.PIPE\r\n    )\r\n    print('child PID:', p.pid)\r\n\r\n    s.close()\r\n    print('closed socket')\r\n\r\n    s = socket.socket()\r\n    s_handle = Handle(s.fileno())\r\n    try:\r\n        s.bind(bind_addr)\r\n        s_addr = s.getsockname()\r\n        print('re-bound socket %s to %r' % (s_handle, s_addr))\r\n    except Exception as e:\r\n        print('re-binding socket failed:', e)\r\n\r\n    # stop the child\r\n    p.stdin.close()\r\n    print('child exit code:', p.wait())\r\n\r\n\r\n# -------------------------------------------------------------------\r\n```\r\n\r\nThanks for your review and feedback.","created_at":"2016-04-08T12:20:19Z","updated_at":"2016-04-08T23:10:54Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1213e60f0ca3f312de5a069dfe3052854bd3ace2","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/opalmer/pywincffi/pulls/66/commits","review_comments_url":"https://api.github.com/repos/opalmer/pywincffi/pulls/66/comments","review_comment_url":"https://api.github.com/repos/opalmer/pywincffi/pulls/comments{/number}","comments_url":"https://api.github.com/repos/opalmer/pywincffi/issues/66/comments","statuses_url":"https://api.github.com/repos/opalmer/pywincffi/statuses/d741b388e213c0d824dfa0f99d2674ceaf0d6a6a","head":{"label":"exvito:handle-get-set-info","ref":"handle-get-set-info","sha":"d741b388e213c0d824dfa0f99d2674ceaf0d6a6a","user":{"login":"exvito","id":7661068,"avatar_url":"https://avatars.githubusercontent.com/u/7661068?v=3","gravatar_id":"","url":"https://api.github.com/users/exvito","html_url":"https://github.com/exvito","followers_url":"https://api.github.com/users/exvito/followers","following_url":"https://api.github.com/users/exvito/following{/other_user}","gists_url":"https://api.github.com/users/exvito/gists{/gist_id}","starred_url":"https://api.github.com/users/exvito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/exvito/subscriptions","organizations_url":"https://api.github.com/users/exvito/orgs","repos_url":"https://api.github.com/users/exvito/repos","events_url":"https://api.github.com/users/exvito/events{/privacy}","received_events_url":"https://api.github.com/users/exvito/received_events","type":"User","site_admin":false},"repo":{"id":55724105,"name":"pywincffi","full_name":"exvito/pywincffi","owner":{"login":"exvito","id":7661068,"avatar_url":"https://avatars.githubusercontent.com/u/7661068?v=3","gravatar_id":"","url":"https://api.github.com/users/exvito","html_url":"https://github.com/exvito","followers_url":"https://api.github.com/users/exvito/followers","following_url":"https://api.github.com/users/exvito/following{/other_user}","gists_url":"https://api.github.com/users/exvito/gists{/gist_id}","starred_url":"https://api.github.com/users/exvito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/exvito/subscriptions","organizations_url":"https://api.github.com/users/exvito/orgs","repos_url":"https://api.github.com/users/exvito/repos","events_url":"https://api.github.com/users/exvito/events{/privacy}","received_events_url":"https://api.github.com/users/exvito/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/exvito/pywincffi","description":"A Python library which wraps Windows functions using CFFI.","fork":true,"url":"https://api.github.com/repos/exvito/pywincffi","forks_url":"https://api.github.com/repos/exvito/pywincffi/forks","keys_url":"https://api.github.com/repos/exvito/pywincffi/keys{/key_id}","collaborators_url":"https://api.github.com/repos/exvito/pywincffi/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/exvito/pywincffi/teams","hooks_url":"https://api.github.com/repos/exvito/pywincffi/hooks","issue_events_url":"https://api.github.com/repos/exvito/pywincffi/issues/events{/number}","events_url":"https://api.github.com/repos/exvito/pywincffi/events","assignees_url":"https://api.github.com/repos/exvito/pywincffi/assignees{/user}","branches_url":"https://api.github.com/repos/exvito/pywincffi/branches{/branch}","tags_url":"https://api.github.com/repos/exvito/pywincffi/tags","blobs_url":"https://api.github.com/repos/exvito/pywincffi/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/exvito/pywincffi/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/exvito/pywincffi/git/refs{/sha}","trees_url":"https://api.github.com/repos/exvito/pywincffi/git/trees{/sha}","statuses_url":"https://api.github.com/repos/exvito/pywincffi/statuses/{sha}","languages_url":"https://api.github.com/repos/exvito/pywincffi/languages","stargazers_url":"https://api.github.com/repos/exvito/pywincffi/stargazers","contributors_url":"https://api.github.com/repos/exvito/pywincffi/contributors","subscribers_url":"https://api.github.com/repos/exvito/pywincffi/subscribers","subscription_url":"https://api.github.com/repos/exvito/pywincffi/subscription","commits_url":"https://api.github.com/repos/exvito/pywincffi/commits{/sha}","git_commits_url":"https://api.github.com/repos/exvito/pywincffi/git/commits{/sha}","comments_url":"https://api.github.com/repos/exvito/pywincffi/comments{/number}","issue_comment_url":"https://api.github.com/repos/exvito/pywincffi/issues/comments{/number}","contents_url":"https://api.github.com/repos/exvito/pywincffi/contents/{+path}","compare_url":"https://api.github.com/repos/exvito/pywincffi/compare/{base}...{head}","merges_url":"https://api.github.com/repos/exvito/pywincffi/merges","archive_url":"https://api.github.com/repos/exvito/pywincffi/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/exvito/pywincffi/downloads","issues_url":"https://api.github.com/repos/exvito/pywincffi/issues{/number}","pulls_url":"https://api.github.com/repos/exvito/pywincffi/pulls{/number}","milestones_url":"https://api.github.com/repos/exvito/pywincffi/milestones{/number}","notifications_url":"https://api.github.com/repos/exvito/pywincffi/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/exvito/pywincffi/labels{/name}","releases_url":"https://api.github.com/repos/exvito/pywincffi/releases{/id}","deployments_url":"https://api.github.com/repos/exvito/pywincffi/deployments","created_at":"2016-04-07T20:00:48Z","updated_at":"2016-04-07T20:00:49Z","pushed_at":"2016-04-08T11:46:03Z","git_url":"git://github.com/exvito/pywincffi.git","ssh_url":"git@github.com:exvito/pywincffi.git","clone_url":"https://github.com/exvito/pywincffi.git","svn_url":"https://github.com/exvito/pywincffi","homepage":null,"size":556,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"opalmer:master","ref":"master","sha":"c29bf1b5dc8966d1b0c84533ea6e78e44accbff6","user":{"login":"opalmer","id":255117,"avatar_url":"https://avatars.githubusercontent.com/u/255117?v=3","gravatar_id":"","url":"https://api.github.com/users/opalmer","html_url":"https://github.com/opalmer","followers_url":"https://api.github.com/users/opalmer/followers","following_url":"https://api.github.com/users/opalmer/following{/other_user}","gists_url":"https://api.github.com/users/opalmer/gists{/gist_id}","starred_url":"https://api.github.com/users/opalmer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opalmer/subscriptions","organizations_url":"https://api.github.com/users/opalmer/orgs","repos_url":"https://api.github.com/users/opalmer/repos","events_url":"https://api.github.com/users/opalmer/events{/privacy}","received_events_url":"https://api.github.com/users/opalmer/received_events","type":"User","site_admin":false},"repo":{"id":37441228,"name":"pywincffi","full_name":"opalmer/pywincffi","owner":{"login":"opalmer","id":255117,"avatar_url":"https://avatars.githubusercontent.com/u/255117?v=3","gravatar_id":"","url":"https://api.github.com/users/opalmer","html_url":"https://github.com/opalmer","followers_url":"https://api.github.com/users/opalmer/followers","following_url":"https://api.github.com/users/opalmer/following{/other_user}","gists_url":"https://api.github.com/users/opalmer/gists{/gist_id}","starred_url":"https://api.github.com/users/opalmer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opalmer/subscriptions","organizations_url":"https://api.github.com/users/opalmer/orgs","repos_url":"https://api.github.com/users/opalmer/repos","events_url":"https://api.github.com/users/opalmer/events{/privacy}","received_events_url":"https://api.github.com/users/opalmer/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/opalmer/pywincffi","description":"A Python library which wraps Windows functions using CFFI.","fork":false,"url":"https://api.github.com/repos/opalmer/pywincffi","forks_url":"https://api.github.com/repos/opalmer/pywincffi/forks","keys_url":"https://api.github.com/repos/opalmer/pywincffi/keys{/key_id}","collaborators_url":"https://api.github.com/repos/opalmer/pywincffi/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/opalmer/pywincffi/teams","hooks_url":"https://api.github.com/repos/opalmer/pywincffi/hooks","issue_events_url":"https://api.github.com/repos/opalmer/pywincffi/issues/events{/number}","events_url":"https://api.github.com/repos/opalmer/pywincffi/events","assignees_url":"https://api.github.com/repos/opalmer/pywincffi/assignees{/user}","branches_url":"https://api.github.com/repos/opalmer/pywincffi/branches{/branch}","tags_url":"https://api.github.com/repos/opalmer/pywincffi/tags","blobs_url":"https://api.github.com/repos/opalmer/pywincffi/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/opalmer/pywincffi/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/opalmer/pywincffi/git/refs{/sha}","trees_url":"https://api.github.com/repos/opalmer/pywincffi/git/trees{/sha}","statuses_url":"https://api.github.com/repos/opalmer/pywincffi/statuses/{sha}","languages_url":"https://api.github.com/repos/opalmer/pywincffi/languages","stargazers_url":"https://api.github.com/repos/opalmer/pywincffi/stargazers","contributors_url":"https://api.github.com/repos/opalmer/pywincffi/contributors","subscribers_url":"https://api.github.com/repos/opalmer/pywincffi/subscribers","subscription_url":"https://api.github.com/repos/opalmer/pywincffi/subscription","commits_url":"https://api.github.com/repos/opalmer/pywincffi/commits{/sha}","git_commits_url":"https://api.github.com/repos/opalmer/pywincffi/git/commits{/sha}","comments_url":"https://api.github.com/repos/opalmer/pywincffi/comments{/number}","issue_comment_url":"https://api.github.com/repos/opalmer/pywincffi/issues/comments{/number}","contents_url":"https://api.github.com/repos/opalmer/pywincffi/contents/{+path}","compare_url":"https://api.github.com/repos/opalmer/pywincffi/compare/{base}...{head}","merges_url":"https://api.github.com/repos/opalmer/pywincffi/merges","archive_url":"https://api.github.com/repos/opalmer/pywincffi/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/opalmer/pywincffi/downloads","issues_url":"https://api.github.com/repos/opalmer/pywincffi/issues{/number}","pulls_url":"https://api.github.com/repos/opalmer/pywincffi/pulls{/number}","milestones_url":"https://api.github.com/repos/opalmer/pywincffi/milestones{/number}","notifications_url":"https://api.github.com/repos/opalmer/pywincffi/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/opalmer/pywincffi/labels{/name}","releases_url":"https://api.github.com/repos/opalmer/pywincffi/releases{/id}","deployments_url":"https://api.github.com/repos/opalmer/pywincffi/deployments","created_at":"2015-06-15T03:24:57Z","updated_at":"2016-03-16T00:43:46Z","pushed_at":"2016-04-08T21:44:13Z","git_url":"git://github.com/opalmer/pywincffi.git","ssh_url":"git@github.com:opalmer/pywincffi.git","clone_url":"https://github.com/opalmer/pywincffi.git","svn_url":"https://github.com/opalmer/pywincffi","homepage":null,"size":601,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":6,"forks":2,"open_issues":6,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/opalmer/pywincffi/pulls/66"},"html":{"href":"https://github.com/opalmer/pywincffi/pull/66"},"issue":{"href":"https://api.github.com/repos/opalmer/pywincffi/issues/66"},"comments":{"href":"https://api.github.com/repos/opalmer/pywincffi/issues/66/comments"},"review_comments":{"href":"https://api.github.com/repos/opalmer/pywincffi/pulls/66/comments"},"review_comment":{"href":"https://api.github.com/repos/opalmer/pywincffi/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/opalmer/pywincffi/pulls/66/commits"},"statuses":{"href":"https://api.github.com/repos/opalmer/pywincffi/statuses/d741b388e213c0d824dfa0f99d2674ceaf0d6a6a"}}}}