copier icon indicating copy to clipboard operation
copier copied to clipboard

Conditional argument ignored when updating

Open lhupfeldt opened this issue 1 year ago • 5 comments

Describe the problem

Commandline data argument is ignored when commandline value is changed during update. Argument is not remembered in answers file.

Template

copier_ignored_arg_bug.zip

To Reproduce

Create a copier.yaml with an argument which is conditional based on another argument.

_min_copier_version: 9.0.0

_subdirectory: "template"

_exclude:
  - "*~"

_message_before_copy: |
  Hi

project_name:
  type: str
  default: X

# Hidden options used for testing

show_internal_test_options:
  type: bool
  help: "Show options for internal use for testing template."
  default: false
  when: false

with_internal1:
  type: bool
  help: "Internal opt 1"
  default: false
  when: "{{ show_internal_test_options }}"

Git commit template. Expand template with "hidden" data arg specified on commandline.

 ]$ mkdir ttt && cd ttt && copier copy ../copier_ignored_arg_bug . --defaults --data with_internal1=true 

Value of with_internal1 is correctly expanded as True in template file, but is not store in answers file. Commit subproject. Make a change in template, e.g. the message. Commit. Update subproject with new value of with_internal1

 ttt]$ copier update -A --data with_internal1=false

Value of with_internal1 is unchanged and remains expanded as True in template file! The template file is unchanged, only answers file is update (with new git commit).

Logs

No response

Expected behavior

The template file should be updated with the value specified on commandline. Copier should save the value in the answers file.

Screenshots/screencasts/logs

No response

Operating system

Linux

Operating system distribution and version

Fedora

Copier version

9.3.1

Python version

3.11.8

Installation method

pip+pypi

Additional context

No response

lhupfeldt avatar Aug 09 '24 12:08 lhupfeldt

Seems a theoretical valid case, but what's the real use case for such feature? I mean: why would you need an answer whose when evaluates to false to be actually stored? If it's changing the output, it's probably a template issue

yajo avatar Aug 10 '24 10:08 yajo

In the simple example I could just specify the show_internal_test_options. But why should I have to? The show_internal_test_options is just for interactive UI usage to make sure the internal test options are not asked in interactive usage, the real option affecting the template expansion is with_internal1. In the actual template where I have the issue I have maybe 15 secret options affecting template expansion. If I set show_internal_test_options I will have to answer those or use --defaults, which then also affects all other options. I don't understand what you mean by "it's probably a template issue". The --data with_internal1=false is silently ignored during update, unlike other options which are changable.

lhupfeldt avatar Aug 11 '24 14:08 lhupfeldt

Sounds like hacking the answer system to customize the CLI interactivity. I sometimes wonder if Copier shouldn't provide some kind of wrapper around it to build more flexible CLIs/TUIs without having to twist its internals. Some kind of Textual form, for example.

pawamoy avatar Aug 11 '24 14:08 pawamoy

I wonder whether we should disallow overriding answers to hidden questions (when: false with both literal false and Jinja expression evaluating as false) via --data/data= for better consistency across interactive and programmatic use of Copier. :thinking: In interactive mode, a hidden question cannot be answered by a user, so the default value will always be used. This default value can be either hardcoded or a computed value. So why should it be possible to override the answer in programmatic mode?

sisp avatar Aug 19 '24 13:08 sisp

That makes sense @sisp. However, that won't fix the fact that skipped answers (when=false) won't be stored.

@lhupfeldt have you tried hacking the .copier-answers.yml.jinja file? Something like this:

# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
{{ dict(_copier_answers, with_internal1=with_internal1) | to_nice_yaml -}}

This way you hardcode a key that's gonna be sometimes skipped in the questionary.

FWIW, keep in mind that, during updates, if you pass -A, you'll only be prompted for new questions. Old ones, already answered, won't ask you again.

yajo avatar Sep 21 '24 06:09 yajo