Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

This will not be a short answer, so let me better first address the shorter issues.

  • A possible IDE to use for debugging purposes is eclipse, install also pydev as plugin inside. This worked for me a long time. Some post that shows how to combine sage devel in eclipse+pydev is here:

    my sage+eclipse+pydev solution (posted as error)

    For short: The IDE must (or should) be started from the terminal, e.g. eclipse &, after setting via

    `sage -sh`
    

in the "sage shell" all system variables to be used. Inside eclipse, each module should have the usual from sage.all import *, and if sage is configured as python interpreter (instead python2.7), than there may be also some change needed... (The problem in the above post.) Important note: There is no preparsing, so things may become delicate. E.g. the p = 2^8-1 is rejected in eclipse, instead, the code should be written as p = 2**8-1, which is accepted in both worlds, sage and python2. Also, the "intervall" [1..10] does exist only after preparsing, and it is a list of ZZ-numbers, not a list of python integers. A simple replacement of [1..10] by the "naive" range(1,11) may thus fail for "unexpected reasons" in eclipse, although sage may load the code without errors... So this was one of the short issues.

  • A deviation / derivative of eclipse is LiClipse, not free... Never tried it, but one may expect also support after paying for it!

  • An other IDE for python can be used, pycharm. The same discussion as in the case of eclipse applies for it. Here is my parallel answer for the pycharm world:

    38750/how-i-use-sage-with-pycharm-in-ubuntu/

  • the sage (iron python) interpreter is my best friend. Just copy+paste (using %cpaste) short pieces of code, or load bigger chunks. (Or install even bigger ones as packages.) There is an automatic TAB-completion for methods, which makes it productive in a different way, compared with a good editor as emacs, my choice. (I could not make emacsconsume the code. Yet.)

  • And the rest of the post goes to pytest.

The following strategy worked for me, some pytest test sage code could be digested as follows.

