Coverage for glotter/project.py: 100%
73 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-09-13 19:09 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-09-13 19:09 +0000
1from enum import Enum, auto
2from typing import ClassVar, Dict, Optional
4from pydantic import BaseModel, conlist, constr, validator
6from glotter.auto_gen_test import AutoGenTest, AutoGenUseTests
9class NamingScheme(Enum):
10 hyphen = auto()
11 underscore = auto()
12 camel = auto()
13 pascal = auto()
14 lower = auto()
17class AcronymScheme(Enum):
18 lower = "lower"
19 upper = "upper"
20 two_letter_limit = "two_letter_limit"
23class Project(BaseModel):
24 VALID_REGEX: ClassVar[str] = "^[0-9a-zA-Z]+$"
26 words: conlist(constr(min_length=1, regex=VALID_REGEX, strict=True), min_items=1)
27 requires_parameters: bool = False
28 acronyms: conlist(constr(min_length=1, regex=VALID_REGEX, strict=True)) = []
29 acronym_scheme: AcronymScheme = AcronymScheme.two_letter_limit
30 use_tests: Optional[AutoGenUseTests] = None
31 tests: Dict[str, AutoGenTest] = {}
33 @validator("acronyms", pre=True, each_item=True)
34 def get_acronym(cls, value):
35 if not isinstance(value, str):
36 return value
38 return value.upper()
40 @validator("tests", pre=True)
41 def get_tests(cls, value, values):
42 if not isinstance(value, dict) or not all(
43 isinstance(test, dict) for test in value.values()
44 ):
45 return value
47 if values.get("use_tests"):
48 raise ValueError('"tests" and "use_tests" items are mutually exclusive')
50 return {
51 test_name: {
52 **test,
53 "requires_parameters": values.get("requires_parameters") or False,
54 "name": test_name,
55 }
56 for test_name, test in value.items()
57 }
59 def set_tests(self, project: "Project"):
60 """
61 If there is a "use_tests" item, then set the specified tests, renaming them
62 according to the "use_tests" item. The "use_tests" item is then removed
64 :params tests: Project with tests to use
65 """
67 if self.use_tests:
68 self.tests = {}
69 for test_name_, test in project.tests.items():
70 test_name = test_name_.replace(self.use_tests.search, self.use_tests.replace)
71 self.tests[test_name] = AutoGenTest(**test.dict(exclude={"name"}), name=test_name)
73 self.requires_parameters = project.requires_parameters
74 self.use_tests = None
76 @property
77 def display_name(self):
78 return self._as_display()
80 def get_project_name_by_scheme(self, naming):
81 """
82 gets a project name for a specific naming scheme
84 :param naming: the naming scheme
85 :return: the project type formatted by the directory's naming scheme
86 """
87 try:
88 return {
89 NamingScheme.hyphen: self._as_hyphen(),
90 NamingScheme.underscore: self._as_underscore(),
91 NamingScheme.camel: self._as_camel(),
92 NamingScheme.pascal: self._as_pascal(),
93 NamingScheme.lower: self._as_lower(),
94 }[naming]
95 except KeyError as e:
96 raise KeyError(f'Unknown naming scheme "{naming}"') from e
98 def _as_hyphen(self):
99 return "-".join(self._try_as_acronym(word, NamingScheme.hyphen) for word in self.words)
101 def _as_underscore(self):
102 return "_".join(self._try_as_acronym(word, NamingScheme.underscore) for word in self.words)
104 def _as_camel(self):
105 return self.words[0].lower() + "".join(
106 self._try_as_acronym(word.title(), NamingScheme.camel) for word in self.words[1:]
107 )
109 def _as_pascal(self):
110 return "".join(
111 self._try_as_acronym(word.title(), NamingScheme.pascal) for word in self.words
112 )
114 def _as_lower(self):
115 return "".join(word.lower() for word in self.words)
117 def _as_display(self):
118 return " ".join(
119 self._try_as_acronym(word.title(), NamingScheme.underscore) for word in self.words
120 )
122 def _is_acronym(self, word):
123 return word.upper() in self.acronyms
125 def _try_as_acronym(self, word, naming_scheme):
126 if self._is_acronym(word):
127 if self.acronym_scheme == AcronymScheme.upper:
128 return word.upper()
129 elif self.acronym_scheme == AcronymScheme.lower:
130 return word.lower()
131 elif len(word) <= 2 and naming_scheme in [
132 NamingScheme.camel,
133 NamingScheme.pascal,
134 ]:
135 return word.upper()
137 return word