{"record":{"id":"460c42fe909f5fb6","repo":"nvbn/thefuck","slug":"path-separators-not-allowed-in-script-names","errorCode":null,"errorMessage":"Path separators not allowed in script names","messagePattern":"Path separators not allowed in script names","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastentrypoints.py","lineNumber":68,"sourceCode":"    sys.argv[0] = re.sub(r'(-script\\.pyw?|\\.exe)?$', '', sys.argv[0])\n    sys.exit({2}())'''\n\n\n@classmethod\ndef get_args(cls, dist, header=None):\n    \"\"\"\n    Yield write_script() argument tuples for a distribution's\n    console_scripts and gui_scripts entry points.\n    \"\"\"\n    if header is None:\n        header = cls.get_header()\n    spec = str(dist.as_requirement())\n    for type_ in 'console', 'gui':\n        group = type_ + '_scripts'\n        for name, ep in dist.get_entry_map(group).items():\n            # ensure_safe_name\n            if re.search(r'[\\\\/]', name):\n                raise ValueError(\"Path separators not allowed in script names\")\n            script_text = TEMPLATE.format(\n                          ep.module_name, ep.attrs[0], '.'.join(ep.attrs),\n                          spec, group, name)\n            args = cls._get_script_args(type_, name, header, script_text)\n            for res in args:\n                yield res\n\n\neasy_install.ScriptWriter.get_args = get_args\n\n\ndef main():\n    import os\n    import re\n    import shutil\n    import sys\n    dests = sys.argv[1:] or ['.']\n    filename = re.sub(r'\\.pyc$', '.py', __file__)","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/nvbn/thefuck/blob/c7e7e1d884d3bb241ea6448f72a989434c2a35ec/fastentrypoints.py#L50-L86","documentation":"This ValueError is raised by fastentrypoints, a package that monkey-patches setuptools' easy_install.ScriptWriter.get_args to generate fast, importlib-based console scripts instead of pkg_resources-based ones. During wheel/build processing it iterates over every entry point in the 'console_scripts' and 'gui_scripts' groups and rejects any whose name contains a forward or back slash. The check exists because a script name with a path separator would cause the generated executable wrapper to be written into unintended directories (or escape the build output tree).","triggerScenarios":"Calling setup.py / setuptools build machinery (e.g. `python setup.py install`, bdist_wheel, or pip installing a project) that has imported fastentrypoints, when the project's setup() declares entry_points like {'console_scripts': ['bin/tool = mymod:main']} or {'gui_scripts': ['sub/dir/app = mymod:main']}. The regex r'[\\\\/]' matches the slash in the entry-point NAME (the part before '='), triggering the raise at fastentrypoints.py:68.","commonSituations":"Typos in setup.py/setup.cfg/pyproject.toml entry_points where a path-like name is written instead of a plain command name; migrating a package whose original scripts lived in a subdirectory and copying that layout into the entry-point name; name fields containing Windows-style backslashes; occasionally a corrupted or mis-parsed entry_points string where '=' or newlines are misplaced so the wrong token is treated as the name.","solutions":["Inspect your project's entry_points declaration (setup.py, setup.cfg [options.entry_points], or pyproject.toml [project.scripts]) and remove any '/' or '\\\\' from the script name, e.g. change 'bin/tool = mymod:main' to 'tool = mymod:main'.","If you intend the script to live in a subdirectory of the environment's bin/, note that entry-point names must be plain command names; pick a unique flat name instead (e.g. 'myproject-tool').","Verify the entry_points string is well formed (correct '=' between name and target, one entry per line in setup.cfg) so the name field is not accidentally picking up a path fragment.","If the offending name comes from a third-party dependency being built from source, report it upstream; as a local workaround you can uninstall/omit fastentrypoints so stock setuptools ScriptWriter is used (which sanitizes differently) while you patch the metadata."],"exampleFix":"# before (setup.py)\nentry_points={\n    'console_scripts': [\n        'bin/mytool = myproject.cli:main',\n    ],\n}\n\n# after\nentry_points={\n    'console_scripts': [\n        'mytool = myproject.cli:main',\n    ],\n}","handlingStrategy":"validation","validationCode":"# In setup.py, before declaring entry points, validate every script name:\nimport re\n\nENTRY_POINTS = {\n    'console_scripts': [\n        'bin/mytool = myproject.cli:main',  # would fail\n    ],\n}\n\nfor group, entries in ENTRY_POINTS.items():\n    for entry in entries:\n        name = entry.split('=', 1)[0].strip()\n        if re.search(r'[\\\\/]', name):\n            raise SystemExit(\n                f\"Invalid entry point name {name!r} in {group}: \"\n                \"path separators are not allowed (fastentrypoints)\")","typeGuard":"# Python: assert entry-point names are flat command names before build\nimport re\n\ndef is_safe_script_name(name: str) -> bool:\n    \"\"\"True if name is a valid console_scripts name for fastentrypoints.\"\"\"\n    return bool(name) and not re.search(r'[\\\\/]', name) and '=' not in name\n\nassert all(is_safe_script_name(e.split('=')[0].strip())\n           for e in CONSOLE_SCRIPT_ENTRIES)","tryCatchPattern":"# If you drive builds programmatically, catch and surface the real entry point:\nfrom setuptools.command.easy_install import easy_install\n\ntry:\n    # build/install path that goes through ScriptWriter.get_args\n    run_setup_command('bdist_wheel')\nexcept ValueError as e:\n    if 'Path separators not allowed' in str(e):\n        raise SystemExit('Fix entry_points: script names must not contain / or \\\\') from e\n    raise","preventionTips":["Treat entry-point names as command names, not file paths — pick a single flat token like 'mytool'.","Add a CI lint step that greps setup.py/setup.cfg/pyproject.toml [project.scripts] sections for '='-LHS values containing '/' or '\\\\'.","Test `pip install .` or `python -m build` in CI so bad entry points fail the build before release.","Prefer pyproject.toml [project.scripts], where tooling and schema checks make stray path characters easier to spot."],"tags":["setuptools","packaging","entry-points","fastentrypoints","build","validation"],"backgroundTag":null,"analyzedSha":"c7e7e1d884d3bb241ea6448f72a989434c2a35ec","analyzedAt":"2026-08-14T19:43:00.961Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}