Skip to content

Commit f8ba75e

Browse files
committed
refactor: begin switch to templating class
1 parent dbfcf63 commit f8ba75e

3 files changed

Lines changed: 140 additions & 75 deletions

File tree

suap/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.1.0-alpha.1"
1+
__version__ = "0.1.0-alpha.2"

suap/commands/packaging/nsis.py

Lines changed: 72 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44
from typer import Exit
55
from pathlib import Path
66

7-
# just so we can get the root path of our library
8-
import suap
9-
107
from ...mime_type import MimeType
118
from ...projects import ProjectData
129
from ...formats import make_nsis_installer
10+
from ...templating import Template, Key
1311

1412
__all__ = (
1513
"format_config_and_make_nsis_installer",
@@ -38,56 +36,62 @@ def format_config_and_make_nsis_installer(
3836
temp_folder_path.mkdir(exist_ok = True)
3937
nsis_installer_script_path = temp_folder_path.joinpath("nsis_installer.nsi")
4038

41-
templates_path = Path(suap.__file__).parent.joinpath("templates")
42-
installer_script_template_path = templates_path.joinpath("nsis_installer_script.nsi")
39+
installer_script_template = Template("nsis_installer_script.nsi")
4340

44-
logger.debug(
45-
f"Opening and reading NSIS template installer script at '{installer_script_template_path}'..."
46-
)
41+
semver = project_data.version
4742

48-
with open(installer_script_template_path, mode = "r") as file:
49-
installer_script_string = file.read()
43+
binary_name_key = Key(name = "binary-name", value = binary_name)
5044

51-
logger.debug("Formatting template and creating custom install script...")
45+
display_name_key = Key(
46+
name = "display-name",
47+
value = display_name if display_name is not None else project_data.name
48+
)
5249

53-
semver = project_data.version
54-
display_name = display_name if display_name is not None else project_data.name
55-
56-
replace_map: dict[str, str] = {
57-
"suap-binary-name": binary_name,
58-
"suap-binary-path": str(binary_path.absolute()),
59-
"suap-binary-dist-path": str(binary_dist_path.absolute()),
60-
"suap-display-name": display_name,
61-
"suap-icon-path": str(icon_path.absolute()),
62-
"suap-icon-file-name": icon_path.name,
63-
64-
"suap-project-name": project_data.name,
65-
"suap-project-version": f"{semver.major}.{semver.minor}.{semver.patch}" \
66-
f".{semver.prerelease.split('.')[-1] if semver.prerelease is not None else 0}",
67-
"suap-project-description": project_data.description,
68-
69-
"suap-app-capabilities-macro": generate_app_capabilities_macro(
70-
mime_types,
71-
templates_path,
72-
binary_name,
73-
display_name,
74-
icon_path,
75-
project_data,
76-
uninstall = False,
77-
),
78-
"suap-app-capabilities-uni-macro": generate_app_capabilities_macro(
79-
mime_types,
80-
templates_path,
81-
binary_name,
82-
display_name,
83-
icon_path,
84-
project_data,
85-
uninstall = True,
86-
),
87-
}
88-
89-
for (suap_key, value) in replace_map.items():
90-
installer_script_string = installer_script_string.replace(f"{{{suap_key}}}", value)
50+
icon_file_name_key = Key(name = "icon-file-name", value = icon_path.name)
51+
52+
installer_script_string = installer_script_template.format(
53+
keys = (
54+
binary_name_key,
55+
Key(name = "binary-path", value = str(binary_path.absolute())),
56+
Key(name = "binary-dist-path", value = str(binary_dist_path.absolute())),
57+
58+
display_name_key,
59+
60+
Key(name = "icon-path", value = str(icon_path.absolute())),
61+
icon_file_name_key,
62+
63+
Key(name = "project-name", value = project_data.name),
64+
Key(
65+
name = "project-version",
66+
value = f"{semver.major}.{semver.minor}.{semver.patch}" \
67+
f".{semver.prerelease.split('.')[-1] if semver.prerelease is not None else 0}"
68+
),
69+
Key(name = "project-description", value = project_data.description),
70+
71+
Key(
72+
name = "app-capabilities-macro",
73+
value = generate_app_capabilities_macro(
74+
mime_types,
75+
binary_name_key,
76+
display_name_key,
77+
icon_file_name_key,
78+
project_data,
79+
uninstall = False,
80+
)
81+
),
82+
Key(
83+
name = "app-capabilities-uni-macro",
84+
value = generate_app_capabilities_macro(
85+
mime_types,
86+
binary_name_key,
87+
display_name_key,
88+
icon_file_name_key,
89+
project_data,
90+
uninstall = True,
91+
)
92+
),
93+
)
94+
)
9195

9296
logger.debug(
9397
f"Creating and writing to custom NSIS installer script at '{nsis_installer_script_path}'..."
@@ -103,22 +107,21 @@ def format_config_and_make_nsis_installer(
103107

104108
def generate_app_capabilities_macro(
105109
mime_types: list[MimeType],
106-
templates_path: Path,
107-
binary_name: str,
108-
display_name: str,
109-
icon_path: Path,
110+
binary_name_key: Key,
111+
display_name_key: Key,
112+
icon_file_name_key: Key,
110113
project_data: ProjectData,
111114
uninstall: bool,
112115
) -> str:
113116
if len(mime_types) == 0:
114117
return ""
115118

116-
app_capabilities_template_path = templates_path.joinpath(
117-
"nsis_app_capabilities_uni_macro.nsi" if uninstall else "nsis_app_capabilities_macro.nsi"
118-
)
119+
template_name = "nsis_app_capabilities_macro.nsi"
120+
121+
if uninstall:
122+
template_name = "nsis_app_capabilities_uni_macro.nsi"
119123

120-
with open(app_capabilities_template_path, mode = "r") as file:
121-
app_capabilities_macro_string = file.read()
124+
app_capabilities_template = Template(template_name)
122125

123126
file_associations_and_types_lines = []
124127

@@ -133,7 +136,7 @@ def generate_app_capabilities_macro(
133136

134137
if not uninstall:
135138
file_associations_and_types_lines.append(
136-
f'WriteRegStr HKCR "Applications\\{binary_name}.exe\\SupportedTypes" "{file_extension}" ""'
139+
f'WriteRegStr HKCR "Applications\\{binary_name_key.name}.exe\\SupportedTypes" "{file_extension}" ""'
137140
)
138141

139142
file_associations_and_types_lines.append(
@@ -146,28 +149,23 @@ def generate_app_capabilities_macro(
146149

147150
else:
148151
file_associations_and_types_lines.append(
149-
f'DeleteRegValue HKCR "Applications\\{binary_name}.exe\\SupportedTypes" "{file_extension}"'
152+
f'DeleteRegValue HKCR "Applications\\{binary_name_key.name}.exe\\SupportedTypes" "{file_extension}"'
150153
)
151154

152155
file_associations_and_types_lines.append(
153156
f'DeleteRegValue HKCR "{file_extension}\\OpenWithProgIds" "Cloudy.{project_name}.1"'
154157
)
155158

156-
replace_map: dict[str, str] = {
157-
"suap-binary-name": binary_name,
158-
"suap-display-name": display_name,
159-
"suap-icon-file-name": icon_path.name,
160-
161-
"suap-project-name": project_data.name,
162-
"suap-project-description": project_data.description,
163-
164-
"suap-file-associations-and-types-macro": "\n".join(file_associations_and_types_lines),
165-
}
166-
167-
for (suap_key, value) in replace_map.items():
168-
app_capabilities_macro_string = app_capabilities_macro_string.replace(
169-
f"{{{suap_key}}}", value
159+
app_capabilities_macro_string = app_capabilities_template.format(
160+
keys = (
161+
binary_name_key,
162+
display_name_key,
163+
icon_file_name_key,
164+
Key("project-name", project_data.name),
165+
Key("project-description", project_data.description),
166+
Key("file-associations-and-types-macro", value = "\n".join(file_associations_and_types_lines)),
170167
)
168+
)
171169

172170
formatted_macro_string = "".join([
173171
f" {line}" for line in app_capabilities_macro_string.splitlines(keepends = True)

suap/templating.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import re
2+
import logging
3+
from pathlib import Path
4+
from dataclasses import dataclass
5+
6+
__all__ = ()
7+
8+
logger = logging.getLogger(__name__)
9+
10+
@dataclass
11+
class Key:
12+
name: str
13+
value: str
14+
15+
class TemplateKeysRemainingError(Exception):
16+
def __init__(self, remaining_keys: set[str]):
17+
super().__init__(
18+
"There are keys defined in the template " \
19+
f"that were not formatted! Remaining Keys: {remaining_keys}"
20+
)
21+
22+
class Template():
23+
def __init__(self, template_name: str):
24+
self.__template_string = self.__get_template_contents(template_name)
25+
26+
# NOTE: Help improving this would be cool, I'm not good at regex
27+
defined_suap_keys_list = re.findall(
28+
"{suap-(.*?)}", self.__template_string, re.DOTALL
29+
)
30+
31+
self.__defined_suap_keys: set[str] = set(defined_suap_keys_list)
32+
33+
print(f"--> {self.__defined_suap_keys}")
34+
35+
def format(self, keys: tuple[Key, ...]) -> str:
36+
formatted_string = self.__template_string
37+
38+
remaining_keys = self.__defined_suap_keys
39+
40+
for key in keys:
41+
key_name = key.name
42+
43+
if key_name in remaining_keys:
44+
logger.debug(f"Formatting template key '{key_name}'...")
45+
46+
remaining_keys.remove(key_name)
47+
48+
formatted_string.replace(
49+
f"{{suap-{key_name}}}", str(key.value)
50+
)
51+
52+
if len(remaining_keys) > 0:
53+
raise TemplateKeysRemainingError(remaining_keys)
54+
55+
return formatted_string
56+
57+
def __get_template_contents(self, template_name: str) -> str:
58+
specific_template_path = Path(__file__).parent.joinpath("templates", template_name)
59+
60+
logger.debug(
61+
f"Opening and reading '{template_name}' template at '{specific_template_path}'..."
62+
)
63+
64+
with open(specific_template_path, mode = "r") as file:
65+
template_contents = file.read()
66+
67+
return template_contents

0 commit comments

Comments
 (0)