Skip to content

validation(scaffold,companyos): reject regular-file target with clear message#13

Open
CryptoJones wants to merge 2 commits into
mainfrom
validation/scaffold-rejects-file-target
Open

validation(scaffold,companyos): reject regular-file target with clear message#13
CryptoJones wants to merge 2 commits into
mainfrom
validation/scaffold-rejects-file-target

Conversation

@CryptoJones
Copy link
Copy Markdown
Owner

5bc304a validation: catch NotADirectoryError in _cmd_companyos too (#cli)

Iter 12 added NotADirectoryError to scaffold_companyos but
_cmd_companyos only caught FileExistsError, so passing a regular
file path crashed with a stacktrace instead of returning 2 + a
clean error message. Catch both errors in the same except clause.

Test added: socrates companyos returns 2 with 'error:' on
stderr and leaves the file untouched.

051e424 validation(scaffold,companyos): reject regular-file target with clear message

If an operator typo'd
socrates init my-project --base ~/notes.txt
or otherwise passed a path that exists as a regular file, scaffold()
and scaffold_companyos() previously hit confusing late-stage errors:

  • scaffold() got "NotADirectoryError: [Errno 20] Not a directory" from
    inside the FILES touch loop — after target.mkdir(exist_ok=overwrite)
    silently no-op'd on the existing-as-file path.
  • scaffold_companyos() blew up inside any(target.iterdir()) because
    Path.iterdir on a file raises NotADirectoryError mid-condition.

Both now check target.is_file() up-front and raise a clean
NotADirectoryError with an actionable message. The file is untouched.

Tests added (3):

  • scaffold() rejects file target — no side effects
  • scaffold(file, overwrite=True) STILL rejects (overwrite is for
    empty dirs, not for silently clobbering user files)
  • scaffold_companyos() symmetric guard

150/150 tests pass; ruff + mypy clean.

This branch has TWO commits:

  1. The original scaffold/companyos fix (NotADirectoryError on file target).
  2. A follow-up that catches NotADirectoryError in _cmd_companyos too — without it, the CLI would have crashed with a stacktrace despite the library function now raising cleanly.

… message

If an operator typo'd
  socrates init my-project --base ~/notes.txt
or otherwise passed a path that exists as a regular file, scaffold()
and scaffold_companyos() previously hit confusing late-stage errors:

- scaffold() got "NotADirectoryError: [Errno 20] Not a directory" from
  inside the FILES touch loop — after target.mkdir(exist_ok=overwrite)
  silently no-op'd on the existing-as-file path.
- scaffold_companyos() blew up inside any(target.iterdir()) because
  Path.iterdir on a file raises NotADirectoryError mid-condition.

Both now check `target.is_file()` up-front and raise a clean
NotADirectoryError with an actionable message. The file is untouched.

Tests added (3):
- scaffold() rejects file target — no side effects
- scaffold(file, overwrite=True) STILL rejects (overwrite is for
  empty dirs, not for silently clobbering user files)
- scaffold_companyos() symmetric guard

150/150 tests pass; ruff + mypy clean.
Iter 12 added NotADirectoryError to scaffold_companyos but
_cmd_companyos only caught FileExistsError, so passing a regular
file path crashed with a stacktrace instead of returning 2 + a
clean error message. Catch both errors in the same except clause.

Test added: socrates companyos <file> returns 2 with 'error:' on
stderr and leaves the file untouched.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant