Skip to content

New syntax for f-strings for Python >= 3.12 #105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

cosimolupo
Copy link
Contributor

As explained in issue #99, Python version 3.12 has changed f-strings handling, causing current syntax of f-strings in Cobrawap -- especially in Snakefiles -- to not be correctly interpreted and execution to fail. This PR changes such syntax, providing an alternative. Also some regex now need to be handled more carefully.
When Snakemake version will be upgraded, this hack will not be necessary any longer, and in principle the old f-string syntax could be put back in place.

@cosimolupo cosimolupo changed the title Pr to ne/bugfix/fstrings New syntax for f-strings for Python >= 3.12 Jul 6, 2025
@cosimolupo cosimolupo self-assigned this Jul 6, 2025
@cosimolupo cosimolupo added the bug label Jul 6, 2025
@mdenker mdenker added this to the v0.2.2 milestone Jul 18, 2025
@gulpgiulia
Copy link
Collaborator

I tested the full pipeline, branch bugfix/fstrings with data and profiles as in https://github.com/APE-group/hands_on_cobrawap/tree/main/test_datasets/imaging_deep_anesthesia. No problems/errors encountered

@gulpgiulia gulpgiulia requested a review from rgutzen July 22, 2025 09:48
@@ -13,7 +13,7 @@ def input_file(wildcards):

def is_clear(wildcards):
if config.RERUN_MODE:
return Path(f'{wildcards.dir}') / 'clear.done'
return Path(str('{wildcards.dir}')) / "clear.done"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return Path(str('{wildcards.dir}')) / "clear.done"
return Path(wildcards.dir) / "clear.done"

wildcards.dir should already be a string. I think it can be simplified like this

# configfile = Path('configs') / f'config_{PROFILE}.yaml'

rule clear:
output:
temp(Path('{path}') / 'clear.done')
params:
block_folder = [Path('{path}') / f'{block}' for block in config.BLOCK_ORDER]
block_folder = [Path('{path}') / str('{block}') for block in config.BLOCK_ORDER]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
block_folder = [Path('{path}') / str('{block}') for block in config.BLOCK_ORDER]
block_folder = [Path('{path}') / block for block in config.BLOCK_ORDER]

this interprets '{block}' as literal, causing an error because ../path/'{block}' doesn't exist.

Comment on lines -46 to +52
params(channels=config.PLOT_CHANNELS,
img_name='processed_trace_channel0.'+config.PLOT_FORMAT,
params(t_start=config.PLOT_TSTART, t_stop=config.PLOT_TSTOP,
channels=config.PLOT_CHANNELS,
img_name="processed_trace_channel0." + config.PLOT_FORMAT,
original_data=config.STAGE_INPUT)
output:
img_dir = directory(OUTPUT_DIR / 'processed_traces_{t_start}-{t_stop}s')
img_dir = directory(OUTPUT_DIR /
str("processed_traces_%s-%ss" % (config.PLOT_TSTART,config.PLOT_TSTOP)))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this edit changes the flexibility of the rule. t_start and t_stop should be determined via the wildcards and not via the config.
The config values are only used in the all rule of this stages that defines str("processed_traces_%s-%ss" % (config.PLOT_TSTART,config.PLOT_TSTOP))) as its input

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'm aware of this change in the behavior. I was wondering how to preserve this flexibility by using the new syntax. Any suggestion?

# 'zscore', 'subsampling'
# 'z_score', 'subsampling'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this changes, but it breaks backwards compatibility and has to be explicitly marked in release notes!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, correct. I changed it coherently everywhere, let's mark it explicitly in the release notes.

Comment on lines -127 to +129
params()
params(t_start=config.SLICE_TSTART,t_stop=config.SLICE_TSTOP)
output:
Path('{dir}') / f'{{data_name}}_{{t_start, [0-9]+}}-{{t_stop, [0-9]+}}s.{config.NEO_FORMAT}'
Path('{dir}') / str('{data_name}' + ("_%s-%ss." % (config.SLICE_TSTART, config.SLICE_TSTOP)) + config.NEO_FORMAT)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same issue as in previous comment. The rule should maintain its flexibility by setting the t_start and t_stop values via the wildcards and not the config values

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like this, you would need to still write the snakemake call with the t_start and t_stop times in the filename, but now it only works if it matches the config settings

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed... as said before, let's find a solution that is coherent with the new syntax, still preserving this degree of flexibility.

output:
Path('{path}_{scale}px.gif')
Path(str('{path}' + "_" + '{scale}' + "px.gif"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Path(str('{path}' + "_" + '{scale}' + "px.gif"))
Path('{path}' + "_" + '{scale}' + "px.gif")

Comment on lines +100 to +105

# TIME_SLICE
# Used for cutting the signal before video production
################
SLICE_TSTART: 0 # float (in s) or 'None' -> starting time of the input signal is used
SLICE_TSTOP: 10 # float (in s) or 'None' -> stopping time of the input signal is used
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove, see comment above

Comment on lines +12 to +13
return [OUTPUT_DIR / m / str(config.EVENT_NAME + "_" + m + ".csv")
for m in config.MEASURES]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return [OUTPUT_DIR / m / str(config.EVENT_NAME + "_" + m + ".csv")
for m in config.MEASURES]
return [OUTPUT_DIR / measure / str(config.EVENT_NAME + "_" + measure + ".csv")
for measure in config.MEASURES]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to avoid any potential overlap between actual snakemake wildcards and other dummy variables used for iterations.

Comment on lines 61 to 64
Path('{dir}') / 'spatial_derivative'
/ str(config.EVENT_NAME + "_spatial_derivative.csv"),
output_img = Path('{dir}') / 'spatial_derivative'
/ str(config.EVENT_NAME + "_spatial_derivative." + config.PLOT_FORMAT)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Path('{dir}') / 'spatial_derivative'
/ str(config.EVENT_NAME + "_spatial_derivative.csv"),
output_img = Path('{dir}') / 'spatial_derivative'
/ str(config.EVENT_NAME + "_spatial_derivative." + config.PLOT_FORMAT)
Path('{dir}') / '{rule_name}'
/ str(config.EVENT_NAME + "_spatial_derivative.csv"),
output_img = Path('{dir}') / '{rule_name}'
/ str(config.EVENT_NAME + "_spatial_derivative." + config.PLOT_FORMAT)

Comment on lines +12 to +13
return [OUTPUT_DIR / m / str(config.EVENT_NAME + "_" + m + ".csv")
for m in config.MEASURES]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return [OUTPUT_DIR / m / str(config.EVENT_NAME + "_" + m + ".csv")
for m in config.MEASURES]
return [OUTPUT_DIR / measure / str(config.EVENT_NAME + "_" + measure + ".csv")
for measure in config.MEASURES]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants