# Buggy code
def make_envconfig(self, name, section, subs, config, replace=True):
    factors = set(name.split("-"))
    reader = SectionReader(
        section, self._cfg, fallbacksections=["testenv"], factors=factors
    )
    tc = TestenvConfig(name, config, factors, reader)
    reader.addsubstitutions(
        envname=name,
        envbindir=tc.get_envbindir,
        envsitepackagesdir=tc.get_envsitepackagesdir,
        envpython=tc.get_envpython,
        **subs,
    )
    for env_attr in config._testenv_attr:
        atype = env_attr.type
        try:
            if atype in (
                "bool",
                "float",
                "path",
                "string",
                "dict",
                "dict_setenv",
                "argv",
                "argvlist",
                "argv_install_command",
            ):
                meth = getattr(reader, "get{}".format(atype))
                res = meth(env_attr.name, env_attr.default, replace=replace)
            elif atype == "basepython":
                no_fallback = name in (config.provision_tox_env,)
                res = reader.getstring(
                    env_attr.name,
                    env_attr.default,
                    replace=replace,
                    no_fallback=no_fallback,
                )
            elif atype == "space-separated-list":
                res = reader.getlist(env_attr.name, sep=" ")
            elif atype == "line-list":
                res = reader.getlist(env_attr.name, sep="\n")
            elif atype == "env-list":
                res = reader.getstring(env_attr.name, replace=False)
                res = tuple(_split_env(res))
            else:
                raise ValueError("unknown type {!r}".format(atype))
            if env_attr.postprocess:
                res = env_attr.postprocess(testenv_config=tc, value=res)
        except tox.exception.MissingSubstitution as e:
            tc._missing_subs.append(e.name)
            res = e.FLAG
        setattr(tc, env_attr.name, res)
        if atype in ("path", "string", "basepython"):
            reader.addsubstitutions(**{env_attr.name: res})
    return tc


# Traceback (AttributeError)
tox -vv
using tox.ini: /home/jayvdb/projects/tox/my-tox-tests/tests/tox.ini (pid 23538)
removing /home/jayvdb/projects/tox/my-tox-tests/tests/.tox/log
[wikimedia] tox-wikimedia is enabled
Traceback (most recent call last):
File "/home/jayvdb/.cache/tox/my-tox-tests/py38-tox3_20-other/bin/tox", line 8, in <module>
sys.exit(cmdline())
File "/home/jayvdb/.cache/tox/my-tox-tests/py38-tox3_20-other/lib/python3.8/site-packages/tox/session/__init__.py", line 44, in cmdline
main(args)
File "/home/jayvdb/.cache/tox/my-tox-tests/py38-tox3_20-other/lib/python3.8/site-packages/tox/session/__init__.py", line 65, in main
config = load_config(args)
File "/home/jayvdb/.cache/tox/my-tox-tests/py38-tox3_20-other/lib/python3.8/site-packages/tox/session/__init__.py", line 81, in load_config
config = parseconfig(args)
File "/home/jayvdb/.cache/tox/my-tox-tests/py38-tox3_20-other/lib/python3.8/site-packages/tox/config/__init__.py", line 281, in parseconfig
pm.hook.tox_configure(config=config)  # post process config object
File "/home/jayvdb/.cache/tox/my-tox-tests/py38-tox3_20-other/lib/python3.8/site-packages/pluggy/hooks.py", line 286, in __call__
return self._hookexec(self, self.get_hookimpls(), kwargs)
File "/home/jayvdb/.cache/tox/my-tox-tests/py38-tox3_20-other/lib/python3.8/site-packages/pluggy/manager.py", line 93, in _hookexec
return self._inner_hookexec(hook, methods, kwargs)
File "/home/jayvdb/.cache/tox/my-tox-tests/py38-tox3_20-other/lib/python3.8/site-packages/pluggy/manager.py", line 84, in <lambda>
self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
File "/home/jayvdb/.cache/tox/my-tox-tests/py38-tox3_20-other/lib/python3.8/site-packages/pluggy/callers.py", line 208, in _multicall
return outcome.get_result()
File "/home/jayvdb/.cache/tox/my-tox-tests/py38-tox3_20-other/lib/python3.8/site-packages/pluggy/callers.py", line 80, in get_result
raise ex[1].with_traceback(ex[2])
File "/home/jayvdb/.cache/tox/my-tox-tests/py38-tox3_20-other/lib/python3.8/site-packages/pluggy/callers.py", line 187, in _multicall
res = hook_impl.function(*args)
File "/home/jayvdb/.cache/tox/my-tox-tests/py38-tox3_20-other/lib/python3.8/site-packages/tox_wikimedia/__init__.py", line 93, in tox_configure
if dep in cdep.name:
AttributeError: 'str' object has no attribute 'name'

# Fixed code
def make_envconfig(self, name, section, subs, config, replace=True):
    factors = set(name.split("-"))
    reader = SectionReader(
        section, self._cfg, fallbacksections=["testenv"], factors=factors
    )
    tc = TestenvConfig(name, config, factors, reader)
    reader.addsubstitutions(
        envname=name,
        envbindir=tc.get_envbindir,
        envsitepackagesdir=tc.get_envsitepackagesdir,
        envpython=tc.get_envpython,
        **subs,
    )
    for env_attr in config._testenv_attr:
        atype = env_attr.type
        try:
            if atype in (
                "bool",
                "float",
                "path",
                "string",
                "dict",
                "dict_setenv",
                "argv",
                "argvlist",
                "argv_install_command",
            ):
                meth = getattr(reader, "get{}".format(atype))
                res = meth(env_attr.name, env_attr.default, replace=replace)
            elif atype == "basepython":
                no_fallback = name in (config.provision_tox_env,)
                res = reader.getstring(
                    env_attr.name,
                    env_attr.default,
                    replace=replace,
                    no_fallback=no_fallback,
                )
            elif atype == "space-separated-list":
                res = reader.getlist(env_attr.name, sep=" ")
            elif atype == "line-list":
                res = reader.getlist(env_attr.name, sep="\n")
            elif atype == "env-list":
                res = reader.getstring(env_attr.name, replace=False)
                res = tuple(_split_env(res))
            else:
                raise ValueError("unknown type {!r}".format(atype))
            if env_attr.postprocess:
                res = env_attr.postprocess(testenv_config=tc, value=res)
        except tox.exception.MissingSubstitution as e:
            tc._missing_subs[env_attr.name] = res = e
        # On Python 2, exceptions are handled in __getattr__
        if not six.PY2 or not isinstance(res, Exception):
            setattr(tc, env_attr.name, res)
        if atype in ("path", "string", "basepython"):
            reader.addsubstitutions(**{env_attr.name: res})
    return tc