Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Config.__iter__ to iterate over ConfigEntry objects #778

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions docs/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ The Config type
.. method:: Config.__iter__()

The :class:`Config` class has an iterator which can be used to loop
through all the entries in the configuration. Each element is a tuple
containing the name and the value of each configuration variable. Be
aware that this may return multiple versions of each entry if they are
set multiple times in the configuration files.
through all the entries in the configuration. Each element is a
``ConfigEntry`` object containing the name, level, and value of each
configuration variable. Be aware that this may return multiple versions of
each entry if they are set multiple times in the configuration files.

.. currentmodule:: pygit2

Expand All @@ -32,3 +32,14 @@ string. In order to apply the git-config parsing rules, you can use

.. automethod:: pygit2.Config.get_bool
.. automethod:: pygit2.Config.get_int


The ConfigEntry type
====================

.. automethod:: pygit2.ConfigEntry.decode_as_string
.. automethod:: pygit2.ConfigEntry._from_c
.. automethod:: pygit2.ConfigEntry.name
.. automethod:: pygit2.ConfigEntry.level
.. automethod:: pygit2.ConfigEntry.value
.. automethod:: pygit2.ConfigEntry.value_string
48 changes: 40 additions & 8 deletions pygit2/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,20 @@ def _next_entry(self):
err = C.git_config_next(centry, self._iter)
check_error(err)

return centry[0]
return ConfigEntry._from_c(centry[0], True)

def next(self):
return self.__next__()

def __next__(self):
entry = self._next_entry()
return ffi.string(entry.name).decode('utf-8')
return entry


class ConfigMultivarIterator(ConfigIterator):
def __next__(self):
entry = self._next_entry()
return ffi.string(entry.value).decode('utf-8')
return entry.value


class Config(object):
Expand Down Expand Up @@ -128,7 +128,7 @@ def __contains__(self, key):
def __getitem__(self, key):
entry = self._get_entry(key)

return ffi.string(entry.value).decode('utf-8')
return entry.value

def __setitem__(self, key, value):
assert_string(key, "key")
Expand Down Expand Up @@ -195,7 +195,7 @@ def get_bool(self, key):

entry = self._get_entry(key)
res = ffi.new('int *')
err = C.git_config_parse_bool(res, entry.value)
err = C.git_config_parse_bool(res, entry.raw_value)
check_error(err)

return res[0] != 0
Expand All @@ -210,7 +210,7 @@ def get_int(self, key):

entry = self._get_entry(key)
res = ffi.new('int64_t *')
err = C.git_config_parse_int64(res, entry.value)
err = C.git_config_parse_int64(res, entry.raw_value)
check_error(err)

return res[0]
Expand Down Expand Up @@ -291,14 +291,46 @@ class ConfigEntry(object):
"""

@classmethod
def _from_c(cls, ptr):
def _from_c(cls, ptr, from_iterator=False):
"""Builds the entry from a ``git_config_entry`` pointer. ``from_iterator``
should be ``True`` when the entry was created during ``git_config_iterator``
actions
"""
entry = cls.__new__(cls)
entry._entry = ptr
entry.from_iterator = from_iterator
return entry

def __del__(self):
C.git_config_entry_free(self._entry)
if not self.from_iterator:
C.git_config_entry_free(self._entry)

@property
def value(self):
"""The entry's value as a string
"""
return self.decode_as_string(self._entry.value)

@property
def level(self):
"""The entry's ``git_config_level_t`` value
"""
return self._entry.level

@property
def name(self):
"""The entry's name
"""
return self.decode_as_string(self._entry.name)

@property
def raw_value(self):
"""The raw ``cData`` entry value
"""
return self._entry.value

@staticmethod
def decode_as_string(value):
"""Returns ``value`` as a decoded ``utf-8`` string.
"""
return ffi.string(value).decode('utf-8')
5 changes: 3 additions & 2 deletions test/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,9 @@ def test_iterator(self):
config = self.repo.config
lst = {}

for name in config:
lst[name] = config[name]
for entry in config:
self.assertGreater(entry.level, -1)
lst[entry.name] = entry.value

self.assertTrue('core.bare' in lst)
self.assertTrue(lst['core.bare'])
Expand Down