diff --git a/src/sage/tensor/modules/comp.py b/src/sage/tensor/modules/comp.py index 5fa035d5596..06d540168d8 100644 --- a/src/sage/tensor/modules/comp.py +++ b/src/sage/tensor/modules/comp.py @@ -5456,10 +5456,10 @@ def interior_product(self, other): raise TypeError("{} is not a fully antisymmetric ".format(other) + "set of components") if other._frame != self._frame: - raise ValueError("The {} are not defined on the ".format(other) + + raise ValueError("the {} are not defined on the ".format(other) + "same frame as the {}".format(self)) if other._nid < self._nid: - raise ValueError("The {} have less indices than ".format(other) + + raise ValueError("the {} have less indices than ".format(other) + "the {}".format(self)) # Number of indices of the result: res_nid = other._nid - self._nid diff --git a/src/sage/tensor/modules/format_utilities.py b/src/sage/tensor/modules/format_utilities.py index 011ec645f4c..0bfcd942006 100644 --- a/src/sage/tensor/modules/format_utilities.py +++ b/src/sage/tensor/modules/format_utilities.py @@ -29,7 +29,7 @@ from sage.misc.latex import LatexExpr -def is_atomic(expr, sep=['+', '-']): +def is_atomic(expr, sep=['+', '-']) -> bool: r""" Helper function to check whether some LaTeX expression is atomic. @@ -70,9 +70,24 @@ def is_atomic(expr, sep=['+', '-']): False sage: is_atomic("(a mod b)", sep=['mod']) True + + TESTS:: + + sage: is_atomic(1, sep=['*']) + Traceback (most recent call last): + ... + TypeError: the argument must be a string + sage: is_atomic("a*b", sep='*') + Traceback (most recent call last): + ... + TypeError: the argument 'sep' must be a list + sage: is_atomic("a*b", sep=[1]) + Traceback (most recent call last): + ... + TypeError: the argument 'sep' must consist of strings """ if not isinstance(expr, str): - raise TypeError("The argument must be a string") + raise TypeError("the argument must be a string") if not isinstance(sep, list): raise TypeError("the argument 'sep' must be a list") elif any(not isinstance(s, str) for s in sep): @@ -91,7 +106,7 @@ def is_atomic(expr, sep=['+', '-']): return True -def is_atomic_wedge_txt(expression): +def is_atomic_wedge_txt(expression) -> bool: r""" Helper function to check whether some text-formatted expression is atomic in terms of wedge products. diff --git a/src/sage/tensor/modules/tensor_with_indices.py b/src/sage/tensor/modules/tensor_with_indices.py index f6c15e72b45..b7753e1bfbc 100644 --- a/src/sage/tensor/modules/tensor_with_indices.py +++ b/src/sage/tensor/modules/tensor_with_indices.py @@ -331,33 +331,33 @@ def _parse_indices(indices, tensor_type=None, allow_contraction=True, IndexError: no symmetry allowed """ # Suppress all '{' and '}' coming from LaTeX notations: - indices = indices.replace('{','').replace('}','') + indices = indices.replace('{', '').replace('}', '') # Check index notation conventions and parse indices allowed_pattern = r"(\(" + _alph_or_dot_pattern + r"{2,}\)|\[" + _alph_or_dot_pattern + r"{2,}\]|" + _alph_or_dot_pattern + r"+)*" con_then_cov = r"^(\^|)" + allowed_pattern + r"(\_" + allowed_pattern + r"|)$" cov_then_con = r"^\_" + allowed_pattern + r"(\^" + allowed_pattern + r"|)$" - if (re.match(con_then_cov,indices) is None - and re.match(cov_then_con,indices) is None): + if (re.match(con_then_cov, indices) is None + and re.match(cov_then_con, indices) is None): raise ValueError("index conventions not satisfied") - elif re.match(con_then_cov,indices): + elif re.match(con_then_cov, indices): try: - con,cov = indices.replace("^","").split("_") + con, cov = indices.replace("^", "").split("_") except ValueError: - con = indices.replace("^","") + con = indices.replace("^", "") cov = "" else: try: - cov,con = indices.replace("_","").split("^") + cov, con = indices.replace("_", "").split("^") except ValueError: - cov = indices.replace("_","") + cov = indices.replace("_", "") con = "" if not allow_contraction: for ind in con: if ind != '.' and ind in cov: raise IndexError("no contraction allowed") - con_without_sym = (con.replace("(","").replace(")","").replace("[","").replace("]","")) - cov_without_sym = (cov.replace("(","").replace(")","").replace("[","").replace("]","")) + con_without_sym = (con.replace("(", "").replace(")", "").replace("[", "").replace("]", "")) + cov_without_sym = (cov.replace("(", "").replace(")", "").replace("[", "").replace("]", "")) if allow_symmetries: if len(con_without_sym) != len(set(con_without_sym)) \ + max(con_without_sym.count(".")-1, 0): @@ -368,9 +368,9 @@ def _parse_indices(indices, tensor_type=None, allow_contraction=True, raise ValueError("index conventions not satisfied: " "repeated indices of same type") else: - if re.search(r"[()\[\]]",con) is not None: + if re.search(r"[()\[\]]", con) is not None: raise IndexError("no symmetry allowed") - if re.search(r"[()\[\]]",cov) is not None: + if re.search(r"[()\[\]]", cov) is not None: raise IndexError("no symmetry allowed") if tensor_type is not None: # Check number of (co/contra)variant indices @@ -380,7 +380,7 @@ def _parse_indices(indices, tensor_type=None, allow_contraction=True, if len(cov_without_sym) != tensor_type[1]: raise IndexError("number of covavariant indices not compatible " "with the tensor type") - return con,cov + return con, cov def __init__(self, tensor, indices): r""" @@ -419,15 +419,15 @@ def __init__(self, tensor, indices): # Latex notations '{' and '}' are totally ignored. # "^{ijkl}_{ib(cd)}" - con,cov = self._parse_indices( + con, cov = self._parse_indices( indices, tensor_type=self._tensor.tensor_type() ) # Apply (anti)symmetrizations on contravariant indices first_sym_regex = r"(\(|\[)" + _alph_or_dot_pattern + r"*[)\]]" - while re.search(first_sym_regex,con): - first_sym = re.search(first_sym_regex,con) + while re.search(first_sym_regex, con): + first_sym = re.search(first_sym_regex, con) sym1 = first_sym.span()[0] sym2 = first_sym.span()[1]-1 if first_sym.groups()[0] == "(": @@ -440,13 +440,13 @@ def __init__(self, tensor, indices): sym1, sym2-1 )) - self._changed = True # self does no longer contain the original tensor + self._changed = True # self does no longer contain the original tensor con = con[:sym1] + con[sym1+1:sym2] + con[sym2+1:] self._con = con # Apply (anti)symmetrizations on covariant indices - while re.search(first_sym_regex,cov): - first_sym = re.search(first_sym_regex,cov) + while re.search(first_sym_regex, cov): + first_sym = re.search(first_sym_regex, cov) sym1 = first_sym.span()[0] sym2 = first_sym.span()[1]-1 if first_sym.groups()[0] == "(": @@ -697,16 +697,16 @@ def __add__(self, other): """ # Check tensor types are compatible if self._tensor.tensor_type() != other._tensor.tensor_type(): - raise ValueError("Tensors are not of the same type") + raise ValueError("tensors are not of the same type") # Check the set of indices are compatible if set(self._cov) != set(other._cov): - raise ValueError("The covariant Indices sets are not identical") + raise ValueError("the covariant Indices sets are not identical") if set(self._con) != set(other._con): - raise ValueError("The contravariant Indices sets are not identical") + raise ValueError("the contravariant Indices sets are not identical") self_wild_card_indices = [match.span()[0] for match in re.finditer(r"\.", self._con)] other_wild_card_indices = [match.span()[0] for match in re.finditer(r"\.", self._cov)] if self_wild_card_indices != other_wild_card_indices: - raise ValueError("Ambiguous wildcard notation") + raise ValueError("ambiguous wildcard notation") # Permutation of the components of self # ------------------------------------- @@ -850,12 +850,12 @@ def __setitem__(self, args, value): True """ if isinstance(args, str): - if not isinstance(value,TensorWithIndices): - raise ValueError("The tensor provided should be with indices") + if not isinstance(value, TensorWithIndices): + raise ValueError("the tensor provided should be with indices") elif self._tensor.tensor_type() != value._tensor.tensor_type(): - raise ValueError("The tensors are not of the same type") + raise ValueError("the tensors are not of the same type") else: - con,cov = self._parse_indices( + con, cov = self._parse_indices( args, tensor_type=self._tensor.tensor_type(), allow_symmetries=False, @@ -878,7 +878,7 @@ def __setitem__(self, args, value): self._tensor[:] = value.permute_indices(permutation)[:] else: - self._tensor.__setitem__(args,value) + self._tensor.__setitem__(args, value) def permute_indices(self, permutation): r""" @@ -938,8 +938,8 @@ def permute_indices(self, permutation): # The associated permutation is as follows def swap(param, N): - i,j,k = param - L = list(range(1,N+1)) + i, j, k = param + L = list(range(1, N+1)) L = L[:i] + L[j:k] + L[i:j] + L[k:] return L @@ -960,7 +960,7 @@ def swap(param, N): decomposition_as_string = [ # Two cases whether the term appear with an exponent or not ("^" in term)*term.split("^") + ("^" not in term)*(term.split("^")+['1']) - for term in decomposition_as_string.replace("x","").split("*") + for term in decomposition_as_string.replace("x", "").split("*") ] decomposition = [(swap_params[int(x)-1], int(y)) for x, y in decomposition_as_string] decomposition.reverse() # /!\ The symmetric group acts on the right by default /!\. @@ -972,7 +972,7 @@ def swap(param, N): # Swap of components swaped_components = self._tensor.comp(basis) - for swap_param,exponent in decomposition: + for swap_param, exponent in decomposition: if exponent > 0: for i in range(exponent): # Apply the swap given by swap_param