2

I am writing a package compatible with both Python 2.7.13 and Python 3.3, and using the following:

try:
    import configparser
except:
    from six.moves import configparser

But when I load my .gitmodules file on Python 2.7:

    configParser   = configparser.RawConfigParser( allow_no_value=True )
    configFilePath = os.path.join( current_directory, '.gitmodules' )

    configParser.read( configFilePath )

It throw the error:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "update.py", line 122, in run
    self.create_backstroke_pulls()
  File "update.py", line 132, in create_backstroke_pulls
    configParser.read( configFilePath )
  File "/usr/lib/python2.7/ConfigParser.py", line 305, in read
    self._read(fp, filename)
  File "/usr/lib/python2.7/ConfigParser.py", line 546, in _read
    raise e
ParsingError: File contains parsing errors: /cygdrive/d/.gitmodules
        [line  2]: '\tpath = .versioning\n'
        [line  3]: '\turl = https://github.com/user/repo\n'

But if I remove the tabs from the .gitmodules file, it works correctly. On Python 3.3 it does work with tabs, only on Python 2.7.13 it is not working with tabs. How can I make it work without removing the tabs?

The tabs are natively put by git when I am adding new submodules, so I definitely not remove them from the original file. I have been thinking I could duplicate the file, while removing the tabs. But is there less costly operation for compatibility with Python?


Related questions:

  1. How can I remove the white characters from configuration file?
Evandro Coan
  • 8,560
  • 11
  • 83
  • 144

1 Answers1

3

A workaround would be to use a io.StringIO, with modified contents, to pass to readfp (which accepts a file handle instead of file name).

The following code is trying to comply to both Python 2 and Python 3 (even if in python 3, readfp is deprecated, now it's read_file. Anyway that still works). Note that I don't need six package, configparser exists natively in 2 & 3 python versions.

try:
    import ConfigParser as configparser
except ImportError:
    import configparser

import io
try:
    unicode
except NameError:
    unicode = str  # python 3: no more unicode

r = configparser.RawConfigParser()

with open(configFilePath) as f:
    fakefile = io.StringIO(unicode(f.read().replace("\t","")))

r.readfp(fakefile,filename=configFilePath)

so the parser is "fooled" by reading a fake file with filecontents minus the tabs.

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • It is throwing this error `fakefile = io.StringIO(f.read().replace("\t","")) TypeError: initial_value must be unicode or None, not str` – Evandro Coan Jul 31 '17 at 12:33
  • I also tried to change `"\t",""` to `u"\t",u""` and it also worked. 1. [TypeError: initial_value must be unicode or None, not str](https://stackoverflow.com/questions/39720919/typeerror-initial-value-must-be-unicode-or-none-not-str) 2. [How can I resolve TypeError with StringIO in Python 2.7?](https://stackoverflow.com/questions/22316333/how-can-i-resolve-typeerror-with-stringio-in-python-2-7) – Evandro Coan Jul 31 '17 at 13:51