Skip to content

Commit a6b6d08

Browse files
committed
Added logic to print errors only when module imports genuinely fail; added logic to format strings according to Prettier's standards as well
1 parent 8bc7fc0 commit a6b6d08

File tree

1 file changed

+69
-28
lines changed

1 file changed

+69
-28
lines changed

src/murfey/cli/generate_route_manifest.py

Lines changed: 69 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
server and backend server to enable lookup of the URLs based on function name.
44
"""
55

6+
import contextlib
67
import importlib
78
import inspect
9+
import io
810
import pkgutil
911
from argparse import ArgumentParser
1012
from pathlib import Path
@@ -28,6 +30,43 @@ def increase_indent(self, flow=False, indentless=False):
2830
return super(PrettierDumper, self).increase_indent(flow, indentless=False)
2931

3032

33+
def prettier_str_representer(dumper, data):
34+
"""
35+
Helper function to format strings according to Prettier's standards:
36+
- No quoting unless it can be misinterpreted as another data type
37+
- When quoting, use double quotes unless string already contains double quotes
38+
"""
39+
40+
def is_implicitly_resolved(value: str) -> bool:
41+
for (
42+
first_char,
43+
resolvers,
44+
) in yaml.resolver.Resolver.yaml_implicit_resolvers.items():
45+
if first_char is None or (value and value[0] in first_char):
46+
for resolver in resolvers:
47+
if len(resolver) == 3:
48+
_, regexp, _ = resolver
49+
else:
50+
_, regexp = resolver
51+
if regexp.match(value):
52+
return True
53+
return False
54+
55+
# If no quoting is needed, use default plain style
56+
if not is_implicitly_resolved(data):
57+
return dumper.represent_scalar("tag:yaml.org,2002:str", data)
58+
59+
# If the string already contains double quotes, fall back to single quotes
60+
if '"' in data and "'" not in data:
61+
return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="'")
62+
63+
# Otherwise, prefer double quotes
64+
return dumper.represent_scalar("tag:yaml.org,2002:str", data, style='"')
65+
66+
67+
PrettierDumper.add_representer(str, prettier_str_representer)
68+
69+
3170
def find_routers(name: str) -> dict[str, APIRouter]:
3271

3372
def _extract_routers_from_module(module: ModuleType):
@@ -41,34 +80,36 @@ def _extract_routers_from_module(module: ModuleType):
4180

4281
routers = {}
4382

44-
# Import the module or package
45-
try:
46-
root = importlib.import_module(name)
47-
except ImportError:
48-
raise ImportError(
49-
f"Cannot import '{name}'. Please ensure that you've installed all the "
50-
"dependencies for the client, instrument server, and backend server "
51-
"before running this command."
52-
)
53-
54-
# If it's a package, walk through submodules and extract routers from each
55-
if hasattr(root, "__path__"):
56-
module_list = pkgutil.walk_packages(root.__path__, prefix=name + ".")
57-
for _, module_name, _ in module_list:
58-
try:
59-
module = importlib.import_module(module_name)
60-
except ImportError:
61-
raise ImportError(
62-
f"Cannot import '{module_name}'. Please ensure that you've "
63-
"installed all the dependencies for the client, instrument "
64-
"server, and backend server before running this command."
65-
)
66-
67-
routers.update(_extract_routers_from_module(module))
68-
69-
# Extract directly from single module
70-
else:
71-
routers.update(_extract_routers_from_module(root))
83+
# Silence output during import and only return messages if imports fail
84+
buffer = io.StringIO()
85+
with contextlib.redirect_stdout(buffer), contextlib.redirect_stderr(buffer):
86+
# Import the module or package
87+
try:
88+
root = importlib.import_module(name)
89+
except Exception as e:
90+
captured_logs = buffer.getvalue().strip()
91+
message = f"Cannot import '{name}': {e}"
92+
if captured_logs:
93+
message += f"\n--- Captured output ---\n{captured_logs}"
94+
raise ImportError(message) from e
95+
96+
# If it's a package, walk through submodules and extract routers from each
97+
if hasattr(root, "__path__"):
98+
module_list = pkgutil.walk_packages(root.__path__, prefix=name + ".")
99+
for _, module_name, _ in module_list:
100+
try:
101+
module = importlib.import_module(module_name)
102+
except Exception as e:
103+
captured_logs = buffer.getvalue().strip()
104+
message = f"Cannot import '{name}': {e}"
105+
if captured_logs:
106+
message += f"\n--- Captured output ---\n{captured_logs}"
107+
raise ImportError(message) from e
108+
routers.update(_extract_routers_from_module(module))
109+
110+
# Extract directly from single module
111+
else:
112+
routers.update(_extract_routers_from_module(root))
72113

73114
return routers
74115

0 commit comments

Comments
 (0)