Skip to content

Commit eadfb18

Browse files
committed
Fix Windows emoji encoding issue causing test_fastapi_cli to fail
Changes applied: •logging.py: Added emoji=False and legacy_windows=True as a fallback. Also introduced force_terminal=True for console configuration. •cli.py: Added OS detection. When running on Windows, emoji output is disabled. •test_cli.py: Added platform checks to assertions involving emoji characters.
1 parent cc841c2 commit eadfb18

3 files changed

Lines changed: 82 additions & 23 deletions

File tree

src/fastapi_cli/cli.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import sys
23
from pathlib import Path
34
from typing import Any, List, Union
45

@@ -70,21 +71,35 @@ def callback(
7071

7172
def _get_module_tree(module_paths: List[Path]) -> Tree:
7273
root = module_paths[0]
73-
name = f"🐍 {root.name}" if root.is_file() else f"📁 {root.name}"
74+
if sys.platform == "win32":
75+
name = f"Python {root.name}" if root.is_file() else f"Folder {root.name}"
76+
else:
77+
name = f"🐍 {root.name}" if root.is_file() else f"📁 {root.name}"
7478

7579
root_tree = Tree(name)
7680

7781
if root.is_dir():
78-
root_tree.add("[dim]🐍 __init__.py[/dim]")
82+
if sys.platform == "win32":
83+
root_tree.add("[dim]Python __init__.py[/dim]")
84+
else:
85+
root_tree.add("[dim]🐍 __init__.py[/dim]")
7986

8087
tree = root_tree
8188
for sub_path in module_paths[1:]:
82-
sub_name = (
83-
f"🐍 {sub_path.name}" if sub_path.is_file() else f"📁 {sub_path.name}"
84-
)
89+
if sys.platform == "win32":
90+
sub_name = (
91+
f"Python {sub_path.name}" if sub_path.is_file() else f"Folder {sub_path.name}"
92+
)
93+
else:
94+
sub_name = (
95+
f"🐍 {sub_path.name}" if sub_path.is_file() else f"📁 {sub_path.name}"
96+
)
8597
tree = tree.add(sub_name)
8698
if sub_path.is_dir():
87-
tree.add("[dim]🐍 __init__.py[/dim]")
99+
if sys.platform == "win32":
100+
tree.add("[dim]Python __init__.py[/dim]")
101+
else:
102+
tree.add("[dim]🐍 __init__.py[/dim]")
88103

89104
return root_tree
90105

@@ -106,7 +121,12 @@ def _run(
106121
with get_rich_toolkit() as toolkit:
107122
server_type = "development" if command == "dev" else "production"
108123

109-
toolkit.print_title(f"Starting {server_type} server 🚀", tag="FastAPI")
124+
if sys.platform == "win32":
125+
title = f"Starting {server_type} server"
126+
else:
127+
title = f"Starting {server_type} server 🚀"
128+
129+
toolkit.print_title(title, tag="FastAPI")
110130
toolkit.print_line()
111131

112132
toolkit.print(

src/fastapi_cli/logging.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def setup_logging(
99
terminal_width: Union[int, None] = None, level: int = logging.INFO
1010
) -> None:
1111
logger = logging.getLogger("fastapi_cli")
12-
console = Console(width=terminal_width) if terminal_width else None
12+
console = Console(width=terminal_width or 80, emoji=False, legacy_windows=True, force_terminal=True)
1313
rich_handler = RichHandler(
1414
show_time=False,
1515
rich_tracebacks=True,

tests/test_cli.py

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,21 @@ def test_dev() -> None:
3434
"log_config": get_uvicorn_log_config(),
3535
}
3636
assert "Using import string: single_file_app:app" in result.output
37-
assert "Starting development server 🚀" in result.output
37+
if sys.platform == "win32":
38+
assert "Starting development server" in result.output
39+
else:
40+
assert "Starting development server 🚀" in result.output
3841
assert "Server started at http://127.0.0.1:8000" in result.output
3942
assert "Documentation at http://127.0.0.1:8000/docs" in result.output
4043
assert (
4144
"Running in development mode, for production use: fastapi run"
4245
in result.output
4346
)
4447

45-
assert "🐍 single_file_app.py" in result.output
48+
if sys.platform == "win32":
49+
assert "Python single_file_app.py" in result.output
50+
else:
51+
assert "🐍 single_file_app.py" in result.output
4652

4753

4854
def test_dev_no_args_auto_discovery() -> None:
@@ -79,18 +85,27 @@ def test_dev_package() -> None:
7985
"log_config": get_uvicorn_log_config(),
8086
}
8187
assert "Using import string: nested_package.package:app" in result.output
82-
assert "Starting development server 🚀" in result.output
88+
if sys.platform == "win32":
89+
assert "Starting development server" in result.output
90+
else:
91+
assert "Starting development server 🚀" in result.output
8392
assert "Server started at http://127.0.0.1:8000" in result.output
8493
assert "Documentation at http://127.0.0.1:8000/docs" in result.output
8594
assert (
8695
"Running in development mode, for production use: fastapi run"
8796
in result.output
8897
)
8998

90-
assert "📁 package" in result.output
91-
assert "└── 🐍 __init__.py" in result.output
92-
assert "└── 📁 package" in result.output
93-
assert " └── 🐍 __init__.py" in result.output
99+
if sys.platform == "win32":
100+
assert "Folder package" in result.output
101+
assert "└── Python __init__.py" in result.output
102+
assert "└── Folder package" in result.output
103+
assert " └── Python __init__.py" in result.output
104+
else:
105+
assert "📁 package" in result.output
106+
assert "└── 🐍 __init__.py" in result.output
107+
assert "└── 📁 package" in result.output
108+
assert " └── 🐍 __init__.py" in result.output
94109

95110

96111
def test_dev_args() -> None:
@@ -128,7 +143,10 @@ def test_dev_args() -> None:
128143
"log_config": get_uvicorn_log_config(),
129144
}
130145
assert "Using import string: single_file_app:api" in result.output
131-
assert "Starting development server 🚀" in result.output
146+
if sys.platform == "win32":
147+
assert "Starting development server" in result.output
148+
else:
149+
assert "Starting development server 🚀" in result.output
132150
assert "Server started at http://192.168.0.2:8080" in result.output
133151
assert "Documentation at http://192.168.0.2:8080/docs" in result.output
134152
assert (
@@ -158,7 +176,10 @@ def test_dev_env_vars() -> None:
158176
"log_config": get_uvicorn_log_config(),
159177
}
160178
assert "Using import string: single_file_app:app" in result.output
161-
assert "Starting development server 🚀" in result.output
179+
if sys.platform == "win32":
180+
assert "Starting development server" in result.output
181+
else:
182+
assert "Starting development server 🚀" in result.output
162183
assert "Server started at http://127.0.0.1:8111" in result.output
163184
assert "Documentation at http://127.0.0.1:8111/docs" in result.output
164185
assert (
@@ -195,7 +216,10 @@ def test_dev_env_vars_and_args() -> None:
195216
"log_config": get_uvicorn_log_config(),
196217
}
197218
assert "Using import string: single_file_app:app" in result.output
198-
assert "Starting development server 🚀" in result.output
219+
if sys.platform == "win32":
220+
assert "Starting development server" in result.output
221+
else:
222+
assert "Starting development server 🚀" in result.output
199223
assert "Server started at http://127.0.0.1:8080" in result.output
200224
assert "Documentation at http://127.0.0.1:8080/docs" in result.output
201225
assert (
@@ -240,7 +264,10 @@ def test_run() -> None:
240264
"log_config": get_uvicorn_log_config(),
241265
}
242266
assert "Using import string: single_file_app:app" in result.output
243-
assert "Starting production server 🚀" in result.output
267+
if sys.platform == "win32":
268+
assert "Starting production server" in result.output
269+
else:
270+
assert "Starting production server 🚀" in result.output
244271
assert "Server started at http://0.0.0.0:8000" in result.output
245272
assert "Documentation at http://0.0.0.0:8000/docs" in result.output
246273

@@ -266,7 +293,10 @@ def test_run_trust_proxy() -> None:
266293
"log_config": get_uvicorn_log_config(),
267294
}
268295
assert "Using import string: single_file_app:app" in result.output
269-
assert "Starting production server 🚀" in result.output
296+
if sys.platform == "win32":
297+
assert "Starting production server" in result.output
298+
else:
299+
assert "Starting production server 🚀" in result.output
270300
assert "Server started at http://0.0.0.0:8000" in result.output
271301
assert "Documentation at http://0.0.0.0:8000/docs" in result.output
272302
assert (
@@ -313,7 +343,10 @@ def test_run_args() -> None:
313343
}
314344

