Issue #135 resolved

Migration name output line breaks are broken on 0.6

created an issue

Currently alembic is outputting the migrations names similar to this:

  Generating /home/<user>/<project>/migrations/versions/2

There is a line break after "/2" splitting the path to the new migration file. It does not use current term width, and can't be turned off (without modifying alembic source). Also it should not be neccessary to add the line-breaks, most terminal emulators will break lines by themselves.

Comments (9)

  1. Mike Bayer repo owner

    is there a change in behavior specific to 0.6 being referred to here? I think the breaking behavior has been the same the whole time. it's wrapping to 80 columns using textwrap (supports an option to not chop words in half?)

  2. fresch reporter

    I don't know if this behavior is specific to 0.6, since that is the only version I have used so far. I just thought to specify the version I'm currently using as a reference.

    I left the issue type as bug, since none of the other options for type made immediate sense to me. You would most likely know better what kind of issue this is.

    I do consider the current behavior of wrapping the lines to be wrong. In my opinion there should not be any wrapping, since terminal emulators will (should) handle that. At least all terminal emulators I have so far used did wrap output: konsole, gnome-terminal, lxterm, Xfce Terminal, xterm, rxvt all on Linux.

    I noticed this while generating migrations by shell script. I had to replace the line endings and the following whitespace to capture the migration filename from the command output. I scrapped that approach and modified "def msg" in the alembic utils module to just write the message to stdout.

    Also I have the habit (from using another migration tool) to just double click the filename and middle-mouse-clicking/pasting this as argument to my editor. Again, most terminal emulators redefine the definition of a "word" as alphanumeric including valid characters in paths. So double clicking a path will select all of it.

    To sum up: I guess a case of "It Breaks My Workflow (TM)" ;)

  3. Mike Bayer repo owner

    the textwrapping is attempting to take term length into account using $COLUMNS:

    strangely though it isn't present, even though it is in my terminal environment:

    classics-MacBook-Pro:alembic classic$ echo $COLUMNS
    classics-MacBook-Pro:alembic classic$ python
    Python 2.7.5 (default, Oct 23 2013, 12:41:26) 
    [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import os
    >>> os.environ['COLUMNS']
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/", line 23, in __getitem__
        raise KeyError(key)
    KeyError: 'COLUMNS'

    there's discussion of how to work around this at though I'm not seeing a simple platform-agnostic version (there's one that gets into ctypes and windll crap which is horrifying).

    I did some runs to figure out why the heck I even need to use textwrap here, it's because I'm trying to indent all the output evenly. But if getting term width is that impossible in Python then maybe it just needs to be whacked....or, maybe the indentation only happens on the unix platform, since I'm not going to start importing ctypes crap just to achieve this.

  4. Mike Bayer repo owner

    to sum up:

    get at "width" using the approach: rows, columns = os.popen('stty size', 'r').read().split(). If this is not available, "width" remains at None. Then def msg() only uses the textwrap/indentation approach if "width" is not None. If it's None, then it just spits out the message plus an optional newline without any indentation.

  5. Mike Bayer repo owner

    correction, here's the best way to get term width, later down in that post (as I figured out independently instead of just scrolling down):

    def terminal_size():
        import fcntl, termios, struct
        h, w, hp, wp = struct.unpack('HHHH',
            fcntl.ioctl(0, termios.TIOCGWINSZ,
            struct.pack('HHHH', 0, 0, 0, 0)))
        return w, h
  6. Michel Albert

    Why even break at all? As fresh said, the terminal usually takes care of this. The current wrapping is really annoying as you cannot simply double-click the file-name to copy/paste. And, at least for me, it has been in alembic for quite some time now. IIRC even as far back as 0.4.

    Reading through this ticket, it seems that this involves quite some low-level terminal code. And that in a library dealing with DB migrations. ;)

  7. Mike Bayer repo owner

    because I'd like the output through that particular messaging function to be indented.

    I wasn't comfortable opening "stty size" but a simple call with fcntl, skip on windows, is fine.

  8. Log in to comment