Repository: gitpython-developers/GitPython
Pull request #522 (2016-10-02 15:00:21)

RF: coveralls (not used/relied on really) -> codecov
codecov in our (datalad, etc) experience provides a better service,
great support, and super-nice intergration with chromium and firefox
for reviewing coverage of pull requests.  In light of the
@with_rw_directory fiasco detected/fixed in #521 I would strongly
recommend to (re-)enable and use coverage reports

edit 1: I think that if you accept this PR codecov might automagically enable itself on this repo, but I could be wrong and someone with authority might need to login into codecov via github and enable

coverage as seen from my clone: https://codecov.io/gh/yarikoptic/GitPython/commit/94ca83c6b6f49bb1244569030ce7989d4e01495c
and trust me integration with browsers is great!    ha -- actually basic (since there were no reports against master -- can't show the difference)  report already appeared here (magic!)

If you want to see it in action -- install codecov browser plugin and look e.g. at https://github.com/datalad/datalad/pull/969/files 


Patch:
diff --git a/.appveyor.yml b/.appveyor.yml
index 9b87d962..47bd1f0b 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -38,10 +38,9 @@ environment:
 install:
     - set PATH=%PYTHON%;%PYTHON%\Scripts;%GIT_PATH%;%PATH%
 
-    ## Print configuration for debugging.
+    ## Print architecture, python & git used for debugging.
     #
     - |
-        echo %PATH%
         uname -a
         where git git-daemon python pip pip3 pip34
         python --version
@@ -78,7 +77,7 @@ install:
 build: false
 
 test_script:
-    - nosetests -v --with-coverage
+    - nosetests --with-coverage
 
 #on_success:
 #    - IF "%PYTHON_VERSION%"=="3.4" (coveralls)
diff --git a/.travis.yml b/.travis.yml
index 0a1b79ff..4e0a829a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,7 +16,7 @@ git:
 install:
   - git submodule update --init --recursive
   - git fetch --tags
-  - pip install coveralls flake8 ddt sphinx
+  - pip install codecov flake8 ddt sphinx
 
   # generate some reflog as git-python tests need it (in master)
   - ./init-tests-after-clone.sh
@@ -29,11 +29,11 @@ install:
   - cat git/test/fixtures/.gitconfig >> ~/.gitconfig
 script:
   # Make sure we limit open handles to see if we are leaking them
-  - ulimit -n 110
+  - ulimit -n 96
   - ulimit -n
-  - nosetests -v --with-coverage
+  - nosetests --with-coverage
   - if [ "$TRAVIS_PYTHON_VERSION" == '3.4' ]; then flake8; fi
   - if [ "$TRAVIS_PYTHON_VERSION" == '3.5' ]; then cd doc && make html; fi
   -
 after_success:
-  - coveralls
+  - codecov
diff --git a/README.md b/README.md
index 42000af5..9e841ee2 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,27 @@
 ## GitPython
 
-GitPython is a python library used to interact with git repositories, high-level like git-porcelain,
+GitPython is a python library used to interact with git repositories, high-level like git-porcelain, 
 or low-level like git-plumbing.
 
-It provides abstractions of git objects for easy access of repository data, and additionally
-allows you to access the git repository more directly using either a pure python implementation,
+It provides abstractions of git objects for easy access of repository data, and additionally 
+allows you to access the git repository more directly using either a pure python implementation, 
 or the faster, but more resource intensive *git command* implementation.
 
-The object database implementation is optimized for handling large quantities of objects and large datasets,
+The object database implementation is optimized for handling large quantities of objects and large datasets, 
 which is achieved by using low-level structures and data streaming.
 
 
 ### REQUIREMENTS
 
-GitPython needs the `git` executable to be installed on the system and available
-in your `PATH` for most operations.
-If it is not in your `PATH`, you can help GitPython find it by setting
+GitPython needs the `git` executable to be installed on the system and available 
+in your `PATH` for most operations. 
+If it is not in your `PATH`, you can help GitPython find it by setting 
 the `GIT_PYTHON_GIT_EXECUTABLE=<path/to/git>` environment variable.
 
 * Git (1.7.x or newer)
 * Python 2.7 to 3.5, while python 2.6 is supported on a *best-effort basis*.
 
-The list of dependencies are listed in `./requirements.txt` and `./test-requirements.txt`.
+The list of dependencies are listed in `./requirements.txt` and `./test-requirements.txt`. 
 The installer takes care of installing them for you.
 
 ### INSTALL
@@ -62,15 +62,10 @@ codebase for `__del__` implementations and call these yourself when you see fit.
 Another way assure proper cleanup of resources is to factor out GitPython into a
 separate process which can be dropped periodically.
 
-#### Windows support
+#### Best-effort for Python 2.6 and Windows support
 
-For *Windows*, we do regularly test it on [Appveyor CI](https://www.appveyor.com/)
-but not all test-cases pass - you may help improve them by exploring
-[Issue #525](https://github.com/gitpython-developers/GitPython/issues/525).
-
-#### Python 2.6
-
-Python 2.6 is supported on best-effort basis; which means that it is likely to deteriorate over time.
+This means that support for these platforms is likely to worsen over time
+as they are kept alive solely by their users, or not.
 
 ### RUNNING TESTS
 
@@ -105,7 +100,7 @@ Please have a look at the [contributions file][contributing].
 * [Questions and Answers](http://stackexchange.com/filters/167317/gitpython)
  * Please post on stackoverflow and use the `gitpython` tag
 * [Issue Tracker](https://github.com/gitpython-developers/GitPython/issues)
-  * Post reproducible bugs and feature requests as a new issue.
+  * Post reproducible bugs and feature requests as a new issue. 
     Please be sure to provide the following information if posting bugs:
     * GitPython version (e.g. `import git; git.__version__`)
     * Python version (e.g. `python --version`)
@@ -136,7 +131,7 @@ New BSD License.  See the LICENSE file.
 [![Stories in Ready](https://badge.waffle.io/gitpython-developers/GitPython.png?label=ready&title=Ready)](https://waffle.io/gitpython-developers/GitPython)
 [![Throughput Graph](https://graphs.waffle.io/gitpython-developers/GitPython/throughput.svg)](https://waffle.io/gitpython-developers/GitPython/metrics/throughput)
 
-Now that there seems to be a massive user base, this should be motivation enough to let git-python
+Now that there seems to be a massive user base, this should be motivation enough to let git-python 
 return to a proper state, which means
 
 * no open pull requests
diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst
index 7ac2eeea..92020975 100644
--- a/doc/source/tutorial.rst
+++ b/doc/source/tutorial.rst
@@ -28,28 +28,28 @@ In the above example, the directory ``self.rorepo.working_tree_dir`` equals ``/U
     :language: python
     :start-after: # [2-test_init_repo_object]
     :end-before: # ![2-test_init_repo_object]
-
+    
 A repo object provides high-level access to your data, it allows you to create and delete heads, tags and remotes and access the configuration of the repository.
-
+    
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [3-test_init_repo_object]
     :end-before: # ![3-test_init_repo_object]
 
 Query the active branch, query untracked files or whether the repository data has been modified.
-
+    
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [4-test_init_repo_object]
     :end-before: # ![4-test_init_repo_object]
-
+    
 Clone from existing repositories or initialize new empty ones.
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [5-test_init_repo_object]
     :end-before: # ![5-test_init_repo_object]
-
+    
 Archive the repository contents to a tar file.
 
 .. literalinclude:: ../../git/test/test_docs.py
@@ -62,7 +62,7 @@ Advanced Repo Usage
 
 And of course, there is much more you can do with this type, most of the following will be explained in greater detail in specific tutorials. Don't worry if you don't understand some of these examples right away, as they may require a thorough understanding of gits inner workings.
 
-Query relevant repository paths ...
+Query relevant repository paths ... 
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
@@ -83,7 +83,7 @@ You can also create new heads ...
     :start-after: # [9-test_init_repo_object]
     :end-before: # ![9-test_init_repo_object]
 
-... and tags ...
+... and tags ... 
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
@@ -118,7 +118,7 @@ The :class:`index <git.index.base.IndexFile>` is also called stage in git-speak.
     :start-after: # [14-test_init_repo_object]
     :end-before: # ![14-test_init_repo_object]
 
-
+    
 Examining References
 ********************
 
@@ -128,28 +128,28 @@ Examining References
     :language: python
     :start-after: # [1-test_references_and_objects]
     :end-before: # ![1-test_references_and_objects]
-
+    
 :class:`Tags <git.refs.tag.TagReference>` are (usually immutable) references to a commit and/or a tag object.
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [2-test_references_and_objects]
     :end-before: # ![2-test_references_and_objects]
-
+    
 A :class:`symbolic reference <git.refs.symbolic.SymbolicReference>` is a special case of a reference as it points to another reference instead of a commit.
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [3-test_references_and_objects]
     :end-before: # ![3-test_references_and_objects]
-
+    
 Access the :class:`reflog <git.refs.log.RefLog>` easily.
-
+    
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [4-test_references_and_objects]
     :end-before: # ![4-test_references_and_objects]
-
+    
 Modifying References
 ********************
 You can easily create and delete :class:`reference types <git.refs.reference.Reference>` or modify where they point to.
@@ -165,7 +165,7 @@ Create or delete :class:`tags <git.refs.tag.TagReference>` the same way except y
     :language: python
     :start-after: # [6-test_references_and_objects]
     :end-before: # ![6-test_references_and_objects]
-
+    
 Change the :class:`symbolic reference <git.refs.symbolic.SymbolicReference>` to switch branches cheaply (without adjusting the index or the working tree).
 
 .. literalinclude:: ../../git/test/test_docs.py
@@ -185,29 +185,29 @@ In GitPython, all objects can be accessed through their common base, can be comp
     :language: python
     :start-after: # [8-test_references_and_objects]
     :end-before: # ![8-test_references_and_objects]
-
-Common fields are ...
+    
+Common fields are ... 
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [9-test_references_and_objects]
     :end-before: # ![9-test_references_and_objects]
-
+    
 :class:`Index objects <git.objects.base.IndexObject>` are objects that can be put into git's index. These objects are trees, blobs and submodules which additionally know about their path in the file system as well as their mode.
-
+    
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [10-test_references_and_objects]
     :end-before: # ![10-test_references_and_objects]
-
+    
 Access :class:`blob <git.objects.blob.Blob>` data (or any object data) using streams.
-
+    
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [11-test_references_and_objects]
     :end-before: # ![11-test_references_and_objects]
-
-
+    
+    
 The Commit object
 *****************
 
@@ -218,35 +218,35 @@ Obtain commits at the specified revision
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [12-test_references_and_objects]
-    :end-before: # ![12-test_references_and_objects]
+    :end-before: # ![12-test_references_and_objects]    
 
 Iterate 50 commits, and if you need paging, you can specify a number of commits to skip.
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [13-test_references_and_objects]
-    :end-before: # ![13-test_references_and_objects]
+    :end-before: # ![13-test_references_and_objects]    
 
 A commit object carries all sorts of meta-data
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [14-test_references_and_objects]
-    :end-before: # ![14-test_references_and_objects]
+    :end-before: # ![14-test_references_and_objects]    
 
 Note: date time is represented in a ``seconds since epoch`` format. Conversion to human readable form can be accomplished with the various `time module <http://docs.python.org/library/time.html>`_ methods.
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [15-test_references_and_objects]
-    :end-before: # ![15-test_references_and_objects]
+    :end-before: # ![15-test_references_and_objects]    
 
 You can traverse a commit's ancestry by chaining calls to ``parents``
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [16-test_references_and_objects]
-    :end-before: # ![16-test_references_and_objects]
+    :end-before: # ![16-test_references_and_objects]        
 
 The above corresponds to ``master^^^`` or ``master~3`` in git parlance.
 
@@ -258,62 +258,62 @@ A :class:`tree <git.objects.tree.Tree>` records pointers to the contents of a di
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [17-test_references_and_objects]
-    :end-before: # ![17-test_references_and_objects]
+    :end-before: # ![17-test_references_and_objects]            
 
 Once you have a tree, you can get its contents
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [18-test_references_and_objects]
-    :end-before: # ![18-test_references_and_objects]
+    :end-before: # ![18-test_references_and_objects]            
 
 It is useful to know that a tree behaves like a list with the ability to query entries by name
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [19-test_references_and_objects]
-    :end-before: # ![19-test_references_and_objects]
+    :end-before: # ![19-test_references_and_objects]            
 
 There is a convenience method that allows you to get a named sub-object from a tree with a syntax similar to how paths are written in a posix system
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [20-test_references_and_objects]
-    :end-before: # ![20-test_references_and_objects]
+    :end-before: # ![20-test_references_and_objects]                
 
 You can also get a commit's root tree directly from the repository
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [21-test_references_and_objects]
-    :end-before: # ![21-test_references_and_objects]
-
+    :end-before: # ![21-test_references_and_objects]    
+    
 As trees allow direct access to their intermediate child entries only, use the traverse method to obtain an iterator to retrieve entries recursively
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [22-test_references_and_objects]
-    :end-before: # ![22-test_references_and_objects]
-
+    :end-before: # ![22-test_references_and_objects]        
+    
 .. note:: If trees return Submodule objects, they will assume that they exist at the current head's commit. The tree it originated from may be rooted at another commit though, that it doesn't know. That is why the caller would have to set the submodule's owning or parent commit using the ``set_parent_commit(my_commit)`` method.
-
+    
 The Index Object
 ****************
 The git index is the stage containing changes to be written with the next commit or where merges finally have to take place. You may freely access and manipulate this information using the :class:`IndexFile <git.index.base.IndexFile>` object.
 Modify the index with ease
-
+    
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [23-test_references_and_objects]
-    :end-before: # ![23-test_references_and_objects]
-
+    :end-before: # ![23-test_references_and_objects]        
+    
 Create new indices from other trees or as result of a merge. Write that result to a new index file for later inspection.
 
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [24-test_references_and_objects]
-    :end-before: # ![24-test_references_and_objects]
-
+    :end-before: # ![24-test_references_and_objects]        
+    
 Handling Remotes
 ****************
 
@@ -322,10 +322,10 @@ Handling Remotes
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [25-test_references_and_objects]
-    :end-before: # ![25-test_references_and_objects]
+    :end-before: # ![25-test_references_and_objects]            
 
 You can easily access configuration information for a remote by accessing options as if they where attributes. The modification of remote configuration is more explicit though.
-
+    
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [26-test_references_and_objects]
@@ -352,7 +352,7 @@ Here's an example executable that can be used in place of the `ssh_executable` a
 Please note that the script must be executable (i.e. `chomd +x script.sh`). `StrictHostKeyChecking=no` is used to avoid prompts asking to save the hosts key to `~/.ssh/known_hosts`, which happens in case you run this as daemon.
 
 You might also have a look at `Git.update_environment(...)` in case you want to setup a changed environment more permanently.
-
+    
 Submodule Handling
 ******************
 :class:`Submodules <git.objects.submodule.base.Submodule>` can be conveniently handled using the methods provided by GitPython, and as an added benefit, GitPython provides functionality which behave smarter and less error prone than its original c-git implementation, that is GitPython tries hard to keep your repository consistent when updating submodules recursively or adjusting the existing configuration.
@@ -360,19 +360,15 @@ Submodule Handling
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [1-test_submodules]
-    :end-before: # ![1-test_submodules]
+    :end-before: # ![1-test_submodules]                
 
-In addition to the query functionality, you can move the submodule's repository to a different path <``move(...)``>,
-write its configuration <``config_writer().set_value(...).release()``>, update its working tree <``update(...)``>,
-and remove or add them <``remove(...)``, ``add(...)``>.
+In addition to the query functionality, you can move the submodule's repository to a different path <``move(...)``>, write its configuration <``config_writer().set_value(...).release()``>, update its working tree <``update(...)``>, and remove or add them <``remove(...)``, ``add(...)``>.
 
-If you obtained your submodule object by traversing a tree object which is not rooted at the head's commit,
-you have to inform the submodule about its actual commit to retrieve the data from
-by using the ``set_parent_commit(...)`` method.
+If you obtained your submodule object by traversing a tree object which is not rooted at the head's commit, you have to inform the submodule about its actual commit to retrieve the data from by using the ``set_parent_commit(...)`` method.
 
 The special :class:`RootModule <git.objects.submodule.root.RootModule>` type allows you to treat your master repository as root of a hierarchy of submodules, which allows very convenient submodule handling. Its ``update(...)`` method is reimplemented to provide an advanced way of updating submodules as they change their values over time. The update method will track changes and make sure your working tree and submodule checkouts stay consistent, which is very useful in case submodules get deleted or added to name just two of the handled cases.
 
-Additionally, GitPython adds functionality to track a specific branch, instead of just a commit. Supported by customized update methods, you are able to automatically update submodules to the latest revision available in the remote repository, as well as to keep track of changes and movements of these submodules. To use it, set the name of the branch you want to track to the ``submodule.$name.branch`` option of the *.gitmodules*  file, and use GitPython update methods on the resulting repository with the ``to_latest_revision`` parameter turned on. In the latter case, the sha of your submodule will be ignored, instead a local tracking branch will be updated to the respective remote branch automatically, provided there are no local changes. The resulting behaviour is much like the one of svn::externals, which can be useful in times.
+Additionally, GitPython adds functionality to track a specific branch, instead of just a commit. Supported by customized update methods, you are able to automatically update submodules to the latest revision available in the remote repository, as well as to keep track of changes and movements of these submodules. To use it, set the name of the branch you want to track to the ``submodule.$name.branch`` option of the *.gitmodules*  file, and use GitPython update methods on the resulting repository with the ``to_latest_revision`` parameter turned on. In the latter case, the sha of your submodule will be ignored, instead a local tracking branch will be updated to the respective remote branch automatically, provided there are no local changes. The resulting behaviour is much like the one of svn::externals, which can be useful in times. 
 
 Obtaining Diff Information
 **************************
@@ -384,7 +380,7 @@ Diffs can be made between the Index and Trees, Index and the working tree, trees
 .. literalinclude:: ../../git/test/test_docs.py
     :language: python
     :start-after: # [27-test_references_and_objects]
-    :end-before: # ![27-test_references_and_objects]
+    :end-before: # ![27-test_references_and_objects]                
 
 The item returned is a DiffIndex which is essentially a list of Diff objects. It provides additional filtering to ease finding what you might be looking for.
 
@@ -396,15 +392,15 @@ The item returned is a DiffIndex which is essentially a list of Diff objects. It
 Use the diff framework if you want to implement git-status like functionality.
 
 * A diff between the index and the commit's tree your HEAD points to
-
+ 
  * use ``repo.index.diff(repo.head.commit)``
-
+  
 * A diff between the index and the working tree
-
+ 
  * use ``repo.index.diff(None)``
-
+  
 * A list of untracked files
-
+ 
  * use ``repo.untracked_files``
 
 Switching Branches
@@ -415,7 +411,7 @@ To switch between branches similar to ``git checkout``, you effectively need to
     :language: python
     :start-after: # [29-test_references_and_objects]
     :end-before: # ![29-test_references_and_objects]
-
+    
 The previous approach would brutally overwrite the user's changes in the working copy and index though and is less sophisticated than a ``git-checkout``. The latter will generally prevent you from destroying your work. Use the safer approach as follows.
 
 .. literalinclude:: ../../git/test/test_docs.py
@@ -443,7 +439,7 @@ In case you are missing functionality as it has not been wrapped, you may conven
     :language: python
     :start-after: # [31-test_references_and_objects]
     :end-before: # ![31-test_references_and_objects]
-
+    
 The return value will by default be a string of the standard output channel produced by the command.
 
 Keyword arguments translate to short and long keyword arguments on the command-line.
@@ -461,14 +457,14 @@ The type of the database determines certain performance characteristics, such as
 GitDB
 =====
 The GitDB is a pure-python implementation of the git object database. It is the default database to use in GitPython 0.3. Its uses less memory when handling huge files, but will be 2 to 5 times slower when extracting large quantities small of objects from densely packed repositories::
-
+    
     repo = Repo("path/to/repo", odbt=GitDB)
 
 
 GitCmdObjectDB
 ==============
 The git command database uses persistent git-cat-file instances to read repository information. These operate very fast under all conditions, but will consume additional memory for the process itself. When extracting large files, memory usage will be much higher than the one of the ``GitDB``::
-
+    
     repo = Repo("path/to/repo", odbt=GitCmdObjectDB)
 
 Git Command Debugging and Customization
@@ -482,10 +478,10 @@ Using environment variables, you can further adjust the behaviour of the git com
  * If set to *full*, the executed git command _and_ its entire output on stdout and stderr will be shown as they happen
 
  **NOTE**: All logging is outputted using a Python logger, so make sure your program is configured to show INFO-level messages.  If this is not the case, try adding the following to your program::
-
+ 
     import logging
     logging.basicConfig(level=logging.INFO)
-
+ 
 * **GIT_PYTHON_GIT_EXECUTABLE**
 
  * If set, it should contain the full path to the git executable, e.g. *c:\\Program Files (x86)\\Git\\bin\\git.exe* on windows or */usr/bin/git* on linux.
diff --git a/git/__init__.py b/git/__init__.py
index 58e4e7b6..e8dae272 100644
--- a/git/__init__.py
+++ b/git/__init__.py
@@ -4,7 +4,7 @@
 # This module is part of GitPython and is released under
 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
 # flake8: noqa
-#@PydevCodeAnalysisIgnore
+
 import os
 import sys
 import inspect
@@ -32,17 +32,17 @@ _init_externals()
 
 #{ Imports
 
-from git.config import GitConfigParser  # @NoMove @IgnorePep8
-from git.objects import *               # @NoMove @IgnorePep8
-from git.refs import *                  # @NoMove @IgnorePep8
-from git.diff import *                  # @NoMove @IgnorePep8
-from git.exc import *                   # @NoMove @IgnorePep8
-from git.db import *                    # @NoMove @IgnorePep8
-from git.cmd import Git                 # @NoMove @IgnorePep8
-from git.repo import Repo               # @NoMove @IgnorePep8
-from git.remote import *                # @NoMove @IgnorePep8
-from git.index import *                 # @NoMove @IgnorePep8
-from git.util import (                  # @NoMove @IgnorePep8
+from git.config import GitConfigParser
+from git.objects import *
+from git.refs import *
+from git.diff import *
+from git.exc import *
+from git.db import *
+from git.cmd import Git
+from git.repo import Repo
+from git.remote import *
+from git.index import *
+from git.util import (
     LockFile,
     BlockingLockFile,
     Stats,
diff --git a/git/cmd.py b/git/cmd.py
index 88d62aa4..f4f5f99a 100644
--- a/git/cmd.py
+++ b/git/cmd.py
@@ -539,8 +539,7 @@ class Git(LazyMixin):
                 cmd_not_found_exception = OSError
         # end handle
 
-        log.debug("Popen(%s, cwd=%s, universal_newlines=%s, shell=%s)",
-                  command, cwd, universal_newlines, shell)
+        log.debug("Popen(%s, cwd=%s, universal_newlines=%s", command, cwd, universal_newlines)
         try:
             proc = Popen(command,
                          env=env,
diff --git a/git/compat.py b/git/compat.py
index e7243e25..441a3761 100644
--- a/git/compat.py
+++ b/git/compat.py
@@ -13,14 +13,14 @@ import sys
 
 from gitdb.utils.compat import (
     xrange,
-    MAXSIZE,    # @UnusedImport
-    izip,       # @UnusedImport
+    MAXSIZE,
+    izip,
 )
 from gitdb.utils.encoding import (
-    string_types,    # @UnusedImport
-    text_type,       # @UnusedImport
-    force_bytes,     # @UnusedImport
-    force_text       # @UnusedImport
+    string_types,
+    text_type,
+    force_bytes,
+    force_text
 )
 
 
@@ -33,21 +33,17 @@ defenc = sys.getdefaultencoding()
 if PY3:
     import io
     FileType = io.IOBase
-
     def byte_ord(b):
         return b
-
     def bchr(n):
         return bytes([n])
-
     def mviter(d):
         return d.values()
-
-    range = xrange  # @ReservedAssignment
+    range = xrange
     unicode = str
     binary_type = bytes
 else:
-    FileType = file  # @UndefinedVariable on PY3
+    FileType = file
     # usually, this is just ascii, which might not enough for our encoding needs
     # Unless it's set specifically, we override it to be utf-8
     if defenc == 'ascii':
@@ -56,8 +52,7 @@ else:
     bchr = chr
     unicode = unicode
     binary_type = str
-    range = xrange  # @ReservedAssignment
-
+    range = xrange
     def mviter(d):
         return d.itervalues()
 
diff --git a/git/config.py b/git/config.py
index eddfac15..ad6192ff 100644
--- a/git/config.py
+++ b/git/config.py
@@ -17,8 +17,6 @@ import logging
 import abc
 import os
 
-from functools import wraps
-
 from git.odict import OrderedDict
 from git.util import LockFile
 from git.compat import (
@@ -40,7 +38,7 @@ log.addHandler(logging.NullHandler())
 class MetaParserBuilder(abc.ABCMeta):
 
     """Utlity class wrapping base-class methods into decorators that assure read-only properties"""
-    def __new__(cls, name, bases, clsdict):
+    def __new__(metacls, name, bases, clsdict):
         """
         Equip all base-class methods with a needs_values decorator, and all non-const methods
         with a set_dirty_and_flush_changes decorator in addition to that."""
@@ -62,18 +60,18 @@ class MetaParserBuilder(abc.ABCMeta):
             # END for each base
         # END if mutating methods configuration is set
 
-        new_type = super(MetaParserBuilder, cls).__new__(cls, name, bases, clsdict)
+        new_type = super(MetaParserBuilder, metacls).__new__(metacls, name, bases, clsdict)
         return new_type
 
 
 def needs_values(func):
     """Returns method assuring we read values (on demand) before we try to access them"""
 
-    @wraps(func)
     def assure_data_present(self, *args, **kwargs):
         self.read()
         return func(self, *args, **kwargs)
     # END wrapper method
+    assure_data_present.__name__ = func.__name__
     return assure_data_present
 
 
@@ -479,15 +477,20 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser, obje
         is_file_lock = isinstance(fp, string_types + (FileType, ))
         if is_file_lock:
             self._lock._obtain_lock()
-        if not hasattr(fp, "seek"):
-            with open(self._file_or_files, "wb") as fp:
+        try:
+            if not hasattr(fp, "seek"):
+                with open(self._file_or_files, "wb") as fp:
+                    self._write(fp)
+            else:
+                fp.seek(0)
+                # make sure we do not overwrite into an existing file
+                if hasattr(fp, 'truncate'):
+                    fp.truncate()
                 self._write(fp)
-        else:
-            fp.seek(0)
-            # make sure we do not overwrite into an existing file
-            if hasattr(fp, 'truncate'):
-                fp.truncate()
-            self._write(fp)
+        finally:
+            # we release the lock - it will not vanish automatically in PY3.5+
+            if is_file_lock:
+                self._lock._release_lock()
 
     def _assure_writable(self, method_name):
         if self.read_only:
diff --git a/git/db.py b/git/db.py
index 39b9872a..c4e19858 100644
--- a/git/db.py
+++ b/git/db.py
@@ -7,7 +7,7 @@ from gitdb.util import (
     bin_to_hex,
     hex_to_bin
 )
-from gitdb.db import GitDB  # @UnusedImport
+from gitdb.db import GitDB
 from gitdb.db import LooseObjectDB
 
 from .exc import (
@@ -54,7 +54,7 @@ class GitCmdObjectDB(LooseObjectDB):
         :note: currently we only raise BadObject as git does not communicate
             AmbiguousObjects separately"""
         try:
-            hexsha, typename, size = self._git.get_object_header(partial_hexsha)  # @UnusedVariable
+            hexsha, typename, size = self._git.get_object_header(partial_hexsha)
             return hex_to_bin(hexsha)
         except (GitCommandError, ValueError):
             raise BadObject(partial_hexsha)
diff --git a/git/exc.py b/git/exc.py
index eb7c3c0e..47215c21 100644
--- a/git/exc.py
+++ b/git/exc.py
@@ -5,7 +5,7 @@
 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
 """ Module containing all exceptions thrown througout the git package, """
 
-from gitdb.exc import *     # NOQA @UnusedWildImport
+from gitdb.exc import *     # NOQA
 from git.compat import UnicodeMixin, safe_decode, string_types
 
 
diff --git a/git/index/base.py b/git/index/base.py
index ac2d3019..9b6d28ab 100644
--- a/git/index/base.py
+++ b/git/index/base.py
@@ -170,7 +170,7 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable):
 
     def _deserialize(self, stream):
         """Initialize this instance with index values read from the given stream"""
-        self.version, self.entries, self._extension_data, conten_sha = read_cache(stream)  # @UnusedVariable
+        self.version, self.entries, self._extension_data, conten_sha = read_cache(stream)
         return self
 
     def _entries_sorted(self):
@@ -404,7 +404,7 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable):
                     continue
             # END glob handling
             try:
-                for root, dirs, files in os.walk(abs_path, onerror=raise_exc):  # @UnusedVariable
+                for root, dirs, files in os.walk(abs_path, onerror=raise_exc):
                     for rela_file in files:
                         # add relative paths only
                         yield os.path.join(root.replace(rs, ''), rela_file)
@@ -599,6 +599,7 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable):
         """Store file at filepath in the database and return the base index entry
         Needs the git_working_dir decorator active ! This must be assured in the calling code"""
         st = os.lstat(filepath)     # handles non-symlinks as well
+        stream = None
         if S_ISLNK(st.st_mode):
             # in PY3, readlink is string, but we need bytes. In PY2, it's just OS encoded bytes, we assume UTF-8
             open_stream = lambda: BytesIO(force_bytes(os.readlink(filepath), encoding=defenc))
@@ -1101,11 +1102,11 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable):
                 try:
                     self.entries[(co_path, 0)]
                 except KeyError:
-                    folder = co_path
-                    if not folder.endswith('/'):
-                        folder += '/'
+                    dir = co_path
+                    if not dir.endswith('/'):
+                        dir += '/'
                     for entry in mviter(self.entries):
-                        if entry.path.startswith(folder):
+                        if entry.path.startswith(dir):
                             p = entry.path
                             self._write_path_to_stdin(proc, p, p, make_exc,
                                                       fprogress, read_from_stdout=False)
diff --git a/git/index/fun.py b/git/index/fun.py
index 7a7593fe..74ac929e 100644
--- a/git/index/fun.py
+++ b/git/index/fun.py
@@ -264,7 +264,7 @@ def write_tree_from_cache(entries, odb, sl, si=0):
 
             # enter recursion
             # ci - 1 as we want to count our current item as well
-            sha, tree_entry_list = write_tree_from_cache(entries, odb, slice(ci - 1, xi), rbound + 1)  # @UnusedVariable
+            sha, tree_entry_list = write_tree_from_cache(entries, odb, slice(ci - 1, xi), rbound + 1)
             tree_items_append((sha, S_IFDIR, base))
 
             # skip ahead
diff --git a/git/index/util.py b/git/index/util.py
index ce798851..0340500c 100644
--- a/git/index/util.py
+++ b/git/index/util.py
@@ -2,9 +2,6 @@
 import struct
 import tempfile
 import os
-
-from functools import wraps
-
 from git.compat import is_win
 
 __all__ = ('TemporaryFileSwap', 'post_clear_cache', 'default_index', 'git_working_dir')
@@ -51,13 +48,13 @@ def post_clear_cache(func):
         natively which in fact is possible, but probably not feasible performance wise.
     """
 
-    @wraps(func)
     def post_clear_cache_if_not_raised(self, *args, **kwargs):
         rval = func(self, *args, **kwargs)
         self._delete_entries_cache()
         return rval
-    # END wrapper method
 
+    # END wrapper method
+    post_clear_cache_if_not_raised.__name__ = func.__name__
     return post_clear_cache_if_not_raised
 
 
@@ -66,7 +63,6 @@ def default_index(func):
     repository index. This is as we rely on git commands that operate
     on that index only. """
 
-    @wraps(func)
     def check_default_index(self, *args, **kwargs):
         if self._file_path != self._index_path():
             raise AssertionError(
@@ -74,6 +70,7 @@ def default_index(func):
         return func(self, *args, **kwargs)
     # END wrpaper method
 
+    check_default_index.__name__ = func.__name__
     return check_default_index
 
 
@@ -81,7 +78,6 @@ def git_working_dir(func):
     """Decorator which changes the current working dir to the one of the git
     repository in order to assure relative paths are handled correctly"""
 
-    @wraps(func)
     def set_git_working_dir(self, *args, **kwargs):
         cur_wd = os.getcwd()
         os.chdir(self.repo.working_tree_dir)
@@ -92,6 +88,7 @@ def git_working_dir(func):
         # END handle working dir
     # END wrapper
 
+    set_git_working_dir.__name__ = func.__name__
     return set_git_working_dir
 
 #} END decorators
diff --git a/git/objects/__init__.py b/git/objects/__init__.py
index 23b2416a..ee642876 100644
--- a/git/objects/__init__.py
+++ b/git/objects/__init__.py
@@ -3,24 +3,22 @@ Import all submodules main classes into the package space
 """
 # flake8: noqa
 from __future__ import absolute_import
-
 import inspect
-
 from .base import *
-from .blob import *
-from .commit import *
-from .submodule import util as smutil
-from .submodule.base import *
-from .submodule.root import *
-from .tag import *
-from .tree import *
 # Fix import dependency - add IndexObject to the util module, so that it can be
 # imported by the submodule.base
+from .submodule import util as smutil
 smutil.IndexObject = IndexObject
 smutil.Object = Object
 del(smutil)
+from .submodule.base import *
+from .submodule.root import *
 
 # must come after submodule was made available
+from .tag import *
+from .blob import *
+from .commit import *
+from .tree import *
 
 __all__ = [name for name, obj in locals().items()
            if not (name.startswith('_') or inspect.ismodule(obj))]
diff --git a/git/objects/base.py b/git/objects/base.py
index 0b849960..77d0ed63 100644
--- a/git/objects/base.py
+++ b/git/objects/base.py
@@ -40,7 +40,7 @@ class Object(LazyMixin):
         assert len(binsha) == 20, "Require 20 byte binary sha, got %r, len = %i" % (binsha, len(binsha))
 
     @classmethod
-    def new(cls, repo, id):  # @ReservedAssignment
+    def new(cls, repo, id):
         """
         :return: New Object instance of a type appropriate to the object type behind
             id. The id of the newly created object will be a binsha even though
diff --git a/git/objects/commit.py b/git/objects/commit.py
index 1534c552..000ab3d0 100644
--- a/git/objects/commit.py
+++ b/git/objects/commit.py
@@ -140,7 +140,7 @@ class Commit(base.Object, Iterable, Diffable, Traversable, Serializable):
     def _set_cache_(self, attr):
         if attr in Commit.__slots__:
             # read the data in a chunk, its faster - then provide a file wrapper
-            binsha, typename, self.size, stream = self.repo.odb.stream(self.binsha)  # @UnusedVariable
+            binsha, typename, self.size, stream = self.repo.odb.stream(self.binsha)
             self._deserialize(BytesIO(stream.read()))
         else:
             super(Commit, self)._set_cache_(attr)
@@ -267,7 +267,7 @@ class Commit(base.Object, Iterable, Diffable, Traversable, Serializable):
             hexsha = line.strip()
             if len(hexsha) > 40:
                 # split additional information, as returned by bisect for instance
-                hexsha, _ = line.split(None, 1)
+                hexsha, rest = line.split(None, 1)
             # END handle extra info
 
             assert len(hexsha) == 40, "Invalid line: %s" % hexsha
diff --git a/git/objects/fun.py b/git/objects/fun.py
index 5c0f4819..c04f80b5 100644
--- a/git/objects/fun.py
+++ b/git/objects/fun.py
@@ -157,9 +157,9 @@ def traverse_trees_recursive(odb, tree_shas, path_prefix):
             if not item:
                 continue
             # END skip already done items
-            entries = [None for _ in range(nt)]
+            entries = [None for n in range(nt)]
             entries[ti] = item
-            sha, mode, name = item                          # its faster to unpack @UnusedVariable
+            sha, mode, name = item                          # its faster to unpack
             is_dir = S_ISDIR(mode)                          # type mode bits
 
             # find this item in all other tree data items
diff --git a/git/objects/submodule/base.py b/git/objects/submodule/base.py
index 6777b121..c6c6d699 100644
--- a/git/objects/submodule/base.py
+++ b/git/objects/submodule/base.py
@@ -1,3 +1,4 @@
+from . import util
 from .util import (
     mkhead,
     sm_name,
@@ -38,9 +39,6 @@ import git
 import os
 import logging
 import uuid
-from unittest.case import SkipTest
-from git.test.lib.helper import HIDE_WINDOWS_KNOWN_ERRORS
-from git.objects.base import IndexObject, Object
 
 __all__ = ["Submodule", "UpdateProgress"]
 
@@ -69,7 +67,7 @@ UPDWKTREE = UpdateProgress.UPDWKTREE
 # IndexObject comes via util module, its a 'hacky' fix thanks to pythons import
 # mechanism which cause plenty of trouble of the only reason for packages and
 # modules is refactoring - subpackages shoudn't depend on parent packages
-class Submodule(IndexObject, Iterable, Traversable):
+class Submodule(util.IndexObject, Iterable, Traversable):
 
     """Implements access to a git submodule. They are special in that their sha
     represents a commit in the submodule's repository which is to be checked out
@@ -398,20 +396,24 @@ class Submodule(IndexObject, Iterable, Traversable):
         # otherwise there is a '-' character in front of the submodule listing
         #  a38efa84daef914e4de58d1905a500d8d14aaf45 mymodule (v0.9.0-1-ga38efa8)
         # -a38efa84daef914e4de58d1905a500d8d14aaf45 submodules/intermediate/one
-        with sm.repo.config_writer() as writer:
-            writer.set_value(sm_section(name), 'url', url)
+        writer = sm.repo.config_writer()
+        writer.set_value(sm_section(name), 'url', url)
+        writer.release()
 
         # update configuration and index
         index = sm.repo.index
-        with sm.config_writer(index=index, write=False) as writer:
-            writer.set_value('url', url)
-            writer.set_value('path', path)
-
-            sm._url = url
-            if not branch_is_default:
-                # store full path
-                writer.set_value(cls.k_head_option, br.path)
-                sm._branch_path = br.path
+        writer = sm.config_writer(index=index, write=False)
+        writer.set_value('url', url)
+        writer.set_value('path', path)
+
+        sm._url = url
+        if not branch_is_default:
+            # store full path
+            writer.set_value(cls.k_head_option, br.path)
+            sm._branch_path = br.path
+        # END handle path
+        writer.release()
+        del(writer)
 
         # we deliberatly assume that our head matches our index !
         sm.binsha = mrepo.head.commit.binsha
@@ -524,7 +526,7 @@ class Submodule(IndexObject, Iterable, Traversable):
 
                         # have a valid branch, but no checkout - make sure we can figure
                         # that out by marking the commit with a null_sha
-                        local_branch.set_object(Object(mrepo, self.NULL_BIN_SHA))
+                        local_branch.set_object(util.Object(mrepo, self.NULL_BIN_SHA))
                         # END initial checkout + branch creation
 
                         # make sure HEAD is not detached
@@ -538,8 +540,9 @@ class Submodule(IndexObject, Iterable, Traversable):
                     # the default implementation will be offended and not update the repository
                     # Maybe this is a good way to assure it doesn't get into our way, but
                     # we want to stay backwards compatible too ... . Its so redundant !
-                    with self.repo.config_writer() as writer:
-                        writer.set_value(sm_section(self.name), 'url', self.url)
+                    writer = self.repo.config_writer()
+                    writer.set_value(sm_section(self.name), 'url', self.url)
+                    writer.release()
                 # END handle dry_run
             # END handle initalization
 
@@ -726,9 +729,11 @@ class Submodule(IndexObject, Iterable, Traversable):
                 # END handle submodule doesn't exist
 
                 # update configuration
-                with self.config_writer(index=index) as writer:        # auto-write
-                    writer.set_value('path', module_checkout_path)
-                    self.path = module_checkout_path
+                writer = self.config_writer(index=index)        # auto-write
+                writer.set_value('path', module_checkout_path)
+                self.path = module_checkout_path
+                writer.release()
+                del(writer)
             # END handle configuration flag
         except Exception:
             if renamed_module:
@@ -831,7 +836,7 @@ class Submodule(IndexObject, Iterable, Traversable):
                         num_branches_with_new_commits += len(mod.git.cherry(rref)) != 0
                     # END for each remote ref
                     # not a single remote branch contained all our commits
-                    if len(rrefs) and num_branches_with_new_commits == len(rrefs):
+                    if num_branches_with_new_commits == len(rrefs):
                         raise InvalidGitRepositoryError(
                             "Cannot delete module at %s as there are new commits" % mod.working_tree_dir)
                     # END handle new commits
@@ -851,25 +856,13 @@ class Submodule(IndexObject, Iterable, Traversable):
                     del(mod)        # release file-handles (windows)
                     import gc
                     gc.collect()
-                    try:
-                        rmtree(wtd)
-                    except Exception as ex:
-                        if HIDE_WINDOWS_KNOWN_ERRORS:
-                            raise SkipTest("FIXME: fails with: PermissionError\n  %s", ex)
-                        else:
-                            raise
+                    rmtree(wtd)
                 # END delete tree if possible
             # END handle force
 
             if not dry_run and os.path.isdir(git_dir):
                 self._clear_cache()
-                try:
-                    rmtree(git_dir)
-                except Exception as ex:
-                    if HIDE_WINDOWS_KNOWN_ERRORS:
-                        raise SkipTest("FIXME: fails with: PermissionError\n  %s", ex)
-                    else:
-                        raise
+                rmtree(git_dir)
             # end handle separate bare repository
         # END handle module deletion
 
@@ -891,11 +884,13 @@ class Submodule(IndexObject, Iterable, Traversable):
 
             # now git config - need the config intact, otherwise we can't query
             # information anymore
-            with self.repo.config_writer() as writer:
-                writer.remove_section(sm_section(self.name))
+            writer = self.repo.config_writer()
+            writer.remove_section(sm_section(self.name))
+            writer.release()
 
-            with self.config_writer() as writer:
-                writer.remove_section()
+            writer = self.config_writer()
+            writer.remove_section()
+            writer.release()
         # END delete configuration
 
         return self
@@ -986,15 +981,18 @@ class Submodule(IndexObject, Iterable, Traversable):
             return self
 
         # .git/config
-        with self.repo.config_writer() as pw:
-            # As we ourselves didn't write anything about submodules into the parent .git/config,
-            # we will not require it to exist, and just ignore missing entries.
-            if pw.has_section(sm_section(self.name)):
-                pw.rename_section(sm_section(self.name), sm_section(new_name))
+        pw = self.repo.config_writer()
+        # As we ourselves didn't write anything about submodules into the parent .git/config, we will not require
+        # it to exist, and just ignore missing entries
+        if pw.has_section(sm_section(self.name)):
+            pw.rename_section(sm_section(self.name), sm_section(new_name))
+        # end
+        pw.release()
 
         # .gitmodules
-        with self.config_writer(write=True) as cw:
-            cw.config.rename_section(sm_section(self.name), sm_section(new_name))
+        cw = self.config_writer(write=True).config
+        cw.rename_section(sm_section(self.name), sm_section(new_name))
+        cw.release()
 
         self._name = new_name
 
diff --git a/git/objects/tag.py b/git/objects/tag.py
index cefff083..c8684447 100644
--- a/git/objects/tag.py
+++ b/git/objects/tag.py
@@ -21,7 +21,7 @@ class TagObject(base.Object):
     type = "tag"
     __slots__ = ("object", "tag", "tagger", "tagged_date", "tagger_tz_offset", "message")
 
-    def __init__(self, repo, binsha, object=None, tag=None,  # @ReservedAssignment
+    def __init__(self, repo, binsha, object=None, tag=None,
                  tagger=None, tagged_date=None, tagger_tz_offset=None, message=None):
         """Initialize a tag object with additional data
 
@@ -55,8 +55,8 @@ class TagObject(base.Object):
             ostream = self.repo.odb.stream(self.binsha)
             lines = ostream.read().decode(defenc).splitlines()
 
-            obj, hexsha = lines[0].split(" ")       # object <hexsha> @UnusedVariable
-            type_token, type_name = lines[1].split(" ")  # type <type_name> @UnusedVariable
+            obj, hexsha = lines[0].split(" ")       # object <hexsha>
+            type_token, type_name = lines[1].split(" ")  # type <type_name>
             self.object = \
                 get_object_type_by_name(type_name.encode('ascii'))(self.repo, hex_to_bin(hexsha))
 
diff --git a/git/refs/head.py b/git/refs/head.py
index a1d8ab46..fe820b10 100644
--- a/git/refs/head.py
+++ b/git/refs/head.py
@@ -133,15 +133,18 @@ class Head(Reference):
             raise ValueError("Incorrect parameter type: %r" % remote_reference)
         # END handle type
 
-        with self.config_writer() as writer:
-            if remote_reference is None:
-                writer.remove_option(self.k_config_remote)
-                writer.remove_option(self.k_config_remote_ref)
-                if len(writer.options()) == 0:
-                    writer.remove_section()
-            else:
-                writer.set_value(self.k_config_remote, remote_reference.remote_name)
-                writer.set_value(self.k_config_remote_ref, Head.to_full_path(remote_reference.remote_head))
+        writer = self.config_writer()
+        if remote_reference is None:
+            writer.remove_option(self.k_config_remote)
+            writer.remove_option(self.k_config_remote_ref)
+            if len(writer.options()) == 0:
+                writer.remove_section()
+            # END handle remove section
+        else:
+            writer.set_value(self.k_config_remote, remote_reference.remote_name)
+            writer.set_value(self.k_config_remote_ref, Head.to_full_path(remote_reference.remote_head))
+        # END handle ref value
+        writer.release()
 
         return self
 
diff --git a/git/refs/reference.py b/git/refs/reference.py
index cc99dc26..3e132aef 100644
--- a/git/refs/reference.py
+++ b/git/refs/reference.py
@@ -50,7 +50,7 @@ class Reference(SymbolicReference, LazyMixin, Iterable):
 
     #{ Interface
 
-    def set_object(self, object, logmsg=None):  # @ReservedAssignment
+    def set_object(self, object, logmsg=None):
         """Special version which checks if the head-log needs an update as well
         :return: self"""
         oldbinsha = None
diff --git a/git/refs/symbolic.py b/git/refs/symbolic.py
index ebaff8ca..894b26d5 100644
--- a/git/refs/symbolic.py
+++ b/git/refs/symbolic.py
@@ -218,7 +218,7 @@ class SymbolicReference(object):
 
         return self
 
-    def set_object(self, object, logmsg=None):  # @ReservedAssignment
+    def set_object(self, object, logmsg=None):
         """Set the object we point to, possibly dereference our symbolic reference first.
         If the reference does not exist, it will be created
 
@@ -229,7 +229,7 @@ class SymbolicReference(object):
         :note: plain SymbolicReferences may not actually point to objects by convention
         :return: self"""
         if isinstance(object, SymbolicReference):
-            object = object.object  # @ReservedAssignment
+            object = object.object
         # END resolve references
 
         is_detached = True
@@ -595,7 +595,7 @@ class SymbolicReference(object):
         # END for each directory to walk
 
         # read packed refs
-        for sha, rela_path in cls._iter_packed_refs(repo):  # @UnusedVariable
+        for sha, rela_path in cls._iter_packed_refs(repo):
             if rela_path.startswith(common_path):
                 rela_paths.add(rela_path)
             # END relative path matches common path
diff --git a/git/remote.py b/git/remote.py
index d35e1fad..c2ffcc1a 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -176,7 +176,7 @@ class PushInfo(object):
             split_token = "..."
             if control_character == " ":
                 split_token = ".."
-            old_sha, new_sha = summary.split(' ')[0].split(split_token)  # @UnusedVariable
+            old_sha, new_sha = summary.split(' ')[0].split(split_token)
             # have to use constructor here as the sha usually is abbreviated
             old_commit = old_sha
         # END message handling
@@ -262,7 +262,7 @@ class FetchInfo(object):
         # parse lines
         control_character, operation, local_remote_ref, remote_local_ref, note = match.groups()
         try:
-            new_hex_sha, fetch_operation, fetch_note = fetch_line.split("\t")  # @UnusedVariable
+            new_hex_sha, fetch_operation, fetch_note = fetch_line.split("\t")
             ref_type_name, fetch_note = fetch_note.split(' ', 1)
         except ValueError:  # unpack error
             raise ValueError("Failed to parse FETCH_HEAD line: %r" % fetch_line)
@@ -625,8 +625,8 @@ class Remote(LazyMixin, Iterable):
             for pline in progress_handler(line):
                 # END handle special messages
                 for cmd in cmds:
-                    if len(pline) > 1 and pline[0] == ' ' and pline[1] == cmd:
-                        fetch_info_lines.append(pline)
+                    if len(line) > 1 and line[0] == ' ' and line[1] == cmd:
+                        fetch_info_lines.append(line)
                         continue
                     # end find command code
                 # end for each comand code we know
diff --git a/git/repo/base.py b/git/repo/base.py
index 8b68b5ff..947d77d2 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -899,12 +899,8 @@ class Repo(object):
         try:
             proc = git.clone(url, path, with_extended_output=True, as_process=True,
                              v=True, **add_progress(kwargs, git, progress))
-            if progress:
-                handle_process_output(proc, None, progress.new_message_handler(), finalize_process)
-            else:
-                (stdout, stderr) = proc.communicate()  # FIXME: Will block of outputs are big!
-                finalize_process(proc, stderr=stderr)
-            # end handle progress
+            progress_handler = progress and progress.new_message_handler() or None
+            handle_process_output(proc, None, progress_handler, finalize_process)
         finally:
             if prev_cwd is not None:
                 os.chdir(prev_cwd)
@@ -924,8 +920,10 @@ class Repo(object):
         # sure
         repo = cls(os.path.abspath(path), odbt=odbt)
         if repo.remotes:
-            with repo.remotes[0].config_writer as writer:
-                writer.set_value('url', repo.remotes[0].url.replace("\\\\", "\\").replace("\\", "/"))
+            writer = repo.remotes[0].config_writer
+            writer.set_value('url', repo.remotes[0].url.replace("\\\\", "\\").replace("\\", "/"))
+            # PY3: be sure cleanup is performed and lock is released
+            writer.release()
         # END handle remote repo
         return repo
 
diff --git a/git/repo/fun.py b/git/repo/fun.py
index 320eb1c8..0483eaa9 100644
--- a/git/repo/fun.py
+++ b/git/repo/fun.py
@@ -284,7 +284,7 @@ def rev_parse(repo, rev):
         try:
             if token == "~":
                 obj = to_commit(obj)
-                for _ in xrange(num):
+                for item in xrange(num):
                     obj = obj.parents[0]
                 # END for each history item to walk
             elif token == "^":
diff --git a/git/util.py b/git/util.py
index c96a6b08..814cd7f4 100644
--- a/git/util.py
+++ b/git/util.py
@@ -14,16 +14,14 @@ import shutil
 import stat
 import time
 
-from functools import wraps
-
 from git.compat import is_win
-from gitdb.util import (    # NOQA
+from gitdb.util import (  # NOQA
     make_sha,
-    LockedFD,               # @UnusedImport
-    file_contents_ro,       # @UnusedImport
-    LazyMixin,              # @UnusedImport
-    to_hex_sha,             # @UnusedImport
-    to_bin_sha              # @UnusedImport
+    LockedFD,
+    file_contents_ro,
+    LazyMixin,
+    to_hex_sha,
+    to_bin_sha
 )
 
 import os.path as osp
@@ -34,7 +32,6 @@ from .compat import (
     PY3
 )
 from .exc import InvalidGitRepositoryError
-from unittest.case import SkipTest
 
 
 # NOTE:  Some of the unused imports might be used/imported by others.
@@ -53,13 +50,13 @@ def unbare_repo(func):
     """Methods with this decorator raise InvalidGitRepositoryError if they
     encounter a bare repository"""
 
-    @wraps(func)
     def wrapper(self, *args, **kwargs):
         if self.repo.bare:
             raise InvalidGitRepositoryError("Method '%s' cannot operate on bare repositories" % func.__name__)
         # END bare method
         return func(self, *args, **kwargs)
     # END wrapper
+    wrapper.__name__ = func.__name__
     return wrapper
 
 
@@ -72,15 +69,7 @@ def rmtree(path):
     def onerror(func, path, exc_info):
         # Is the error an access error ?
         os.chmod(path, stat.S_IWUSR)
-
-        try:
-            func(path)  # Will scream if still not possible to delete.
-        except Exception as ex:
-            from git.test.lib.helper import HIDE_WINDOWS_KNOWN_ERRORS
-            if HIDE_WINDOWS_KNOWN_ERRORS:
-                raise SkipTest("FIXME: fails with: PermissionError\n  %s", ex)
-            else:
-                raise
+        func(path)  # Will scream if still not possible to delete.
 
     return shutil.rmtree(path, False, onerror)
 
@@ -251,7 +240,7 @@ class RemoteProgress(object):
             # END could not get match
 
             op_code = 0
-            remote, op_name, percent, cur_count, max_count, message = match.groups()  # @UnusedVariable
+            remote, op_name, percent, cur_count, max_count, message = match.groups()
 
             # get operation id
             if op_name == "Counting objects":


Test patch:
diff --git a/git/test/lib/asserts.py b/git/test/lib/asserts.py
index 6f5ba714..9edc49e0 100644
--- a/git/test/lib/asserts.py
+++ b/git/test/lib/asserts.py
@@ -8,18 +8,18 @@ import re
 import stat
 
 from nose.tools import (
-    assert_equal,       # @UnusedImport
-    assert_not_equal,   # @UnusedImport
-    assert_raises,      # @UnusedImport
-    raises,             # @UnusedImport
-    assert_true,        # @UnusedImport
-    assert_false        # @UnusedImport
+    assert_equal,
+    assert_not_equal,
+    assert_raises,
+    raises,
+    assert_true,
+    assert_false
 )
 
 try:
     from unittest.mock import patch
 except ImportError:
-    from mock import patch  # @NoMove @UnusedImport
+    from mock import patch
 
 __all__ = ['assert_instance_of', 'assert_not_instance_of',
            'assert_none', 'assert_not_none',
diff --git a/git/test/lib/helper.py b/git/test/lib/helper.py
index e92ce8b4..a85ac2fd 100644
--- a/git/test/lib/helper.py
+++ b/git/test/lib/helper.py
@@ -12,8 +12,7 @@ import tempfile
 import io
 import logging
 
-from functools import wraps
-
+from git import Repo, Remote, GitCommandError, Git
 from git.util import rmtree
 from git.compat import string_types, is_win
 import textwrap
@@ -31,11 +30,6 @@ __all__ = (
 
 log = logging.getLogger('git.util')
 
-#: We need an easy way to see if Appveyor TCs start failing,
-#: so the errors marked with this var are considered "acknowledged" ones, awaiting remedy,
-#: till then, we wish to hide them.
-HIDE_WINDOWS_KNOWN_ERRORS = is_win and os.environ.get('HIDE_WINDOWS_KNOWN_ERRORS', True)
-
 #{ Routines
 
 
@@ -92,7 +86,6 @@ def with_rw_directory(func):
     """Create a temporary directory which can be written to, remove it if the
     test succeeds, but leave it otherwise to aid additional debugging"""
 
-    @wraps(func)
     def wrapper(self):
         path = tempfile.mktemp(prefix=func.__name__)
         os.mkdir(path)
@@ -101,8 +94,8 @@ def with_rw_directory(func):
             try:
                 return func(self, path)
             except Exception:
-                log.info("Test %s.%s failed, output is at %r\n",
-                         type(self).__name__, func.__name__, path)
+                log.info.write("Test %s.%s failed, output is at %r\n",
+                               type(self).__name__, func.__name__, path)
                 keep = True
                 raise
         finally:
@@ -115,8 +108,6 @@ def with_rw_directory(func):
             if not keep:
                 rmtree(path)
 
-    return wrapper
-
 
 def with_rw_repo(working_tree_ref, bare=False):
     """
@@ -131,7 +122,6 @@ def with_rw_repo(working_tree_ref, bare=False):
     assert isinstance(working_tree_ref, string_types), "Decorator requires ref name for working tree checkout"
 
     def argument_passer(func):
-        @wraps(func)
         def repo_creator(self):
             prefix = 'non_'
             if bare:
@@ -165,13 +155,13 @@ def with_rw_repo(working_tree_ref, bare=False):
                 # END rm test repo if possible
             # END cleanup
         # END rw repo creator
+        repo_creator.__name__ = func.__name__
         return repo_creator
     # END argument passer
     return argument_passer
 
 
 def launch_git_daemon(temp_dir, ip, port):
-    from git import Git
     if is_win:
         ## On MINGW-git, daemon exists in .\Git\mingw64\libexec\git-core\,
         #  but if invoked as 'git daemon', it detaches from parent `git` cmd,
@@ -217,12 +207,10 @@ def with_rw_and_rw_remote_repo(working_tree_ref):
     See working dir info in with_rw_repo
     :note: We attempt to launch our own invocation of git-daemon, which will be shutdown at the end of the test.
     """
-    from git import Remote, GitCommandError
     assert isinstance(working_tree_ref, string_types), "Decorator requires ref name for working tree checkout"
 
     def argument_passer(func):
 
-        @wraps(func)
         def remote_repo_creator(self):
             remote_repo_dir = _mktemp("remote_repo_%s" % func.__name__)
             repo_dir = _mktemp("remote_clone_non_bare_repo")
@@ -237,13 +225,16 @@ def with_rw_and_rw_remote_repo(working_tree_ref):
             rw_remote_repo.daemon_export = True
 
             # this thing is just annoying !
-            with rw_remote_repo.config_writer() as crw:
-                section = "daemon"
-                try:
-                    crw.add_section(section)
-                except Exception:
-                    pass
-                crw.set(section, "receivepack", True)
+            crw = rw_remote_repo.config_writer()
+            section = "daemon"
+            try:
+                crw.add_section(section)
+            except Exception:
+                pass
+            crw.set(section, "receivepack", True)
+            # release lock
+            crw.release()
+            del(crw)
 
             # initialize the remote - first do it as local remote and pull, then
             # we change the url to point to the daemon. The daemon should be started
@@ -252,8 +243,7 @@ def with_rw_and_rw_remote_repo(working_tree_ref):
             d_remote.fetch()
             remote_repo_url = "git://localhost:%s%s" % (GIT_DAEMON_PORT, remote_repo_dir)
 
-            with d_remote.config_writer as cw:
-                cw.set('url', remote_repo_url)
+            d_remote.config_writer.set('url', remote_repo_url)
 
             temp_dir = osp(_mktemp())
             gd = launch_git_daemon(temp_dir, '127.0.0.1', GIT_DAEMON_PORT)
@@ -329,9 +319,10 @@ def with_rw_and_rw_remote_repo(working_tree_ref):
                     gd.proc.wait()
             # END cleanup
         # END bare repo creator
+        remote_repo_creator.__name__ = func.__name__
         return remote_repo_creator
         # END remote repo creator
-    # END argument parser
+    # END argument parsser
 
     return argument_passer
 
@@ -367,7 +358,6 @@ class TestBase(TestCase):
         Dynamically add a read-only repository to our actual type. This way
         each test type has its own repository
         """
-        from git import Repo
         import gc
         gc.collect()
         cls.rorepo = Repo(GIT_REPO)
diff --git a/git/test/performance/lib.py b/git/test/performance/lib.py
index 0c4c20a4..eebbfd76 100644
--- a/git/test/performance/lib.py
+++ b/git/test/performance/lib.py
@@ -19,7 +19,6 @@ from git.util import rmtree
 
 #{ Invvariants
 k_env_git_repo = "GIT_PYTHON_TEST_GIT_REPO_BASE"
-
 #} END invariants
 
 
diff --git a/git/test/performance/test_odb.py b/git/test/performance/test_odb.py
index 6f07a615..9abe2d42 100644
--- a/git/test/performance/test_odb.py
+++ b/git/test/performance/test_odb.py
@@ -5,8 +5,7 @@ import sys
 from time import time
 from unittest.case import skipIf
 
-from git.compat import PY3
-from git.test.lib.helper import HIDE_WINDOWS_KNOWN_ERRORS
+from git.compat import is_win, PY3
 
 from .lib import (
     TestBigRepoR
@@ -15,8 +14,7 @@ from .lib import (
 
 class TestObjDBPerformance(TestBigRepoR):
 
-    @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and PY3,
-            "FIXME: smmp fails with: TypeError: Can't convert 'bytes' object to str implicitly")
+    @skipIf(is_win and PY3, "FIXME: smmp fails with: TypeError: Can't convert 'bytes' object to str implicitly")
     def test_random_access(self):
         results = [["Iterate Commits"], ["Iterate Blobs"], ["Retrieve Blob Data"]]
         for repo in (self.gitrorepo, self.puregitrorepo):
diff --git a/git/test/performance/test_streams.py b/git/test/performance/test_streams.py
index 42cbade5..8194547c 100644
--- a/git/test/performance/test_streams.py
+++ b/git/test/performance/test_streams.py
@@ -120,7 +120,7 @@ class TestObjDBPerformance(TestBigRepoR):
 
             # read all
             st = time()
-            hexsha, typename, size, data = rwrepo.git.get_object_data(gitsha)  # @UnusedVariable
+            s, t, size, data = rwrepo.git.get_object_data(gitsha)
             gelapsed_readall = time() - st
             print("Read %i KiB of %s data at once using git-cat-file in %f s ( %f Read KiB / s)"
                   % (size_kib, desc, gelapsed_readall, size_kib / gelapsed_readall), file=sys.stderr)
@@ -131,7 +131,7 @@ class TestObjDBPerformance(TestBigRepoR):
 
             # read chunks
             st = time()
-            hexsha, typename, size, stream = rwrepo.git.stream_object_data(gitsha)  # @UnusedVariable
+            s, t, size, stream = rwrepo.git.stream_object_data(gitsha)
             while True:
                 data = stream.read(cs)
                 if len(data) < cs:
diff --git a/git/test/test_commit.py b/git/test/test_commit.py
index fd9777fb..66d988a3 100644
--- a/git/test/test_commit.py
+++ b/git/test/test_commit.py
@@ -123,7 +123,7 @@ class TestCommit(TestBase):
         check_entries(stats.total)
         assert "files" in stats.total
 
-        for filepath, d in stats.files.items():  # @UnusedVariable
+        for filepath, d in stats.files.items():
             check_entries(d)
         # END for each stated file
 
diff --git a/git/test/test_config.py b/git/test/test_config.py
index 32873f24..154aaa24 100644
--- a/git/test/test_config.py
+++ b/git/test/test_config.py
@@ -60,8 +60,7 @@ class TestBase(TestCase):
                 self.assertEqual(file_obj.getvalue(), self._to_memcache(fixture_path(filename)).getvalue())
 
                 # creating an additional config writer must fail due to exclusive access
-                with self.assertRaises(IOError):
-                    GitConfigParser(file_obj, read_only=False)
+                self.failUnlessRaises(IOError, GitConfigParser, file_obj, read_only=False)
 
                 # should still have a lock and be able to make changes
                 assert w_config._lock._has_lock()
@@ -92,21 +91,18 @@ class TestBase(TestCase):
     @with_rw_directory
     def test_lock_reentry(self, rw_dir):
         fpl = os.path.join(rw_dir, 'l')
-        gcp = GitConfigParser(fpl, read_only=False)
-        with gcp as cw:
-            cw.set_value('include', 'some_value', 'a')
+        with GitConfigParser(fpl, read_only=False) as gcp:
+            gcp.set_value('include', 'some_value', 'a')
         # entering again locks the file again...
         with gcp as cw:
             cw.set_value('include', 'some_other_value', 'b')
             # ...so creating an additional config writer must fail due to exclusive access
-            with self.assertRaises(IOError):
-                GitConfigParser(fpl, read_only=False)
+            self.failUnlessRaises(IOError, GitConfigParser, fpl, read_only=False)
         # but work when the lock is removed
         with GitConfigParser(fpl, read_only=False):
             assert os.path.exists(fpl)
             # reentering with an existing lock must fail due to exclusive access
-            with self.assertRaises(IOError):
-                gcp.__enter__()
+            self.failUnlessRaises(IOError, gcp.__enter__)
 
     def test_multi_line_config(self):
         file_obj = self._to_memcache(fixture_path("git_config_with_comments"))
@@ -148,13 +144,10 @@ class TestBase(TestCase):
                 assert "\n" not in val
 
                 # writing must fail
-                with self.assertRaises(IOError):
-                    r_config.set(section, option, None)
-                with self.assertRaises(IOError):
-                    r_config.remove_option(section, option)
+                self.failUnlessRaises(IOError, r_config.set, section, option, None)
+                self.failUnlessRaises(IOError, r_config.remove_option, section, option)
             # END for each option
-            with self.assertRaises(IOError):
-                r_config.remove_section(section)
+            self.failUnlessRaises(IOError, r_config.remove_section, section)
         # END for each section
         assert num_sections and num_options
         assert r_config._is_initialized is True
@@ -164,8 +157,7 @@ class TestBase(TestCase):
         assert r_config.get_value("doesnt", "exist", default) == default
 
         # it raises if there is no default though
-        with self.assertRaises(cp.NoSectionError):
-            r_config.get_value("doesnt", "exist")
+        self.failUnlessRaises(cp.NoSectionError, r_config.get_value, "doesnt", "exist")
 
     @with_rw_directory
     def test_config_include(self, rw_dir):
@@ -214,8 +206,7 @@ class TestBase(TestCase):
             write_test_value(cw, tv)
 
         with GitConfigParser(fpa, read_only=True) as cr:
-            with self.assertRaises(cp.NoSectionError):
-                check_test_value(cr, tv)
+            self.failUnlessRaises(cp.NoSectionError, check_test_value, cr, tv)
 
         # But can make it skip includes alltogether, and thus allow write-backs
         with GitConfigParser(fpa, read_only=False, merge_includes=False) as cw:
@@ -227,10 +218,8 @@ class TestBase(TestCase):
     def test_rename(self):
         file_obj = self._to_memcache(fixture_path('git_config'))
         with GitConfigParser(file_obj, read_only=False, merge_includes=False) as cw:
-            with self.assertRaises(ValueError):
-                cw.rename_section("doesntexist", "foo")
-            with self.assertRaises(ValueError):
-                cw.rename_section("core", "include")
+            self.failUnlessRaises(ValueError, cw.rename_section, "doesntexist", "foo")
+            self.failUnlessRaises(ValueError, cw.rename_section, "core", "include")
 
             nn = "bee"
             assert cw.rename_section('core', nn) is cw
@@ -248,5 +237,4 @@ class TestBase(TestCase):
 
         assert cr.get_value('core', 'filemode'), "Should read keys with values"
 
-        with self.assertRaises(cp.NoOptionError):
-            cr.get_value('color', 'ui')
+        self.failUnlessRaises(cp.NoOptionError, cr.get_value, 'color', 'ui')
diff --git a/git/test/test_docs.py b/git/test/test_docs.py
index e2bfcb21..8a2dff0f 100644
--- a/git/test/test_docs.py
+++ b/git/test/test_docs.py
@@ -16,9 +16,6 @@ class Tutorials(TestBase):
         import gc
         gc.collect()
 
-    # @skipIf(HIDE_WINDOWS_KNOWN_ERRORS,
-    #         "FIXME: helper.wrapper fails with: PermissionError: [WinError 5] Access is denied: "
-    #         "'C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\test_work_tree_unsupportedryfa60di\\master_repo\\.git\\objects\\pack\\pack-bc9e0787aef9f69e1591ef38ea0a6f566ec66fe3.idx")  # noqa E501
     @with_rw_directory
     def test_init_repo_object(self, rw_dir):
         # [1-test_init_repo_object]
@@ -39,8 +36,8 @@ class Tutorials(TestBase):
 
         # [3-test_init_repo_object]
         repo.config_reader()             # get a config reader for read-only access
-        with repo.config_writer():       # get a config writer to change configuration
-            pass                         # call release() to be sure changes are written and locks are released
+        cw = repo.config_writer()        # get a config writer to change configuration
+        cw.release()                     # call release() to be sure changes are written and locks are released
         # ![3-test_init_repo_object]
 
         # [4-test_init_repo_object]
@@ -70,8 +67,7 @@ class Tutorials(TestBase):
         # heads, tags and references
         # heads are branches in git-speak
         # [8-test_init_repo_object]
-        self.assertEqual(repo.head.ref, repo.heads.master,  # head is a sym-ref pointing to master
-                         "It's ok if TC not running from `master`.")
+        self.assertEqual(repo.head.ref, repo.heads.master)                  # head is a sym-ref pointing to master
         self.assertEqual(repo.tags['0.3.5'], repo.tag('refs/tags/0.3.5'))   # you can access tags in various ways too
         self.assertEqual(repo.refs.master, repo.heads['master'])            # .refs provides all refs, ie heads ...
 
@@ -243,9 +239,9 @@ class Tutorials(TestBase):
         # [8-test_references_and_objects]
         hc = repo.head.commit
         hct = hc.tree
-        hc != hct                           # @NoEffect
-        hc != repo.tags[0]                  # @NoEffect
-        hc == repo.head.reference.commit    # @NoEffect
+        hc != hct
+        hc != repo.tags[0]
+        hc == repo.head.reference.commit
         # ![8-test_references_and_objects]
 
         # [9-test_references_and_objects]
@@ -348,7 +344,7 @@ class Tutorials(TestBase):
         # The index contains all blobs in a flat list
         assert len(list(index.iter_blobs())) == len([o for o in repo.head.commit.tree.traverse() if o.type == 'blob'])
         # Access blob objects
-        for (path, stage), entry in index.entries.items():  # @UnusedVariable
+        for (path, stage), entry in index.entries.items():
             pass
         new_file_path = os.path.join(repo.working_tree_dir, 'new-file-name')
         open(new_file_path, 'w').close()
@@ -398,8 +394,9 @@ class Tutorials(TestBase):
 
         # [26-test_references_and_objects]
         assert origin.url == repo.remotes.origin.url
-        with origin.config_writer as cw:
-            cw.set("pushurl", "other_url")
+        cw = origin.config_writer
+        cw.set("pushurl", "other_url")
+        cw.release()
 
         # Please note that in python 2, writing origin.config_writer.set(...) is totally safe.
         # In py3 __del__ calls can be delayed, thus not writing changes in time.
diff --git a/git/test/test_exc.py b/git/test/test_exc.py
index 33f44034..7e6b023e 100644
--- a/git/test/test_exc.py
+++ b/git/test/test_exc.py
@@ -29,13 +29,13 @@ _cmd_argvs = (
     ('θνιψοδε', 'κι', 'αλλα', 'non-unicode', 'args'),
 )
 _causes_n_substrings = (
-    (None,                      None),                          # noqa: E241 @IgnorePep8
-    (7,                         "exit code(7)"),                # noqa: E241 @IgnorePep8
-    ('Some string',             "'Some string'"),               # noqa: E241 @IgnorePep8
-    ('παλιο string',            "'παλιο string'"),              # noqa: E241 @IgnorePep8
-    (Exception("An exc."),      "Exception('An exc.')"),        # noqa: E241 @IgnorePep8
-    (Exception("Κακια exc."),   "Exception('Κακια exc.')"),     # noqa: E241 @IgnorePep8
-    (object(),                  "<object object at "),          # noqa: E241 @IgnorePep8
+    (None,                      None),                          # noqa: E241
+    (7,                         "exit code(7)"),                           # noqa: E241
+    ('Some string',             "'Some string'"),               # noqa: E241
+    ('παλιο string',            "'παλιο string'"),              # noqa: E241
+    (Exception("An exc."),      "Exception('An exc.')"),        # noqa: E241
+    (Exception("Κακια exc."),   "Exception('Κακια exc.')"),     # noqa: E241
+    (object(),                  "<object object at "),         # noqa: E241
 )
 
 _streams_n_substrings = (None, 'steram', 'ομορφο stream', )
diff --git a/git/test/test_git.py b/git/test/test_git.py
index 58ee8e9c..94614cd1 100644
--- a/git/test/test_git.py
+++ b/git/test/test_git.py
@@ -121,7 +121,7 @@ class TestGit(TestBase):
 
         # read data - have to read it in one large chunk
         size = int(obj_info.split()[2])
-        g.stdout.read(size)
+        data = g.stdout.read(size)
         g.stdout.read(1)
 
         # now we should be able to read a new object
@@ -131,7 +131,7 @@ class TestGit(TestBase):
 
         # same can be achived using the respective command functions
         hexsha, typename, size = self.git.get_object_header(hexsha)
-        hexsha, typename_two, size_two, data = self.git.get_object_data(hexsha)  # @UnusedVariable
+        hexsha, typename_two, size_two, data = self.git.get_object_data(hexsha)
         self.assertEqual(typename, typename_two)
         self.assertEqual(size, size_two)
 
diff --git a/git/test/test_index.py b/git/test/test_index.py
index 34014064..1ffbe9e2 100644
--- a/git/test/test_index.py
+++ b/git/test/test_index.py
@@ -5,16 +5,17 @@
 # This module is part of GitPython and is released under
 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
 
-from io import BytesIO
-import os
-from stat import (
-    S_ISLNK,
-    ST_MODE
+from git.test.lib import (
+    TestBase,
+    fixture_path,
+    fixture,
+    with_rw_repo
+)
+from git.util import Actor, rmtree
+from git.exc import (
+    HookExecutionError,
+    InvalidGitRepositoryError
 )
-import sys
-import tempfile
-from unittest.case import skipIf
-
 from git import (
     IndexFile,
     Repo,
@@ -27,27 +28,24 @@ from git import (
     CheckoutError,
 )
 from git.compat import string_types, is_win
-from git.exc import (
-    HookExecutionError,
-    InvalidGitRepositoryError
+from gitdb.util import hex_to_bin
+import os
+import sys
+import tempfile
+from stat import (
+    S_ISLNK,
+    ST_MODE
 )
-from git.index.fun import hook_path
+
+from io import BytesIO
+from gitdb.base import IStream
+from git.objects import Blob
 from git.index.typ import (
     BaseIndexEntry,
     IndexEntry
 )
-from git.objects import Blob
-from git.test.lib import (
-    TestBase,
-    fixture_path,
-    fixture,
-    with_rw_repo
-)
-from git.test.lib.helper import HIDE_WINDOWS_KNOWN_ERRORS
+from git.index.fun import hook_path
 from git.test.lib import with_rw_directory
-from git.util import Actor, rmtree
-from gitdb.base import IStream
-from gitdb.util import hex_to_bin
 
 
 class TestIndex(TestBase):
@@ -58,7 +56,7 @@ class TestIndex(TestBase):
 
     def _assert_fprogress(self, entries):
         self.assertEqual(len(entries), len(self._fprogress_map))
-        for path, call_count in self._fprogress_map.items():  # @UnusedVariable
+        for path, call_count in self._fprogress_map.items():
             self.assertEqual(call_count, 2)
         # END for each item in progress map
         self._reset_progress()
@@ -188,7 +186,7 @@ class TestIndex(TestBase):
 
         # test BlobFilter
         prefix = 'lib/git'
-        for stage, blob in base_index.iter_blobs(BlobFilter([prefix])):  # @UnusedVariable
+        for stage, blob in base_index.iter_blobs(BlobFilter([prefix])):
             assert blob.path.startswith(prefix)
 
         # writing a tree should fail with an unmerged index
@@ -412,9 +410,10 @@ class TestIndex(TestBase):
 
         uname = u"Thomas Müller"
         umail = "sd@company.com"
-        with rw_repo.config_writer() as writer:
-            writer.set_value("user", "name", uname)
-            writer.set_value("user", "email", umail)
+        writer = rw_repo.config_writer()
+        writer.set_value("user", "name", uname)
+        writer.set_value("user", "email", umail)
+        writer.release()
         self.assertEqual(writer.get_value("user", "name"), uname)
 
         # remove all of the files, provide a wild mix of paths, BaseIndexEntries,
@@ -822,10 +821,6 @@ class TestIndex(TestBase):
             asserted = True
         assert asserted, "Adding using a filename is not correctly asserted."
 
-    @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and sys.version_info[:2] == (2, 7), r"""
-        FIXME:  File "C:\projects\gitpython\git\util.py", line 125, in to_native_path_linux
-        return path.replace('\\', '/')
-        UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)""")
     @with_rw_directory
     def test_add_utf8P_path(self, rw_dir):
         # NOTE: fp is not a Unicode object in python 2 (which is the source of the problem)
diff --git a/git/test/test_refs.py b/git/test/test_refs.py
index 43f1dcc7..9816fb50 100644
--- a/git/test/test_refs.py
+++ b/git/test/test_refs.py
@@ -101,13 +101,15 @@ class TestRefs(TestBase):
             assert prev_object == cur_object        # represent the same git object
             assert prev_object is not cur_object    # but are different instances
 
-            with head.config_writer() as writer:
-                tv = "testopt"
-                writer.set_value(tv, 1)
-                assert writer.get_value(tv) == 1
+            writer = head.config_writer()
+            tv = "testopt"
+            writer.set_value(tv, 1)
+            assert writer.get_value(tv) == 1
+            writer.release()
             assert head.config_reader().get_value(tv) == 1
-            with head.config_writer() as writer:
-                writer.remove_option(tv)
+            writer = head.config_writer()
+            writer.remove_option(tv)
+            writer.release()
 
             # after the clone, we might still have a tracking branch setup
             head.set_tracking_branch(None)
@@ -173,7 +175,7 @@ class TestRefs(TestBase):
 
     def test_orig_head(self):
         assert type(self.rorepo.head.orig_head()) == SymbolicReference
-
+        
     @with_rw_repo('0.1.6')
     def test_head_checkout_detached_head(self, rw_repo):
         res = rw_repo.remotes.origin.refs.master.checkout()
@@ -280,7 +282,7 @@ class TestRefs(TestBase):
 
         # tag ref
         tag_name = "5.0.2"
-        TagReference.create(rw_repo, tag_name)
+        light_tag = TagReference.create(rw_repo, tag_name)
         self.failUnlessRaises(GitCommandError, TagReference.create, rw_repo, tag_name)
         light_tag = TagReference.create(rw_repo, tag_name, "HEAD~1", force=True)
         assert isinstance(light_tag, TagReference)
@@ -440,7 +442,7 @@ class TestRefs(TestBase):
 
         self.failUnlessRaises(OSError, SymbolicReference.create, rw_repo, symref_path, cur_head.reference.commit)
         # it works if the new ref points to the same reference
-        SymbolicReference.create(rw_repo, symref.path, symref.reference).path == symref.path  # @NoEffect
+        SymbolicReference.create(rw_repo, symref.path, symref.reference).path == symref.path
         SymbolicReference.delete(rw_repo, symref)
         # would raise if the symref wouldn't have been deletedpbl
         symref = SymbolicReference.create(rw_repo, symref_path, cur_head.reference)
diff --git a/git/test/test_remote.py b/git/test/test_remote.py
index 7b52ccce..b99e49cf 100644
--- a/git/test/test_remote.py
+++ b/git/test/test_remote.py
@@ -90,7 +90,7 @@ class TestRemoteProgress(RemoteProgress):
         assert self._stages_per_op
 
         # must have seen all stages
-        for op, stages in self._stages_per_op.items():  # @UnusedVariable
+        for op, stages in self._stages_per_op.items():
             assert stages & self.STAGE_MASK == self.STAGE_MASK
         # END for each op/stage
 
@@ -267,8 +267,7 @@ class TestRemote(TestBase):
 
         # put origin to git-url
         other_origin = other_repo.remotes.origin
-        with other_origin.config_writer as cw:
-            cw.set("url", remote_repo_url)
+        other_origin.config_writer.set("url", remote_repo_url)
         # it automatically creates alternates as remote_repo is shared as well.
         # It will use the transport though and ignore alternates when fetching
         # assert not other_repo.alternates  # this would fail
@@ -332,7 +331,7 @@ class TestRemote(TestBase):
         # push new tags
         progress = TestRemoteProgress()
         to_be_updated = "my_tag.1.0RV"
-        new_tag = TagReference.create(rw_repo, to_be_updated)  # @UnusedVariable
+        new_tag = TagReference.create(rw_repo, to_be_updated)
         other_tag = TagReference.create(rw_repo, "my_obj_tag.2.1aRV", message="my message")
         res = remote.push(progress=progress, tags=True)
         assert res[-1].flags & PushInfo.NEW_TAG
@@ -417,12 +416,13 @@ class TestRemote(TestBase):
                 self.failUnlessRaises(IOError, reader.set, opt, "test")
 
                 # change value
-                with remote.config_writer as writer:
-                    new_val = "myval"
-                    writer.set(opt, new_val)
-                    assert writer.get(opt) == new_val
-                    writer.set(opt, val)
-                    assert writer.get(opt) == val
+                writer = remote.config_writer
+                new_val = "myval"
+                writer.set(opt, new_val)
+                assert writer.get(opt) == new_val
+                writer.set(opt, val)
+                assert writer.get(opt) == val
+                del(writer)
                 assert getattr(remote, opt) == val
             # END for each default option key
 
@@ -432,7 +432,7 @@ class TestRemote(TestBase):
             assert remote.rename(other_name) == remote
             assert prev_name != remote.name
             # multiple times
-            for _ in range(2):
+            for time in range(2):
                 assert remote.rename(prev_name).name == prev_name
             # END for each rename ( back to prev_name )
 
diff --git a/git/test/test_repo.py b/git/test/test_repo.py
index 1d537e93..ae2bf2f0 100644
--- a/git/test/test_repo.py
+++ b/git/test/test_repo.py
@@ -7,11 +7,11 @@
 import glob
 from io import BytesIO
 import itertools
+import functools as fnt
 import os
 import pickle
 import sys
 import tempfile
-from unittest.case import skipIf
 
 from git import (
     InvalidGitRepositoryError,
@@ -50,14 +50,13 @@ from git.test.lib import (
     assert_true,
     raises
 )
-from git.test.lib.helper import HIDE_WINDOWS_KNOWN_ERRORS
 from git.test.lib import with_rw_directory
 from git.util import join_path_native, rmtree, rmfile
 from gitdb.util import bin_to_hex
 from nose import SkipTest
 
-import functools as fnt
 import os.path as osp
+from unittest.case import skipIf
 
 
 def iter_flatten(lol):
@@ -487,7 +486,7 @@ class TestRepo(TestBase):
 
     @with_rw_directory
     def test_tilde_and_env_vars_in_repo_path(self, rw_dir):
-        ph = os.environ.get('HOME')
+        ph = os.environ['HOME']
         try:
             os.environ['HOME'] = rw_dir
             Repo.init(os.path.join('~', 'test.git'), bare=True)
@@ -495,9 +494,8 @@ class TestRepo(TestBase):
             os.environ['FOO'] = rw_dir
             Repo.init(os.path.join('$FOO', 'test.git'), bare=True)
         finally:
-            if ph:
-                os.environ['HOME'] = ph
-                del os.environ['FOO']
+            os.environ['HOME'] = ph
+            del os.environ['FOO']
         # end assure HOME gets reset to what it was
 
     def test_git_cmd(self):
@@ -797,8 +795,7 @@ class TestRepo(TestBase):
         git_file_repo = Repo(rwrepo.working_tree_dir)
         self.assertEqual(os.path.abspath(git_file_repo.git_dir), real_path_abs)
 
-    @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and PY3,
-            "FIXME: smmp fails with: TypeError: Can't convert 'bytes' object to str implicitly")
+    @skipIf(is_win and PY3, "FIXME: smmp fails with: TypeError: Can't convert 'bytes' object to str implicitly")
     def test_file_handle_leaks(self):
         def last_commit(repo, rev, path):
             commit = next(repo.iter_commits(rev, path, max_count=1))
@@ -809,7 +806,7 @@ class TestRepo(TestBase):
         # And we expect to set max handles to a low value, like 64
         # You should set ulimit -n X, see .travis.yml
         # The loops below would easily create 500 handles if these would leak (4 pipes + multiple mapped files)
-        for _ in range(64):
+        for i in range(64):
             for repo_type in (GitCmdObjectDB, GitDB):
                 repo = Repo(self.rorepo.working_tree_dir, odbt=repo_type)
                 last_commit(repo, 'master', 'git/test/test_base.py')
@@ -897,9 +894,6 @@ class TestRepo(TestBase):
         for i, j in itertools.permutations([c1, 'ffffff', ''], r=2):
             self.assertRaises(GitCommandError, repo.is_ancestor, i, j)
 
-    # @skipIf(HIDE_WINDOWS_KNOWN_ERRORS,
-    #         "FIXME: helper.wrapper fails with: PermissionError: [WinError 5] Access is denied: "
-    #         "'C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\test_work_tree_unsupportedryfa60di\\master_repo\\.git\\objects\\pack\\pack-bc9e0787aef9f69e1591ef38ea0a6f566ec66fe3.idx")  # noqa E501
     @with_rw_directory
     def test_work_tree_unsupported(self, rw_dir):
         git = Git(rw_dir)
diff --git a/git/test/test_submodule.py b/git/test/test_submodule.py
index 46928f51..bfa0379d 100644
--- a/git/test/test_submodule.py
+++ b/git/test/test_submodule.py
@@ -1,36 +1,35 @@
 # This module is part of GitPython and is released under
 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
-import os
 import sys
-from unittest.case import skipIf
+import os
 
 import git
-from git.compat import string_types, is_win
+
+from git.test.lib import (
+    TestBase,
+    with_rw_repo
+)
+from git.test.lib import with_rw_directory
 from git.exc import (
     InvalidGitRepositoryError,
     RepositoryDirtyError
 )
 from git.objects.submodule.base import Submodule
 from git.objects.submodule.root import RootModule, RootUpdateProgress
+from git.util import to_native_path_linux, join_path_native
+from git.compat import string_types, is_win
 from git.repo.fun import (
     find_git_dir,
     touch
 )
-from git.test.lib import (
-    TestBase,
-    with_rw_repo
-)
-from git.test.lib import with_rw_directory
-from git.test.lib.helper import HIDE_WINDOWS_KNOWN_ERRORS
-from git.util import to_native_path_linux, join_path_native
-
+from unittest.case import skipIf
 
 # Change the configuration if possible to prevent the underlying memory manager
 # to keep file handles open. On windows we get problems as they are not properly
 # closed due to mmap bugs on windows (as it appears)
 if is_win:
     try:
-        import smmap.util  # @UnusedImport
+        import smmap.util
         smmap.util.MapRegion._test_read_into_memory = True
     except ImportError:
         sys.stderr.write("The submodule tests will fail as some files cannot be removed due to open file handles.\n")
@@ -98,32 +97,28 @@ class TestSubmodule(TestBase):
 
         # force it to reread its information
         del(smold._url)
-        smold.url == sm.url  # @NoEffect
+        smold.url == sm.url
 
         # test config_reader/writer methods
         sm.config_reader()
         new_smclone_path = None             # keep custom paths for later
         new_csmclone_path = None                #
         if rwrepo.bare:
-            with self.assertRaises(InvalidGitRepositoryError):
-                with sm.config_writer() as cw:
-                    pass
+            self.failUnlessRaises(InvalidGitRepositoryError, sm.config_writer)
         else:
-            with sm.config_writer() as writer:
-                # for faster checkout, set the url to the local path
-                new_smclone_path = to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, sm.path))
-                writer.set_value('url', new_smclone_path)
-                writer.release()
-                assert sm.config_reader().get_value('url') == new_smclone_path
-                assert sm.url == new_smclone_path
+            writer = sm.config_writer()
+            # for faster checkout, set the url to the local path
+            new_smclone_path = to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, sm.path))
+            writer.set_value('url', new_smclone_path)
+            writer.release()
+            assert sm.config_reader().get_value('url') == new_smclone_path
+            assert sm.url == new_smclone_path
         # END handle bare repo
         smold.config_reader()
 
         # cannot get a writer on historical submodules
         if not rwrepo.bare:
-            with self.assertRaises(ValueError):
-                with smold.config_writer():
-                    pass
+            self.failUnlessRaises(ValueError, smold.config_writer)
         # END handle bare repo
 
         # make the old into a new - this doesn't work as the name changed
@@ -214,8 +209,9 @@ class TestSubmodule(TestBase):
 
             # adjust the path of the submodules module to point to the local destination
             new_csmclone_path = to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, sm.path, csm.path))
-            with csm.config_writer() as writer:
-                writer.set_value('url', new_csmclone_path)
+            writer = csm.config_writer()
+            writer.set_value('url', new_csmclone_path)
+            writer.release()
             assert csm.url == new_csmclone_path
 
             # dry-run does nothing
@@ -228,7 +224,7 @@ class TestSubmodule(TestBase):
             assert csm.module_exists()
 
             # tracking branch once again
-            csm.module().head.ref.tracking_branch() is not None  # @NoEffect
+            csm.module().head.ref.tracking_branch() is not None
 
             # this flushed in a sub-submodule
             assert len(list(rwrepo.iter_submodules())) == 2
@@ -277,8 +273,9 @@ class TestSubmodule(TestBase):
             # module() is supposed to point to gitdb, which has a child-submodule whose URL is still pointing
             # to github. To save time, we will change it to
             csm.set_parent_commit(csm.repo.head.commit)
-            with csm.config_writer() as cw:
-                cw.set_value('url', self._small_repo_url())
+            cw = csm.config_writer()
+            cw.set_value('url', self._small_repo_url())
+            cw.release()
             csm.repo.index.commit("adjusted URL to point to local source, instead of the internet")
 
             # We have modified the configuration, hence the index is dirty, and the
@@ -286,10 +283,12 @@ class TestSubmodule(TestBase):
             # NOTE: As we did  a few updates in the meanwhile, the indices were reset
             # Hence we create some changes
             csm.set_parent_commit(csm.repo.head.commit)
-            with sm.config_writer() as writer:
-                writer.set_value("somekey", "somevalue")
-            with csm.config_writer() as writer:
-                writer.set_value("okey", "ovalue")
+            writer = sm.config_writer()
+            writer.set_value("somekey", "somevalue")
+            writer.release()
+            writer = csm.config_writer()
+            writer.set_value("okey", "ovalue")
+            writer.release()
             self.failUnlessRaises(InvalidGitRepositoryError, sm.remove)
             # if we remove the dirty index, it would work
             sm.module().index.reset()
@@ -318,8 +317,8 @@ class TestSubmodule(TestBase):
             # forcibly delete the child repository
             prev_count = len(sm.children())
             self.failUnlessRaises(ValueError, csm.remove, force=True)
-            # We removed sm, which removed all submodules. However, the instance we
-            # have still points to the commit prior to that, where it still existed
+            # We removed sm, which removed all submodules. Howver, the instance we have
+            # still points to the commit prior to that, where it still existed
             csm.set_parent_commit(csm.repo.commit(), check=False)
             assert not csm.exists()
             assert not csm.module_exists()
@@ -418,10 +417,9 @@ class TestSubmodule(TestBase):
         # Error if there is no submodule file here
         self.failUnlessRaises(IOError, Submodule._config_parser, rwrepo, rwrepo.commit(self.k_no_subm_tag), True)
 
-    # @skipIf(HIDE_WINDOWS_KNOWN_ERRORS,
-    #         "FIXME: fails with: PermissionError: [WinError 32] The process cannot access the file because"
-    #         "it is being used by another process: "
-    #         "'C:\\Users\\ankostis\\AppData\\Local\\Temp\\tmp95c3z83bnon_bare_test_base_rw\\git\\ext\\gitdb\\gitdb\\ext\\smmap'")  # noqa E501
+    @skipIf(is_win, "FIXME: fails with: PermissionError: [WinError 32] The process cannot access the file because"
+            "it is being used by another process: "
+            "'C:\\Users\\ankostis\\AppData\\Local\\Temp\\tmp95c3z83bnon_bare_test_base_rw\\git\\ext\\gitdb\\gitdb\\ext\\smmap'")  # noqa E501
     @with_rw_repo(k_subm_current)
     def test_base_rw(self, rwrepo):
         self._do_base_tests(rwrepo)
@@ -430,11 +428,6 @@ class TestSubmodule(TestBase):
     def test_base_bare(self, rwrepo):
         self._do_base_tests(rwrepo)
 
-    @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and sys.version_info[:2] == (3, 5), """
-        File "C:\projects\gitpython\git\cmd.py", line 559, in execute
-        raise GitCommandNotFound(command, err)
-        git.exc.GitCommandNotFound: Cmd('git') not found due to: OSError('[WinError 6] The handle is invalid')
-        cmdline: git clone -n --shared -v C:\projects\gitpython\.git Users\appveyor\AppData\Local\Temp\1\tmplyp6kr_rnon_bare_test_root_module""")  # noqa E501
     @with_rw_repo(k_subm_current, bare=False)
     def test_root_module(self, rwrepo):
         # Can query everything without problems
@@ -452,8 +445,8 @@ class TestSubmodule(TestBase):
 
         assert len(rm.list_items(rm.module())) == 1
         rm.config_reader()
-        with rm.config_writer():
-            pass
+        w = rm.config_writer()
+        w.release()
 
         # deep traversal gitdb / async
         rsmsp = [sm.path for sm in rm.traverse()]
@@ -478,8 +471,9 @@ class TestSubmodule(TestBase):
         assert not sm.module_exists()               # was never updated after rwrepo's clone
 
         # assure we clone from a local source
-        with sm.config_writer() as writer:
-            writer.set_value('url', to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, sm.path)))
+        writer = sm.config_writer()
+        writer.set_value('url', to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, sm.path)))
+        writer.release()
 
         # dry-run does nothing
         sm.update(recursive=False, dry_run=True, progress=prog)
@@ -487,8 +481,9 @@ class TestSubmodule(TestBase):
 
         sm.update(recursive=False)
         assert sm.module_exists()
-        with sm.config_writer() as writer:
-            writer.set_value('path', fp)    # change path to something with prefix AFTER url change
+        writer = sm.config_writer()
+        writer.set_value('path', fp)    # change path to something with prefix AFTER url change
+        writer.release()
 
         # update fails as list_items in such a situations cannot work, as it cannot
         # find the entry at the changed path
@@ -575,8 +570,9 @@ class TestSubmodule(TestBase):
         # repository at the different url
         nsm.set_parent_commit(csmremoved)
         nsmurl = to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, rsmsp[0]))
-        with nsm.config_writer() as writer:
-            writer.set_value('url', nsmurl)
+        writer = nsm.config_writer()
+        writer.set_value('url', nsmurl)
+        writer.release()
         csmpathchange = rwrepo.index.commit("changed url")
         nsm.set_parent_commit(csmpathchange)
 
@@ -606,8 +602,9 @@ class TestSubmodule(TestBase):
         nsmm = nsm.module()
         prev_commit = nsmm.head.commit
         for branch in ("some_virtual_branch", cur_branch.name):
-            with nsm.config_writer() as writer:
-                writer.set_value(Submodule.k_head_option, git.Head.to_full_path(branch))
+            writer = nsm.config_writer()
+            writer.set_value(Submodule.k_head_option, git.Head.to_full_path(branch))
+            writer.release()
             csmbranchchange = rwrepo.index.commit("changed branch to %s" % branch)
             nsm.set_parent_commit(csmbranchchange)
         # END for each branch to change
@@ -635,8 +632,9 @@ class TestSubmodule(TestBase):
         assert nsm.exists() and nsm.module_exists() and len(nsm.children()) >= 1
         # assure we pull locally only
         nsmc = nsm.children()[0]
-        with nsmc.config_writer() as writer:
-            writer.set_value('url', subrepo_url)
+        writer = nsmc.config_writer()
+        writer.set_value('url', subrepo_url)
+        writer.release()
         rm.update(recursive=True, progress=prog, dry_run=True)      # just to run the code
         rm.update(recursive=True, progress=prog)
 
@@ -728,9 +726,6 @@ class TestSubmodule(TestBase):
         assert commit_sm.binsha == sm_too.binsha
         assert sm_too.binsha != sm.binsha
 
-    # @skipIf(HIDE_WINDOWS_KNOWN_ERRORS,
-    #         "FIXME: helper.wrapper fails with: PermissionError: [WinError 5] Access is denied: "
-    #         "'C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\test_work_tree_unsupportedryfa60di\\master_repo\\.git\\objects\\pack\\pack-bc9e0787aef9f69e1591ef38ea0a6f566ec66fe3.idx")  # noqa E501
     @with_rw_directory
     def test_git_submodule_compatibility(self, rwdir):
         parent = git.Repo.init(os.path.join(rwdir, 'parent'))
@@ -788,8 +783,8 @@ class TestSubmodule(TestBase):
         rsm = parent.submodule_update()
         assert_exists(sm)
         assert_exists(csm)
-        with csm.config_writer().set_value('url', 'bar'):
-            pass
+        csm_writer = csm.config_writer().set_value('url', 'bar')
+        csm_writer.release()
         csm.repo.index.commit("Have to commit submodule change for algorithm to pick it up")
         assert csm.url == 'bar'
 
@@ -806,24 +801,6 @@ class TestSubmodule(TestBase):
             assert os.path.isdir(sm_module_path) == dry_run
         # end for each dry-run mode
 
-    @with_rw_directory
-    def test_remove_norefs(self, rwdir):
-        parent = git.Repo.init(os.path.join(rwdir, 'parent'))
-        sm_name = 'mymodules/myname'
-        sm = parent.create_submodule(sm_name, sm_name, url=self._small_repo_url())
-        assert sm.exists()
-
-        parent.index.commit("Added submodule")
-
-        assert sm.repo is parent  # yoh was surprised since expected sm repo!!
-        # so created a new instance for submodule
-        smrepo = git.Repo(os.path.join(rwdir, 'parent', sm.path))
-        # Adding a remote without fetching so would have no references
-        smrepo.create_remote('special', 'git@server-shouldnotmatter:repo.git')
-        # And we should be able to remove it just fine
-        sm.remove()
-        assert not sm.exists()
-
     @with_rw_directory
     def test_rename(self, rwdir):
         parent = git.Repo.init(os.path.join(rwdir, 'parent'))
@@ -867,8 +844,9 @@ class TestSubmodule(TestBase):
         sm.repo.index.commit("added new file")
 
         # change designated submodule checkout branch to the new upstream feature branch
-        with sm.config_writer() as smcw:
-            smcw.set_value('branch', sm_fb.name)
+        smcw = sm.config_writer()
+        smcw.set_value('branch', sm_fb.name)
+        smcw.release()
         assert sm.repo.is_dirty(index=True, working_tree=False)
         sm.repo.index.commit("changed submodule branch to '%s'" % sm_fb)
 
@@ -892,8 +870,9 @@ class TestSubmodule(TestBase):
         sm_source_repo.index.commit("new file added, to past of '%r'" % sm_fb)
 
         # Change designated submodule checkout branch to a new commit in its own past
-        with sm.config_writer() as smcw:
-            smcw.set_value('branch', sm_pfb.path)
+        smcw = sm.config_writer()
+        smcw.set_value('branch', sm_pfb.path)
+        smcw.release()
         sm.repo.index.commit("changed submodule branch to '%s'" % sm_pfb)
 
         # Test submodule updates - must fail if submodule is dirty
diff --git a/git/test/test_tree.py b/git/test/test_tree.py
index bb62d9bf..f9282411 100644
--- a/git/test/test_tree.py
+++ b/git/test/test_tree.py
@@ -4,26 +4,18 @@
 # This module is part of GitPython and is released under
 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
 
-from io import BytesIO
 import os
-import sys
-from unittest.case import skipIf
-
+from git.test.lib import TestBase
 from git import (
     Tree,
     Blob
 )
-from git.test.lib.helper import HIDE_WINDOWS_KNOWN_ERRORS
-from git.test.lib import TestBase
+
+from io import BytesIO
 
 
 class TestTree(TestBase):
 
-    @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and sys.version_info[:2] == (3, 5), """
-        File "C:\projects\gitpython\git\cmd.py", line 559, in execute
-        raise GitCommandNotFound(command, err)
-        git.exc.GitCommandNotFound: Cmd('git') not found due to: OSError('[WinError 6] The handle is invalid')
-        cmdline: git cat-file --batch-check""")
     def test_serializable(self):
         # tree at the given commit contains a submodule as well
         roottree = self.rorepo.tree('6c1faef799095f3990e9970bc2cb10aa0221cf9c')
@@ -52,11 +44,6 @@ class TestTree(TestBase):
             testtree._deserialize(stream)
         # END for each item in tree
 
-    @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and sys.version_info[:2] == (3, 5), """
-        File "C:\projects\gitpython\git\cmd.py", line 559, in execute
-        raise GitCommandNotFound(command, err)
-        git.exc.GitCommandNotFound: Cmd('git') not found due to: OSError('[WinError 6] The handle is invalid')
-        cmdline: git cat-file --batch-check""")
     def test_traverse(self):
         root = self.rorepo.tree('0.1.6')
         num_recursive = 0
diff --git a/git/test/test_util.py b/git/test/test_util.py
index e07417b4..36fb5be3 100644
--- a/git/test/test_util.py
+++ b/git/test/test_util.py
@@ -27,22 +27,18 @@ from git.cmd import dashify
 from git.compat import string_types, is_win
 
 import time
-import ddt
 
 
 class TestIterableMember(object):
 
     """A member of an iterable list"""
-    __slots__ = "name"
+    __slots__ = ("name", "prefix_name")
 
     def __init__(self, name):
         self.name = name
+        self.prefix_name = name
 
-    def __repr__(self):
-        return "TestIterableMember(%r)" % self.name
 
-
-@ddt.ddt
 class TestUtils(TestBase):
 
     def setup(self):
@@ -101,21 +97,20 @@ class TestUtils(TestBase):
         self.assertLess(elapsed, wait_time + extra_time)
 
     def test_user_id(self):
-        self.assertIn('@', get_user_id())
+        assert '@' in get_user_id()
 
     def test_parse_date(self):
         # test all supported formats
         def assert_rval(rval, veri_time, offset=0):
-            self.assertEqual(len(rval), 2)
-            self.assertIsInstance(rval[0], int)
-            self.assertIsInstance(rval[1], int)
-            self.assertEqual(rval[0], veri_time)
-            self.assertEqual(rval[1], offset)
+            assert len(rval) == 2
+            assert isinstance(rval[0], int) and isinstance(rval[1], int)
+            assert rval[0] == veri_time
+            assert rval[1] == offset
 
             # now that we are here, test our conversion functions as well
             utctz = altz_to_utctz_str(offset)
-            self.assertIsInstance(utctz, string_types)
-            self.assertEqual(utctz_to_altz(verify_utctz(utctz)), offset)
+            assert isinstance(utctz, string_types)
+            assert utctz_to_altz(verify_utctz(utctz)) == offset
         # END assert rval utility
 
         rfc = ("Thu, 07 Apr 2005 22:13:11 +0000", 0)
@@ -136,56 +131,53 @@ class TestUtils(TestBase):
 
     def test_actor(self):
         for cr in (None, self.rorepo.config_reader()):
-            self.assertIsInstance(Actor.committer(cr), Actor)
-            self.assertIsInstance(Actor.author(cr), Actor)
+            assert isinstance(Actor.committer(cr), Actor)
+            assert isinstance(Actor.author(cr), Actor)
         # END assure config reader is handled
 
-    @ddt.data(('name', ''), ('name', 'prefix_'))
-    def test_iterable_list(self, case):
-        name, prefix = case
-        l = IterableList(name, prefix)
-
-        name1 = "one"
-        name2 = "two"
-        m1 = TestIterableMember(prefix + name1)
-        m2 = TestIterableMember(prefix + name2)
-
-        l.extend((m1, m2))
-
-        self.assertEqual(len(l), 2)
-
-        # contains works with name and identity
-        self.assertIn(name1, l)
-        self.assertIn(name2, l)
-        self.assertIn(m2, l)
-        self.assertIn(m2, l)
-        self.assertNotIn('invalid', l)
-
-        # with string index
-        self.assertIs(l[name1], m1)
-        self.assertIs(l[name2], m2)
-
-        # with int index
-        self.assertIs(l[0], m1)
-        self.assertIs(l[1], m2)
-
-        # with getattr
-        self.assertIs(l.one, m1)
-        self.assertIs(l.two, m2)
-
-        # test exceptions
-        self.failUnlessRaises(AttributeError, getattr, l, 'something')
-        self.failUnlessRaises(IndexError, l.__getitem__, 'something')
-
-        # delete by name and index
-        self.failUnlessRaises(IndexError, l.__delitem__, 'something')
-        del(l[name2])
-        self.assertEqual(len(l), 1)
-        self.assertNotIn(name2, l)
-        self.assertIn(name1, l)
-        del(l[0])
-        self.assertNotIn(name1, l)
-        self.assertEqual(len(l), 0)
-
-        self.failUnlessRaises(IndexError, l.__delitem__, 0)
-        self.failUnlessRaises(IndexError, l.__delitem__, 'something')
+    def test_iterable_list(self):
+        for args in (('name',), ('name', 'prefix_')):
+            l = IterableList('name')
+
+            m1 = TestIterableMember('one')
+            m2 = TestIterableMember('two')
+
+            l.extend((m1, m2))
+
+            assert len(l) == 2
+
+            # contains works with name and identity
+            assert m1.name in l
+            assert m2.name in l
+            assert m2 in l
+            assert m2 in l
+            assert 'invalid' not in l
+
+            # with string index
+            assert l[m1.name] is m1
+            assert l[m2.name] is m2
+
+            # with int index
+            assert l[0] is m1
+            assert l[1] is m2
+
+            # with getattr
+            assert l.one is m1
+            assert l.two is m2
+
+            # test exceptions
+            self.failUnlessRaises(AttributeError, getattr, l, 'something')
+            self.failUnlessRaises(IndexError, l.__getitem__, 'something')
+
+            # delete by name and index
+            self.failUnlessRaises(IndexError, l.__delitem__, 'something')
+            del(l[m2.name])
+            assert len(l) == 1
+            assert m2.name not in l and m1.name in l
+            del(l[0])
+            assert m1.name not in l
+            assert len(l) == 0
+
+            self.failUnlessRaises(IndexError, l.__delitem__, 0)
+            self.failUnlessRaises(IndexError, l.__delitem__, 'something')
+        # END for each possible mode