Skip to content
This repository was archived by the owner on Jan 30, 2023. It is now read-only.

Commit 5fd92ee

Browse files
committed
Trac 7946: fix TestSuite failures for affine schemes
1 parent dcf608f commit 5fd92ee

File tree

4 files changed

+123
-27
lines changed

4 files changed

+123
-27
lines changed

src/sage/schemes/generic/morphism.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,10 @@ def _call_(self, x):
784784
785785
The image scheme point.
786786
787-
EXAMPLES::
787+
EXAMPLES:
788+
789+
The following fails because inverse images of prime ideals
790+
under ring homomorphisms are not yet implemented::
788791
789792
sage: R.<x> = PolynomialRing(QQ)
790793
sage: phi = R.hom([QQ(7)])
@@ -793,10 +796,7 @@ def _call_(self, x):
793796
sage: f(X.an_element()) # indirect doctest
794797
Traceback (most recent call last):
795798
...
796-
TypeError: Point on Spectrum of Rational Field defined by the
797-
Principal ideal (0) of Rational Field fails to convert into the
798-
map's domain Spectrum of Rational Field, but a `pushforward`
799-
method is not properly implemented
799+
NotImplementedError
800800
"""
801801
# By virtue of argument preprocessing in __call__, we can assume that
802802
# x is a topological scheme point of self

src/sage/schemes/generic/point.py

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@ class SchemePoint(Element):
2020
Base class for points on a scheme, either topological or defined
2121
by a morphism.
2222
"""
23-
def __init__(self, S):
23+
def __init__(self, S, parent=None):
2424
"""
2525
INPUT:
2626
27+
- ``S`` -- a scheme
2728
28-
- ``S`` - a scheme
29+
- ``parent`` -- the parent in which to construct this point
2930
3031
TESTS::
3132
@@ -34,7 +35,7 @@ def __init__(self, S):
3435
sage: P = SchemePoint(S); P
3536
Point on Spectrum of Integer Ring
3637
"""
37-
Element.__init__(self, S.Hom(S))
38+
Element.__init__(self, parent)
3839
self.__S = S
3940

4041
def scheme(self):
@@ -74,19 +75,40 @@ def is_SchemeTopologicalPoint(x):
7475
return isinstance(x, SchemeTopologicalPoint)
7576

7677
class SchemeTopologicalPoint(SchemePoint):
77-
pass
78+
"""
79+
Base class for topological points on schemes.
80+
"""
81+
def __init__(self, S):
82+
"""
83+
INPUT:
84+
85+
- ``S`` -- a scheme
86+
87+
TESTS:
88+
89+
The parent of a topological point is the scheme on which it
90+
lies (see :trac:`7946`)::
91+
92+
sage: R = Zmod(8)
93+
sage: S = Spec(R)
94+
sage: x = S(R.ideal(2))
95+
sage: isinstance(x, sage.schemes.generic.point.SchemeTopologicalPoint)
96+
True
97+
sage: x.parent() is S
98+
True
99+
"""
100+
SchemePoint.__init__(self, S, parent=S)
78101

79102
class SchemeTopologicalPoint_affine_open(SchemeTopologicalPoint):
80103
def __init__(self, u, x):
81104
"""
82105
INPUT:
83106
107+
- ``u`` -- morphism with domain an affine scheme `U`
84108
85-
- ``u`` - morphism with domain U an affine scheme
86-
87-
- ``x`` - point on U
109+
- ``x`` -- topological point on `U`
88110
"""
89-
SchemePoint.__init__(self, u.codomain())
111+
SchemeTopologicalPoint.__init__(self, u.codomain())
90112
self.__u = u
91113
self.__x = x
92114

