# Buggy code
def clean_ini(path, section, parameter):
    """Delete sections and parameters (aka option) in the file"""

    def write(parser, ini_file):
        """
        Reimplementation of the original RowConfigParser write function.

        This function is 99% same as its origin. The only change is
        removing a cast to str. This is needed to handle unicode chars.
        """
        if parser._defaults:
            ini_file.write("[%s]\n" % "DEFAULT")
            for key, value in parser._defaults.items():
                ini_file.write("%s = %s\n" % (key, str(value).replace("\n", "\n\t")))
            ini_file.write("\n")
        for section in parser._sections:
            ini_file.write("[%s]\n" % section)
            for key, value in parser._sections[section].items():
                if key == "__name__":
                    continue
                if (value is not None) or (parser._optcre == parser.OPTCRE):
                    # The line bellow is the only changed line of the original function.
                    # This is the orignal line for reference:
                    # key = " = ".join((key, str(value).replace('\n', '\n\t')))
                    key = " = ".join((key, value.replace("\n", "\n\t")))
                ini_file.write("%s\n" % (key))
            ini_file.write("\n")

    encoding = detect_encoding(path) or "utf_8_sig"

    # read file to parser
    config = bleachbit.RawConfigParser()
    config.write = write
    with open(path, "r", encoding=encoding) as fp:
        config.read_file(fp)

    # change file
    changed = False
    if config.has_section(section):
        if parameter is None:
            changed = True
            config.remove_section(section)
        elif config.has_option(section, parameter):
            changed = True
            config.remove_option(section, parameter)

    # write file
    if changed:
        from bleachbit.Options import options

        fp.close()
        if options.get("shred"):
            delete(path, True)
        with open(path, "w", encoding=encoding, newline="") as fp:
            config.write(config, fp)


# Traceback (configparser.DuplicateOptionError)
clean_operation('vlc'), options = '['mru']'
Error: vlc.mru: Command to clean .ini path=/home/dzmitry/.config/vlc/vlc-qt-interface.conf, section=General, parameter=filedialog-path
Traceback (most recent call last):
File "/home/dzmitry/Downloads/bleachbit-master/bleachbit/Worker.py", line 87, in execute
for ret in cmd.execute(self.really_delete):
File "/home/dzmitry/Downloads/bleachbit-master/bleachbit/Command.py", line 210, in execute
FileUtilities.clean_ini(self.path, self.section, self.parameter)
File "/home/dzmitry/Downloads/bleachbit-master/bleachbit/FileUtilities.py", line 232, in clean_ini
config.read_file(fp)
File "/usr/lib/python3.5/configparser.py", line 715, in read_file
self._read(f, source)
File "/usr/lib/python3.5/configparser.py", line 1089, in _read
fpname, lineno)
configparser.DuplicateOptionError: While reading from '/home/dzmitry/.config/vlc/vlc-qt-interface.conf' [line 16]: option 'bgsize' in section 'MainWindow' already exists
Error: vlc.mru: Command to clean .ini path=/home/dzmitry/.config/vlc/vlc-qt-interface.conf, section=RecentsMRL, parameter=None
Traceback (most recent call last):
File "/home/dzmitry/Downloads/bleachbit-master/bleachbit/Worker.py", line 87, in execute
for ret in cmd.execute(self.really_delete):
File "/home/dzmitry/Downloads/bleachbit-master/bleachbit/Command.py", line 210, in execute
FileUtilities.clean_ini(self.path, self.section, self.parameter)
File "/home/dzmitry/Downloads/bleachbit-master/bleachbit/FileUtilities.py", line 232, in clean_ini
config.read_file(fp)
File "/usr/lib/python3.5/configparser.py", line 715, in read_file
self._read(f, source)
File "/usr/lib/python3.5/configparser.py", line 1089, in _read
fpname, lineno)
configparser.DuplicateOptionError: While reading from '/home/dzmitry/.config/vlc/vlc-qt-interface.conf' [line 16]: option 'bgsize' in section 'MainWindow' already exists
Error: vlc.mru: Command to clean .ini path=/home/dzmitry/.config/vlc/vlc-qt-interface.conf, section=OpenDialog, parameter=netMRL
Traceback (most recent call last):
File "/home/dzmitry/Downloads/bleachbit-master/bleachbit/Worker.py", line 87, in execute
for ret in cmd.execute(self.really_delete):
File "/home/dzmitry/Downloads/bleachbit-master/bleachbit/Command.py", line 210, in execute
FileUtilities.clean_ini(self.path, self.section, self.parameter)
File "/home/dzmitry/Downloads/bleachbit-master/bleachbit/FileUtilities.py", line 232, in clean_ini
config.read_file(fp)
File "/usr/lib/python3.5/configparser.py", line 715, in read_file
self._read(f, source)
File "/usr/lib/python3.5/configparser.py", line 1089, in _read
fpname, lineno)
configparser.DuplicateOptionError: While reading from '/home/dzmitry/.config/vlc/vlc-qt-interface.conf' [line 16]: option 'bgsize' in section 'MainWindow' already exists

Disk space recovered: 0
Files deleted: 0
Errors: 3
elapsed time: 0 seconds

# Fixed code
def clean_ini(path, section, parameter):
    """Delete sections and parameters (aka option) in the file"""

    def write(parser, ini_file):
        """
        Reimplementation of the original RowConfigParser write function.

        This function is 99% same as its origin. The only change is
        removing a cast to str. This is needed to handle unicode chars.
        """
        if parser._defaults:
            ini_file.write("[%s]\n" % "DEFAULT")
            for key, value in parser._defaults.items():
                ini_file.write("%s = %s\n" % (key, str(value).replace("\n", "\n\t")))
            ini_file.write("\n")
        for section in parser._sections:
            ini_file.write("[%s]\n" % section)
            for key, value in parser._sections[section].items():
                if key == "__name__":
                    continue
                if (value is not None) or (parser._optcre == parser.OPTCRE):
                    # The line bellow is the only changed line of the original function.
                    # This is the orignal line for reference:
                    # key = " = ".join((key, str(value).replace('\n', '\n\t')))
                    key = " = ".join((key, value.replace("\n", "\n\t")))
                ini_file.write("%s\n" % (key))
            ini_file.write("\n")

    encoding = detect_encoding(path) or "utf_8_sig"

    # read file to parser
    config = bleachbit.RawConfigParser()
    config.optionxform = lambda option: option
    config.write = write
    with open(path, "r", encoding=encoding) as fp:
        config.read_file(fp)

    # change file
    changed = False
    if config.has_section(section):
        if parameter is None:
            changed = True
            config.remove_section(section)
        elif config.has_option(section, parameter):
            changed = True
            config.remove_option(section, parameter)

    # write file
    if changed:
        from bleachbit.Options import options

        fp.close()
        if options.get("shred"):
            delete(path, True)
        with open(path, "w", encoding=encoding, newline="") as fp:
            config.write(config, fp)