Skip to content

Commit 57b37d8

Browse files
committed
global language config
1 parent bcdb0ef commit 57b37d8

15 files changed

Lines changed: 221 additions & 76 deletions

codeflash/api/aiservice.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from codeflash.code_utils.env_utils import get_codeflash_api_key
1515
from codeflash.code_utils.git_utils import get_last_commit_author_if_pr_exists, get_repo_owner_and_name
1616
from codeflash.code_utils.time_utils import humanize_runtime
17+
from codeflash.languages import is_javascript, is_python
1718
from codeflash.models.ExperimentMetadata import ExperimentMetadata
1819
from codeflash.models.models import (
1920
AIServiceRefinerRequest,
@@ -178,7 +179,7 @@ def optimize_code( # noqa: D417
178179
# Add language-specific version fields
179180
# Always include python_version for backward compatibility with older backend
180181
payload["python_version"] = platform.python_version()
181-
if language == "python":
182+
if is_python():
182183
pass # python_version already set
183184
else:
184185
payload["language_version"] = language_version or "ES2022"
@@ -432,7 +433,7 @@ def optimize_code_refinement(self, request: list[AIServiceRefinerRequest]) -> li
432433

433434
# Add language version - always include python_version for backward compatibility
434435
item["python_version"] = platform.python_version()
435-
if opt.language == "python":
436+
if is_python():
436437
pass # python_version already set
437438
elif opt.language_version:
438439
item["language_version"] = opt.language_version
@@ -752,11 +753,11 @@ def generate_regression_tests( # noqa: D417
752753
# Validate test framework based on language
753754
python_frameworks = ["pytest", "unittest"]
754755
javascript_frameworks = ["jest", "mocha", "vitest"]
755-
if language == "python":
756+
if is_python():
756757
assert test_framework in python_frameworks, (
757758
f"Invalid test framework for Python, got {test_framework} but expected one of {python_frameworks}"
758759
)
759-
elif language in ("javascript", "typescript"):
760+
elif is_javascript():
760761
assert test_framework in javascript_frameworks, (
761762
f"Invalid test framework for JavaScript, got {test_framework} but expected one of {javascript_frameworks}"
762763
)
@@ -781,7 +782,7 @@ def generate_regression_tests( # noqa: D417
781782
# Add language-specific version fields
782783
# Always include python_version for backward compatibility with older backend
783784
payload["python_version"] = platform.python_version()
784-
if language == "python":
785+
if is_python():
785786
pass # python_version already set
786787
else:
787788
payload["language_version"] = language_version or "ES2022"
@@ -873,7 +874,7 @@ def get_optimization_review(
873874
"codeflash_version": codeflash_version,
874875
"calling_fn_details": calling_fn_details,
875876
"language": language,
876-
"python_version": platform.python_version() if language == "python" else None,
877+
"python_version": platform.python_version() if is_python() else None,
877878
"call_sequence": self.get_next_sequence(),
878879
}
879880
console.rule()

codeflash/code_utils/code_replacer.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from codeflash.code_utils.config_parser import find_conftest_files
1919
from codeflash.code_utils.formatter import sort_imports
2020
from codeflash.code_utils.line_profile_utils import ImportAdder
21+
from codeflash.languages import is_python
2122
from codeflash.models.models import FunctionParent
2223

2324
if TYPE_CHECKING:
@@ -445,7 +446,7 @@ def replace_function_definitions_in_module(
445446
function_to_optimize: Optional[FunctionToOptimize] = None,
446447
) -> bool:
447448
# Route to language-specific implementation for non-Python languages
448-
if optimized_code.language and optimized_code.language != "python":
449+
if not is_python():
449450
return replace_function_definitions_for_language(
450451
function_names, optimized_code, module_abspath, project_root_path, function_to_optimize
451452
)

codeflash/code_utils/deduplicate_code.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from typing import TYPE_CHECKING
1212

1313
from codeflash.code_utils.normalizers import get_normalizer
14+
from codeflash.languages import current_language, is_python
1415

1516
if TYPE_CHECKING:
1617
pass
@@ -20,7 +21,7 @@ def normalize_code(
2021
code: str,
2122
remove_docstrings: bool = True, # noqa: FBT001, FBT002
2223
return_ast_dump: bool = False, # noqa: FBT001, FBT002
23-
language: str = "python",
24+
language: str | None = None,
2425
) -> str:
2526
"""Normalize code by parsing, cleaning, and normalizing variable names.
2627
@@ -30,16 +31,19 @@ def normalize_code(
3031
code: Source code as string
3132
remove_docstrings: Whether to remove docstrings (Python only)
3233
return_ast_dump: Return AST dump instead of unparsed code (Python only)
33-
language: Language of the code ('python', 'javascript', 'typescript')
34+
language: Language of the code. If None, uses the current session language.
3435
3536
Returns:
3637
Normalized code as string
3738
"""
39+
if language is None:
40+
language = current_language().value
41+
3842
try:
3943
normalizer = get_normalizer(language)
4044

4145
# Python has additional options
42-
if language == "python":
46+
if is_python():
4347
if return_ast_dump:
4448
return normalizer.normalize_for_hash(code)
4549
return normalizer.normalize(code, remove_docstrings=remove_docstrings)
@@ -51,7 +55,7 @@ def normalize_code(
5155
return _basic_normalize(code)
5256
except Exception:
5357
# Parsing error - try other languages or fall back
54-
if language == "python":
58+
if is_python():
5559
# Try JavaScript as fallback
5660
try:
5761
js_normalizer = get_normalizer("javascript")
@@ -76,16 +80,19 @@ def _basic_normalize(code: str) -> str:
7680
return " ".join(code.split())
7781

7882

79-
def get_code_fingerprint(code: str, language: str = "python") -> str:
83+
def get_code_fingerprint(code: str, language: str | None = None) -> str:
8084
"""Generate a fingerprint for normalized code.
8185
8286
Args:
8387
code: Source code
84-
language: Language of the code ('python', 'javascript', 'typescript')
88+
language: Language of the code. If None, uses the current session language.
8589
8690
Returns:
8791
SHA-256 hash of normalized code
8892
"""
93+
if language is None:
94+
language = current_language().value
95+
8996
try:
9097
normalizer = get_normalizer(language)
9198
return normalizer.get_fingerprint(code)
@@ -95,17 +102,20 @@ def get_code_fingerprint(code: str, language: str = "python") -> str:
95102
return hashlib.sha256(normalized.encode()).hexdigest()
96103

97104

98-
def are_codes_duplicate(code1: str, code2: str, language: str = "python") -> bool:
105+
def are_codes_duplicate(code1: str, code2: str, language: str | None = None) -> bool:
99106
"""Check if two code segments are duplicates after normalization.
100107
101108
Args:
102109
code1: First code segment
103110
code2: Second code segment
104-
language: Language of the code ('python', 'javascript', 'typescript')
111+
language: Language of the code. If None, uses the current session language.
105112
106113
Returns:
107114
True if codes are structurally identical (ignoring local variable names)
108115
"""
116+
if language is None:
117+
language = current_language().value
118+
109119
try:
110120
normalizer = get_normalizer(language)
111121
return normalizer.are_duplicates(code1, code2)

codeflash/context/code_context_extractor.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from codeflash.discovery.functions_to_optimize import FunctionToOptimize # noqa: TC001
2424

2525
# Language support imports for multi-language code context extraction
26+
from codeflash.languages import is_python
2627
from codeflash.languages.base import Language
2728
from codeflash.models.models import (
2829
CodeContextType,
@@ -79,7 +80,7 @@ def get_code_optimization_context(
7980
testgen_token_limit: int = TESTGEN_CONTEXT_TOKEN_LIMIT,
8081
) -> CodeOptimizationContext:
8182
# Route to language-specific implementation for non-Python languages
82-
if function_to_optimize.language and function_to_optimize.language != "python":
83+
if not is_python():
8384
return get_code_optimization_context_for_language(
8485
function_to_optimize, project_root_path, optim_token_limit, testgen_token_limit
8586
)

codeflash/context/unused_definition_remover.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
from codeflash.cli_cmds.console import logger
1313
from codeflash.code_utils.code_replacer import replace_function_definitions_in_module
14+
from codeflash.languages import is_javascript
1415
from codeflash.models.models import CodeString, CodeStringsMarkdown
1516

1617
if TYPE_CHECKING:
@@ -717,7 +718,7 @@ def detect_unused_helper_functions(
717718
718719
"""
719720
# Skip this analysis for non-Python languages since we use Python's ast module
720-
if function_to_optimize.language in ("javascript", "typescript"):
721+
if is_javascript():
721722
logger.debug("Skipping unused helper function detection for JavaScript/TypeScript")
722723
return []
723724

codeflash/discovery/discover_unit_tests.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
module_name_from_file_path,
2929
)
3030
from codeflash.code_utils.compat import SAFE_SYS_EXECUTABLE, codeflash_cache_db
31+
from codeflash.languages import is_javascript, is_python
3132
from codeflash.code_utils.shell_utils import get_cross_platform_subprocess_run_args
3233
from codeflash.models.models import CodePosition, FunctionCalledInTest, TestsInFile, TestType
3334

@@ -659,10 +660,10 @@ def discover_unit_tests(
659660
language = _detect_language_from_functions(file_to_funcs_to_optimize)
660661

661662
# Route to language-specific test discovery for non-Python languages
662-
if language and language != "python":
663+
if not is_python():
663664
# For JavaScript/TypeScript, tests_project_rootdir should be tests_root itself
664665
# The Jest helper will be configured to NOT include "tests." prefix to match
665-
if language in ("javascript", "typescript"):
666+
if is_javascript():
666667
cfg.tests_project_rootdir = cfg.tests_root
667668
return discover_tests_for_language(cfg, language, file_to_funcs_to_optimize)
668669

codeflash/languages/__init__.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@
2828
TestInfo,
2929
TestResult,
3030
)
31+
from codeflash.languages.current import (
32+
current_language,
33+
current_language_support,
34+
is_javascript,
35+
is_python,
36+
is_typescript,
37+
reset_current_language,
38+
set_current_language,
39+
)
3140
from codeflash.languages.registry import (
3241
detect_project_language,
3342
get_language_support,
@@ -43,18 +52,26 @@
4352

4453
__all__ = [
4554
# Base types
55+
"CodeContext",
56+
"FunctionInfo",
57+
"HelperFunction",
4658
"Language",
4759
"LanguageSupport",
48-
"FunctionInfo",
4960
"ParentInfo",
50-
"CodeContext",
51-
"HelperFunction",
52-
"TestResult",
5361
"TestInfo",
62+
"TestResult",
63+
# Current language singleton
64+
"current_language",
65+
"current_language_support",
66+
"is_javascript",
67+
"is_python",
68+
"is_typescript",
69+
"reset_current_language",
70+
"set_current_language",
5471
# Registry functions
55-
"get_language_support",
5672
"detect_project_language",
57-
"register_language",
58-
"get_supported_languages",
73+
"get_language_support",
5974
"get_supported_extensions",
75+
"get_supported_languages",
76+
"register_language",
6077
]

codeflash/languages/current.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
"""Singleton for the current language being used in the codeflash session.
2+
3+
This module provides a centralized way to access and set the current language
4+
throughout the codeflash codebase, eliminating scattered language checks and
5+
string comparisons.
6+
7+
Usage:
8+
from codeflash.languages import current_language, set_current_language, is_python
9+
10+
# Set the language at the start of a session
11+
set_current_language(Language.PYTHON)
12+
# or
13+
set_current_language("javascript")
14+
15+
# Check the current language anywhere in the codebase
16+
if is_python():
17+
# Python-specific code
18+
...
19+
20+
# Get the current language
21+
lang = current_language()
22+
23+
# Get language support for the current language
24+
support = current_language_support()
25+
"""
26+
27+
from __future__ import annotations
28+
29+
from typing import TYPE_CHECKING
30+
31+
from codeflash.languages.base import Language
32+
33+
if TYPE_CHECKING:
34+
from codeflash.languages.base import LanguageSupport
35+
36+
# Module-level singleton for the current language
37+
_current_language: Language = Language.PYTHON
38+
39+
40+
def current_language() -> Language:
41+
"""Get the current language being used in this codeflash session.
42+
43+
Returns:
44+
The current Language enum value.
45+
"""
46+
return _current_language
47+
48+
49+
def set_current_language(language: Language | str) -> None:
50+
"""Set the current language for this codeflash session.
51+
52+
This should be called once at the start of an optimization run,
53+
typically after reading the project configuration.
54+
55+
Args:
56+
language: Either a Language enum value or a string like "python", "javascript", "typescript".
57+
"""
58+
global _current_language
59+
60+
if isinstance(language, str):
61+
_current_language = Language(language)
62+
else:
63+
_current_language = language
64+
65+
66+
def reset_current_language() -> None:
67+
"""Reset the current language to the default (Python).
68+
69+
Useful for testing or when starting a new session.
70+
"""
71+
global _current_language
72+
_current_language = Language.PYTHON
73+
74+
75+
def is_python() -> bool:
76+
"""Check if the current language is Python.
77+
78+
Returns:
79+
True if the current language is Python.
80+
"""
81+
return _current_language == Language.PYTHON
82+
83+
84+
def is_javascript() -> bool:
85+
"""Check if the current language is JavaScript or TypeScript.
86+
87+
This returns True for both JavaScript and TypeScript since they are
88+
typically treated the same way in the optimization pipeline.
89+
90+
Returns:
91+
True if the current language is JavaScript or TypeScript.
92+
"""
93+
return _current_language in (Language.JAVASCRIPT, Language.TYPESCRIPT)
94+
95+
96+
def is_typescript() -> bool:
97+
"""Check if the current language is TypeScript specifically.
98+
99+
Returns:
100+
True if the current language is TypeScript.
101+
"""
102+
return _current_language == Language.TYPESCRIPT
103+
104+
105+
def current_language_support() -> LanguageSupport:
106+
"""Get the LanguageSupport instance for the current language.
107+
108+
Returns:
109+
The LanguageSupport instance for the current language.
110+
"""
111+
from codeflash.languages.registry import get_language_support
112+
113+
return get_language_support(_current_language)

0 commit comments

Comments
 (0)