@@ -147,8 +169,10 @@ def __init__(self, S, P, check=False):
147169
"""
148170
R = S.coordinate_ring()
149171
from sage.rings.ideal import is_Ideal
150-
if not (is_Ideal(P) and P.ring() is R):
172+
if not is_Ideal(P):
151173
P = R.ideal(P)
174+
elif P.ring() is not R:
175+
P = R.ideal(P.gens())
152176
# ideally we would have check=True by default, but
153177
# unfortunately is_prime() is only implemented in a small
154178
# number of cases
@@ -186,6 +210,20 @@ def prime_ideal(self):
186210
"""
187211
return self.__P
188212

213+
def __cmp__(self, other):
214+
"""
215+
Compare ``self`` to ``other``.
216+
217+
TESTS::
218+
219+
sage: S = Spec(ZZ)
220+
sage: x = S(ZZ.ideal(5))
221+
sage: y = S(ZZ.ideal(7))
222+
sage: x == y
223+
False
224+
"""
225+
return cmp(self.__P, other.__P)
226+
189227
########################################################
190228
# Points on a scheme defined by a morphism
191229
########################################################
@@ -201,7 +239,7 @@ def __init__(self, f):
201239
202240
- ``f`` - a morphism of schemes
203241
"""
204-
SchemePoint.__init__(self, f.codomain())
242+
SchemePoint.__init__(self, f.codomain(), parent=f.parent())
205243
self.__f = f
206244

207245
def _repr_(self):

src/sage/schemes/generic/scheme.py

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,18 @@
2121
# http://www.gnu.org/licenses/
2222
#*****************************************************************************
2323

24-
2524
from sage.structure.parent import Parent
2625
from sage.misc.all import cached_method
2726
from sage.rings.all import (IntegerRing,
2827
ZZ, GF, PowerSeriesRing,
2928
Rationals)
3029

3130
from sage.rings.commutative_ring import is_CommutativeRing
31+
from sage.rings.ideal import is_Ideal
3232
from sage.rings.morphism import is_RingHomomorphism
3333

34+
from sage.schemes.generic.point import SchemeTopologicalPoint_prime_ideal
35+
3436
def is_Scheme(x):
3537
"""
3638
Test whether ``x`` is a scheme.
@@ -92,14 +94,16 @@ def __init__(self, X=None, category=None):
9294
"""
9395
Construct a scheme.
9496
95-
TESTS::
97+
TESTS:
98+
99+
The full test suite works since :trac:`7946`::
96100
97101
sage: R.<x, y> = QQ[]
98102
sage: I = (x^2 - y^2)*R
99103
sage: RmodI = R.quotient(I)
100104
sage: X = Spec(RmodI)
101-
sage: TestSuite(X).run(skip = ["_test_an_element", "_test_elements",
102-
... "_test_some_elements", "_test_category"]) # See #7946
105+
sage: TestSuite(X).run()
106+
103107
"""
104108
from sage.schemes.generic.morphism import is_SchemeMorphism
105109

