<commit_before>from sympy.core.function import Function, UndefinedFunction, AppliedUndef, Application, FunctionClass
from sympy.core.cache import cacheit
from sympy.core.core import BasicMeta
from sympy.core.sympify import sympify
from sympy.core.expr import Expr

# this is the function used in other operations to check if something is a tensor.
def isTensor(x):
    return isinstance(x,Tensor)

class Tensor(Function):
    @cacheit
    def __new__(cls, *args, **options):
        # Handle calls like Tensor('F')
        if cls is Tensor:
            return UndefinedTensor(*args, **options)
    
    __slots__ = ['_mhash',              # hash value
                 '_args',               # arguments
                 '_assumptions'
                 'index'                # idecis
                ]

class UndefinedTensor(UndefinedFunction):

    def __new__(mcl, name, **kwargs):
        ret = BasicMeta.__new__(mcl, name, (AppliedTensor,), kwargs)
        ret.__module__ = None
        return ret



#    def __eq__(self, other):
#        return (isinstance(other, self.__class__) and (self.class_key() == other.class_key()))

#copy pased with UndefinedFunction -> UndefinedTensor. I have no idea what this does
#UndefinedTensor.__eq__ = lambda s, o: (isinstance(o, s.__class__) and 
#   


class AppliedTensor(AppliedUndef,Tensor):
    def __new__(cls, *args):
        obj = object.__new__(cls)
        obj._assumptions = cls.default_assumptions
        obj._mhash = None  # will be set by __hash__ method.

        if isinstance(args[0], tuple):
            obj.index = tuple(map(sympify, args[0]))
            obj._args= tuple(map(sympify, args[1:]))
        else:
            obj._args = ()
            obj.index = tuple(map(sympify, args))
        return obj

    def withNewIndex(self,*index):
        if not self.args:
            return type(self)(*index)
        l=[index]
        l.extend(self.args)
        return type(self)(*l)
        
    @property
    def indexAndArgs(self):
        if not self.args:
            return self.index
        l=[self.index]
        l.extend(self.args)
        return tuple(l)

    def __unicode__(self):
        return type(self).__name__ + unicode(self.indexAndArgs)

#    def __str__(self):
#        return type(self).__name__ + str(self.indexAndArgs)

#    def __repr__(self):
#        return type(self).__name__ + repr(self.indexAndArgs)

    def __eq__(self, other):
        return type(self)==type(other) and self.indexAndArgs==other.indexAndArgs

    def __hash__(self):
        return hash(str(self))

'''
Tensor is a copy of the contruction of Function with the addition .index() and .is_tensor

User guide: Put the indecis as an tupple, as the rist index in the TensorFunktion

Example1: To get the tensor $T_{a,b}$, witie:
>>> T=Tenosr('T')
>>> T((a,b))
Example2: To get the tensor $T_{a,b}(x,y)$, witie:
>>> T=Tenosr('T')
>>> T((a,b),x,y)

It is suggested to ouse the class Dummy for indecis and the class Symbol for ordinary variables, to keep them appart.
'''



import sympy.printing.str

def stringPrinter_Tensor(self,tensor):
    return type(tensor).__name__ + str(tensor.indexAndArgs)

sympy.printing.str.StrPrinter._print_Tensor=stringPrinter_Tensor
    <commit_msg>Just some comments, I think<commit_after>from sympy.core.function import Function, UndefinedFunction, AppliedUndef, Application, FunctionClass
from sympy.core.cache import cacheit
from sympy.core.core import BasicMeta
from sympy.core.sympify import sympify
from sympy.core.expr import Expr

# this is the function used in other operations to check if something is a tensor.
def isTensor(x):
    return isinstance(x,Tensor)

class Tensor(Function):
    @cacheit
    def __new__(cls, *args, **options):
        # Handle calls like Tensor('F')
        if cls is Tensor:
            return UndefinedTensor(*args, **options)
    
    __slots__ = ['_mhash',              # hash value
                 '_args',               # arguments
                 '_assumptions'
                 'index'                # idecis
                ]

class UndefinedTensor(UndefinedFunction):

    def __new__(mcl, name, **kwargs):
        ret = BasicMeta.__new__(mcl, name, (AppliedTensor,), kwargs)
        ret.__module__ = None
        return ret



#    def __eq__(self, other):
#        return (isinstance(other, self.__class__) and (self.class_key() == other.class_key()))

#copy pased with UndefinedFunction -> UndefinedTensor. I have no idea what this does
#UndefinedTensor.__eq__ = lambda s, o: (isinstance(o, s.__class__) and 
#   


class AppliedTensor(AppliedUndef,Tensor):
    def __new__(cls, *args):
        obj = object.__new__(cls)
        obj._assumptions = cls.default_assumptions
        obj._mhash = None  # will be set by __hash__ method.

        if isinstance(args[0], tuple):
            obj.index = tuple(map(sympify, args[0]))
            obj._args= tuple(map(sympify, args[1:]))
        else:
            obj._args = ()
            obj.index = tuple(map(sympify, args))
        return obj

    def withNewIndex(self,*index):
        if not self.args:
            return type(self)(*index)
        l=[index]
        l.extend(self.args)
        return type(self)(*l)
        
    @property
    def indexAndArgs(self):
        if not self.args:
            return self.index
        l=[self.index]
        l.extend(self.args)
        return tuple(l)

    def __unicode__(self):
        return type(self).__name__ + unicode(self.indexAndArgs)

#    def __str__(self):
#        return type(self).__name__ + str(self.indexAndArgs)

#    def __repr__(self):
#        return type(self).__name__ + repr(self.indexAndArgs)

    def __eq__(self, other):
        return type(self)==type(other) and self.indexAndArgs==other.indexAndArgs

    def __hash__(self):
        return hash(str(self))

'''
Tensor is a copy of the contruction of Function with the addition .index() and .is_tensor

User guide: Put the indecis as an tupple, as the rist index in the TensorFunktion

Example1: To get the tensor $T_{a,b}$, witie:
>>> T=Tenosr('T')
>>> T((a,b))
Example2: To get the tensor $T_{a,b}(x,y)$, witie:
>>> T=Tenosr('T')
>>> T((a,b),x,y)

It is suggested to ouse the class Dummy for indecis and the class Symbol for ordinary variables, to keep them appart.
'''



import sympy.printing.str

def stringPrinter_Tensor(self,expr):
    return type(expr).__name__ + str(expr.indexAndArgs)

sympy.printing.str.StrPrinter._print_Tensor = stringPrinter_Tensor

# in ReprPrinter
#    def _print_Function(self, expr):
#        r = self._print(expr.func)
#        r += '(%s)' % ', '.join([self._print(a) for a in expr.args])
#        return r

# in StringPrinter 
#   def _print_Function(self, expr):
#        return expr.func.__name__ + "(%s)" % self.stringify(expr.args, ", ")

# sympy.printing.repr.ReprPrinter._print_Function = reprPrinter_Tensor
    
{'fraction_non_alphanumeric': 0.11481373690337601, 'fraction_numerical': 0.0014551804423748546, 'mean_word_length': 2.751637554585153, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4969483', 'n_tokens_mistral': 2168, 'n_tokens_neox': 2124, 'n_words': 576}