-
-
Notifications
You must be signed in to change notification settings - Fork 404
/
interfaces.py
237 lines (184 loc) · 7.57 KB
/
interfaces.py
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# sage_setup: distribution = sagemath-environment
r"""
Features for testing whether interpreter interfaces to ``magma``, ``maple``, ``mathematica`` etc. are functional
"""
# ****************************************************************************
# Copyright (C) 2021 Matthias Koeppe
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
# https://www.gnu.org/licenses/
# ****************************************************************************
import importlib
from . import Feature, FeatureTestResult, PythonModule
class InterfaceFeature(Feature):
r"""
A :class:`~sage.features.Feature` describing whether an :class:`~sage.interfaces.interface.Interface` is present and functional.
TESTS::
sage: from sage.features.interfaces import InterfaceFeature
sage: broken = InterfaceFeature("broken_interface", "sage.interfaces.does_not_exist")
sage: broken.is_present()
FeatureTestResult('sage.interfaces.does_not_exist', False)
sage: _.reason
"Failed to import `sage.interfaces.does_not_exist`: No module named 'sage.interfaces.does_not_exist'"
sage: also_broken = InterfaceFeature("also_broken_interface", "sage.interfaces.interface")
sage: also_broken.is_present()
FeatureTestResult('also_broken_interface', False)
sage: _.reason
"Interface also_broken_interface cannot be imported: module 'sage.interfaces.interface' has no attribute 'also_broken_interface'"
"""
@staticmethod
def __classcall__(cls, name, module, description=None):
"""
TESTS::
sage: from sage.features import PythonModule
sage: from sage.features.interfaces import InterfaceFeature
sage: f = InterfaceFeature("test_interface", "sage.interfaces.interface")
sage: f is InterfaceFeature("test_interface", PythonModule("sage.interfaces.interface"))
True
"""
if isinstance(module, str):
module = PythonModule(module)
return Feature.__classcall__(cls, name, module, description)
def __init__(self, name, module, description):
"""
TESTS::
sage: from sage.features.interfaces import InterfaceFeature
sage: f = InterfaceFeature("test_interface", "sage.interfaces.interface")
sage: isinstance(f, InterfaceFeature)
True
"""
super().__init__(name, description=description)
self.module = module
def _is_present(self):
"""
TESTS::
sage: from sage.features.interfaces import InterfaceFeature
sage: from sage.interfaces.sage0 import Sage
sage: f = InterfaceFeature("sage0", "sage.interfaces.sage0")
sage: f.is_present()
FeatureTestResult('sage0', True)
"""
result = self.module.is_present()
if not result:
return result
m = importlib.import_module(self.module.name)
try:
interface = getattr(m, self.name)
except Exception as exception:
return FeatureTestResult(self, False,
reason=f"Interface {self.name} cannot be imported: {exception}")
try:
interface('2+3')
return FeatureTestResult(self, True)
except Exception as exception:
return FeatureTestResult(self, False,
reason=f"Interface {interface} is not functional: {exception}")
# The following are provided by external software only (no SPKG)
class Magma(InterfaceFeature):
r"""
A :class:`~sage.features.Feature` describing whether :class:`sage.interfaces.magma.Magma`
is present and functional.
EXAMPLES::
sage: from sage.features.interfaces import Magma
sage: Magma().is_present() # random
FeatureTestResult('magma', False)
"""
@staticmethod
def __classcall__(cls):
return InterfaceFeature.__classcall__(cls, 'magma', 'sage.interfaces.magma')
class Matlab(InterfaceFeature):
r"""
A :class:`~sage.features.Feature` describing whether :class:`sage.interfaces.matlab.Matlab`
is present and functional.
EXAMPLES::
sage: from sage.features.interfaces import Matlab
sage: Matlab().is_present() # random
FeatureTestResult('matlab', False)
"""
@staticmethod
def __classcall__(cls):
return InterfaceFeature.__classcall__(cls, 'matlab', 'sage.interfaces.matlab')
class Mathematica(InterfaceFeature):
r"""
A :class:`~sage.features.Feature` describing whether :class:`sage.interfaces.mathematica.Mathematica`
is present and functional.
EXAMPLES::
sage: from sage.features.interfaces import Mathematica
sage: Mathematica().is_present() # not tested
FeatureTestResult('mathematica', False)
"""
@staticmethod
def __classcall__(cls):
return InterfaceFeature.__classcall__(cls, 'mathematica', 'sage.interfaces.mathematica')
class Maple(InterfaceFeature):
r"""
A :class:`~sage.features.Feature` describing whether :class:`sage.interfaces.maple.Maple`
is present and functional.
EXAMPLES::
sage: from sage.features.interfaces import Maple
sage: Maple().is_present() # random
FeatureTestResult('maple', False)
"""
@staticmethod
def __classcall__(cls):
return InterfaceFeature.__classcall__(cls, 'maple', 'sage.interfaces.maple')
class Macaulay2(InterfaceFeature):
r"""
A :class:`~sage.features.Feature` describing whether :class:`sage.interfaces.macaulay2.Macaulay2`
is present and functional.
EXAMPLES::
sage: from sage.features.interfaces import Macaulay2
sage: Macaulay2().is_present() # random
FeatureTestResult('macaulay2', False)
"""
@staticmethod
def __classcall__(cls):
return InterfaceFeature.__classcall__(cls, 'macaulay2', 'sage.interfaces.macaulay2')
class Octave(InterfaceFeature):
r"""
A :class:`~sage.features.Feature` describing whether :class:`sage.interfaces.octave.Octave`
is present and functional.
EXAMPLES::
sage: from sage.features.interfaces import Octave
sage: Octave().is_present() # random
FeatureTestResult('octave', False)
"""
@staticmethod
def __classcall__(cls):
return InterfaceFeature.__classcall__(cls, 'octave', 'sage.interfaces.octave')
class Scilab(InterfaceFeature):
r"""
A :class:`~sage.features.Feature` describing whether :class:`sage.interfaces.scilab.Scilab`
is present and functional.
EXAMPLES::
sage: from sage.features.interfaces import Scilab
sage: Scilab().is_present() # random
FeatureTestResult('scilab', False)
"""
@staticmethod
def __classcall__(cls):
return InterfaceFeature.__classcall__(cls, 'scilab', 'sage.interfaces.scilab')
def all_features():
r"""
Return features corresponding to interpreter interfaces.
EXAMPLES::
sage: from sage.features.interfaces import all_features
sage: list(all_features())
[Feature('magma'),
Feature('matlab'),
Feature('mathematica'),
Feature('maple'),
Feature('macaulay2'),
Feature('octave'),
Feature('scilab')]
"""
return [Magma(),
Matlab(),
Mathematica(),
Maple(),
Macaulay2(),
Octave(),
Scilab()]