Coverage for glotter/project.py: 100%
73 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-12 02:25 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-12 02:25 +0000
1# pylint hates pydantic
2# pylint: disable=E0213,E0611
3from typing import Dict, Optional, ClassVar
4from enum import Enum, auto
6from pydantic import BaseModel, validator, conlist, constr
8from glotter.auto_gen_test import AutoGenTest, AutoGenUseTests
11class NamingScheme(Enum):
12 hyphen = auto()
13 underscore = auto()
14 camel = auto()
15 pascal = auto()
16 lower = auto()
19class AcronymScheme(Enum):
20 lower = "lower"
21 upper = "upper"
22 two_letter_limit = "two_letter_limit"
25class Project(BaseModel):
26 VALID_REGEX: ClassVar[str] = "^[0-9a-zA-Z]+$"
28 words: conlist(constr(min_length=1, regex=VALID_REGEX, strict=True), min_items=1)
29 requires_parameters: bool = False
30 acronyms: conlist(constr(min_length=1, regex=VALID_REGEX, strict=True)) = []
31 acronym_scheme: AcronymScheme = AcronymScheme.two_letter_limit
32 use_tests: Optional[AutoGenUseTests] = None
33 tests: Dict[str, AutoGenTest] = {}
35 @validator("acronyms", pre=True, each_item=True)
36 def get_acronym(cls, value):
37 if not isinstance(value, str):
38 return value
40 return value.upper()
42 @validator("tests", pre=True)
43 def get_tests(cls, value, values):
44 if not isinstance(value, dict) or not all(
45 isinstance(test, dict) for test in value.values()
46 ):
47 return value
49 if values.get("use_tests"):
50 raise ValueError('"tests" and "use_tests" items are mutually exclusive')
52 return {
53 test_name: {
54 **test,
55 "requires_parameters": values.get("requires_parameters") or False,
56 "name": test_name,
57 }
58 for test_name, test in value.items()
59 }
61 def set_tests(self, project: "Project"):
62 """
63 If there is a "use_tests" item, then set the specified tests, renaming them
64 according to the "use_tests" item. The "use_tests" item is then removed
66 :params tests: Project with tests to use
67 """
69 if self.use_tests:
70 self.tests = {}
71 for test_name, test in project.tests.items():
72 test_name = test_name.replace(
73 self.use_tests.search, self.use_tests.replace
74 )
75 self.tests[test_name] = AutoGenTest(
76 **test.dict(exclude={"name"}), name=test_name
77 )
79 self.requires_parameters = project.requires_parameters
80 self.use_tests = None
82 @property
83 def display_name(self):
84 return self._as_display()
86 def get_project_name_by_scheme(self, naming):
87 """
88 gets a project name for a specific naming scheme
90 :param naming: the naming scheme
91 :return: the project type formatted by the directory's naming scheme
92 """
93 try:
94 return {
95 NamingScheme.hyphen: self._as_hyphen(),
96 NamingScheme.underscore: self._as_underscore(),
97 NamingScheme.camel: self._as_camel(),
98 NamingScheme.pascal: self._as_pascal(),
99 NamingScheme.lower: self._as_lower(),
100 }[naming]
101 except KeyError as e:
102 raise KeyError(f'Unknown naming scheme "{naming}"') from e
104 def _as_hyphen(self):
105 return "-".join(
106 self._try_as_acronym(word, NamingScheme.hyphen) for word in self.words
107 )
109 def _as_underscore(self):
110 return "_".join(
111 self._try_as_acronym(word, NamingScheme.underscore) for word in self.words
112 )
114 def _as_camel(self):
115 return self.words[0].lower() + "".join(
116 self._try_as_acronym(word.title(), NamingScheme.camel)
117 for word in self.words[1:]
118 )
120 def _as_pascal(self):
121 return "".join(
122 self._try_as_acronym(word.title(), NamingScheme.pascal)
123 for word in self.words
124 )
126 def _as_lower(self):
127 return "".join(word.lower() for word in self.words)
129 def _as_display(self):
130 return " ".join(
131 self._try_as_acronym(word.title(), NamingScheme.underscore)
132 for word in self.words
133 )
135 def _is_acronym(self, word):
136 return word.upper() in self.acronyms
138 def _try_as_acronym(self, word, naming_scheme):
139 if self._is_acronym(word):
140 if self.acronym_scheme == AcronymScheme.upper:
141 return word.upper()
142 elif self.acronym_scheme == AcronymScheme.lower:
143 return word.lower()
144 else:
145 if len(word) <= 2 and naming_scheme in [
146 NamingScheme.camel,
147 NamingScheme.pascal,
148 ]:
149 return word.upper()
151 return word