Repository: sympy/sympy

Issue:
Update documentation, Wiki, README to not use git://
See https://github.blog/2021-09-01-improving-git-protocol-security-github/

I do not really know which combinations we should encourage instead.

Discussion:

Patch:
diff --git a/README.md b/README.md
index b4152c14a4..db5a0e2304 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ You can also get the latest version of SymPy from
 
 To get the git version do
 
-    $ git clone git://github.com/sympy/sympy.git
+    $ git clone https://github.com/sympy/sympy.git
 
 For other options (tarballs, debs, etc.), see
 <https://docs.sympy.org/dev/install.html>.
diff --git a/release/Dockerfile b/release/Dockerfile
index 0ae128cee3..abc0337994 100644
--- a/release/Dockerfile
+++ b/release/Dockerfile
@@ -19,7 +19,7 @@ ENV MATPLOTLIBRC=/root/matplotlibrc
 RUN mkdir -p $MATPLOTLIBRC
 RUN echo "backend : Agg" > $MATPLOTLIBRC/matplotlibrc
 
-RUN git clone git://github.com/sympy/sympy.git
+RUN git clone https://github.com/sympy/sympy.git
 
 WORKDIR /root/sympy/release
 
diff --git a/sympy/abc.py b/sympy/abc.py
index 177e8902e7..050f3da126 100644
--- a/sympy/abc.py
+++ b/sympy/abc.py
@@ -57,7 +57,6 @@
 
 from .core import Symbol, symbols
 from .core.alphabets import greeks
-from sympy.parsing.sympy_parser import null
 
 ##### Symbol definitions #####
 
@@ -99,13 +98,13 @@
 while ns:
     _k, _ = ns.popitem()
     if _k in _greek:
-        _clash2[_k] = null
+        _clash2[_k] = None
         _greek.remove(_k)
     elif _k in _latin:
-        _clash1[_k] = null
+        _clash1[_k] = None
         _latin.remove(_k)
 _clash = {}
 _clash.update(_clash1)
 _clash.update(_clash2)
 
-del _latin, _greek, Symbol, _k, null
+del _latin, _greek, Symbol, _k
diff --git a/sympy/core/add.py b/sympy/core/add.py
index 41b5728fb8..890d313692 100644
--- a/sympy/core/add.py
+++ b/sympy/core/add.py
@@ -613,8 +613,6 @@ def as_numer_denom(self):
         """
         # clear rational denominator
         content, expr = self.primitive()
-        if not isinstance(expr, Add):
-            return Mul(content, expr, evaluate=False).as_numer_denom()
         ncon, dcon = content.as_numer_denom()
 
         # collect numerators and denominators of the terms
diff --git a/sympy/core/relational.py b/sympy/core/relational.py
index 3f551dda33..7a4be766fd 100644
--- a/sympy/core/relational.py
+++ b/sympy/core/relational.py
@@ -578,8 +578,7 @@ def _eval_rewrite_as_Add(self, *args, **kwargs):
         the result set pass `evaluate=True` to give L - R;
         if `evaluate=None` then terms in L and R will not cancel
         but they will be listed in canonical order; otherwise
-        non-canonical args will be returned. If one side is 0, the
-        non-zero side will be returned.
+        non-canonical args will be returned.
 
         Examples
         ========
@@ -596,10 +595,6 @@ def _eval_rewrite_as_Add(self, *args, **kwargs):
         """
         from .add import _unevaluated_Add, Add
         L, R = args
-        if L == 0:
-            return R
-        if R == 0:
-            return L
         evaluate = kwargs.get('evaluate', True)
         if evaluate:
             # allow cancellation of args
diff --git a/sympy/parsing/sympy_parser.py b/sympy/parsing/sympy_parser.py
index ae79514670..e403654cb4 100644
--- a/sympy/parsing/sympy_parser.py
+++ b/sympy/parsing/sympy_parser.py
@@ -20,8 +20,6 @@
 from sympy.functions.elementary.miscellaneous import Max, Min
 
 
