# Buggy code
def _apply_wildcards(
    self,
    newitems,
    olditems,
    wildcards,
    concretize=None,
    check_return_type=True,
    omit_callable=False,
    mapping=None,
    no_flattening=False,
    aux_params=None,
    apply_default_remote=True,
    incomplete_checkpoint_func=lambda e: None,
    allow_unpack=True,
):
    if aux_params is None:
        aux_params = dict()
    for name, item in olditems.allitems():
        start = len(newitems)
        is_unpack = is_flagged(item, "unpack")
        _is_callable = is_callable(item)

        if _is_callable:
            if omit_callable:
                continue
            item, incomplete = self.apply_input_function(
                item,
                wildcards,
                incomplete_checkpoint_func=incomplete_checkpoint_func,
                is_unpack=is_unpack,
                **aux_params,
            )
            if apply_default_remote:
                item = self.apply_default_remote(item)

        if is_unpack and not incomplete:
            if not allow_unpack:
                raise WorkflowError(
                    "unpack() is not allowed with params. "
                    "Simply return a dictionary which can be directly ."
                    "used, e.g. via {params[mykey]}."
                )
            # Sanity checks before interpreting unpack()
            if not isinstance(item, (list, dict)):
                raise WorkflowError("Can only use unpack() on list and dict", rule=self)
            if name:
                raise WorkflowError(
                    "Cannot combine named input file with unpack()", rule=self
                )
            # Allow streamlined code with/without unpack
            if isinstance(item, list):
                pairs = zip([None] * len(item), item)
            else:
                assert isinstance(item, dict)
                pairs = item.items()
        else:
            pairs = [(name, item)]

        for name, item in pairs:
            is_iterable = True
            if not_iterable(item) or no_flattening:
                item = [item]
                is_iterable = False
            for item_ in item:
                if check_return_type and not isinstance(item_, str):
                    raise WorkflowError(
                        "Function did not return str or list of str.", rule=self
                    )
                concrete = concretize(item_, wildcards, _is_callable)
                newitems.append(concrete)
                if mapping is not None:
                    mapping[concrete] = item_

            if name:
                newitems.set_name(
                    name, start, end=len(newitems) if is_iterable else None
                )
                start = len(newitems)


# Traceback (TypeError)
snakemake  --report
Building DAG of jobs...
Creating report...
Adding foo.rst (0 MB).
Could not detect mimetype for foo.rst, assuming text/plain.
Traceback (most recent call last):
File "/mnt/work/Qc.py375.venv/lib/python3.7/site-packages/snakemake/__init__.py", line 618, in snakemake
batch=batch,
File "/mnt/work/Qc.py375.venv/lib/python3.7/site-packages/snakemake/workflow.py", line 617, in execute
auto_report(dag, report)
File "/mnt/work/Qc.py375.venv/lib/python3.7/site-packages/snakemake/report/__init__.py", line 552, in auto_report
FileRecord(f, job, report_obj.caption, env, category)
File "/mnt/work/Qc.py375.venv/lib/python3.7/site-packages/snakemake/report/__init__.py", line 326, in __init__
self.params = logging.format_dict(job.params)
File "/mnt/work/Qc.py375.venv/lib/python3.7/site-packages/snakemake/logging.py", line 384, in format_dict
for name, value in dict.items()
TypeError: 'str' object is not callable

# Fixed code
def _apply_wildcards(
    self,
    newitems,
    olditems,
    wildcards,
    concretize=None,
    check_return_type=True,
    omit_callable=False,
    mapping=None,
    no_flattening=False,
    aux_params=None,
    apply_default_remote=True,
    incomplete_checkpoint_func=lambda e: None,
    allow_unpack=True,
):
    if aux_params is None:
        aux_params = dict()
    for name, item in olditems._allitems():
        start = len(newitems)
        is_unpack = is_flagged(item, "unpack")
        _is_callable = is_callable(item)

        if _is_callable:
            if omit_callable:
                continue
            item, incomplete = self.apply_input_function(
                item,
                wildcards,
                incomplete_checkpoint_func=incomplete_checkpoint_func,
                is_unpack=is_unpack,
                **aux_params,
            )
            if apply_default_remote:
                item = self.apply_default_remote(item)

        if is_unpack and not incomplete:
            if not allow_unpack:
                raise WorkflowError(
                    "unpack() is not allowed with params. "
                    "Simply return a dictionary which can be directly ."
                    "used, e.g. via {params[mykey]}."
                )
            # Sanity checks before interpreting unpack()
            if not isinstance(item, (list, dict)):
                raise WorkflowError("Can only use unpack() on list and dict", rule=self)
            if name:
                raise WorkflowError(
                    "Cannot combine named input file with unpack()", rule=self
                )
            # Allow streamlined code with/without unpack
            if isinstance(item, list):
                pairs = zip([None] * len(item), item)
            else:
                assert isinstance(item, dict)
                pairs = item.items()
        else:
            pairs = [(name, item)]

        for name, item in pairs:
            is_iterable = True
            if not_iterable(item) or no_flattening:
                item = [item]
                is_iterable = False
            for item_ in item:
                if check_return_type and not isinstance(item_, str):
                    raise WorkflowError(
                        "Function did not return str or list of str.", rule=self
                    )
                concrete = concretize(item_, wildcards, _is_callable)
                newitems.append(concrete)
                if mapping is not None:
                    mapping[concrete] = item_

            if name:
                newitems._set_name(
                    name, start, end=len(newitems) if is_iterable else None
                )
                start = len(newitems)