First of all, i installed pytest for the python2.7 interpreter. (Default is to use it for python3.) On this manjaro machine i installed the package python2-pytest in version 3,3,2-1 from the community manjaro repository. (This is thus an official manjaro package, and sage is also an official one in this distro! I'll stay with it...)

Then in a terminal: sage -sh - same game as for eclipse and pycharm, this sets all related SAGE paths and libraries. (Environment variables.) The prompter changes correspondingly.

With the new prompter i started:

(sage-sh) dan@k7:asksage$ python2.7 -m pytest pytest_sagetest.py

i.e. the command python2.7 -m pytest pytest_sagetest.py from the folder asksage where the file pytest_sagetest.py with the following content lives in:

# content of pytest_sagetest.py

from sage.all import *

def test_HasseBoundTest():
    """"Test the computations of the order of an elliptic curve
    by testing if it stays in the Hasse interval.
    """
    p = 127
    F = GF(p)
    for a in GF(p):
        try:
            E = EllipticCurve( F, [a,0] )
        except Exception:
            continue
        ord = E.order()
        # lower bound check
        assert( ord >= p + 1 - 2*sqrt(p) )
        assert( ord <= p + 1 + 2*sqrt(p) )

def test_LowerHasseBoundTaken():
    p = next_prime(100)
    F = GF(p)
    orders = []
    for a in F:
        for b in F:
            try:
                E = EllipticCurve( F, [a,b] )
            except Exception:
                pass    # discriminant is zero...
        ord = E.order()
        if ord not in orders:
            orders.append( ord )
        # lower bound check
    assert( min(orders) ==  ceil(p + 1 - 2*sqrt(p)) )
    assert( max(orders) == floor(p + 1 + 2*sqrt(p)) )


def test_AllOrdersTaken():
    p = 71
    F = GF(p)
    orders = []
    for a in F:
        for b in F:
            try:
                E = EllipticCurve( F, [a,b] )
            except Exception:
                pass    # discriminant is zero...
        ord = E.order()
        if ord not in orders:
            orders.append( ord )
        # lower bound check
    orders.sort()
    assert( orders == range( ceil (p + 1 - 2*sqrt(p)) ,
                             floor(p + 1 + 2*sqrt(p)) + 1 ) )

It was an intention to produce "errors". (Of course, some not so intentioned errors are also present... Since we want more errors, they remained in the landscape.) Then the pytest digestive delivers the following information:

(sage-sh) dan@k7:asksage$ python2.7 -m pytest pytest_sagetest.py
================================ test session starts ================================
platform linux2 -- Python 2.7.14, pytest-3.3.2, py-1.5.0, pluggy-0.6.0
rootdir: /home/dan/asksage/asksage, inifile:
collected 3 items                                                                   

pytest_sagetest.py .FF                                                        [100%]

===================================== FAILURES ======================================
_____________________________ test_LowerHasseBoundTaken _____________________________

    def test_LowerHasseBoundTaken():
        p = next_prime(100)
        F = GF(p)
        orders = []
        for a in F:
            for b in F:
                try:
                    E = EllipticCurve( F, [a,b] )
                except Exception:
                    pass    # discriminant is zero...
            ord = E.order()
            if ord not in orders:
                orders.append( ord )
            # lower bound check
>       assert( min(orders) ==  ceil(p + 1 - 2*sqrt(p)) )
E       assert 83 == 82
E        +  where 83 = min([102, 105, 92, 114, 112, 87, ...])
E        +  and   82 = ceil(((101 + 1) - (2 * sqrt(101))))
E        +    where sqrt(101) = sqrt(101)

pytest_sagetest.py:37: AssertionError
________________________________ test_AllOrdersTaken ________________________________

    def test_AllOrdersTaken():
        p = 71
        F = GF(p)
        orders = []                                                                  
        for a in F:                                                                  
            for b in F:                                                              
                try:                                                                 
                    E = EllipticCurve( F, [a,b] )                                    
                except Exception:                                                    
                    pass    # discriminant is zero...                                
            ord = E.order()                                                          
            if ord not in orders:                                                    
                orders.append( ord )                                                 
            # lower bound check                                                      
        orders.sort()
>       assert( orders == range( ceil (p + 1 - 2*sqrt(p)) ,
                                 floor(p + 1 + 2*sqrt(p)) + 1 ) )
E       assert [56, 57, 59, 60, 61, 62, ...] == [56, 57, 58, 59, 60, 61, ...]
E         At index 2 diff: 59 != 58
E         Right contains more items, first extra item: 85
E         Use -v to get the full diff

pytest_sagetest.py:56: AssertionError
================================= warnings summary ==================================
pytest_sagetest.py::TestSuite
  cannot collect test class 'TestSuite' because it has a __init__ constructor

-- Docs: http://doc.pytest.org/en/latest/warnings.html
================== 2 failed, 1 passed, 1 warnings in 7.43 seconds ===================
(sage-sh) dan@k7:asksage$

(And here there is a lot of colourful highlight gone. Just start in a proper termina...)

Note: pytest is rather a "unit test" tool, it may be used in a "test driven devel" process. Personally, for my research this is too much (i.e. life is too short). But this is of huge importance while for devel+maintain of the packages. Sage has also a proper mechanism for doing this. In fact, after installing sage one has already the chance to test it against the unit test code sage comes with...

This will not be a short answer, so let me better first address the shorter issues.

  • A possible IDE to use for debugging purposes is eclipse, install also pydev as plugin inside. This worked for me a long time. Some post that shows how to combine sage devel in eclipse+pydev is here:

    my sage+eclipse+pydev solution (posted as error)

    For short: The IDE must (or should) be started from the terminal, e.g. eclipse &, after setting via

    `sage -sh`
    

in the "sage shell" all system variables to be used. Inside eclipse, each module should have the usual from sage.all import *, and if sage is configured as python interpreter (instead python2.7), than there may be also some change needed... (The problem in the above post.) Important note: There is no preparsing, so things may become delicate. E.g. the p = 2^8-1 is rejected in eclipse, instead, the code should be written as p = 2**8-1, which is accepted in both worlds, sage and python2. Also, the "intervall" [1..10] does exist only after preparsing, and it is a list of ZZ-numbers, not a list of python integers. A simple replacement of [1..10] by the "naive" range(1,11) may thus fail for "unexpected reasons" in eclipse, although sage may load the code without errors... So this was one of the short issues.

  • A deviation / derivative of eclipse is LiClipse, not free... Never tried it, but one may expect also support after paying for it!

  • An other IDE for python can be used, pycharm. The same discussion as in the case of eclipse applies for it. Here is my parallel answer for the pycharm world:

    38750/how-i-use-sage-with-pycharm-in-ubuntu/

  • the sage (iron python) interpreter is my best friend. Just copy+paste (using %cpaste) short pieces of code, or load bigger chunks. (Or install even bigger ones as packages.) There is an automatic TAB-completion for methods, which makes it productive in a different way, compared with a good editor as emacs, my choice. (I could not make emacsconsume the code. Yet.)

  • And the rest of the post goes to pytest.

The following strategy worked for me, some pytest test sage code could be digested as follows.

First of all, i installed pytest for the python2.7 interpreter. (Default is to use it for python3.) On this manjaro machine i installed the package python2-pytest in version 3,3,2-1 from the community manjaro repository. (This is thus an official manjaro package, and sage is also an official one in this distro! I'll stay with it...)

Then in a terminal: sage -sh - same game as for eclipse and pycharm, this sets all related SAGE paths and libraries. (Environment variables.) The prompter changes correspondingly.

With the new prompter i started:

(sage-sh) dan@k7:asksage$ python2.7 -m pytest pytest_sagetest.py

i.e. the command python2.7 -m pytest pytest_sagetest.py from the folder asksage where the file pytest_sagetest.py with the following content lives in:

# content of pytest_sagetest.py

from sage.all import *

def test_HasseBoundTest():
    """"Test """Test the computations of the order of an elliptic curve
    by testing if it stays in the Hasse interval.
    """
    p = 127
    F = GF(p)
    for a in GF(p):
        try:
            E = EllipticCurve( F, [a,0] )
        except Exception:
            continue
        ord = E.order()
        # lower bound check
        assert( ord >= p + 1 - 2*sqrt(p) )
        assert( ord <= p + 1 + 2*sqrt(p) )

def test_LowerHasseBoundTaken():
    p = next_prime(100)
    F = GF(p)
    orders = []
    for a in F:
        for b in F:
            try:
                E = EllipticCurve( F, [a,b] )
            except Exception:
                pass    # discriminant is zero...
        ord = E.order()
        if ord not in orders:
            orders.append( ord )
        # lower bound check
    assert( min(orders) ==  ceil(p + 1 - 2*sqrt(p)) )
    assert( max(orders) == floor(p + 1 + 2*sqrt(p)) )


def test_AllOrdersTaken():
    p = 71
    F = GF(p)
    orders = []
    for a in F:
        for b in F:
            try:
                E = EllipticCurve( F, [a,b] )
            except Exception:
                pass    # discriminant is zero...
        ord = E.order()
        if ord not in orders:
            orders.append( ord )
        # lower bound check
    orders.sort()
    assert( orders == range( ceil (p + 1 - 2*sqrt(p)) ,
                             floor(p + 1 + 2*sqrt(p)) + 1 ) )

It was an intention to produce "errors". (Of course, some not so intentioned errors are also present... Since we want more errors, they remained in the landscape.) Then the pytest digestive delivers the following information:

(sage-sh) dan@k7:asksage$ python2.7 -m pytest pytest_sagetest.py
================================ test session starts ================================
platform linux2 -- Python 2.7.14, pytest-3.3.2, py-1.5.0, pluggy-0.6.0
rootdir: /home/dan/asksage/asksage, inifile:
collected 3 items                                                                   

pytest_sagetest.py .FF                                                        [100%]

===================================== FAILURES ======================================
_____________________________ test_LowerHasseBoundTaken _____________________________

    def test_LowerHasseBoundTaken():
        p = next_prime(100)
        F = GF(p)
        orders = []
        for a in F:
            for b in F:
                try:
                    E = EllipticCurve( F, [a,b] )
                except Exception:
                    pass    # discriminant is zero...
            ord = E.order()
            if ord not in orders:
                orders.append( ord )
            # lower bound check
>       assert( min(orders) ==  ceil(p + 1 - 2*sqrt(p)) )
E       assert 83 == 82
E        +  where 83 = min([102, 105, 92, 114, 112, 87, ...])
E        +  and   82 = ceil(((101 + 1) - (2 * sqrt(101))))
E        +    where sqrt(101) = sqrt(101)

pytest_sagetest.py:37: AssertionError
________________________________ test_AllOrdersTaken ________________________________

    def test_AllOrdersTaken():
        p = 71
        F = GF(p)
        orders = []                                                                  
        for a in F:                                                                  
            for b in F:                                                              
                try:                                                                 
                    E = EllipticCurve( F, [a,b] )                                    
                except Exception:                                                    
                    pass    # discriminant is zero...                                
            ord = E.order()                                                          
            if ord not in orders:                                                    
                orders.append( ord )                                                 
            # lower bound check                                                      
        orders.sort()
>       assert( orders == range( ceil (p + 1 - 2*sqrt(p)) ,
                                 floor(p + 1 + 2*sqrt(p)) + 1 ) )
E       assert [56, 57, 59, 60, 61, 62, ...] == [56, 57, 58, 59, 60, 61, ...]
E         At index 2 diff: 59 != 58
E         Right contains more items, first extra item: 85
E         Use -v to get the full diff

pytest_sagetest.py:56: AssertionError
================================= warnings summary ==================================
pytest_sagetest.py::TestSuite
  cannot collect test class 'TestSuite' because it has a __init__ constructor

-- Docs: http://doc.pytest.org/en/latest/warnings.html
================== 2 failed, 1 passed, 1 warnings in 7.43 seconds ===================
(sage-sh) dan@k7:asksage$

(And here there is a lot of colourful highlight gone. Just start in a proper termina...)

Note: pytest is rather a "unit test" tool, it may be used in a "test driven devel" process. Personally, for my research this is too much (i.e. life is too short). But this is of huge importance while for devel+maintain of the packages. Sage has also a proper mechanism for doing this. In fact, after installing sage one has already the chance to test it against the unit test code sage comes with...

This will not be a short answer, so let me better first address the shorter issues.

  • A possible IDE to use for debugging purposes is eclipse, install also pydev as plugin inside. This worked for me a long time. Some post that shows how to combine sage devel in eclipse+pydev is here:

    my sage+eclipse+pydev solution (posted as error)

    For short: The IDE must (or should) be started from the terminal, e.g. eclipse &, after setting via

    `sage -sh`
    

    in the "sage shell" all system variables to be used. Inside eclipse, each module should have the usual from sage.all import *, and if sage is configured as python interpreter (instead python2.7), than there may be also some change needed... (The problem in the above post.) Important note: There is no preparsing, so things may become delicate. E.g. the p = 2^8-1 is rejected in eclipse, instead, the code should be written as p = 2**8-1, which is accepted in both worlds, sage and python2. Also, the "intervall" [1..10] does exist only after preparsing, and it is a list of ZZ-numbers, not a list of python integers. A simple replacement of [1..10] by the "naive" range(1,11) may thus fail for "unexpected reasons" in eclipse, although sage may load the code without errors... So this was one of the short issues.

  • A deviation / derivative of eclipse is LiClipse, not free... Never tried it, but one may expect also support after paying for it!

  • An other IDE for python can be used, pycharm. The same discussion as in the case of eclipse applies for it. Here is my parallel answer for the pycharm world:

    38750/how-i-use-sage-with-pycharm-in-ubuntu/

  • the sage (iron python) interpreter is my best friend. Just copy+paste (using %cpaste) short pieces of code, or load bigger chunks. (Or install even bigger ones as packages.) There is an automatic TAB-completion for methods, which makes it productive in a different way, compared with a good editor as emacs, my choice. (I could not make emacsconsume the code. Yet.)

  • And the rest of the post goes to pytest.

The following strategy worked for me, some pytest test sage code could be digested as follows.

First of all, i installed pytest for the python2.7 interpreter. (Default is to use it for python3.) On this manjaro machine i installed the package python2-pytest in version 3,3,2-1 from the community manjaro repository. (This is thus an official manjaro package, and sage is also an official one in this distro! I'll stay with it...)

Then in a terminal: sage -sh - same game as for eclipse and pycharm, this sets all related SAGE paths and libraries. (Environment variables.) The prompter changes correspondingly.

With the new prompter i started:

(sage-sh) dan@k7:asksage$ python2.7 -m pytest pytest_sagetest.py

i.e. the command python2.7 -m pytest pytest_sagetest.py from the folder asksage where the file pytest_sagetest.py with the following content lives in:

# content of pytest_sagetest.py

from sage.all import *

def test_HasseBoundTest():
    """Test the computations of the order of an elliptic curve
    by testing if it stays in the Hasse interval.
    """
    p = 127
    F = GF(p)
    for a in GF(p):
        try:
            E = EllipticCurve( F, [a,0] )
        except Exception:
            continue
        ord = E.order()
        # lower bound check
        assert( ord >= p + 1 - 2*sqrt(p) )
        assert( ord <= p + 1 + 2*sqrt(p) )

def test_LowerHasseBoundTaken():
    p = next_prime(100)
    F = GF(p)
    orders = []
    for a in F:
        for b in F:
            try:
                E = EllipticCurve( F, [a,b] )
            except Exception:
                pass    # discriminant is zero...
        ord = E.order()
        if ord not in orders:
            orders.append( ord )
        # lower bound check
    assert( min(orders) ==  ceil(p + 1 - 2*sqrt(p)) )
    assert( max(orders) == floor(p + 1 + 2*sqrt(p)) )


def test_AllOrdersTaken():
    p = 71
    F = GF(p)
    orders = []
    for a in F:
        for b in F:
            try:
                E = EllipticCurve( F, [a,b] )
            except Exception:
                pass    # discriminant is zero...
        ord = E.order()
        if ord not in orders:
            orders.append( ord )
        # lower bound check
    orders.sort()
    assert( orders == range( ceil (p + 1 - 2*sqrt(p)) ,
                             floor(p + 1 + 2*sqrt(p)) + 1 ) )

It was an intention to produce "errors". (Of course, some not so intentioned errors are also present... Since we want more errors, they remained in the landscape.) Then the pytest digestive delivers the following information:

(sage-sh) dan@k7:asksage$ python2.7 -m pytest pytest_sagetest.py
================================ test session starts ================================
platform linux2 -- Python 2.7.14, pytest-3.3.2, py-1.5.0, pluggy-0.6.0
rootdir: /home/dan/asksage/asksage, inifile:
collected 3 items                                                                   

pytest_sagetest.py .FF                                                        [100%]

===================================== FAILURES ======================================
_____________________________ test_LowerHasseBoundTaken _____________________________

    def test_LowerHasseBoundTaken():
        p = next_prime(100)
        F = GF(p)
        orders = []
        for a in F:
            for b in F:
                try:
                    E = EllipticCurve( F, [a,b] )
                except Exception:
                    pass    # discriminant is zero...
            ord = E.order()
            if ord not in orders:
                orders.append( ord )
            # lower bound check
>       assert( min(orders) ==  ceil(p + 1 - 2*sqrt(p)) )
E       assert 83 == 82
E        +  where 83 = min([102, 105, 92, 114, 112, 87, ...])
E        +  and   82 = ceil(((101 + 1) - (2 * sqrt(101))))
E        +    where sqrt(101) = sqrt(101)

pytest_sagetest.py:37: AssertionError
________________________________ test_AllOrdersTaken ________________________________

    def test_AllOrdersTaken():
        p = 71
        F = GF(p)
        orders = []                                                                  
        for a in F:                                                                  
            for b in F:                                                              
                try:                                                                 
                    E = EllipticCurve( F, [a,b] )                                    
                except Exception:                                                    
                    pass    # discriminant is zero...                                
            ord = E.order()                                                          
            if ord not in orders:                                                    
                orders.append( ord )                                                 
            # lower bound check                                                      
        orders.sort()
>       assert( orders == range( ceil (p + 1 - 2*sqrt(p)) ,
                                 floor(p + 1 + 2*sqrt(p)) + 1 ) )
E       assert [56, 57, 59, 60, 61, 62, ...] == [56, 57, 58, 59, 60, 61, ...]
E         At index 2 diff: 59 != 58
E         Right contains more items, first extra item: 85
E         Use -v to get the full diff

pytest_sagetest.py:56: AssertionError
================================= warnings summary ==================================
pytest_sagetest.py::TestSuite
  cannot collect test class 'TestSuite' because it has a __init__ constructor

-- Docs: http://doc.pytest.org/en/latest/warnings.html
================== 2 failed, 1 passed, 1 warnings in 7.43 seconds ===================
(sage-sh) dan@k7:asksage$

(And here there is a lot of colourful highlight gone. Just start in a proper termina...)

Note: pytest is rather a "unit test" tool, it may be used in a "test driven devel" process. Personally, for my research this is too much (i.e. life is too short). But this is of huge importance while for devel+maintain of the packages. Sage has also a proper mechanism for doing this. In fact, after installing sage one has already the chance to test it against the unit test code sage comes with...

LATER EDIT :: import issues

Note that pytest has a specific way to use a python path.

https://docs.pytest.org/en/latest/pythonpath.html

There is even a package pytest-pythonpath that may make complicated things easier.

https://pypi.python.org/pypi/pytest-pythonpath

In our case, a simplistic situation as the following one could import a module (in the same directory).

Here is the situation:

[dan@k7 ~/asksage/asksage]$ ls tests
mycomputations.py  test_sage.py
[dan@k7 ~/asksage/asksage]$ cat tests/mycomputations.py 
# content of mycomputations.py
from sage.all import *

def PythonInteger(k):
    return int(k)

def ZZInteger(k):
    return ZZ(k)
[dan@k7 ~/asksage/asksage]$ cat tests/test_sage.py 
# content of test_sage.py
from sage.all import *
import mycomputations

def test_type1():
    a = mycomputations.PythonInteger(100)
    assert type(a) == type(ZZ(0))

def test_type2():
    a = mycomputations.ZZInteger(100)
    assert type(a) == type(ZZ(0))

[dan@k7 ~/asksage/asksage]$

Then:

[dan@k7 ~/asksage/asksage]$ pytest2 tests
======================== test session starts =========================
platform linux2 -- Python 2.7.14, pytest-3.3.2, py-1.5.0, pluggy-0.6.0
rootdir: /home/dan/asksage/asksage, inifile:
collected 2 items                                                    

tests/test_sage.py F.                                          [100%]

============================== FAILURES ==============================
_____________________________ test_type1 _____________________________

    def test_type1():
        a = mycomputations.PythonInteger(100)
>       assert type(a) == type(ZZ(0))
E       AssertionError: assert <type 'int'> == <type 'sage.rings.integer.Integer'>
E        +  where <type 'int'> = type(100)
E        +  and   <type 'sage.rings.integer.Integer'> = type(0)
E        +    where 0 = ZZ(0)

tests/test_sage.py:7: AssertionError
========================== warnings summary ==========================
tests/test_sage.py::TestSuite
  cannot collect test class 'TestSuite' because it has a __init__ constructor

-- Docs: http://doc.pytest.org/en/latest/warnings.html
=========== 1 failed, 1 passed, 1 warnings in 3.69 seconds ===========
[dan@k7 ~/asksage/asksage]$

More complicated unit test situations are covered by the pytest documentation / framework. If such issues remain, please consider using an IDE, eclipse and/or pycharm, both are comming with a supported unit test environment.

The post also mentions (asks for) debugging possibilities, same answer, eclipse+pydev and/or pycharm so far.

Personal note: People that have not used such IDEs (e.g. because having a pure mathematical formation and/or because using rather the notebook part of sage) will discover a new world with good productivity mechanisms.