-null = ''
-
 def _token_splittable(token):
     """
     Predicate for whether a token name can be split into multiple tokens.
@@ -561,11 +559,11 @@ def auto_symbol(tokens, local_dict, global_dict):
                     or (prevTok[0] == OP and prevTok[1] in ('(', ',')
                         and nextTokNum == OP and nextTokVal == '=')
                     # the name has already been defined
-                    or name in local_dict and local_dict[name] is not null):
+                    or name in local_dict and local_dict[name] is not None):
                 result.append((NAME, name))
                 continue
             elif name in local_dict:
-                local_dict.setdefault(null, set()).add(name)
+                local_dict.setdefault(None, set()).add(name)
                 if nextTokVal == '(':
                     local_dict[name] = Function(name)
                 else:
@@ -1048,8 +1046,6 @@ def parse_expr(s, local_dict=None, transformations=standard_transformations,
         local_dict = {}
     elif not isinstance(local_dict, dict):
         raise TypeError('expecting local_dict to be a dict')
-    elif null in local_dict:
-        raise ValueError('cannot use "" in local_dict')
 
     if global_dict is None:
         global_dict = {}
@@ -1094,13 +1090,13 @@ def parse_expr(s, local_dict=None, transformations=standard_transformations,
     try:
         rv = eval_expr(code, local_dict, global_dict)
         # restore neutral definitions for names
-        for i in local_dict.pop(null, ()):
-            local_dict[i] = null
+        for i in local_dict.pop(None, ()):
+            local_dict[i] = None
         return rv
     except Exception as e:
         # restore neutral definitions for names
-        for i in local_dict.pop(null, ()):
-            local_dict[i] = null
+        for i in local_dict.pop(None, ()):
+            local_dict[i] = None
         raise e from ValueError(f"Error from parse_expr with transformed code: {code!r}")
 
 
diff --git a/sympy/simplify/cse_main.py b/sympy/simplify/cse_main.py
index 88e3f9335e..d649dd02a9 100644
--- a/sympy/simplify/cse_main.py
+++ b/sympy/simplify/cse_main.py
@@ -567,7 +567,6 @@ def tree_cse(exprs, symbols, opt_subs=None, order='canonical', ignore=()):
         Substitutions containing any Symbol from ``ignore`` will be ignored.
     """
     from sympy.matrices.expressions import MatrixExpr, MatrixSymbol, MatMul, MatAdd
-    from sympy.matrices.expressions.matexpr import MatrixElement
     from sympy.polys.rootoftools import RootOf
 
     if opt_subs is None:
@@ -587,10 +586,7 @@ def _find_repeated(expr):
         if isinstance(expr, RootOf):
             return
 
-        if isinstance(expr, Basic) and (
-                expr.is_Atom or
-                expr.is_Order or
-                isinstance(expr, (MatrixSymbol, MatrixElement))):
+        if isinstance(expr, Basic) and (expr.is_Atom or expr.is_Order):
             if expr.is_Symbol:
                 excluded_symbols.add(expr)
             return


Test patch:
diff --git a/.github/workflows/runtests.yml b/.github/workflows/runtests.yml
index eed7f8f15d..b9b0cd2102 100644
--- a/.github/workflows/runtests.yml
+++ b/.github/workflows/runtests.yml
@@ -272,7 +272,7 @@ jobs:
         with:
           python-version: '3.9'
       - run: release/aptinstall.sh
-      - run: pip install -r doc/requirements.txt
+      - run: pip install -r release/requirements.txt
       - run: bin/test_sphinx.sh
 
 
diff --git a/sympy/core/tests/test_expr.py b/sympy/core/tests/test_expr.py
index eccb45ad90..b332f89d33 100644
--- a/sympy/core/tests/test_expr.py
+++ b/sympy/core/tests/test_expr.py
@@ -827,10 +827,6 @@ def test_as_numer_denom():
     assert ((A*B*C)**-1).as_numer_denom() == ((A*B*C)**-1, 1)
     assert ((A*B*C)**-1/x).as_numer_denom() == ((A*B*C)**-1, x)
 
-    # the following morphs from Add to Mul during processing
-    assert Add(0, (x + y)/z/-2, evaluate=False).as_numer_denom(
-        ) == (-x - y, 2*z)
-
 
 def test_trunc():
     import math
diff --git a/sympy/core/tests/test_relational.py b/sympy/core/tests/test_relational.py
index 57d5d65d2d..21fcaf9711 100644
--- a/sympy/core/tests/test_relational.py
+++ b/sympy/core/tests/test_relational.py
@@ -1034,9 +1034,6 @@ def test_Equality_rewrite_as_Add():
     assert eq.rewrite(Add) == 2*x
     assert eq.rewrite(Add, evaluate=None).args == (x, x, y, -y)
     assert eq.rewrite(Add, evaluate=False).args == (x, y, x, -y)
-    for e in (True, False, None):
-        assert Eq(x, 0, evaluate=e).rewrite(Add) == x
-        assert Eq(0, x, evaluate=e).rewrite(Add) == x
 
 
 def test_issue_15847():
