Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def aggressive(monkeypatch):
monkeypatch.setattr(state, "aggressive", True)
yield
def concat_candidates(code: str):
tree = ast.parse(code)
ch = ConcatHound()
ch.visit(tree)
state.concat_candidates += len(ch.victims)
yield from ch.victims
)
parser.add_argument(
"src", action="store", nargs="+", help="source file(s) or directory"
)
args = parser.parse_args()
if args.transform_concats:
if sys.version_info < (3, 8):
raise Exception(
f"""Transforming string concatenations is only possible with flynt
installed to a python3.8+ interpreter. Currently using {sys.version_info}."""
)
state.aggressive = args.aggressive
state.verbose = args.verbose
state.quiet = args.quiet
return fstringify(
args.src,
multiline=not args.no_multiline,
len_limit=int(args.line_length),
fail_on_changes=args.fail_on_change,
transform_concat=args.transform_concats,
)
def _print_report(
changed_files, total_cc_new, total_cc_original, total_expr, total_time
):
print("\nFlynt run has finished. Stats:")
print(f"\nExecution time: {total_time:.3f}s")
print(f"Files modified: {changed_files}")
if changed_files:
cc_reduction = total_cc_original - total_cc_new
cc_percent_reduction = cc_reduction / total_cc_original
print(
f"Character count reduction: {cc_reduction} ({cc_percent_reduction:.2%})\n"
)
print("Per expression type:")
if state.percent_candidates:
percent_fraction = state.percent_transforms / state.percent_candidates
print(
f"Old style (`%`) expressions attempted: {state.percent_transforms}/"
f"{state.percent_candidates} ({percent_fraction:.1%})"
)
else:
print("No old style (`%`) expressions attempted.")
if state.call_candidates:
print(
f"`.format(...)` calls attempted: {state.call_transforms}/"
f"{state.call_candidates} ({state.call_transforms / state.call_candidates:.1%})"
)
else:
print("No `.format(...)` calls attempted.")
if state.concat_candidates:
def formatted_value(fmt_prefix, fmt_spec, val):
if fmt_spec in conversion_methods:
if not state.aggressive and fmt_prefix:
raise FlyntException(
"Default text alignment has changed between percent fmt and fstrings. "
"Proceeding would result in changed code behaviour."
)
fv = ast_formatted_value(
val, fmt_str=fmt_prefix, conversion=conversion_methods[fmt_spec]
)
else:
fmt_spec = translate_conversion_types.get(fmt_spec, fmt_spec)
if fmt_spec == "d":
if state.aggressive:
val = ast.Call(
func=ast.Name(id="int", ctx=ast.Load()), args=[val], keywords={}
)
fmt_spec = ""
else:
raise FlyntException(
"Skipping %d formatting - fstrings behave differently from % formatting."
)
fv = ast_formatted_value(val, fmt_str=fmt_prefix + fmt_spec)
return fv
def formatted_value(fmt_prefix, fmt_spec, val):
if fmt_spec in conversion_methods:
if not state.aggressive and fmt_prefix:
raise FlyntException(
"Default text alignment has changed between percent fmt and fstrings. "
"Proceeding would result in changed code behaviour."
)
fv = ast_formatted_value(
val, fmt_str=fmt_prefix, conversion=conversion_methods[fmt_spec]
)
else:
fmt_spec = translate_conversion_types.get(fmt_spec, fmt_spec)
if fmt_spec == "d":
if state.aggressive:
val = ast.Call(
func=ast.Name(id="int", ctx=ast.Load()), args=[val], keywords={}
)
fmt_spec = ""
else:
traceback.print_exc()
state.invalid_conversions += 1
return code, False
else:
if changed:
new_code = astor.to_source(converted)
new_code = new_code.strip()
new_code = set_quote_type(
new_code, quote_type if not str_in_str else QuoteTypes.double
)
new_code = new_code.replace("\n", "\\n")
new_code = new_code.replace("\t", "\\t")
try:
ast.parse(new_code)
except Exception as e:
if state.verbose:
print(
f"Failed to parse transformed code '{new_code}' given original '{code}'"
)
print(e)
traceback.print_exc()
state.invalid_conversions += 1
return code, False
else:
return new_code, changed
return code, False
changed_files = 0
total_charcount_original = 0
total_charcount_new = 0
total_expressions = 0
start_time = time.time()
for path in files:
changed, count_expressions, charcount_original, charcount_new = _fstringify_file(
path, multiline, len_limit, transform_concat
)
if changed:
changed_files += 1
total_expressions += count_expressions
total_charcount_original += charcount_original
total_charcount_new += charcount_new
if state.verbose:
status = "modified" if count_expressions else "no change"
print(f"fstringifying {path}...{status}")
total_time = time.time() - start_time
if not state.quiet:
_print_report(
changed_files,
total_charcount_new,
total_charcount_original,
total_expressions,
total_time,
)
return changed_files