I think it is a bug, so thank you for pointing it out.
Generally when seeking help or clarification on an error, it is best to post the full traceback. Even if it looks like meaningless gibberish to you, it does not look meaningless to the developers. In this case I get:
sage: 'hello' in CC
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-2-2a4614162c6a> in <module>()
----> 1 'hello' in CC
/home/embray/src/sagemath/sage/local/lib/python2.7/site-packages/sage/structure/parent.pyx in sage.structure.parent.Parent.__conta_ (build/cythonized/sage/structure/parent.c:9863)()
1090 return True
1091 try:
-> 1092 x2 = self(x)
1093 EQ = (x2 == x)
1094 if EQ is True:
/home/embray/src/sagemath/sage/local/lib/python2.7/site-packages/sage/rings/complex_field.pyc in __call__(self, x, im)
385 if im is not None:
386 x = x, im
--> 387 return Parent.__call__(self, x)
388
389 def _element_constructor_(self, x):
/home/embray/src/sagemath/sage/local/lib/python2.7/site-packages/sage/structure/parent.pyx in sage.structure.parent.Parent.__call_uild/cythonized/sage/structure/parent.c:9197)()
898 if mor is not None:
899 if no_extra_args:
--> 900 return mor._call_(x)
901 else:
902 return mor._call_with_args(x, args, kwds)
/home/embray/src/sagemath/sage/local/lib/python2.7/site-packages/sage/structure/coerce_maps.pyx in sage.structure.coerce_maps.DefaonvertMap_unique._call_ (build/cythonized/sage/structure/coerce_maps.c:4556)()
160 print(type(C), C)
161 print(type(C._element_constructor), C._element_constructor)
--> 162 raise
163
164 cpdef Element _call_with_args(self, x, args=(), kwds={}):
/home/embray/src/sagemath/sage/local/lib/python2.7/site-packages/sage/structure/coerce_maps.pyx in sage.structure.coerce_maps.DefaonvertMap_unique._call_ (build/cythonized/sage/structure/coerce_maps.c:4448)()
155 cdef Parent C = self._codomain
156 try:
--> 157 return C._element_constructor(x)
158 except Exception:
159 if print_warnings:
/home/embray/src/sagemath/sage/local/lib/python2.7/site-packages/sage/rings/complex_field.pyc in _element_constructor_(self, x)
411 # efficient way to do this. -- Martin Albrecht
412 return ComplexNumber(self,
--> 413 sage_eval(x.replace(' ',''), locals={"I":self.gen(),"i":self.gen()}))
414
415 late_import()
/home/embray/src/sagemath/sage/local/lib/python2.7/site-packages/sage/misc/sage_eval.pyc in sage_eval(source, locals, cmds, prepar
201 return locals['_sage_eval_returnval_']
202 else:
--> 203 return eval(source, sage.all.__dict__, locals)
204
205
/home/embray/src/sagemath/sage/local/lib/python2.7/site-packages/sage/all.pyc in <module>()
NameError: name 'hello' is not defined
Sage definitely shouldn't be throwing seemingly bizarre NameError
s in such cases.
Looking two frames up we see a fragment of a strange comment ending with "efficient way to do this." so let's start there in sage/rings/complex_field.py
, line 413 or thereabout:
389 def _element_constructor_(self, x):
390 """
391 Construct a complex number.
392
393 EXAMPLES::
394
395 sage: CC((1,2)) # indirect doctest
396 1.00000000000000 + 2.00000000000000*I
397
398 Check that :trac:`14989` is fixed::
399
400 sage: QQi = NumberField(x^2+1, 'i', embedding=CC(0,1))
401 sage: i = QQi.order(QQi.gen()).gen(1)
402 sage: CC(i)
403 1.00000000000000*I
404
405 """
406 if not isinstance(x, (RealNumber, tuple)):
407 if isinstance(x, ComplexDoubleElement):
408 return ComplexNumber(self, x.real(), x.imag())
409 elif isinstance(x, str):
410 # TODO: this is probably not the best and most
411 # efficient way to do this. -- Martin Albrecht
412 return ComplexNumber(self,
413 sage_eval(x.replace(' ',''), locals={"I":self.gen(),"i":self.gen()}))
Okay, so the full comment was not all that helpful. But I can still kind of see what's happening here. When you do something like x in F
where F
is some field, and x
is some element that may or may not belong to that field, one of the first things it will do is try to convert x
to an element of F
if possible.
This process passes through CC._element_constructor_
, where it seems if x
is not already a RealNumber
, a (real, imag)
tuple, or a ComplexDoubleElement
, it will check if x
was a string. Then there is some code which, as far as I can tell, is trying to see if the string is a valid string representation of a complex number (using either i
or I
as the complex unit). It is doing this by calling eval
on the given string. It's expecting that you're going to try to do something like '1+2*i' in CC
(which, incidentally, returns False
for some reason, so it doesn't even work as expected). But this is double bad because it could fail in all sorts of ways beyond just giving a NameError
. For example:
sage: '@@@@@@@@@@@@@@@@' in CC
File "<string>", line 1
@@@@@@@@@@@@@@@@
^
SyntaxError: invalid syntax
Or
sage: # DON'T TRY THIS AT HOME
sage: # NO, REALLY
sage: # 'import shutil; shutil.rmtree(sage.__path__[0])' in CC
So yes, I think this is a bug. sage_eval
has no business being used in this context, and I suspect this code isn't even tested.
I would qualify this as "garbage in > garbage out"..
I am sorry, @FrédéricC, but I didn't understand your comment. Can you elaborate, please?
I disagree. I think it is a bug.