Skip to content

Commit bc1b396

Browse files
committed
Implemented a CompilerVersion type to mimic the existing wrapper in swift_build_support and return a more detailed object from ClangVersionType and SwiftVersionType.
1 parent 26b6c4d commit bc1b396

File tree

5 files changed

+166
-15
lines changed

5 files changed

+166
-15
lines changed

utils/build_swift/argparse/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323

2424
from .actions import Action, Nargs
2525
from .parser import ArgumentParser
26-
from .types import (BoolType, ClangVersionType, PathType, RegexType,
27-
ShellSplitType, SwiftVersionType)
26+
from .types import (BoolType, ClangVersionType, CompilerVersion, PathType,
27+
RegexType, ShellSplitType, SwiftVersionType)
2828

2929

3030
__all__ = [
@@ -39,6 +39,7 @@
3939
'RawDescriptionHelpFormatter',
4040
'RawTextHelpFormatter',
4141

42+
'CompilerVersion',
4243
'BoolType',
4344
'FileType',
4445
'PathType',

utils/build_swift/argparse/types.py

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222

2323
__all__ = [
24+
'CompilerVersion',
25+
2426
'BoolType',
2527
'PathType',
2628
'RegexType',
@@ -32,6 +34,44 @@
3234

3335
# -----------------------------------------------------------------------------
3436

37+
class CompilerVersion(object):
38+
"""Wrapper type around compiler version strings.
39+
"""
40+
41+
def __init__(self, *components):
42+
if len(components) == 1:
43+
if isinstance(components[0], str):
44+
components = components[0].split('.')
45+
elif isinstance(components[0], list):
46+
components = tuple(components[0])
47+
elif isinstance(components[0], tuple):
48+
components = components[0]
49+
50+
if len(components) == 0:
51+
raise ValueError('compiler version cannot be empty')
52+
53+
self.components = tuple(int(part) for part in components)
54+
55+
def __eq__(self, other):
56+
return self.components == other.components
57+
58+
def __str__(self):
59+
return '.'.join([str(part) for part in self.components])
60+
61+
62+
# -----------------------------------------------------------------------------
63+
64+
def _repr(cls, args):
65+
"""Helper function for implementing __repr__ methods on *Type classes.
66+
"""
67+
68+
_args = []
69+
for key, value in args.viewitems():
70+
_args.append('{}={}'.format(key, repr(value)))
71+
72+
return '{}({})'.format(type(cls).__name__, ', '.join(_args))
73+
74+
3575
class BoolType(object):
3676
"""Argument type used to validate an input string as a bool-like type.
3777
Callers are able to override valid true and false values.
@@ -55,6 +95,12 @@ def __call__(self, value):
5595
else:
5696
raise ArgumentTypeError('{} is not a boolean value'.format(value))
5797

98+
def __repr__(self):
99+
return _repr(self, {
100+
'true_values': self._true_values,
101+
'false_values': self._false_values,
102+
})
103+
58104

59105
class PathType(object):
60106
"""PathType denotes a valid path-like object. When called paths will be
@@ -63,25 +109,28 @@ class PathType(object):
63109
"""
64110

65111
def __init__(self, assert_exists=False, assert_executable=False):
66-
if assert_executable:
67-
assert_exists = True
68-
69-
self.assert_exists = assert_exists
70-
self.assert_executable = assert_executable
112+
self._assert_exists = assert_exists
113+
self._assert_executable = assert_executable
71114

72115
def __call__(self, path):
73116
path = os.path.expanduser(path)
74117
path = os.path.abspath(path)
75118
path = os.path.realpath(path)
76119

77-
if self.assert_exists and not os.path.exists(path):
120+
if self._assert_exists and not os.path.exists(path):
78121
raise ArgumentTypeError('{} does not exists'.format(path))
79122

80-
if self.assert_executable and not PathType._is_executable(path):
123+
if self._assert_executable and not PathType._is_executable(path):
81124
raise ArgumentTypeError('{} is not an executable'.format(path))
82125

83126
return path
84127

128+
def __repr__(self):
129+
return _repr(self, {
130+
'assert_exists': self._assert_exists,
131+
'assert_executable': self._assert_executable,
132+
})
133+
85134
@staticmethod
86135
def _is_executable(path):
87136
return os.path.isfile(path) and os.access(path, os.X_OK)
@@ -101,7 +150,13 @@ def __call__(self, value):
101150
if matches is None:
102151
raise ArgumentTypeError(self._error_message, value)
103152

104-
return value
153+
return matches
154+
155+
def __repr__(self):
156+
return _repr(self, {
157+
'regex': self._regex,
158+
'error_message': self._error_message,
159+
})
105160

106161

107162
class ClangVersionType(RegexType):
@@ -118,6 +173,12 @@ def __init__(self):
118173
ClangVersionType.VERSION_REGEX,
119174
ClangVersionType.ERROR_MESSAGE)
120175

176+
def __call__(self, value):
177+
matches = super(ClangVersionType, self).__call__(value)
178+
components = filter(None, matches.group(1, 2, 3, 5))
179+
180+
return CompilerVersion(components)
181+
121182

122183
class SwiftVersionType(RegexType):
123184
"""Argument type used to validate Swift version strings.
@@ -132,6 +193,12 @@ def __init__(self):
132193
SwiftVersionType.VERSION_REGEX,
133194
SwiftVersionType.ERROR_MESSAGE)
134195

196+
def __call__(self, value):
197+
matches = super(SwiftVersionType, self).__call__(value)
198+
components = filter(None, matches.group(1, 2, 4))
199+
200+
return CompilerVersion(components)
201+
135202

136203
class ShellSplitType(object):
137204
"""Parse and split shell arguments into a list of strings. Recognizes `,`
@@ -151,3 +218,6 @@ def __call__(self, value):
151218
lex.whitespace_split = True
152219
lex.whitespace += ','
153220
return list(lex)
221+
222+
def __repr__(self):
223+
return _repr(self, {})

utils/build_swift/defaults.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@
66
# See http://swift.org/LICENSE.txt for license information
77
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
88

9+
910
"""
1011
Default option value definitions.
1112
"""
1213

14+
15+
from .argparse import CompilerVersion
16+
17+
1318
__all__ = [
1419
# Command line configuarable
1520
'BUILD_VARIANT',
@@ -35,8 +40,8 @@
3540
CMAKE_GENERATOR = 'Ninja'
3641

3742
COMPILER_VENDOR = 'none'
38-
SWIFT_USER_VISIBLE_VERSION = '4.1'
39-
CLANG_USER_VISIBLE_VERSION = '5.0.0'
43+
SWIFT_USER_VISIBLE_VERSION = CompilerVersion('4.1')
44+
CLANG_USER_VISIBLE_VERSION = CompilerVersion('5.0.0')
4045
SWIFT_ANALYZE_CODE_COVERAGE = 'false'
4146

4247
DARWIN_XCRUN_TOOLCHAIN = 'default'

utils/build_swift/tests/argparse/test_types.py

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,66 @@
1515

1616
# -----------------------------------------------------------------------------
1717

18+
class TestCompilerVersion(TestCase):
19+
20+
def test_init_valid_value(self):
21+
version = types.CompilerVersion(1, 0, 0, 1)
22+
self.assertEqual(version.components, (1, 0, 0, 1))
23+
24+
def test_init_list(self):
25+
version = types.CompilerVersion([1, 0, 0])
26+
self.assertEqual(version.components, (1, 0, 0))
27+
28+
with self.assertNotRaises(ValueError):
29+
types.CompilerVersion([1, 0])
30+
types.CompilerVersion([2, 3, 4])
31+
types.CompilerVersion([3, 1, 4, 1, 5, 9])
32+
33+
def test_init_tuple(self):
34+
version = types.CompilerVersion((1, 0, 0))
35+
self.assertEqual(version.components, (1, 0, 0))
36+
37+
with self.assertNotRaises(ValueError):
38+
types.CompilerVersion((1, 0))
39+
types.CompilerVersion((2, 3, 4))
40+
types.CompilerVersion((3, 1, 4, 1, 5, 9))
41+
42+
def test_init_str(self):
43+
version = types.CompilerVersion('1.0.0')
44+
self.assertEqual(version.components, (1, 0, 0))
45+
46+
with self.assertNotRaises(ValueError):
47+
types.CompilerVersion('1.0')
48+
types.CompilerVersion('2.3.4')
49+
types.CompilerVersion('3.1.4.1.5.9')
50+
51+
def test_init_invalid_value(self):
52+
with self.assertRaises(ValueError):
53+
types.CompilerVersion()
54+
types.CompilerVersion([])
55+
types.CompilerVersion(())
56+
types.CompilerVersion('')
57+
types.CompilerVersion(True)
58+
types.CompilerVersion('a')
59+
types.CompilerVersion(dict())
60+
61+
def test_eq(self):
62+
v1 = types.CompilerVersion('1.0.0')
63+
v2 = types.CompilerVersion('1.2.4.8')
64+
65+
self.assertEqual(v1, v1)
66+
self.assertEqual(v2, v2)
67+
self.assertNotEqual(v1, v2)
68+
self.assertNotEqual(v2, v1)
69+
70+
def test_str(self):
71+
version = types.CompilerVersion('1.0.0')
72+
self.assertEqual(str(version), '1.0.0')
73+
74+
version = types.CompilerVersion('1.0.0.1')
75+
self.assertEqual(str(version), '1.0.0.1')
76+
77+
1878
class TestBoolType(TestCase):
1979

2080
def test_true_values(self):
@@ -100,8 +160,6 @@ def test_assert_exists(self):
100160
def test_assert_executable(self):
101161
path_type = types.PathType(assert_executable=True)
102162

103-
self.assertTrue(path_type.assert_exists)
104-
105163
bash_path = '/bin/bash'
106164
if os.path.isfile(bash_path) and os.access(bash_path, os.X_OK):
107165
with self.assertNotRaises(ArgumentTypeError):
@@ -135,6 +193,14 @@ class TestClangVersionType(TestCase):
135193
def test_valid_clang_version(self):
136194
clang_version_type = types.ClangVersionType()
137195

196+
version = clang_version_type('1.0.0')
197+
self.assertIsInstance(version, types.CompilerVersion)
198+
self.assertEqual(version.components, (1, 0, 0))
199+
200+
version = clang_version_type('1.0.0.1')
201+
self.assertIsInstance(version, types.CompilerVersion)
202+
self.assertEqual(version.components, (1, 0, 0, 1))
203+
138204
with self.assertNotRaises(ArgumentTypeError):
139205
clang_version_type('1.0.0')
140206
clang_version_type('3.0.2.1')
@@ -156,6 +222,14 @@ class TestSwiftVersionType(TestCase):
156222
def test_valid_swift_version(self):
157223
swift_version_type = types.SwiftVersionType()
158224

225+
version = swift_version_type('1.0')
226+
self.assertIsInstance(version, types.CompilerVersion)
227+
self.assertEqual(version.components, (1, 0))
228+
229+
version = swift_version_type('1.0.1')
230+
self.assertIsInstance(version, types.CompilerVersion)
231+
self.assertEqual(version.components, (1, 0, 1))
232+
159233
with self.assertNotRaises(ArgumentTypeError):
160234
swift_version_type('1.0')
161235
swift_version_type('3.0.2')

utils/swift_build_support/swift_build_support/cmake.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ def common_options(self):
114114
"Debug;Release;MinSizeRel;RelWithDebInfo")
115115

116116
if args.clang_user_visible_version:
117-
major, minor, patch, _ = args.clang_user_visible_version.components
117+
major, minor, patch = \
118+
args.clang_user_visible_version.components[0:3]
118119
define("LLVM_VERSION_MAJOR:STRING", major)
119120
define("LLVM_VERSION_MINOR:STRING", minor)
120121
define("LLVM_VERSION_PATCH:STRING", patch)

0 commit comments

Comments
 (0)