Skip to content

Commit

Permalink
remove some of the last vestiges of ipython_genutils
Browse files Browse the repository at this point in the history
  • Loading branch information
Carreau committed Sep 29, 2023
1 parent ecb3aa8 commit 65f046e
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 9 deletions.
2 changes: 1 addition & 1 deletion qtconsole/comms.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@

from traitlets.config import LoggingConfigurable

from ipython_genutils.importstring import import_item

import uuid

from qtpy import QtCore
from qtconsole.util import MetaQObjectHasTraits, SuperQObject
from .util import import_item


class CommManager(MetaQObjectHasTraits(
Expand Down
7 changes: 3 additions & 4 deletions qtconsole/completion_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

import ipython_genutils.text as text

from qtpy import QtCore, QtGui, QtWidgets
from .util import compute_item_matrix

#--------------------------------------------------------------------------
# Return an HTML table with selected item in a special class
Expand Down Expand Up @@ -311,9 +311,8 @@ def show_items(self, cursor, items, prefix_length=0):
width = self._text_edit.document().textWidth()
char_width = self._console_widget._get_font_width()
displaywidth = int(max(10, (width / char_width) - 1))
items_m, ci = text.compute_item_matrix(items, empty=' ',
displaywidth=displaywidth)
self._sliding_interval = SlidingInterval(len(items_m)-1, width=self._rows)
items_m, ci = compute_item_matrix(items, empty=" ", displaywidth=displaywidth)
self._sliding_interval = SlidingInterval(len(items_m) - 1, width=self._rows)

self._items = items_m
self._size = (ci['rows_numbers'], ci['columns_numbers'])
Expand Down
4 changes: 2 additions & 2 deletions qtconsole/completion_plain.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Distributed under the terms of the Modified BSD License.

from qtpy import QtCore, QtGui, QtWidgets
import ipython_genutils.text as text
from .util import columnize


class CompletionPlain(QtWidgets.QWidget):
Expand Down Expand Up @@ -53,7 +53,7 @@ def show_items(self, cursor, items, prefix_length=0):
if not items :
return
self.cancel_completion()
strng = text.columnize(items)
strng = columnize(items)
# Move cursor to start of the prefix to replace it
# when a item is selected
cursor.movePosition(QtGui.QTextCursor.Left, n=prefix_length)
Expand Down
2 changes: 1 addition & 1 deletion qtconsole/console_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from qtconsole.rich_text import HtmlExporter
from qtconsole.util import MetaQObjectHasTraits, get_font, superQ

from ipython_genutils.text import columnize
from traitlets.config.configurable import LoggingConfigurable
from traitlets import Bool, Enum, Integer, Unicode

Expand All @@ -28,6 +27,7 @@
from .completion_html import CompletionHtml
from .completion_plain import CompletionPlain
from .kill_ring import QtKillRing
from .util import columnize


def is_letter_or_number(char):
Expand Down
2 changes: 1 addition & 1 deletion qtconsole/frontend_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
import re

from qtpy import QtCore, QtGui, QtWidgets
from ipython_genutils.importstring import import_item

from qtconsole.base_frontend_mixin import BaseFrontendMixin
from traitlets import Any, Bool, Instance, Unicode, DottedObjectName, default
from .bracket_matcher import BracketMatcher
from .call_tip_widget import CallTipWidget
from .history_console_widget import HistoryConsoleWidget
from .pygments_highlighter import PygmentsHighlighter
from .util import import_item


class FrontendHighlighter(PygmentsHighlighter):
Expand Down
212 changes: 212 additions & 0 deletions qtconsole/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,215 @@ def get_font(family, fallback=None):
if fallback is not None and font_info.family() != family:
font = QtGui.QFont(fallback)
return font


# -----------------------------------------------------------------------------
# Vendored from ipython_genutils
# -----------------------------------------------------------------------------
def _col_chunks(l, max_rows, row_first=False):
"""Yield successive max_rows-sized column chunks from l."""
if row_first:
ncols = (len(l) // max_rows) + (len(l) % max_rows > 0)
for i in range(ncols):
yield [l[j] for j in range(i, len(l), ncols)]
else:
for i in range(0, len(l), max_rows):
yield l[i : (i + max_rows)]


def _find_optimal(rlist, row_first=False, separator_size=2, displaywidth=80):
"""Calculate optimal info to columnize a list of string"""
for max_rows in range(1, len(rlist) + 1):
col_widths = list(map(max, _col_chunks(rlist, max_rows, row_first)))
sumlength = sum(col_widths)
ncols = len(col_widths)
if sumlength + separator_size * (ncols - 1) <= displaywidth:
break
return {
"num_columns": ncols,
"optimal_separator_width": (displaywidth - sumlength) // (ncols - 1)
if (ncols - 1)
else 0,
"max_rows": max_rows,
"column_widths": col_widths,
}


def _get_or_default(mylist, i, default=None):
"""return list item number, or default if don't exist"""
if i >= len(mylist):
return default
else:
return mylist[i]


def compute_item_matrix(items, row_first=False, empty=None, *args, **kwargs):
"""Returns a nested list, and info to columnize items
Parameters
----------
items
list of strings to columize
row_first : (default False)
Whether to compute columns for a row-first matrix instead of
column-first (default).
empty : (default None)
default value to fill list if needed
separator_size : int (default=2)
How much characters will be used as a separation between each columns.
displaywidth : int (default=80)
The width of the area onto which the columns should enter
Returns
-------
strings_matrix
nested list of string, the outer most list contains as many list as
rows, the innermost lists have each as many element as columns. If the
total number of elements in `items` does not equal the product of
rows*columns, the last element of some lists are filled with `None`.
dict_info
some info to make columnize easier:
num_columns
number of columns
max_rows
maximum number of rows (final number may be less)
column_widths
list of with of each columns
optimal_separator_width
best separator width between columns
Examples
--------
::
In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l']
In [2]: list, info = compute_item_matrix(l, displaywidth=12)
In [3]: list
Out[3]: [['aaa', 'f', 'k'], ['b', 'g', 'l'], ['cc', 'h', None], ['d', 'i', None], ['eeeee', 'j', None]]
In [4]: ideal = {'num_columns': 3, 'column_widths': [5, 1, 1], 'optimal_separator_width': 2, 'max_rows': 5}
In [5]: all((info[k] == ideal[k] for k in ideal.keys()))
Out[5]: True
"""
info = _find_optimal(list(map(len, items)), row_first, *args, **kwargs)
nrow, ncol = info["max_rows"], info["num_columns"]
if row_first:
return (
[
[
_get_or_default(items, r * ncol + c, default=empty)
for c in range(ncol)
]
for r in range(nrow)
],
info,
)
else:
return (
[
[
_get_or_default(items, c * nrow + r, default=empty)
for c in range(ncol)
]
for r in range(nrow)
],
info,
)


def columnize(items, row_first=False, separator=" ", displaywidth=80, spread=False):
"""Transform a list of strings into a single string with columns.
Parameters
----------
items : sequence of strings
The strings to process.
row_first : (default False)
Whether to compute columns for a row-first matrix instead of
column-first (default).
separator : str, optional [default is two spaces]
The string that separates columns.
displaywidth : int, optional [default is 80]
Width of the display in number of characters.
Returns
-------
The formatted string.
"""
if not items:
return "\n"
matrix, info = compute_item_matrix(
items,
row_first=row_first,
separator_size=len(separator),
displaywidth=displaywidth,
)
if spread:
separator = separator.ljust(int(info["optimal_separator_width"]))
fmatrix = [filter(None, x) for x in matrix]
sjoin = lambda x: separator.join(
[y.ljust(w, " ") for y, w in zip(x, info["column_widths"])]
)
return "\n".join(map(sjoin, fmatrix)) + "\n"


def get_text_list(list_, last_sep=" and ", sep=", ", wrap_item_with=""):
"""
Return a string with a natural enumeration of items
>>> get_text_list(['a', 'b', 'c', 'd'])
'a, b, c and d'
>>> get_text_list(['a', 'b', 'c'], ' or ')
'a, b or c'
>>> get_text_list(['a', 'b', 'c'], ', ')
'a, b, c'
>>> get_text_list(['a', 'b'], ' or ')
'a or b'
>>> get_text_list(['a'])
'a'
>>> get_text_list([])
''
>>> get_text_list(['a', 'b'], wrap_item_with="`")
'`a` and `b`'
>>> get_text_list(['a', 'b', 'c', 'd'], " = ", sep=" + ")
'a + b + c = d'
"""
if len(list_) == 0:
return ""
if wrap_item_with:
list_ = ["%s%s%s" % (wrap_item_with, item, wrap_item_with) for item in list_]
if len(list_) == 1:
return list_[0]
return "%s%s%s" % (sep.join(i for i in list_[:-1]), last_sep, list_[-1])


def import_item(name):
"""Import and return ``bar`` given the string ``foo.bar``.
Calling ``bar = import_item("foo.bar")`` is the functional equivalent of
executing the code ``from foo import bar``.
Parameters
----------
name : string
The fully qualified name of the module/package being imported.
Returns
-------
mod : module object
The module that was imported.
"""

parts = name.rsplit(".", 1)
if len(parts) == 2:
# called with 'foo.bar....'
package, obj = parts
module = __import__(package, fromlist=[obj])
try:
pak = getattr(module, obj)
except AttributeError:
raise ImportError("No module named %s" % obj)
return pak
else:
# called with un-dotted string
return __import__(parts[0])

0 comments on commit 65f046e

Please sign in to comment.