Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/cookiecutter_python/backend/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ def parse_context(config_file: str):
user_default_context = {}
user_interpreters = cook_json['interpreters']

context_defaults = dict(
cook_json,
**{k: v for k, v in user_default_context.items()},
**{k: v[0] for k, v in choices.items() if k not in user_default_context},
)
# Optimize: Build context_defaults in a single pass
context_defaults = dict(cook_json, **user_default_context)
for k, v in choices.items():
if k not in context_defaults:
context_defaults[k] = v[0]

# Render cookiecutter.json again with context to resolve derived fields
# This ensures derived fields like pkg_name get computed properly
template = env.get_template('cookiecutter.json')
# Optimize: Reuse template object instead of getting it again
rendered_with_context = template.render({'cookiecutter': context_defaults})
resolved_cook_json: t.Mapping[str, t.Any] = json.loads(rendered_with_context)

Expand Down
12 changes: 4 additions & 8 deletions src/cookiecutter_python/backend/hosting_services/extract_name.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,16 @@ def __call__(self, config_file: str) -> str:
try:
return self.name_extractor(context_data)
except KeyError as error:
# Optimize: Sort before converting to string, remove unnecessary indent and sort_keys
available_vars = ', '.join(str(x) for x in sorted(context_data.keys()))
raise ContextVariableDoesNotExist(
"{msg}: {data}".format(
msg="Attempted to retrieve non-existant variable",
msg="Attempted to retrieve non-existent variable",
data=json.dumps(
{
'variable_name': str(self.name_extractor),
'available_variables': '[{keys}]'.format(
keys=', '.join(
tuple(sorted([str(x) for x in context_data.keys()]))
),
),
'available_variables': f'[{available_vars}]',
},
indent=4,
sort_keys=True,
),
),
) from error
Expand Down
2 changes: 0 additions & 2 deletions src/cookiecutter_python/backend/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,4 @@ def log_info_args(message: str, *args, **kwargs) -> Tuple[str, str]:
'keyword_args': {k: str(v) for k, v in kwargs.items()},
'positional_args': [str(arg_value) for arg_value in args],
},
indent=4,
sort_keys=True,
)
6 changes: 3 additions & 3 deletions src/cookiecutter_python/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ def load(interface: t.Type[T], module: t.Optional[str] = None) -> t.List[t.Type[
'{package}.{module}'.format(package=dotted_lib_path, module=module_name)
)

for attribute_name in dir(module_object):
attribute = getattr(module_object, attribute_name)

# Optimize: Use vars() instead of dir() + getattr() for better performance
# Note: For module objects, vars() returns the same attributes as dir() (excluding builtins)
for attribute_name, attribute in vars(module_object).items():
if (
attribute != interface
and isclass(attribute)
Expand Down
Loading