Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • SFIToolkit in v16.0

    This question is about the display and displayln methods of the SFIToolkit added in Stata version 16.

    According to the documentation, they are defined as:
    display(s[, asis]) Output a string to the Stata Results window.
    displayln(s[, asis]) Output a string to the Stata Results window and automatically add a line terminator at the end.
    Yet when I use them I find that display actually does what displayln is declared to do, and displayln adds yet another empty line.

    For example, the following code:

    Code:
      SFIToolkit.display('A') 
      SFIToolkit.display('B')
      SFIToolkit.display('C')
      SFIToolkit.display('D')
      SFIToolkit.displayln('.')
      SFIToolkit.display('X')
      SFIToolkit.displayln('Y')
      SFIToolkit.display('Z')
      SFIToolkit.display('T')
      SFIToolkit.display('.')
    Produces this output:
    Code:
    A
    B
    C
    D
    .
    
    X
    Y
    
    Z
    T
    .
    While my expectation is this:
    Code:
    ABCD.
    XY
    ZT.
    How do I tell SFIToolkit to continue the output in the same line??

    Thank you, Sergiy

  • #2
    It looks like the
    Code:
    sfi.SFIToolkit.display()
    function calls
    Code:
    sfi._stp._st_display()
    which has 3 arguments, the string, the "asis" and a line break. See the following.
    Code:
    . python
    ----------------------------------------------- python (type end to exit) --------------------------------------------------------------------------------
    >>> sfi._stp._st_display("boo", 0, 0)
    boo>>> sfi._stp._st_display("boo", 0, 1)
    boo
    >>> sfi._stp._st_display("boo", 1, 1)
    boo
    >>> sfi._stp._st_display("boo", 1, 0)
    boo>>> end
    
    .
    I think the current implementation of
    Code:
    sfi.SFIToolkit.display()
    may have an error.

    I say this as inspecting the code for display shows its last argument is a 1 - which should perhaps be a 0 to continue on the same line as the example above.

    Additionally, displayln has a 2, which may be a typo as I assume the function only takes 0 and 1 values.

    Code:
    . python
    ----------------------------------------------- python (type end to exit) --------------------------------------------------------------------------------
    >>> import inspect
    >>> sfi.SFIToolkit.display(inspect.getsource(sfi.SFIToolkit.displayln))
        @staticmethod
        def displayln(s, asis=False):
            """
            Output a string to the Stata Results window and automatically
            add a line terminator at the end. Before the string is printed,
            it is run through the Stata SMCL interpreter.
    
            Parameters
            ----------
            s : str
                The string to output.
    
            asis : bool, optional
                When True, the string is printed without using the Stata SMCL
                interpreter. Default is False.
            """
            if asis is True:        
                asis = 1
            elif asis is False:
                asis = 0
            else:
                raise TypeError("asis must be a boolean value")
    
            return _stp._st_display(s+"\n", asis, 2)
    
    >>> sfi.SFIToolkit.display(inspect.getsource(sfi.SFIToolkit.display))
        @staticmethod
        def display(s, asis=False):
            """
            Output a string to the Stata Results window. Before the string
            is printed, it is run through the Stata SMCL interpreter.
    
            Parameters
            ----------
            s : str
                The string to output.
    
            asis : bool, optional
                When True, the string is printed without using the Stata SMCL
                interpreter. Default is False.
            """
            if asis is True:        
                asis = 1
            elif asis is False:
                asis = 0
            else:
                raise TypeError("asis must be a boolean value")
    
            return _stp._st_display(s, asis, 1)
    
    >>> end
    ----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    .
    Maybe that is the intended use (could someone at StataCorp can inform us if that is so?), but it seems that you could use sfi._st_display() to get the behavior you are seeking that does not break a line.

    - joe
    Last edited by Joseph Luchman; 15 Jan 2020, 14:43.
    Joseph Nicholas Luchman, Ph.D., PStatĀ® (American Statistical Association)
    ----
    Research Fellow
    Fors Marsh

    ----
    Version 18.0 MP

    Comment


    • #3
      Joseph Luchman , thank you for the investigation. I'd also like to have this clarified.

      sfi._st_display() is a good find, but as everything that belongs to the world of 'undocumented' it's risky in the long run. Perhaps, for the moment, I will define a mydisplay() as a proxy to sfi._st_display() and redact it later when/if the documented function is fixed.

      Comment


      • #4
        Hi Sergiy Radyakin:

        When you call display() and displayln() interactively through Stata's Command window, the contents will be
        displayed with a new line so that the >>> prompt will always appear on a fresh line. The difference is that
        displayln() will print an extra new line. For example:

        Code:
        . python
        ----------------------------------------------- python (type end to exit) -----
        >>> from sfi import SFIToolkit
        >>> SFIToolkit.display('a')
        a
        >>> SFIToolkit.displayln('a')
        a
        
        >>> end
        -------------------------------------------------------------------------------------

        The same rule will apply to running the above code in a .do file. For example:

        ------------------------------------------------- pytest.do -------------------
        python
        from sfi import SFIToolkit
        SFIToolkit.display('a')
        SFIToolkit.displayln('a')
        end
        ----------------------------------------------------------------------------------

        Code:
        . do pytest
        
        . python
        ----------------------------------------------- python (type end to exit) -----
        >>> from sfi import SFIToolkit
        >>> SFIToolkit.display('a')
        a
        >>> SFIToolkit.displayln('a')
        a
        
        >>> end
        -------------------------------------------------------------------------------
        .
        end of do-file


        However, you have discovered a bug where in some cases SFIToolkit.display() does not work correctly.
        If you put the above code in a python function, it should do what the documentation describes, but it
        currently does not. We will fix it in a future update.

        By the way, SFIToolkit.display() currently works as expected if you call it from a .py file. You might be
        able to use this as a work around until we get the fix released.

        Here is an example:

        ------------------------------------------------- pytest.py -------------------
        from sfi import SFIToolkit

        SFIToolkit.display('A')
        SFIToolkit.display('B')
        SFIToolkit.display('C')
        SFIToolkit.display('D')
        SFIToolkit.displayln('.')
        SFIToolkit.display('X')
        SFIToolkit.displayln('Y')
        SFIToolkit.display('Z')
        SFIToolkit.display('T')
        SFIToolkit.display('.')
        ----------------------------------------------------------------------------------

        Code:
        . python script pytest.py
        ABCD.
        XY
        ZT.
        Thank you for reporting this.

        Comment


        • #5
          Dear Zhao Xu,

          thank you very much for confirming. The problem was not mission-critical, and thank you very much for suggesting the workaround.

          Best, Sergiy

          Comment

          Working...
          X