Skip to content

Commit db0cd3b

Browse files
authored
Merge pull request #80 from eric-wieser/strict-positional-mv-args
Raise TypeError for bad arguments to `Mv`
2 parents 9c35d01 + c1458c9 commit db0cd3b

File tree

2 files changed

+66
-31
lines changed

2 files changed

+66
-31
lines changed

galgebra/mv.py

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,18 @@ def characterise_Mv(self):
165165
# helper methods called by __init__. Note that these names must not change,
166166
# as the part of the name after `_make_` is public API via the string
167167
# argument passed to __init__.
168+
#
169+
# The double underscores in argument names are to force the passing
170+
# positionally. When python 3.8 is the lowest supported version, we can
171+
# switch to using the / syntax from PEP570
168172

169173
@staticmethod
170-
def _make_grade(ga, *args, **kwargs):
174+
def _make_grade(ga, __name_or_coeffs, __grade, **kwargs):
171175
""" Make a pure grade multivector. """
172-
grade = args[1]
173-
if utils.isstr(args[0]):
174-
root = args[0] + '__'
176+
grade = __grade
177+
if utils.isstr(__name_or_coeffs):
178+
name = __name_or_coeffs
179+
root = name + '__'
175180
if isinstance(kwargs['f'], bool) and not kwargs['f']: #Is a constant mulitvector function
176181
return sum([Symbol(root + super_script, real=True) * base
177182
for (super_script, base) in zip(ga.blade_super_scripts[grade], ga.blades[grade])])
@@ -183,69 +188,72 @@ def _make_grade(ga, *args, **kwargs):
183188
else: #Is a multivector function of tuple kwargs['f'] variables
184189
return sum([Function(root + super_script, real=True)(*kwargs['f']) * base
185190
for (super_script, base) in zip(ga.blade_super_scripts[grade], ga.blades[grade])])
186-
elif isinstance(args[0],(list,tuple)):
187-
if len(args[0]) <= len(ga.blades[grade]):
191+
elif isinstance(__name_or_coeffs, (list, tuple)):
192+
coeffs = __name_or_coeffs
193+
if len(coeffs) <= len(ga.blades[grade]):
188194
return sum([coef * base
189-
for (coef, base) in zip(args[0], ga.blades[grade][:len(args[0])])])
195+
for (coef, base) in zip(coeffs, ga.blades[grade][:len(coeffs)])])
190196
else:
191197
raise ValueError("Too many coefficients")
192198
else:
193199
raise TypeError("Expected a string, list, or tuple")
194200

195201
@staticmethod
196-
def _make_scalar(ga, *args, **kwargs):
202+
def _make_scalar(ga, __name_or_value, **kwargs):
197203
""" Make a scalar multivector """
198-
if utils.isstr(args[0]):
204+
if utils.isstr(__name_or_value):
205+
name = __name_or_value
199206
if 'f' in kwargs and isinstance(kwargs['f'],bool):
200207
if kwargs['f']:
201-
return Function(args[0])(*ga.coords)
208+
return Function(name)(*ga.coords)
202209
else:
203-
return Symbol(args[0], real=True)
210+
return Symbol(name, real=True)
204211
else:
205212
if 'f' in kwargs and isinstance(kwargs['f'],tuple):
206-
return Function(args[0])(*kwargs['f'])
213+
return Function(name)(*kwargs['f'])
207214
else:
208-
return args[0]
215+
value = __name_or_value
216+
return value
209217

210218
@staticmethod
211-
def _make_vector(ga, *args, **kwargs):
219+
def _make_vector(ga, __name_or_coeffs, **kwargs):
212220
""" Make a vector multivector """
213-
return Mv._make_grade(ga, args[0], 1, **kwargs)
221+
return Mv._make_grade(ga, __name_or_coeffs, 1, **kwargs)
214222

215223
@staticmethod
216-
def _make_bivector(ga, *args, **kwargs):
224+
def _make_bivector(ga, __name_or_coeffs, **kwargs):
217225
""" Make a bivector multivector """
218-
return Mv._make_grade(ga, args[0], 2, **kwargs)
226+
return Mv._make_grade(ga, __name_or_coeffs, 2, **kwargs)
219227

220228
@staticmethod
221-
def _make_pseudo(ga, *args, **kwargs):
229+
def _make_pseudo(ga, __name_or_coeffs, **kwargs):
222230
""" Make a pseudo scalar multivector """
223-
return Mv._make_grade(ga, args[0], ga.n, **kwargs)
231+
return Mv._make_grade(ga, __name_or_coeffs, ga.n, **kwargs)
224232