diff --git a/sympy/core/tests/test_sympify.py b/sympy/core/tests/test_sympify.py
index 4e736bc341..3e4e9e0189 100644
--- a/sympy/core/tests/test_sympify.py
+++ b/sympy/core/tests/test_sympify.py
@@ -12,7 +12,6 @@
 from sympy.functions.elementary.trigonometric import (cos, sin)
 from sympy.logic.boolalg import (false, Or, true, Xor)
 from sympy.matrices.dense import Matrix
-from sympy.parsing.sympy_parser import null
 from sympy.polys.polytools import Poly
 from sympy.printing.repr import srepr
 from sympy.sets.fancysets import Range
@@ -541,7 +540,7 @@ def test_issue_6046():
     assert len(S('pi + x', locals=_clash2).free_symbols) == 2
     # but not both
     raises(TypeError, lambda: S('pi + pi(x)', locals=_clash2))
-    assert all(set(i.values()) == {null} for i in (
+    assert all(set(i.values()) == {None} for i in (
         _clash, _clash1, _clash2))
 
 
diff --git a/sympy/parsing/tests/test_sympy_parser.py b/sympy/parsing/tests/test_sympy_parser.py
index a03dd73952..2e326c576d 100644
--- a/sympy/parsing/tests/test_sympy_parser.py
+++ b/sympy/parsing/tests/test_sympy_parser.py
@@ -330,9 +330,3 @@ def test_builtins():
     for built_in_func_call, sympy_func_call in cases:
         assert parse_expr(built_in_func_call) == parse_expr(sympy_func_call)
     assert str(parse_expr('pow(38, -1, 97)')) == '23'
-
-
-def test_issue_22822():
-    raises(ValueError, lambda: parse_expr('x', {'': 1}))
-    data = {'some_parameter': None}
-    assert parse_expr('some_parameter is None', data) is True
diff --git a/sympy/simplify/tests/test_cse.py b/sympy/simplify/tests/test_cse.py
index ed6c97d72f..eb9cc23131 100644
--- a/sympy/simplify/tests/test_cse.py
+++ b/sympy/simplify/tests/test_cse.py
@@ -347,10 +347,6 @@ def test_cse_MatrixSymbol():
     B = MatrixSymbol("B", n, n)
     assert cse(B) == ([], [B])
 
-    assert cse(A[0] * A[0]) == ([], [A[0]*A[0]])
-
-    assert cse(A[0,0]*A[0,1] + A[0,0]*A[0,1]*A[0,2]) == ([(x0, A[0, 0]*A[0, 1])], [x0*A[0, 2] + x0])
-
 def test_cse_MatrixExpr():
     A = MatrixSymbol('A', 3, 3)
     y = MatrixSymbol('y', 3, 1)
diff --git a/sympy/utilities/tests/test_codegen.py b/sympy/utilities/tests/test_codegen.py
index f90d5eaa68..9d90e3d8a4 100644
--- a/sympy/utilities/tests/test_codegen.py
+++ b/sympy/utilities/tests/test_codegen.py
@@ -531,9 +531,26 @@ def test_multidim_c_argument_cse():
         '#include "test.h"\n'
         "#include <math.h>\n"
         "void c(double *A, double *b, double *out) {\n"
-        "   out[0] = A[0]*b[0] + A[1]*b[1] + A[2]*b[2];\n"
-        "   out[1] = A[3]*b[0] + A[4]*b[1] + A[5]*b[2];\n"
-        "   out[2] = A[6]*b[0] + A[7]*b[1] + A[8]*b[2];\n"
+        "   double x0[9];\n"
+        "   x0[0] = A[0];\n"
+        "   x0[1] = A[1];\n"
+        "   x0[2] = A[2];\n"
+        "   x0[3] = A[3];\n"
+        "   x0[4] = A[4];\n"
+        "   x0[5] = A[5];\n"
+        "   x0[6] = A[6];\n"
+        "   x0[7] = A[7];\n"
+        "   x0[8] = A[8];\n"
+        "   double x1[3];\n"
+        "   x1[0] = b[0];\n"
+        "   x1[1] = b[1];\n"
+        "   x1[2] = b[2];\n"
+        "   const double x2 = x1[0];\n"
+        "   const double x3 = x1[1];\n"
+        "   const double x4 = x1[2];\n"
+        "   out[0] = x2*x0[0] + x3*x0[1] + x4*x0[2];\n"
+        "   out[1] = x2*x0[3] + x3*x0[4] + x4*x0[5];\n"
+        "   out[2] = x2*x0[6] + x3*x0[7] + x4*x0[8];\n"
         "}\n"
     )
     assert code == expected