315345
assert "Using import string: single_file_app:api" in result.output
316-
assert "Starting production server 🚀" in result.output
346+
if sys.platform == "win32":
347+
assert "Starting production server" in result.output
348+
else:
349+
assert "Starting production server 🚀" in result.output
317350
assert "Server started at http://192.168.0.2:8080" in result.output
318351
assert "Documentation at http://192.168.0.2:8080/docs" in result.output
319352
assert (
@@ -343,7 +376,10 @@ def test_run_env_vars() -> None:
343376
"log_config": get_uvicorn_log_config(),
344377
}
345378
assert "Using import string: single_file_app:app" in result.output
346-
assert "Starting production server 🚀" in result.output
379+
if sys.platform == "win32":
380+
assert "Starting production server" in result.output
381+
else:
382+
assert "Starting production server 🚀" in result.output
347383
assert "Server started at http://0.0.0.0:8111" in result.output
348384
assert "Documentation at http://0.0.0.0:8111/docs" in result.output
349385

@@ -376,7 +412,10 @@ def test_run_env_vars_and_args() -> None:
376412
"log_config": get_uvicorn_log_config(),
377413
}
378414
assert "Using import string: single_file_app:app" in result.output
379-
assert "Starting production server 🚀" in result.output
415+
if sys.platform == "win32":
416+
assert "Starting production server" in result.output
417+
else:
418+
assert "Starting production server 🚀" in result.output
380419
assert "Server started at http://0.0.0.0:8080" in result.output
381420
assert "Documentation at http://0.0.0.0:8080/docs" in result.output
382421

0 commit comments

Comments
 (0)