{"action":"closed","number":776,"pull_request":{"url":"https://api.github.com/repos/libgit2/pygit2/pulls/776","id":174269940,"html_url":"https://github.com/libgit2/pygit2/pull/776","diff_url":"https://github.com/libgit2/pygit2/pull/776.diff","patch_url":"https://github.com/libgit2/pygit2/pull/776.patch","issue_url":"https://api.github.com/repos/libgit2/pygit2/issues/776","number":776,"state":"closed","locked":false,"title":"Update Config.__iter__ to match the documentation","user":{"login":"thecjharries","id":6250642,"avatar_url":"https://avatars2.githubusercontent.com/u/6250642?v=4","gravatar_id":"","url":"https://api.github.com/users/thecjharries","html_url":"https://github.com/thecjharries","followers_url":"https://api.github.com/users/thecjharries/followers","following_url":"https://api.github.com/users/thecjharries/following{/other_user}","gists_url":"https://api.github.com/users/thecjharries/gists{/gist_id}","starred_url":"https://api.github.com/users/thecjharries/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thecjharries/subscriptions","organizations_url":"https://api.github.com/users/thecjharries/orgs","repos_url":"https://api.github.com/users/thecjharries/repos","events_url":"https://api.github.com/users/thecjharries/events{/privacy}","received_events_url":"https://api.github.com/users/thecjharries/received_events","type":"User","site_admin":false},"body":"## Problem\r\n\r\n[The `Config.__iter__` docs](http://www.pygit2.org/config.html#Config.__iter__) say the method iterates over all entries, where \"[e]ach element is a tuple containing the name and the value\", which could be problematic as the method \"may return multiple versions of each entry if they are set multiple times.\" However, the (final) `next` method on the iterator only [returns the `name` of the entry](https://github.com/libgit2/pygit2/blob/master/pygit2/config.py#L64). There's a very good chance it's never returned a tuple, [evidenced by the `blame`](https://github.com/libgit2/pygit2/blame/master/pygit2/config.py#L66).\r\n\r\n### Example\r\n```python\r\nfrom __future__ import print_function\r\nfrom tempfile import NamedTemporaryFile\r\nfrom pygit2 import Config\r\n\r\n# Start with a blank slate\r\nblank = Config()\r\n\r\n# https://git-scm.com/docs/git-config#git-config-pushdefault\r\nfor index, value in list(enumerate(['nothing', 'current', 'upstream'])):\r\n    # There's probably a better way to do this\r\n    with NamedTemporaryFile() as config_file:\r\n        config_file.write(\"[push]\\n\\tdefault = %s\" % value)\r\n        config_file.seek(0)\r\n        blank.add_file(config_file.name, index)\r\n\r\n# This executes Config.__iter__\r\nfor key in blank:\r\n    # Since it doesn't return a value, we're stuck with the default return\r\n    print(key, blank[key])\r\n# push.default upstream\r\n# push.default upstream\r\n# push.default upstream\r\n\r\n# It's not actually a multivar, but we can see everything this way\r\nfor value in blank.get_multivar('push.default'):\r\n    print(value)\r\n# nothing\r\n# current\r\n# upstream\r\n```\r\n## Pull Request\r\n\r\nI updated `__next__`'s return to also include the value. This matches what the docs describe, returning a tuple of name and value. Since the change only affects the iterator, the default value return isn't affected.\r\n\r\nI also updated the test to consume the tuple. There's probably more that could go there, but I'm not quite sure what yet.\r\n\r\n### `libgit2`\r\n\r\nI think `libgit2` supports my interpretation of things. [`git_config_iterator`](https://libgit2.github.com/libgit2/#HEAD/type/git_config_iterator) iterates over [`git_config_entry`](https://libgit2.github.com/libgit2/#HEAD/type/git_config_entry), which contains both the name and the value (as well as some other information that might be useful to use). \r\n\r\n### Extension\r\n\r\nLooking at my example above, it doesn't seem like `(key, value)` is all that useful. It might be a good idea to also return `level`. It's [in `git_config_entry`](https://libgit2.github.com/libgit2/#HEAD/type/git_config_entry), so it's available to the iterator.\r\n\r\n## Alternative\r\n\r\nAs I pointed out, I don't think this has worked as intended [for years](https://github.com/thecjharries/pygit2/blame/master/pygit2/config.py). An equally simple solution would be to update the docs to match the current behavior. I'd be more than happy to do that if this PR is rejected.\r\n","created_at":"2018-03-12T04:23:53Z","updated_at":"2018-03-17T01:56:09Z","closed_at":"2018-03-17T01:56:09Z","merged_at":null,"merge_commit_sha":"646c7c28c0f9285f9a5572a763a0af4807b72dbd","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/libgit2/pygit2/pulls/776/commits","review_comments_url":"https://api.github.com/repos/libgit2/pygit2/pulls/776/comments","review_comment_url":"https://api.github.com/repos/libgit2/pygit2/pulls/comments{/number}","comments_url":"https://api.github.com/repos/libgit2/pygit2/issues/776/comments","statuses_url":"https://api.github.com/repos/libgit2/pygit2/statuses/ca93b9ba69d8bde0a3751dbc20cac78adc9cde69","head":{"label":"thecjharries:feature/update-config-iter-to-match-docs","ref":"feature/update-config-iter-to-match-docs","sha":"ca93b9ba69d8bde0a3751dbc20cac78adc9cde69","user":{"login":"thecjharries","id":6250642,"avatar_url":"https://avatars2.githubusercontent.com/u/6250642?v=4","gravatar_id":"","url":"https://api.github.com/users/thecjharries","html_url":"https://github.com/thecjharries","followers_url":"https://api.github.com/users/thecjharries/followers","following_url":"https://api.github.com/users/thecjharries/following{/other_user}","gists_url":"https://api.github.com/users/thecjharries/gists{/gist_id}","starred_url":"https://api.github.com/users/thecjharries/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thecjharries/subscriptions","organizations_url":"https://api.github.com/users/thecjharries/orgs","repos_url":"https://api.github.com/users/thecjharries/repos","events_url":"https://api.github.com/users/thecjharries/events{/privacy}","received_events_url":"https://api.github.com/users/thecjharries/received_events","type":"User","site_admin":false},"repo":{"id":124826105,"name":"pygit2","full_name":"thecjharries/pygit2","owner":{"login":"thecjharries","id":6250642,"avatar_url":"https://avatars2.githubusercontent.com/u/6250642?v=4","gravatar_id":"","url":"https://api.github.com/users/thecjharries","html_url":"https://github.com/thecjharries","followers_url":"https://api.github.com/users/thecjharries/followers","following_url":"https://api.github.com/users/thecjharries/following{/other_user}","gists_url":"https://api.github.com/users/thecjharries/gists{/gist_id}","starred_url":"https://api.github.com/users/thecjharries/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thecjharries/subscriptions","organizations_url":"https://api.github.com/users/thecjharries/orgs","repos_url":"https://api.github.com/users/thecjharries/repos","events_url":"https://api.github.com/users/thecjharries/events{/privacy}","received_events_url":"https://api.github.com/users/thecjharries/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/thecjharries/pygit2","description":"Python bindings for libgit2","fork":true,"url":"https://api.github.com/repos/thecjharries/pygit2","forks_url":"https://api.github.com/repos/thecjharries/pygit2/forks","keys_url":"https://api.github.com/repos/thecjharries/pygit2/keys{/key_id}","collaborators_url":"https://api.github.com/repos/thecjharries/pygit2/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/thecjharries/pygit2/teams","hooks_url":"https://api.github.com/repos/thecjharries/pygit2/hooks","issue_events_url":"https://api.github.com/repos/thecjharries/pygit2/issues/events{/number}","events_url":"https://api.github.com/repos/thecjharries/pygit2/events","assignees_url":"https://api.github.com/repos/thecjharries/pygit2/assignees{/user}","branches_url":"https://api.github.com/repos/thecjharries/pygit2/branches{/branch}","tags_url":"https://api.github.com/repos/thecjharries/pygit2/tags","blobs_url":"https://api.github.com/repos/thecjharries/pygit2/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/thecjharries/pygit2/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/thecjharries/pygit2/git/refs{/sha}","trees_url":"https://api.github.com/repos/thecjharries/pygit2/git/trees{/sha}","statuses_url":"https://api.github.com/repos/thecjharries/pygit2/statuses/{sha}","languages_url":"https://api.github.com/repos/thecjharries/pygit2/languages","stargazers_url":"https://api.github.com/repos/thecjharries/pygit2/stargazers","contributors_url":"https://api.github.com/repos/thecjharries/pygit2/contributors","subscribers_url":"https://api.github.com/repos/thecjharries/pygit2/subscribers","subscription_url":"https://api.github.com/repos/thecjharries/pygit2/subscription","commits_url":"https://api.github.com/repos/thecjharries/pygit2/commits{/sha}","git_commits_url":"https://api.github.com/repos/thecjharries/pygit2/git/commits{/sha}","comments_url":"https://api.github.com/repos/thecjharries/pygit2/comments{/number}","issue_comment_url":"https://api.github.com/repos/thecjharries/pygit2/issues/comments{/number}","contents_url":"https://api.github.com/repos/thecjharries/pygit2/contents/{+path}","compare_url":"https://api.github.com/repos/thecjharries/pygit2/compare/{base}...{head}","merges_url":"https://api.github.com/repos/thecjharries/pygit2/merges","archive_url":"https://api.github.com/repos/thecjharries/pygit2/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/thecjharries/pygit2/downloads","issues_url":"https://api.github.com/repos/thecjharries/pygit2/issues{/number}","pulls_url":"https://api.github.com/repos/thecjharries/pygit2/pulls{/number}","milestones_url":"https://api.github.com/repos/thecjharries/pygit2/milestones{/number}","notifications_url":"https://api.github.com/repos/thecjharries/pygit2/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/thecjharries/pygit2/labels{/name}","releases_url":"https://api.github.com/repos/thecjharries/pygit2/releases{/id}","deployments_url":"https://api.github.com/repos/thecjharries/pygit2/deployments","created_at":"2018-03-12T03:01:26Z","updated_at":"2018-03-12T03:01:28Z","pushed_at":"2018-03-17T01:16:06Z","git_url":"git://github.com/thecjharries/pygit2.git","ssh_url":"git@github.com:thecjharries/pygit2.git","clone_url":"https://github.com/thecjharries/pygit2.git","svn_url":"https://github.com/thecjharries/pygit2","homepage":"","size":3034,"stargazers_count":0,"watchers_count":0,"language":"Python","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":"other","name":"Other","spdx_id":null,"url":null},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"libgit2:master","ref":"master","sha":"0f64ac420bc24f2a5d2368f83b5e21120ddf623d","user":{"login":"libgit2","id":394745,"avatar_url":"https://avatars1.githubusercontent.com/u/394745?v=4","gravatar_id":"","url":"https://api.github.com/users/libgit2","html_url":"https://github.com/libgit2","followers_url":"https://api.github.com/users/libgit2/followers","following_url":"https://api.github.com/users/libgit2/following{/other_user}","gists_url":"https://api.github.com/users/libgit2/gists{/gist_id}","starred_url":"https://api.github.com/users/libgit2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/libgit2/subscriptions","organizations_url":"https://api.github.com/users/libgit2/orgs","repos_url":"https://api.github.com/users/libgit2/repos","events_url":"https://api.github.com/users/libgit2/events{/privacy}","received_events_url":"https://api.github.com/users/libgit2/received_events","type":"Organization","site_admin":false},"repo":{"id":1062237,"name":"pygit2","full_name":"libgit2/pygit2","owner":{"login":"libgit2","id":394745,"avatar_url":"https://avatars1.githubusercontent.com/u/394745?v=4","gravatar_id":"","url":"https://api.github.com/users/libgit2","html_url":"https://github.com/libgit2","followers_url":"https://api.github.com/users/libgit2/followers","following_url":"https://api.github.com/users/libgit2/following{/other_user}","gists_url":"https://api.github.com/users/libgit2/gists{/gist_id}","starred_url":"https://api.github.com/users/libgit2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/libgit2/subscriptions","organizations_url":"https://api.github.com/users/libgit2/orgs","repos_url":"https://api.github.com/users/libgit2/repos","events_url":"https://api.github.com/users/libgit2/events{/privacy}","received_events_url":"https://api.github.com/users/libgit2/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/libgit2/pygit2","description":"Python bindings for libgit2","fork":false,"url":"https://api.github.com/repos/libgit2/pygit2","forks_url":"https://api.github.com/repos/libgit2/pygit2/forks","keys_url":"https://api.github.com/repos/libgit2/pygit2/keys{/key_id}","collaborators_url":"https://api.github.com/repos/libgit2/pygit2/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/libgit2/pygit2/teams","hooks_url":"https://api.github.com/repos/libgit2/pygit2/hooks","issue_events_url":"https://api.github.com/repos/libgit2/pygit2/issues/events{/number}","events_url":"https://api.github.com/repos/libgit2/pygit2/events","assignees_url":"https://api.github.com/repos/libgit2/pygit2/assignees{/user}","branches_url":"https://api.github.com/repos/libgit2/pygit2/branches{/branch}","tags_url":"https://api.github.com/repos/libgit2/pygit2/tags","blobs_url":"https://api.github.com/repos/libgit2/pygit2/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/libgit2/pygit2/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/libgit2/pygit2/git/refs{/sha}","trees_url":"https://api.github.com/repos/libgit2/pygit2/git/trees{/sha}","statuses_url":"https://api.github.com/repos/libgit2/pygit2/statuses/{sha}","languages_url":"https://api.github.com/repos/libgit2/pygit2/languages","stargazers_url":"https://api.github.com/repos/libgit2/pygit2/stargazers","contributors_url":"https://api.github.com/repos/libgit2/pygit2/contributors","subscribers_url":"https://api.github.com/repos/libgit2/pygit2/subscribers","subscription_url":"https://api.github.com/repos/libgit2/pygit2/subscription","commits_url":"https://api.github.com/repos/libgit2/pygit2/commits{/sha}","git_commits_url":"https://api.github.com/repos/libgit2/pygit2/git/commits{/sha}","comments_url":"https://api.github.com/repos/libgit2/pygit2/comments{/number}","issue_comment_url":"https://api.github.com/repos/libgit2/pygit2/issues/comments{/number}","contents_url":"https://api.github.com/repos/libgit2/pygit2/contents/{+path}","compare_url":"https://api.github.com/repos/libgit2/pygit2/compare/{base}...{head}","merges_url":"https://api.github.com/repos/libgit2/pygit2/merges","archive_url":"https://api.github.com/repos/libgit2/pygit2/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/libgit2/pygit2/downloads","issues_url":"https://api.github.com/repos/libgit2/pygit2/issues{/number}","pulls_url":"https://api.github.com/repos/libgit2/pygit2/pulls{/number}","milestones_url":"https://api.github.com/repos/libgit2/pygit2/milestones{/number}","notifications_url":"https://api.github.com/repos/libgit2/pygit2/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/libgit2/pygit2/labels{/name}","releases_url":"https://api.github.com/repos/libgit2/pygit2/releases{/id}","deployments_url":"https://api.github.com/repos/libgit2/pygit2/deployments","created_at":"2010-11-08T16:27:48Z","updated_at":"2018-03-15T15:47:55Z","pushed_at":"2018-03-17T01:55:40Z","git_url":"git://github.com/libgit2/pygit2.git","ssh_url":"git@github.com:libgit2/pygit2.git","clone_url":"https://github.com/libgit2/pygit2.git","svn_url":"https://github.com/libgit2/pygit2","homepage":"","size":3031,"stargazers_count":1031,"watchers_count":1031,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":260,"mirror_url":null,"archived":false,"open_issues_count":102,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":260,"open_issues":102,"watchers":1031,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/libgit2/pygit2/pulls/776"},"html":{"href":"https://github.com/libgit2/pygit2/pull/776"},"issue":{"href":"https://api.github.com/repos/libgit2/pygit2/issues/776"},"comments":{"href":"https://api.github.com/repos/libgit2/pygit2/issues/776/comments"},"review_comments":{"href":"https://api.github.com/repos/libgit2/pygit2/pulls/776/comments"},"review_comment":{"href":"https://api.github.com/repos/libgit2/pygit2/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/libgit2/pygit2/pulls/776/commits"},"statuses":{"href":"https://api.github.com/repos/libgit2/pygit2/statuses/ca93b9ba69d8bde0a3751dbc20cac78adc9cde69"}},"author_association":"NONE","merged":false,"mergeable":true,"rebaseable":true,"mergeable_state":"clean","merged_by":null,"comments":4,"review_comments":0,"maintainer_can_modify":false,"commits":2,"additions":6,"deletions":3,"changed_files":2}}
{"actor":{"display_login":"thecjharries"}}