@@ -190,7 +194,7 @@ def _morphism(self, *args, **kwds):
190194
191195
TESTS:
192196
193-
This shows that issue at trac ticket 7389 is solved::
197+
This shows that issue at :trac:`7389` is solved::
194198
195199
sage: S = Spec(ZZ)
196200
sage: f = S.identity_morphism()
@@ -992,7 +996,7 @@ def __call__(self, *args):
992996
sage: P = S(ZZ.ideal(3)); P
993997
Point on Spectrum of Integer Ring defined by the Principal ideal (3) of Integer Ring
994998
sage: type(P)
995-
<class 'sage.schemes.generic.point.SchemeTopologicalPoint_prime_ideal'>
999+
<class 'sage.schemes.generic.point.AffineScheme_with_category.element_class'>
9961000
sage: S(ZZ.ideal(next_prime(1000000)))
9971001
Point on Spectrum of Integer Ring defined by the Principal ideal (1000003) of Integer Ring
9981002
@@ -1015,15 +1019,69 @@ def __call__(self, *args):
10151019
Set of morphisms
10161020
From: Spectrum of Integer Ring
10171021
To: Spectrum of Integer Ring
1022+
1023+
For affine or projective varieties, passing the correct number
1024+
of elements of the base ring constructs the rational point
1025+
with these elements as coordinates::
1026+
1027+
sage: S = AffineSpace(ZZ, 1)
1028+
sage: S(0)
1029+
(0)
1030+
1031+
To prevent confusion with this usage, topological points must
1032+
be constructed by explicitly specifying a prime ideal, not
1033+
just generators::
1034+
1035+
sage: R = S.coordinate_ring()
1036+
sage: S(R.ideal(0))
1037+
Point on Affine Space of dimension 1 over Integer Ring defined by the Ideal (0) of Multivariate Polynomial Ring in x over Integer Ring
1038+
1039+
This explains why the following example raises an error rather
1040+
than constructing the topological point defined by the prime
1041+
ideal `(0)` as one might expect::
1042+
1043+
sage: S = Spec(ZZ)
1044+
sage: S(0)
1045+
Traceback (most recent call last):
1046+
...
1047+
TypeError: cannot call Spectrum of Integer Ring with arguments (0,)
10181048
"""
10191049
if len(args) == 1:
1020-
from sage.rings.ideal import is_Ideal
10211050
x = args[0]
1022-
if is_Ideal(x) and x.ring() is self.coordinate_ring():
1023-
from sage.schemes.generic.point import SchemeTopologicalPoint_prime_ideal
1024-
return SchemeTopologicalPoint_prime_ideal(self, x)
1051+
if ((isinstance(x, self.element_class) and (x.parent() is self or x.parent() == self))
1052+
or (is_Ideal(x) and x.ring() is self.coordinate_ring())):
1053+
# Construct a topological point from x.
1054+
return self._element_constructor_(x)
1055+
try:
1056+
# Construct a scheme homset or a scheme-valued point from
1057+
# args using the generic Scheme.__call__() method.
1058+
return super(AffineScheme, self).__call__(*args)
1059+
except NotImplementedError:
1060+
# This arises from self._morphism() not being implemented.
1061+
# We must convert it into a TypeError to keep the coercion
1062+
# system working.
1063+
raise TypeError('cannot call %s with arguments %s' % (self, args))
1064+
1065+
Element = SchemeTopologicalPoint_prime_ideal
10251066

1026-
return super(AffineScheme, self).__call__(*args)
1067+
def _element_constructor_(self, x):
1068+
"""
1069+
Construct a topological point from `x`.
1070+
1071+
TESTS::
1072+
1073+
sage: S = Spec(ZZ)
1074+
sage: S(ZZ.ideal(0))
1075+
Point on Spectrum of Integer Ring defined by the Principal ideal (0) of Integer Ring
1076+
"""
1077+
if isinstance(x, self.element_class):
1078+
if x.parent() is self:
1079+
return x
1080+
elif x.parent() == self:
1081+
return self.element_class(self, x.prime_ideal())
1082+
elif is_Ideal(x) and x.ring() is self.coordinate_ring():
1083+
return self.element_class(self, x)
1084+
raise TypeError('cannot convert %s to a topological point of %s' % (x, self))
10271085

10281086
def _an_element_(self):
10291087
r"""

src/sage/schemes/generic/spec.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def Spec(R, S=None):
4444
Spectrum of Multivariate Polynomial Ring in x0, x1, x2 over Rational Field
4545
sage: X = Spec(PolynomialRing(GF(49,'a'), 3, 'x')); X
4646
Spectrum of Multivariate Polynomial Ring in x0, x1, x2 over Finite Field in a of size 7^2
47-
sage: TestSuite(X).run(skip=["_test_an_element", "_test_elements", "_test_some_elements"])
47+
sage: TestSuite(X).run()
4848
4949
Applying ``Spec`` twice gives equal but non-identical output::
5050

0 commit comments

Comments
 (0)