1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
# Copyright 2019 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import typing as T
import hashlib
from pathlib import Path, PurePath
from .. import mlog
from . import ExtensionModule
from . import ModuleReturnValue
from ..mesonlib import MesonException
from ..interpreterbase import stringArgs, noKwargs
if T.TYPE_CHECKING:
from ..interpreter import ModuleState
class FSModule(ExtensionModule):
def __init__(self, interpreter):
super().__init__(interpreter)
self.snippets.add('generate_dub_file')
def _resolve_dir(self, state: 'ModuleState', arg: str) -> Path:
"""
resolves (makes absolute) a directory relative to calling meson.build,
if not already absolute
"""
return Path(state.source_root) / state.subdir / Path(arg).expanduser()
def _check(self, check: str, state: 'ModuleState', args: T.Sequence[str]) -> ModuleReturnValue:
if len(args) != 1:
raise MesonException('fs.{} takes exactly one argument.'.format(check))
test_file = self._resolve_dir(state, args[0])
return ModuleReturnValue(getattr(test_file, check)(), [])
@stringArgs
@noKwargs
def exists(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
return self._check('exists', state, args)
@stringArgs
@noKwargs
def is_symlink(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
return self._check('is_symlink', state, args)
@stringArgs
@noKwargs
def is_file(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
return self._check('is_file', state, args)
@stringArgs
@noKwargs
def is_dir(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
return self._check('is_dir', state, args)
@stringArgs
@noKwargs
def hash(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
if len(args) != 2:
raise MesonException('method takes exactly two arguments.')
file = self._resolve_dir(state, args[0])
if not file.is_file():
raise MesonException('{} is not a file and therefore cannot be hashed'.format(file))
try:
h = hashlib.new(args[1])
except ValueError:
raise MesonException('hash algorithm {} is not available'.format(args[1]))
mlog.debug('computing {} sum of {} size {} bytes'.format(args[1], file, file.stat().st_size))
h.update(file.read_bytes())
return ModuleReturnValue(h.hexdigest(), [])
@stringArgs
@noKwargs
def size(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
if len(args) != 1:
raise MesonException('method takes exactly one argument.')
file = self._resolve_dir(state, args[0])
if not file.is_file():
raise MesonException('{} is not a file and therefore cannot be sized'.format(file))
try:
return ModuleReturnValue(file.stat().st_size, [])
except ValueError:
raise MesonException('{} size could not be determined'.format(args[0]))
@stringArgs
@noKwargs
def is_samepath(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
if len(args) != 2:
raise MesonException('fs.is_samepath takes exactly two arguments.')
file1 = self._resolve_dir(state, args[0])
file2 = self._resolve_dir(state, args[1])
if not file1.exists():
return ModuleReturnValue(False, [])
if not file2.exists():
return ModuleReturnValue(False, [])
try:
return ModuleReturnValue(file1.samefile(file2), [])
except OSError:
return ModuleReturnValue(False, [])
@stringArgs
@noKwargs
def replace_suffix(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
if len(args) != 2:
raise MesonException('method takes exactly two arguments.')
original = PurePath(args[0])
new = original.with_suffix(args[1])
return ModuleReturnValue(str(new), [])
@stringArgs
@noKwargs
def parent(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
if len(args) != 1:
raise MesonException('method takes exactly one argument.')
original = PurePath(args[0])
new = original.parent
return ModuleReturnValue(str(new), [])
@stringArgs
@noKwargs
def name(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
if len(args) != 1:
raise MesonException('method takes exactly one argument.')
original = PurePath(args[0])
new = original.name
return ModuleReturnValue(str(new), [])
def initialize(*args, **kwargs) -> FSModule:
return FSModule(*args, **kwargs)
|