Repository: frappe/frappe

Issue:
re.error: missing ), unterminated subpattern via remove_db_aggregation (patch)
<!--
Welcome to the Frappe Framework issue tracker! Before creating an issue, please heed the following:

1. This tracker should only be used to report bugs and request features / enhancements to Frappe
    - For questions and general support, use https://stackoverflow.com/questions/tagged/frappe
    - For documentation issues, refer to https://frappeframework.com/docs/user/en or the developer cheetsheet https://github.com/frappe/frappe/wiki/Developer-Cheatsheet
2. Use the search function before creating a new issue. Duplicates will be closed and directed to
   the original discussion.
3. When making a bug report, make sure you provide all required information. The easier it is for
   maintainers to reproduce, the faster it'll be fixed.
4. If you think you know what the reason for the bug is, share it with us. Maybe put in a PR 😉
-->

## Description of the issue

## Context information (for bug reports)

**Output of `bench version`**
```
chat 0.0.1
erpnext 13.x.x-develop
erpnext_support 0.0.3
foundation 0.0.1
frappe 14.x.x-develop
frappe_docs 0.0.1
frappe_graphql 1.0.0
getanerp 0.0.1
healthcare 0.0.1
photos 0.0.1
press 0.0.1
release 0.0.1
wiki 0.0.1
zlast 0.0.1
```

## Steps to reproduce the issue

1. pull frappe, erpnext 
2. bench start 
3. bench migrate

### Observed Result / Stacktrace

```
Migrating erpnext
Executing frappe.patches.v14_0.remove_db_aggregation in erpnext (_76cf18db07302d32)

Traceback (most recent call last):
  File "/opt/homebrew/Cellar/python@3.9/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/opt/homebrew/Cellar/python@3.9/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/Users/gavin/Desktop/frappe-bench-dev/apps/frappe/frappe/utils/bench_helper.py", line 104, in <module>
    main()
  File "/Users/gavin/Desktop/frappe-bench-dev/apps/frappe/frappe/utils/bench_helper.py", line 18, in main
    click.Group(commands=commands)(prog_name='bench')
  File "/Users/gavin/Desktop/frappe-bench-dev/env/lib/python3.9/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/Users/gavin/Desktop/frappe-bench-dev/env/lib/python3.9/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/Users/gavin/Desktop/frappe-bench-dev/env/lib/python3.9/site-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/Users/gavin/Desktop/frappe-bench-dev/env/lib/python3.9/site-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/Users/gavin/Desktop/frappe-bench-dev/env/lib/python3.9/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/Users/gavin/Desktop/frappe-bench-dev/env/lib/python3.9/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/Users/gavin/Desktop/frappe-bench-dev/env/lib/python3.9/site-packages/click/decorators.py", line 21, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/Users/gavin/Desktop/frappe-bench-dev/apps/frappe/frappe/commands/__init__.py", line 26, in _func
    ret = f(frappe._dict(ctx.obj), *args, **kwargs)
  File "/Users/gavin/Desktop/frappe-bench-dev/apps/frappe/frappe/commands/site.py", line 457, in migrate
    migrate(
  File "/Users/gavin/Desktop/frappe-bench-dev/apps/frappe/frappe/migrate.py", line 68, in migrate
    frappe.modules.patch_handler.run_all(skip_failing)
  File "/Users/gavin/Desktop/frappe-bench-dev/apps/frappe/frappe/modules/patch_handler.py", line 36, in run_all
    run_patch(patch)
  File "/Users/gavin/Desktop/frappe-bench-dev/apps/frappe/frappe/modules/patch_handler.py", line 25, in run_patch
    if not run_single(patchmodule = patch):
  File "/Users/gavin/Desktop/frappe-bench-dev/apps/frappe/frappe/modules/patch_handler.py", line 66, in run_single
    return execute_patch(patchmodule, method, methodargs)
  File "/Users/gavin/Desktop/frappe-bench-dev/apps/frappe/frappe/modules/patch_handler.py", line 86, in execute_patch
    frappe.get_attr(patchmodule.split()[0] + ".execute")()
  File "/Users/gavin/Desktop/frappe-bench-dev/apps/frappe/frappe/patches/v14_0/remove_db_aggregation.py", line 30, in execute
    script = re.sub(f"frappe.db.{agg}(", f"frappe.qb.{agg}(", script)
  File "/opt/homebrew/Cellar/python@3.9/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/re.py", line 210, in sub
    return _compile(pattern, flags).sub(repl, string, count)
  File "/opt/homebrew/Cellar/python@3.9/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/re.py", line 304, in _compile
    p = sre_compile.compile(pattern, flags)
  File "/opt/homebrew/Cellar/python@3.9/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/sre_compile.py", line 764, in compile
    p = sre_parse.parse(p, flags)
  File "/opt/homebrew/Cellar/python@3.9/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/sre_parse.py", line 948, in parse
    p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
  File "/opt/homebrew/Cellar/python@3.9/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/sre_parse.py", line 443, in _parse_sub
    itemsappend(_parse(source, state, verbose, nested + 1,
  File "/opt/homebrew/Cellar/python@3.9/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/sre_parse.py", line 836, in _parse
    raise source.error("missing ), unterminated subpattern",
re.error: missing ), unterminated subpattern at position 13
```

## Additional information

Python 3.9.7


Discussion:

Resolving patch:
diff --git a/frappe/patches/v14_0/remove_db_aggregation.py b/frappe/patches/v14_0/remove_db_aggregation.py
--- a/frappe/patches/v14_0/remove_db_aggregation.py
+++ b/frappe/patches/v14_0/remove_db_aggregation.py
@@ -27,6 +27,6 @@ def execute():
 		name, script = server_script["name"], server_script["script"]
 
 		for agg in ["avg", "max", "min", "sum"]:
-			script = re.sub(f"frappe.db.{agg}(", f"frappe.qb.{agg}(", script)
+			script = re.sub(f"frappe.db.{agg}\(", f"frappe.qb.{agg}(", script)
 
 		frappe.db.update("Server Script", name, "script", script)


Test patch: