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

Commit

Permalink
Move Set_PythonType to a new file
Browse files Browse the repository at this point in the history
  • Loading branch information
jdemeyer committed Jul 12, 2018
1 parent f1debe3 commit 7e7daef
Show file tree
Hide file tree
Showing 20 changed files with 284 additions and 266 deletions.
1 change: 1 addition & 0 deletions src/doc/en/reference/sets/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Set Constructions
sage/sets/finite_set_maps
sage/sets/finite_set_map_cy
sage/sets/totally_ordered_finite_set
sage/sets/pythonclass

Sets of Numbers
---------------
Expand Down
5 changes: 3 additions & 2 deletions src/sage/categories/homset.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,9 @@ def Hom(X, Y, category=None, check=True):
Facade parents over plain Python types are supported::
sage: R = sage.structure.parent.Set_PythonType(int)
sage: S = sage.structure.parent.Set_PythonType(float)
sage: from sage.sets.pythonclass import Set_PythonType
sage: R = Set_PythonType(int)
sage: S = Set_PythonType(float)
sage: Hom(R, S)
Set of Morphisms from Set of Python objects of class 'int' to Set of Python objects of class 'float' in Category of sets
Expand Down
2 changes: 1 addition & 1 deletion src/sage/categories/map.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ from . import homset
import weakref
from sage.ext.stdsage cimport HAS_DICTIONARY
from sage.arith.power cimport generic_power
from sage.structure.parent cimport Set_PythonType
from sage.sets.pythonclass cimport Set_PythonType
from sage.misc.constant_function import ConstantFunction
from sage.misc.superseded import deprecated_function_alias
from sage.structure.element cimport parent
Expand Down
2 changes: 1 addition & 1 deletion src/sage/combinat/words/alphabet.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ def build_alphabet(data=None, names=None, name=None):

# Alphabet(**nothing**)
if data is None: # name is also None
from sage.structure.parent import Set_PythonType
from sage.sets.pythonclass import Set_PythonType
return Set_PythonType(object)

raise ValueError("unable to construct an alphabet from the given parameters")
Expand Down
4 changes: 2 additions & 2 deletions src/sage/rings/complex_double.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2426,7 +2426,7 @@ cdef class FloatToCDF(Morphism):
"""
from sage.categories.homset import Hom
if isinstance(R, type):
from sage.structure.parent import Set_PythonType
from sage.sets.pythonclass import Set_PythonType
R = Set_PythonType(R)
Morphism.__init__(self, Hom(R, CDF))

Expand Down Expand Up @@ -2476,7 +2476,7 @@ cdef class ComplexToCDF(Morphism):
def __init__(self, R):
from sage.categories.homset import Hom
if isinstance(R, type):
from sage.structure.parent import Set_PythonType
from sage.sets.pythonclass import Set_PythonType
R = Set_PythonType(R)
Morphism.__init__(self, Hom(R, CDF))

Expand Down
2 changes: 1 addition & 1 deletion src/sage/rings/finite_rings/integer_mod.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -4370,7 +4370,7 @@ cdef class Int_to_IntegerMod(IntegerMod_hom):
"""
def __init__(self, R):
import sage.categories.homset
from sage.structure.parent import Set_PythonType
from sage.sets.pythonclass import Set_PythonType
IntegerMod_hom.__init__(self, sage.categories.homset.Hom(Set_PythonType(int), R))

cpdef Element _call_(self, x):
Expand Down
4 changes: 2 additions & 2 deletions src/sage/rings/integer.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -7080,7 +7080,7 @@ cdef class int_to_Z(Morphism):
Set of Morphisms from Set of Python objects of class 'int' to Integer Ring in Category of sets
"""
import sage.categories.homset
from sage.structure.parent import Set_PythonType
from sage.sets.pythonclass import Set_PythonType
Morphism.__init__(self, sage.categories.homset.Hom(Set_PythonType(int), integer_ring.ZZ))

cpdef Element _call_(self, a):
Expand Down Expand Up @@ -7126,7 +7126,7 @@ cdef class long_to_Z(Morphism):
"""
def __init__(self):
import sage.categories.homset
from sage.structure.parent import Set_PythonType
from sage.sets.pythonclass import Set_PythonType
Morphism.__init__(self, sage.categories.homset.Hom(Set_PythonType(long), integer_ring.ZZ))

cpdef Element _call_(self, a):
Expand Down
4 changes: 2 additions & 2 deletions src/sage/rings/rational.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -4221,7 +4221,7 @@ cdef class int_to_Q(Morphism):
"""
from . import rational_field
import sage.categories.homset
from sage.structure.parent import Set_PythonType
from sage.sets.pythonclass import Set_PythonType
Morphism.__init__(self, sage.categories.homset.Hom(Set_PythonType(int), rational_field.QQ))

cpdef Element _call_(self, a):
Expand Down Expand Up @@ -4281,7 +4281,7 @@ cdef class long_to_Q(Morphism):
"""
from . import rational_field
import sage.categories.homset
from sage.structure.parent import Set_PythonType
from sage.sets.pythonclass import Set_PythonType
Morphism.__init__(self, sage.categories.homset.Hom(
Set_PythonType(long), rational_field.QQ))

Expand Down
2 changes: 1 addition & 1 deletion src/sage/rings/real_double.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2703,7 +2703,7 @@ cdef class ToRDF(Morphism):
"""
from sage.categories.homset import Hom
if isinstance(R, type):
from sage.structure.parent import Set_PythonType
from sage.sets.pythonclass import Set_PythonType
R = Set_PythonType(R)
Morphism.__init__(self, Hom(R, RDF))
Expand Down
2 changes: 1 addition & 1 deletion src/sage/rings/real_lazy.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ cdef class LazyField(Field):
"""
if isinstance(R, type):
if R in [int, long]:
from sage.structure.parent import Set_PythonType
from sage.sets.pythonclass import Set_PythonType
return LazyWrapperMorphism(Set_PythonType(R), self)
elif R.is_exact():
ivf = self.interval_field()
Expand Down
2 changes: 1 addition & 1 deletion src/sage/sets/finite_enumerated_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def __call__(self, el):
2
sage: phi.register_as_conversion()
sage: from sage.structure.parent import Set_PythonType_class
sage: from sage.sets.pythonclass import Set_PythonType_class
sage: psi = Hom(Set_PythonType_class(str), F, Sets())(lambda s: ZZ(len(s)))
sage: psi.register_as_conversion()
sage: psi('a')
Expand Down
8 changes: 8 additions & 0 deletions src/sage/sets/pythonclass.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from sage.structure.parent cimport Set_generic


cdef class Set_PythonType_class(Set_generic):
cdef type _type


cpdef Set_PythonType(typ)
247 changes: 247 additions & 0 deletions src/sage/sets/pythonclass.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
"""
Set of all objects of a given Python class
"""

#*****************************************************************************
# Copyright (C) 2018 Jeroen Demeyer <[email protected]>
#
# 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.
# http://www.gnu.org/licenses/
#*****************************************************************************

from cpython.object cimport Py_EQ, Py_NE
from cpython.version cimport PY_MAJOR_VERSION
from sage.structure.richcmp cimport rich_to_bool
from sage.categories.sets_cat import Sets


cdef dict _type_set_cache = {}

cpdef Set_PythonType(typ):
"""
Return the (unique) Parent that represents the set of Python objects
of a specified type.
EXAMPLES::
sage: from sage.sets.pythonclass import Set_PythonType
sage: Set_PythonType(list)
Set of Python objects of class 'list'
sage: Set_PythonType(list) is Set_PythonType(list)
True
sage: S = Set_PythonType(tuple)
sage: S([1,2,3])
(1, 2, 3)
S is a parent which models the set of all lists::
sage: S.category()
Category of sets
"""
try:
return _type_set_cache[typ]
except KeyError:
_type_set_cache[typ] = theSet = Set_PythonType_class(typ)
return theSet


cdef class Set_PythonType_class(Set_generic):
r"""
The set of Python objects of a given class.
The elements of this set are not instances of
:class:`~sage.structure.element.Element`; they are instances of
the given class.
INPUT:
- ``typ`` -- a Python (new-style) class
EXAMPLES::
sage: from sage.sets.pythonclass import Set_PythonType
sage: S = Set_PythonType(int); S
Set of Python objects of class 'int'
sage: int('1') in S
True
sage: Integer('1') in S
False
sage: Set_PythonType(2)
Traceback (most recent call last):
...
TypeError: must be initialized with a class, not 2
"""

def __init__(self, typ):
"""
EXAMPLES::
sage: from sage.sets.pythonclass import Set_PythonType
sage: Set_PythonType(float).category()
Category of sets
"""
if not isinstance(typ, type):
raise TypeError(f"must be initialized with a class, not {typ!r}")
super().__init__(category=Sets())
self._type = <type>typ

def _element_constructor_(self, *args, **kwds):
"""
Construct an instance of the class.
EXAMPLES::
sage: from sage.sets.pythonclass import Set_PythonType
sage: S = Set_PythonType(complex)
sage: S._element_constructor_(5)
(5+0j)
sage: S._element_constructor_(1, 5/2)
(1+2.5j)
"""
return self._type(*args, **kwds)

def __reduce__(self):
r"""
Pickling support
TESTS::
sage: from sage.sets.pythonclass import Set_PythonType
sage: S = Set_PythonType(object)
sage: loads(dumps(S))
Set of Python objects of class 'object'
"""
return type(self), (self._type,)

def __call__(self, x):
"""
Construct a new instance from ``x``. If ``x`` is already an
instance of the correct class, directly return ``x`` itself.
EXAMPLES::
sage: from sage.sets.pythonclass import Set_PythonType
sage: S = Set_PythonType(float)
sage: S(5)
5.0
sage: S(9/3)
3.0
sage: S(1/3)
0.333333333333333...
sage: a = float(3); S(a) is a
True
"""
if isinstance(x, self._type):
return x
return self._type(x)

def __hash__(self):
"""
TESTS::
sage: from sage.sets.pythonclass import Set_PythonType
sage: S = Set_PythonType(int)
sage: hash(S) == -hash(int)
True
"""
return -hash(self._type)

def __richcmp__(self, other, int op):
"""
Two Python class sets are considered the same if they contain
the same class.
EXAMPLES::
sage: from sage.sets.pythonclass import Set_PythonType
sage: S = Set_PythonType(int)
sage: T = Set_PythonType(int)
sage: U = type(S)(int) # bypass caching
sage: S is T
True
sage: S == T
True
sage: S is U
False
sage: S == U
True
sage: S == Set_PythonType(float)
False
sage: S == int
False
"""
if not (op == Py_EQ or op == Py_NE):
return NotImplemented
if self is other:
return rich_to_bool(op, 0)
if not isinstance(other, Set_PythonType_class):
return rich_to_bool(op, 1)
s = (<Set_PythonType_class>self)._type
o = (<Set_PythonType_class>other)._type
return rich_to_bool(op, s is not o)

def __contains__(self, x):
"""
Only things of the right class (or subclasses thereof) are
considered to belong to the set.
EXAMPLES::
sage: from sage.sets.pythonclass import Set_PythonType
sage: S = Set_PythonType(tuple)
sage: (1,2,3) in S
True
sage: () in S
True
sage: [1,2] in S
False
"""
return isinstance(x, self._type)

def _repr_(self):
"""
EXAMPLES::
sage: from sage.sets.pythonclass import Set_PythonType
sage: Set_PythonType(tuple)
Set of Python objects of class 'tuple'
sage: Set_PythonType(Integer)
Set of Python objects of class 'Integer'
sage: Set_PythonType(Parent)
Set of Python objects of class 'Parent'
"""
return f"Set of Python objects of class '{self._type.__name__}'"

def object(self):
"""
EXAMPLES::
sage: from sage.sets.pythonclass import Set_PythonType
sage: Set_PythonType(tuple).object()
<... 'tuple'>
"""
return self._type

def cardinality(self):
"""
EXAMPLES::
sage: from sage.sets.pythonclass import Set_PythonType
sage: S = Set_PythonType(bool)
sage: S.cardinality()
2
sage: S = Set_PythonType(int)
sage: S.cardinality()
+Infinity
"""
if self._type is bool:
from sage.rings.integer import Integer
return Integer(2)
else:
# Probably infinite
import sage.rings.infinity
return sage.rings.infinity.infinity
Loading

0 comments on commit 7e7daef

Please sign in to comment.