225233
@staticmethod
226-
def _make_mv(ga, *args, **kwargs):
234+
def _make_mv(ga, __name, **kwargs):
227235
""" Make a general (2**n components) multivector """
228-
tmp = Mv._make_scalar(ga, args[0], **kwargs)
236+
tmp = Mv._make_scalar(ga, __name, **kwargs)
229237
for grade in ga.n_range:
230-
tmp += Mv._make_grade(ga, args[0], grade + 1, **kwargs)
238+
tmp += Mv._make_grade(ga, __name, grade + 1, **kwargs)
231239
return tmp
232240

233241
@staticmethod
234-
def _make_spinor(ga, *args, **kwargs):
242+
def _make_spinor(ga, __name, **kwargs):
235243
""" Make a general even (spinor) multivector """
236-
tmp = Mv._make_scalar(ga, args[0], **kwargs)
244+
tmp = Mv._make_scalar(ga, __name, **kwargs)
237245
for grade in ga.n_range:
238246
if (grade + 1) % 2 == 0:
239-
tmp += Mv._make_grade(ga, args[0], grade + 1, **kwargs)
247+
tmp += Mv._make_grade(ga, __name, grade + 1, **kwargs)
240248
return tmp
241249

242250
@staticmethod
243-
def _make_odd(ga, *args, **kwargs):
251+
def _make_odd(ga, __name_or_coeffs, **kwargs):
244252
""" Make a general odd multivector """
245253
tmp = S(0)
246254
for grade in ga.n_range:
247255
if (grade + 1) % 2 == 1:
248-
tmp += Mv._make_grade(args[0], grade + 1, **kwargs)
256+
tmp += Mv._make_grade(ga, __name_or_coeffs, grade + 1, **kwargs)
249257
return tmp
250258

251259
# aliases
@@ -289,15 +297,18 @@ def __init__(self, *args, **kwargs):
289297
self.characterise_Mv()
290298
else:
291299
if utils.isstr(args[1]):
292-
args = list(args)
293-
mode = args.pop(1)
300+
make_args = list(args)
301+
mode = make_args.pop(1)
294302
make_func = getattr(Mv, '_make_{}'.format(mode), None)
295303
if make_func is None:
296304
raise ValueError('{!r} is not an allowed multivector type.'.format(mode))
297-
self.obj = make_func(self.Ga, *args, **kwargs)
305+
self.obj = make_func(self.Ga, *make_args, **kwargs)
298306
elif isinstance(args[1], int): # args[1] = r (integer) Construct grade r multivector
299307
if args[1] == 0:
300-
self.obj = Mv._make_scalar(self.Ga, *args, **kwargs)
308+
# make_grade does not work for scalars (gh-82)
309+
make_args = list(args)
310+
make_args.pop(1)
311+
self.obj = Mv._make_scalar(self.Ga, *make_args, **kwargs)
301312
else:
302313
self.obj = Mv._make_grade(self.Ga, *args, **kwargs)
303314
else:

test/test_mv.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,27 @@ def test_rep_switching(self):
8484
self.assertFalse(m0_base.is_blade_rep) # original should not change
8585
self.assertTrue(m0_base_blade.is_blade_rep)
8686
self.assertEqual(m0, m0_base_blade)
87+
88+
def test_construction(self):
89+
(ga, e_1, e_2, e_3) = Ga.build('e*1|2|3')
90+
91+
# non-function symbol construction
92+
self.assertEqual(ga.mv('A', 'scalar').grades, [0])
93+
self.assertEqual(ga.mv('A', 0).grades, [0])
94+
self.assertEqual(ga.mv('A', 'vector').grades, [1])
95+
self.assertEqual(ga.mv('A', 'grade', 1).grades, [1])
96+
self.assertEqual(ga.mv('A', 1).grades, [1])
97+
self.assertEqual(ga.mv('A', 'bivector').grades, [2])
98+
self.assertEqual(ga.mv('A', 'grade2').grades, [2])
99+
self.assertEqual(ga.mv('A', 2).grades, [2])
100+
self.assertEqual(ga.mv('A', 'pseudo').grades, [3])
101+
self.assertEqual(ga.mv('A', 'spinor').grades, [0, 2])
102+
self.assertEqual(ga.mv('A', 'even').grades, [0, 2])
103+
self.assertEqual(ga.mv('A', 'odd').grades, [1, 3])
104+
self.assertEqual(ga.mv('A', 'mv').grades, [0, 1, 2, 3])
105+
106+
# illegal arguments
107+
with self.assertRaises(TypeError):
108+
ga.mv('A', 'vector', "too many arguments")
109+
with self.assertRaises(TypeError):
110+
ga.mv('A', 'grade') # too few arguments

0 commit comments

Comments
 (0)