summaryrefslogtreecommitdiff
path: root/git/remote.py
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2014-11-17 10:14:43 +0100
committerSebastian Thiel <byronimo@gmail.com>2014-11-17 10:14:43 +0100
commite4d8fb73daa82420bdc69c37f0d58f7cb4cd505a (patch)
tree38e1241fd6d756f783b6b56dc6628ac3ca41ed4f /git/remote.py
parent7aba59a2609ec768d5d495dafd23a4bce8179741 (diff)
parentc8e70749887370a99adeda972cc3503397b5f9a7 (diff)
downloadgitpython-e4d8fb73daa82420bdc69c37f0d58f7cb4cd505a.tar.gz
Merge pull request #204 from hashar/pep8-linting
Pep8 linting
Diffstat (limited to 'git/remote.py')
-rw-r--r--git/remote.py322
1 files changed, 162 insertions, 160 deletions
diff --git a/git/remote.py b/git/remote.py
index 75e88e43..c1fc8078 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -20,14 +20,14 @@ from git.util import (
from refs import (
Reference,
RemoteReference,
- SymbolicReference,
+ SymbolicReference,
TagReference
)
from git.util import (
- join_path,
- finalize_process
- )
+ join_path,
+ finalize_process
+ )
from gitdb.util import join
import re
@@ -38,11 +38,12 @@ __all__ = ('RemoteProgress', 'PushInfo', 'FetchInfo', 'Remote')
#{ Utilities
+
def digest_process_messages(fh, progress):
"""Read progress messages from file-like object fh, supplying the respective
progress messages to the progress instance.
-
- :param fh: File handle to read from
+
+ :param fh: File handle to read from
:return: list(line, ...) list of lines without linebreaks that did
not contain progress information"""
line_so_far = ''
@@ -61,9 +62,10 @@ def digest_process_messages(fh, progress):
# END while file is not done reading
return dropped_lines
+
def add_progress(kwargs, git, progress):
- """Add the --progress flag to the given kwargs dict if supported by the
- git command. If the actual progress in the given progress instance is not
+ """Add the --progress flag to the given kwargs dict if supported by the
+ git command. If the actual progress in the given progress instance is not
given, we do not request any progress
:return: possibly altered kwargs"""
if progress is not None:
@@ -76,32 +78,33 @@ def add_progress(kwargs, git, progress):
#} END utilities
-
+
class PushInfo(object):
+
"""
Carries information about the result of a push operation of a single head::
-
+
info = remote.push()[0]
info.flags # bitflags providing more information about the result
info.local_ref # Reference pointing to the local reference that was pushed
# It is None if the ref was deleted.
info.remote_ref_string # path to the remote reference located on the remote side
- info.remote_ref # Remote Reference on the local side corresponding to
+ info.remote_ref # Remote Reference on the local side corresponding to
# the remote_ref_string. It can be a TagReference as well.
info.old_commit # commit at which the remote_ref was standing before we pushed
# it to local_ref.commit. Will be None if an error was indicated
info.summary # summary line providing human readable english text about the push
"""
__slots__ = ('local_ref', 'remote_ref_string', 'flags', 'old_commit', '_remote', 'summary')
-
+
NEW_TAG, NEW_HEAD, NO_MATCH, REJECTED, REMOTE_REJECTED, REMOTE_FAILURE, DELETED, \
- FORCED_UPDATE, FAST_FORWARD, UP_TO_DATE, ERROR = [ 1 << x for x in range(11) ]
+ FORCED_UPDATE, FAST_FORWARD, UP_TO_DATE, ERROR = [1 << x for x in range(11)]
+
+ _flag_map = {'X': NO_MATCH, '-': DELETED, '*': 0,
+ '+': FORCED_UPDATE, ' ': FAST_FORWARD,
+ '=': UP_TO_DATE, '!': ERROR}
- _flag_map = { 'X' : NO_MATCH, '-' : DELETED, '*' : 0,
- '+' : FORCED_UPDATE, ' ' : FAST_FORWARD,
- '=' : UP_TO_DATE, '!' : ERROR }
-
- def __init__(self, flags, local_ref, remote_ref_string, remote, old_commit=None,
+ def __init__(self, flags, local_ref, remote_ref_string, remote, old_commit=None,
summary=''):
""" Initialize a new instance """
self.flags = flags
@@ -110,12 +113,12 @@ class PushInfo(object):
self._remote = remote
self.old_commit = old_commit
self.summary = summary
-
+
@property
def remote_ref(self):
"""
:return:
- Remote Reference or TagReference in the local repository corresponding
+ Remote Reference or TagReference in the local repository corresponding
to the remote_ref_string kept in this instance."""
# translate heads to a local remote, tags stay as they are
if self.remote_ref_string.startswith("refs/tags"):
@@ -125,29 +128,29 @@ class PushInfo(object):
return RemoteReference(self._remote.repo, "refs/remotes/%s/%s" % (str(self._remote), remote_ref.name))
else:
raise ValueError("Could not handle remote ref: %r" % self.remote_ref_string)
- # END
-
+ # END
+
@classmethod
def _from_line(cls, remote, line):
"""Create a new PushInfo instance as parsed from line which is expected to be like
refs/heads/master:refs/heads/master 05d2687..1d0568e"""
control_character, from_to, summary = line.split('\t', 3)
flags = 0
-
+
# control character handling
try:
- flags |= cls._flag_map[ control_character ]
+ flags |= cls._flag_map[control_character]
except KeyError:
- raise ValueError("Control Character %r unknown as parsed from line %r" % (control_character, line))
+ raise ValueError("Control Character %r unknown as parsed from line %r" % (control_character, line))
# END handle control character
-
+
# from_to handling
from_ref_string, to_ref_string = from_to.split(':')
if flags & cls.DELETED:
from_ref = None
else:
from_ref = Reference.from_path(remote.repo, from_ref_string)
-
+
# commit handling, could be message or commit info
old_commit = None
if summary.startswith('['):
@@ -165,7 +168,7 @@ class PushInfo(object):
flags |= cls.NEW_HEAD
# uptodate encoded in control character
else:
- # fast-forward or forced update - was encoded in control character,
+ # fast-forward or forced update - was encoded in control character,
# but we parse the old and new commit
split_token = "..."
if control_character == " ":
@@ -174,36 +177,37 @@ class PushInfo(object):
# have to use constructor here as the sha usually is abbreviated
old_commit = remote.repo.commit(old_sha)
# END message handling
-
+
return PushInfo(flags, from_ref, to_ref_string, remote, old_commit, summary)
-
+
class FetchInfo(object):
+
"""
Carries information about the results of a fetch operation of a single head::
-
+
info = remote.fetch()[0]
- info.ref # Symbolic Reference or RemoteReference to the changed
+ info.ref # Symbolic Reference or RemoteReference to the changed
# remote head or FETCH_HEAD
- info.flags # additional flags to be & with enumeration members,
- # i.e. info.flags & info.REJECTED
+ info.flags # additional flags to be & with enumeration members,
+ # i.e. info.flags & info.REJECTED
# is 0 if ref is SymbolicReference
info.note # additional notes given by git-fetch intended for the user
- info.old_commit # if info.flags & info.FORCED_UPDATE|info.FAST_FORWARD,
+ info.old_commit # if info.flags & info.FORCED_UPDATE|info.FAST_FORWARD,
# field is set to the previous location of ref, otherwise None
"""
- __slots__ = ('ref','old_commit', 'flags', 'note')
-
+ __slots__ = ('ref', 'old_commit', 'flags', 'note')
+
NEW_TAG, NEW_HEAD, HEAD_UPTODATE, TAG_UPDATE, REJECTED, FORCED_UPDATE, \
- FAST_FORWARD, ERROR = [ 1 << x for x in range(8) ]
-
+ FAST_FORWARD, ERROR = [1 << x for x in range(8)]
+
# %c %-*s %-*s -> %s (%s)
re_fetch_result = re.compile("^\s*(.) (\[?[\w\s\.]+\]?)\s+(.+) -> ([/\w_\+\.-]+)( \(.*\)?$)?")
-
- _flag_map = { '!' : ERROR, '+' : FORCED_UPDATE, '-' : TAG_UPDATE, '*' : 0,
- '=' : HEAD_UPTODATE, ' ' : FAST_FORWARD }
-
- def __init__(self, ref, flags, note = '', old_commit = None):
+
+ _flag_map = {'!': ERROR, '+': FORCED_UPDATE, '-': TAG_UPDATE, '*': 0,
+ '=': HEAD_UPTODATE, ' ': FAST_FORWARD}
+
+ def __init__(self, ref, flags, note='', old_commit=None):
"""
Initialize a new instance
"""
@@ -211,28 +215,28 @@ class FetchInfo(object):
self.flags = flags
self.note = note
self.old_commit = old_commit
-
+
def __str__(self):
return self.name
-
+
@property
def name(self):
""":return: Name of our remote ref"""
return self.ref.name
-
+
@property
def commit(self):
""":return: Commit of our remote ref"""
return self.ref.commit
-
+
@classmethod
def _from_line(cls, repo, line, fetch_line):
"""Parse information from the given line as returned by git-fetch -v
and return a new FetchInfo object representing this information.
-
+
We can handle a line as follows
"%c %-*s %-*s -> %s%s"
-
+
Where c is either ' ', !, +, -, *, or =
! means error
+ means success forcing update
@@ -240,13 +244,13 @@ class FetchInfo(object):
* means birth of new branch or tag
= means the head was up to date ( and not moved )
' ' means a fast-forward
-
+
fetch line is the corresponding line from FETCH_HEAD, like
acb0fa8b94ef421ad60c8507b634759a472cd56c not-for-merge branch '0.1.7RC' of /tmp/tmpya0vairemote_repo"""
match = cls.re_fetch_result.match(line)
if match is None:
raise ValueError("Failed to parse line: %r" % line)
-
+
# parse lines
control_character, operation, local_remote_ref, remote_local_ref, note = match.groups()
try:
@@ -254,11 +258,11 @@ class FetchInfo(object):
ref_type_name, fetch_note = fetch_note.split(' ', 1)
except ValueError: # unpack error
raise ValueError("Failed to parse FETCH__HEAD line: %r" % fetch_line)
-
+
# handle FETCH_HEAD and figure out ref type
- # If we do not specify a target branch like master:refs/remotes/origin/master,
+ # If we do not specify a target branch like master:refs/remotes/origin/master,
# the fetch result is stored in FETCH_HEAD which destroys the rule we usually
- # have. In that case we use a symbolic reference which is detached
+ # have. In that case we use a symbolic reference which is detached
ref_type = None
if remote_local_ref == "FETCH_HEAD":
ref_type = SymbolicReference
@@ -271,10 +275,10 @@ class FetchInfo(object):
else:
raise TypeError("Cannot handle reference type: %r" % ref_type_name)
#END handle ref type
-
+
# create ref instance
if ref_type is SymbolicReference:
- remote_local_ref = ref_type(repo, "FETCH_HEAD")
+ remote_local_ref = ref_type(repo, "FETCH_HEAD")
else:
# determine prefix. Tags are usually pulled into refs/tags, they may have subdirectories.
# It is not clear sometimes where exactly the item is, unless we have an absolute path as indicated
@@ -296,22 +300,22 @@ class FetchInfo(object):
else:
ref_path = join_path(ref_type._common_path_default, remote_local_ref)
#END obtain refpath
-
- # even though the path could be within the git conventions, we make
+
+ # even though the path could be within the git conventions, we make
# sure we respect whatever the user wanted, and disabled path checking
remote_local_ref = ref_type(repo, ref_path, check_path=False)
- # END create ref instance
-
- note = ( note and note.strip() ) or ''
-
+ # END create ref instance
+
+ note = (note and note.strip()) or ''
+
# parse flags from control_character
flags = 0
try:
flags |= cls._flag_map[control_character]
except KeyError:
raise ValueError("Control character %r unknown as parsed from line %r" % (control_character, line))
- # END control char exception hanlding
-
+ # END control char exception hanlding
+
# parse operation string for more info - makes no sense for symbolic refs
old_commit = None
if isinstance(remote_local_ref, Reference):
@@ -328,46 +332,47 @@ class FetchInfo(object):
old_commit = repo.rev_parse(operation.split(split_token)[0])
# END handle refspec
# END reference flag handling
-
+
return cls(remote_local_ref, flags, note, old_commit)
-
+
class Remote(LazyMixin, Iterable):
+
"""Provides easy read and write access to a git remote.
-
- Everything not part of this interface is considered an option for the current
+
+ Everything not part of this interface is considered an option for the current
remote, allowing constructs like remote.pushurl to query the pushurl.
-
+
NOTE: When querying configuration, the configuration accessor will be cached
to speed up subsequent accesses."""
-
- __slots__ = ( "repo", "name", "_config_reader" )
+
+ __slots__ = ("repo", "name", "_config_reader")
_id_attribute_ = "name"
-
+
def __init__(self, repo, name):
"""Initialize a remote instance
-
+
:param repo: The repository we are a remote of
:param name: the name of the remote, i.e. 'origin'"""
self.repo = repo
self.name = name
-
+
if os.name == 'nt':
# some oddity: on windows, python 2.5, it for some reason does not realize
# that it has the config_writer property, but instead calls __getattr__
# which will not yield the expected results. 'pinging' the members
- # with a dir call creates the config_writer property that we require
+ # with a dir call creates the config_writer property that we require
# ... bugs like these make me wonder wheter python really wants to be used
# for production. It doesn't happen on linux though.
dir(self)
# END windows special handling
-
+
def __getattr__(self, attr):
- """Allows to call this instance like
+ """Allows to call this instance like
remote.special( *args, **kwargs) to call git-remote special self.name"""
if attr == "_config_reader":
return super(Remote, self).__getattr__(attr)
-
+
# sometimes, probably due to a bug in python itself, we are being called
# even though a slot of the same name exists
try:
@@ -375,32 +380,31 @@ class Remote(LazyMixin, Iterable):
except NoOptionError:
return super(Remote, self).__getattr__(attr)
# END handle exception
-
+
def _config_section_name(self):
return 'remote "%s"' % self.name
-
+
def _set_cache_(self, attr):
if attr == "_config_reader":
self._config_reader = SectionConstraint(self.repo.config_reader(), self._config_section_name())
else:
super(Remote, self)._set_cache_(attr)
-
-
+
def __str__(self):
- return self.name
-
+ return self.name
+
def __repr__(self):
return '<git.%s "%s">' % (self.__class__.__name__, self.name)
-
+
def __eq__(self, other):
return self.name == other.name
-
+
def __ne__(self, other):
- return not ( self == other )
-
+ return not (self == other)
+
def __hash__(self):
return hash(self.name)
-
+
@classmethod
def iter_items(cls, repo):
""":return: Iterator yielding Remote objects of the given repository"""
@@ -411,43 +415,43 @@ class Remote(LazyMixin, Iterable):
rbound = section.rfind('"')
if lbound == -1 or rbound == -1:
raise ValueError("Remote-Section has invalid format: %r" % section)
- yield Remote(repo, section[lbound+1:rbound])
+ yield Remote(repo, section[lbound + 1:rbound])
# END for each configuration section
-
+
@property
def refs(self):
"""
:return:
- IterableList of RemoteReference objects. It is prefixed, allowing
+ IterableList of RemoteReference objects. It is prefixed, allowing
you to omit the remote path portion, i.e.::
remote.refs.master # yields RemoteReference('/refs/remotes/origin/master')"""
out_refs = IterableList(RemoteReference._id_attribute_, "%s/" % self.name)
out_refs.extend(RemoteReference.list_items(self.repo, remote=self.name))
assert out_refs, "Remote %s did not have any references" % self.name
return out_refs
-
+
@property
def stale_refs(self):
"""
:return:
- IterableList RemoteReference objects that do not have a corresponding
- head in the remote reference anymore as they have been deleted on the
+ IterableList RemoteReference objects that do not have a corresponding
+ head in the remote reference anymore as they have been deleted on the
remote side, but are still available locally.
-
+
The IterableList is prefixed, hence the 'origin' must be omitted. See
'refs' property for an example."""
out_refs = IterableList(RemoteReference._id_attribute_, "%s/" % self.name)
for line in self.repo.git.remote("prune", "--dry-run", self).splitlines()[2:]:
- # expecting
+ # expecting
# * [would prune] origin/new_branch
- token = " * [would prune] "
+ token = " * [would prune] "
if not line.startswith(token):
raise ValueError("Could not parse git-remote prune result: %r" % line)
- fqhn = "%s/%s" % (RemoteReference._common_path_default,line.replace(token, ""))
+ fqhn = "%s/%s" % (RemoteReference._common_path_default, line.replace(token, ""))
out_refs.append(RemoteReference(self.repo, fqhn))
- # END for each line
+ # END for each line
return out_refs
-
+
@classmethod
def create(cls, repo, name, url, **kwargs):
"""Create a new remote to the given repository
@@ -456,30 +460,30 @@ class Remote(LazyMixin, Iterable):
:param url: URL which corresponds to the remote's name
:param kwargs:
Additional arguments to be passed to the git-remote add command
-
+
:return: New Remote instance
-
+
:raise GitCommandError: in case an origin with that name already exists"""
- repo.git.remote( "add", name, url, **kwargs )
+ repo.git.remote("add", name, url, **kwargs)
return cls(repo, name)
-
+
# add is an alias
add = create
-
+
@classmethod
- def remove(cls, repo, name ):
+ def remove(cls, repo, name):
"""Remove the remote with the given name"""
repo.git.remote("rm", name)
-
+
# alias
rm = remove
-
+
def rename(self, new_name):
"""Rename self to the given new_name
:return: self """
if self.name == new_name:
return self
-
+
self.repo.git.remote("rename", self.name, new_name)
self.name = new_name
try:
@@ -488,24 +492,23 @@ class Remote(LazyMixin, Iterable):
pass
#END handle exception
return self
-
+
def update(self, **kwargs):
- """Fetch all changes for this remote, including new branches which will
+ """Fetch all changes for this remote, including new branches which will
be forced in ( in case your local remote branch is not part the new remote branches
ancestry anymore ).
-
+
:param kwargs:
Additional arguments passed to git-remote update
-
+
:return: self """
self.repo.git.remote("update", self.name)
return self
-
+
def _get_fetch_info_from_stderr(self, proc, progress):
# skip first line as it is some remote info we are not interested in
output = IterableList('name')
-
# lines which are no progress are fetch info lines
# this also waits for the command to finish
# Skip some progress lines that don't provide relevant information
@@ -522,30 +525,30 @@ class Remote(LazyMixin, Iterable):
# END handle special messages
fetch_info_lines.append(line)
# END for each line
-
- # read head information
- fp = open(join(self.repo.git_dir, 'FETCH_HEAD'),'r')
+
+ # read head information
+ fp = open(join(self.repo.git_dir, 'FETCH_HEAD'), 'r')
fetch_head_info = fp.readlines()
fp.close()
-
+
# NOTE: HACK Just disabling this line will make github repositories work much better.
- # I simply couldn't stand it anymore, so here is the quick and dirty fix ... .
+ # I simply couldn't stand it anymore, so here is the quick and dirty fix ... .
# This project needs a lot of work !
# assert len(fetch_info_lines) == len(fetch_head_info), "len(%s) != len(%s)" % (fetch_head_info, fetch_info_lines)
-
- output.extend(FetchInfo._from_line(self.repo, err_line, fetch_line)
- for err_line,fetch_line in zip(fetch_info_lines, fetch_head_info))
-
+
+ output.extend(FetchInfo._from_line(self.repo, err_line, fetch_line)
+ for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info))
+
finalize_process(proc)
return output
-
+
def _get_push_info(self, proc, progress):
# read progress information from stderr
# we hope stdout can hold all the data, it should ...
# read the lines manually as it will use carriage returns between the messages
# to override the previous one. This is why we read the bytes manually
digest_process_messages(proc.stderr, progress)
-
+
output = IterableList('name')
for line in proc.stdout.readlines():
try:
@@ -553,26 +556,25 @@ class Remote(LazyMixin, Iterable):
except ValueError:
# if an error happens, additional info is given which we cannot parse
pass
- # END exception handling
+ # END exception handling
# END for each line
-
+
finalize_process(proc)
return output
-
-
+
def fetch(self, refspec=None, progress=None, **kwargs):
"""Fetch the latest changes for this remote
-
+
:param refspec:
- A "refspec" is used by fetch and push to describe the mapping
- between remote ref and local ref. They are combined with a colon in
- the format <src>:<dst>, preceded by an optional plus sign, +.
- For example: git fetch $URL refs/heads/master:refs/heads/origin means
- "grab the master branch head from the $URL and store it as my origin
- branch head". And git push $URL refs/heads/master:refs/heads/to-upstream
- means "publish my master branch head as to-upstream branch at $URL".
+ A "refspec" is used by fetch and push to describe the mapping
+ between remote ref and local ref. They are combined with a colon in
+ the format <src>:<dst>, preceded by an optional plus sign, +.
+ For example: git fetch $URL refs/heads/master:refs/heads/origin means
+ "grab the master branch head from the $URL and store it as my origin
+ branch head". And git push $URL refs/heads/master:refs/heads/to-upstream
+ means "publish my master branch head as to-upstream branch at $URL".
See also git-push(1).
-
+
Taken from the git manual
Fetch supports multiple refspecs (as the
@@ -581,11 +583,11 @@ class Remote(LazyMixin, Iterable):
:param progress: See 'push' method
:param kwargs: Additional arguments to be passed to git-fetch
:return:
- IterableList(FetchInfo, ...) list of FetchInfo instances providing detailed
+ IterableList(FetchInfo, ...) list of FetchInfo instances providing detailed
information about the fetch results
-
+
:note:
- As fetch does not provide progress information to non-ttys, we cannot make
+ As fetch does not provide progress information to non-ttys, we cannot make
it available here unfortunately as in the 'push' method."""
kwargs = add_progress(kwargs, self.repo.git, progress)
if isinstance(refspec, list):
@@ -594,11 +596,11 @@ class Remote(LazyMixin, Iterable):
args = [refspec]
proc = self.repo.git.fetch(self, *args, with_extended_output=True, as_process=True, v=True, **kwargs)
return self._get_fetch_info_from_stderr(proc, progress or RemoteProgress())
-
+
def pull(self, refspec=None, progress=None, **kwargs):
- """Pull changes from the given branch, being the same as a fetch followed
+ """Pull changes from the given branch, being the same as a fetch followed
by a merge of branch with your local branch.
-
+
:param refspec: see 'fetch' method
:param progress: see 'push' method
:param kwargs: Additional arguments to be passed to git-pull
@@ -606,20 +608,20 @@ class Remote(LazyMixin, Iterable):
kwargs = add_progress(kwargs, self.repo.git, progress)
proc = self.repo.git.pull(self, refspec, with_extended_output=True, as_process=True, v=True, **kwargs)
return self._get_fetch_info_from_stderr(proc, progress or RemoteProgress())
-
+
def push(self, refspec=None, progress=None, **kwargs):
"""Push changes from source branch in refspec to target branch in refspec.
-
+
:param refspec: see 'fetch' method
:param progress:
- Instance of type RemoteProgress allowing the caller to receive
+ Instance of type RemoteProgress allowing the caller to receive
progress information until the method returns.
If None, progress information will be discarded
-
+
:param kwargs: Additional arguments to be passed to git-push
:return:
- IterableList(PushInfo, ...) iterable list of PushInfo instances, each
- one informing about an individual head which had been updated on the remote
+ IterableList(PushInfo, ...) iterable list of PushInfo instances, each
+ one informing about an individual head which had been updated on the remote
side.
If the push contains rejected heads, these will have the PushInfo.ERROR bit set
in their flags.
@@ -628,7 +630,7 @@ class Remote(LazyMixin, Iterable):
kwargs = add_progress(kwargs, self.repo.git, progress)
proc = self.repo.git.push(self, refspec, porcelain=True, as_process=True, **kwargs)
return self._get_push_info(proc, progress or RemoteProgress())
-
+
@property
def config_reader(self):
"""
@@ -636,20 +638,20 @@ class Remote(LazyMixin, Iterable):
GitConfigParser compatible object able to read options for only our remote.
Hence you may simple type config.get("pushurl") to obtain the information"""
return self._config_reader
-
+
@property
def config_writer(self):
"""
:return: GitConfigParser compatible object able to write options for this remote.
:note:
- You can only own one writer at a time - delete it to release the
+ You can only own one writer at a time - delete it to release the
configuration file and make it useable by others.
-
- To assure consistent results, you should only query options through the
- writer. Once you are done writing, you are free to use the config reader
+
+ To assure consistent results, you should only query options through the
+ writer. Once you are done writing, you are free to use the config reader
once again."""
writer = self.repo.config_writer()
-
+
# clear our cache to assure we re-read the possibly changed configuration
try:
del(self._config_reader)